串口通信——接收串口数据并处理(C语言)

本文提供了一个详细的串口数据接收程序示例,包括编程逻辑、通用函数模块和完整的代码实例。介绍了如何设置波特率、数据位、停止位和奇偶校验位等关键参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文主要内容包含:

 1.接收串口数据程序的编程逻辑示意图;

 2.接收串口数据程序要用到的通用函数模块(可直接引用,无需更改);

 3.接收串口数据程序的示例。


1.接收串口数据程序的编程逻辑示意图:

2.与串口有关的函数模块及数组(可直接引用到自己的程序中):

//设置波特率函数会用到的数组
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
        B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
        38400,  19200,  9600, 4800, 2400, 1200,  300, };
int OpenDev(char *Dev) //打开串口
{
	int fd = open(Dev,O_RDWR | O_NOCTTY | O_NONBLOCK);
	if(-1 == fd)
	{
		perror("Can't Open Serial Port");
		return -1;
	}
	else
	{
		printf("Open com success!!!!!!!!!!!");
		return fd;
	}
}

void set_speed(int fd, int speed)  //设置波特率
{
  int   i;
  int   status;
  struct termios   Opt;
  tcgetattr(fd, &Opt);
  for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
   {
    if  (speed == name_arr[i])
    {
        tcflush(fd, TCIOFLUSH);
        cfsetispeed(&Opt, speed_arr[i]);
        cfsetospeed(&Opt, speed_arr[i]);
        status = tcsetattr(fd, TCSANOW, &Opt);
        if  (status != 0)
            perror("tcsetattr fd1");
        return;
        }
   tcflush(fd,TCIOFLUSH);
   }
}

int set_Parity(int fd,int databits,int stopbits,int parity)  //设置数据位、奇偶位、停止位等
{
   struct termios options;
 if  ( tcgetattr( fd,&options)  !=  0)
  {
    perror("SetupSerial 1");
    return(0);
  }
  bzero(&options,sizeof(options));
  options.c_cflag |= CLOCAL | CREAD;
  options.c_cflag &= ~CSIZE;
  switch (databits) /*设置数据位*/
  {
    case 7:
        options.c_cflag |= CS7;
        break;
    case 8:
        options.c_cflag |= CS8;
        break;
    default:
        fprintf(stderr,"Unsupported data size\n");
        return (0);
    }
  switch (parity)/*设置校验位*/
    {
    case 'n':
    case 'N':
        options.c_cflag &= ~PARENB;  
        //options.c_iflag &= ~INPCK;    
        break;
    case 'o':
    case 'O':
        options.c_cflag |= (PARODD | PARENB);  
        options.c_iflag |= (INPCK | ISTRIP);            
        break;
    case 'e':
    case 'E':
        options.c_cflag |= PARENB;    
        options.c_cflag &= ~PARODD;  
        options.c_iflag |= (INPCK | ISTRIP);       
        break;
    case 'S':
    case 's':  
        options.c_cflag &= ~PARENB;
        options.c_cflag &= ~CSTOPB;
        break;
    default:
        fprintf(stderr,"Unsupported parity\n");
        return (0);
        }
  switch (stopbits)/*设置停止位*/
    {
    case 1:
        options.c_cflag &= ~CSTOPB;
        break;
    case 2:
        options.c_cflag |= CSTOPB;
        break;
    default:
        fprintf(stderr,"Unsupported stop bits\n");
        return (FALSE);
    }
  if (parity != 'n')
    options.c_iflag |= INPCK;
    options.c_cc[VTIME] = 0; 
    options.c_cc[VMIN] = 0;
  tcflush(fd,TCIFLUSH); 
  if (tcsetattr(fd,TCSANOW,&options) != 0)
    {
        perror("SetupSerial 3");
        return (0);
    }
  return (1);
 }

3.示例:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0

int analysis(char *buff);
int OpenDev(char *Dev);
void set_speed(int fd, int speed);
int set_Parity(int fd,int databits,int stopbits,int parity);

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
int OpenDev(char *Dev)
{
  int fd = open(Dev,O_RDWR | O_NOCTTY | O_NONBLOCK);
  if(-1 == fd)
    {
      perror("Can't Open Serial Port");
      return -1;
    } 
  else 
    {
      printf("Open com success!!!!!!!!!!!");
      return fd;
    }
} 
void set_speed(int fd, int speed)
{ 
  int i; 
  int status; 
  struct termios Opt;
 tcgetattr(fd, &Opt); 
  for ( i= 0; i < sizeof(speed_arr) / sizeof(int); i++)
   { 
      if (speed == name_arr[i]) 
        { 
          tcflush(fd, TCIOFLUSH); 
          cfsetispeed(&Opt, speed_arr[i]);
         cfsetospeed(&Opt, speed_arr[i]);
         status = tcsetattr(fd, TCSANOW, &Opt); 
          if (status != 0) perror("tcsetattr fd1");
         return;
       } 
    tcflush(fd,TCIOFLUSH);
    }
}
int set_Parity(int fd,int databits,int stopbits,int parity) 
{ 
  struct termios options; 
  if ( tcgetattr( fd,&options) != 0) 
  {
   perror("SetupSerial 1");
   return(FALSE);
 } 
  bzero(&options,sizeof(options)); 
  options.c_cflag |= CLOCAL | CREAD;
 options.c_cflag &= ~CSIZE; 
  switch (databits) 
  { 
    case 7: 
    options.c_cflag |= CS7;
   break;
   case 8:
   options.c_cflag |= CS8;
   break; 
    default: fprintf(stderr,"Unsupported data size\n");
   return (FALSE); 
  } 
  switch (parity) 
  {
   case 'n': 
    case 'N':
   options.c_cflag &= ~PARENB;
   options.c_iflag &= ~INPCK; 
    break; 
    case 'o':
   case 'O': 
    options.c_cflag |= (PARODD | PARENB);
   options.c_iflag |= (INPCK | ISTRIP); 
    break; 
    case 'e': 
    case 'E': 
    options.c_cflag |= PARENB;
   options.c_cflag &= ~PARODD; 
    options.c_iflag |= (INPCK | ISTRIP); 
    break; 
    case 'S': 
    case 's': 
    options.c_cflag &= ~PARENB; 
    options.c_cflag &= ~CSTOPB;
   break;
   default: fprintf(stderr,"Unsupported parity\n"); 
   return (FALSE); 
  } 
  switch (stopbits)
 { 
    case 1:
   options.c_cflag &= ~CSTOPB; 
    break; 
    case 2: 
    options.c_cflag |= CSTOPB;
   break; 
    default: fprintf(stderr,"Unsupported stop bits\n"); 
    return (FALSE); 
    } 
    if (parity != 'n') 
    options.c_iflag |= INPCK; 
    options.c_cc[VTIME] = 0;
   options.c_cc[VMIN] = 0;
   tcflush(fd,TCIFLUSH); 
    if (tcsetattr(fd,TCSANOW,&options) != 0)
   {  
        perror("SetupSerial 3"); 
        return (FALSE);
   } 
    return (TRUE);
}

int analysis (char *buff)
{
  int i;
  char *p;
  p=buff;
  for(i=0;i<255,i++)
    {
      printf("%s ",p[i]);
    }
  return 0;
}

void main(void)
{
  int fd;
  int nread;
  char buff[255];
  char *dev_name = "/dev/ttymxc4";//根据实际情况选择串口
  while(1) 
    {  
      fd = OpenDev(dev_name); //打开串口 

      if(fd>0) 
      set_speed(fd,9600); //设置波特率 
      else 
      { 
         printf("Can't Open Serial Port!\n"); 
         sleep(1);
        continue; 
      } 
  break;
}

if(set_Parity(fd,8,1,'N')==FALSE) //设置校验位 
{
  printf("Set Parity Error\n"); 
  exit(1);
}

while(1) 
  { 
    sleep(3); 
    nread = read(fd,buff,sizeof(buff));
    if((nread>0))
      {		
	printf("Success!\n"); 
       }
    analysis(buff);
  }
}



<think>好的,我需要帮助用户找到关于K210芯片通过串口接收数组的实现方法或代码示例。首先,我需要回忆一下K210的串口通信相关知识。K210通常使用UART模块进行串口通信,用户可能需要配置串口参数,比如波特率、数据位、停止位等。然后设置接收中断或者DMA来接收数据,这样可以避免阻塞主程序。 接下来,用户提供的引用中有一些代码片段,比如创建环形缓冲区、打开串口设备、配置DMA通道等。这可能涉及到RT-Thread操作系统的API,比如rt_ringbuffer_create、rt_device_open、rt_device_control等函数。需要结合这些代码来构建一个接收数组的示例。 另外,用户提到了使用DMA来降低MCU压力,这说明DMA配置是关键步骤之一。需要确保DMA正确初始化,设置好接收缓冲区和中断处理函数。环形缓冲区用于存储接收到的数据,这样可以有效管理数据流,避免溢出。 还需要考虑数据解析的问题。用户可能需要将接收到的字节数组转换为有意义的数据结构,比如协议包。示例中的k210_msg_packer可能负责打包和解包数据,这需要对应的回调函数来处理接收到的数据包。 在编写代码示例时,应该分步骤说明:初始化串口、配置DMA、设置环形缓冲区、实现中断服务函数或DMA回调函数,以及数据解析部分。同时要注意错误处理,比如串口打开失败或配置错误时的处理。 用户可能遇到的问题包括数据接收不完整、缓冲区溢出、数据解析错误等,所以在代码中需要加入适当的错误检查和日志输出。此外,波特率匹配、数据位设置等硬件相关配置也需要与发送端一致,否则会导致通信失败。 最后,生成相关问题时,应该围绕串口配置、DMA使用、数据解析、错误处理等方面展开,帮助用户全面理解K210的串口接收实现方法。</think>### K210串口接收数组实现方法 K210芯片通过串口接收数组的实现主要涉及**串口初始化、中断配置、缓冲区管理**三个核心环节。以下是基于RT-Thread操作系统的实现步骤及代码示例: --- #### 一、串口设备初始化 配置串口参数注册接收回调函数: ```c // 定义串口设备指针 rt_device_t k210_serial = RT_NULL; // 初始化串口2(以115200波特率为例) void uart2_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; config.baud_rate = BAUD_RATE_115200; k210_serial = rt_device_find("uart2"); if (k210_serial == RT_NULL) { rt_kprintf("Find uart2 failed\n"); return; } /* 以读写及中断接收方式打开串口 */ if (rt_device_open(k210_serial, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX) != RT_EOK) { rt_kprintf("Open uart2 failed\n"); return; } /* 配置串口参数 */ rt_device_control(k210_serial, RT_DEVICE_CTRL_CONFIG, &config); /* 设置接收回调函数 */ rt_device_set_rx_indicate(k210_serial, uart2_rx_callback); } ``` --- #### 二、环形缓冲区与DMA配置 使用环形缓冲区和DMA提高接收效率: ```c #define UART2_RB_SIZE 256 static struct rt_ringbuffer *uart2_rb; // 创建环形缓冲区 uart2_rb = rt_ringbuffer_create(UART2_RB_SIZE); if (uart2_rb == RT_NULL) { rt_kprintf("Create ringbuffer failed\n"); return; } // DMA通道初始化(需根据具体硬件实现) void uart2_dma_config(void) { // 配置DMA接收通道,设置目标地址和缓冲区大小 // 具体实现需参考K210手册 } ``` --- #### 三、中断回调函数实现 处理接收数据存入缓冲区: ```c // 串口接收中断回调 static rt_err_t uart2_rx_callback(rt_device_t dev, rt_size_t size) { uint8_t ch; while (rt_device_read(dev, 0, &ch, 1) > 0) { rt_ringbuffer_put(uart2_rb, &ch, 1); } return RT_EOK; } ``` --- #### 四、数据解析示例 从缓冲区提取完整数据包: ```c void process_uart_data(void) { uint8_t buffer[64]; rt_size_t len; // 检查缓冲区是否有数据 len = rt_ringbuffer_data_len(uart2_rb); if (len > 0) { // 读取数据(可根据协议解析) len = rt_ringbuffer_get(uart2_rb, buffer, sizeof(buffer)); rt_kprintf("Received %d bytes: ", len); for (int i = 0; i < len; i++) { rt_kprintf("%02X ", buffer[i]); } rt_kprintf("\n"); } } ``` --- #### 关键点说明 1. **中断模式**:使用`RT_DEVICE_FLAG_INT_RX`标志启用接收中断 2. **DMA优化**:通过DMA传输减少CPU占用(参考引用[1]中的`uart2_dma_config()`) 3. **协议处理**:建议配合数据打包协议(如引用[1]中的`upacker_init()`) --- ###
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值