单片机学习小组
直播中

张浩

7年用户 1145经验值
私信 关注

请问一下串口接收是如何去处理数据的

请问一下串口接收是如何去处理数据的?分为哪几个部分呢?

回帖(1)

李天竹

2022-1-27 11:35:12
串口接收处理数据

串口初始化

stm32的串口初始化

void USART_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;


        // 打开串口GPIO的时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
       
        // 打开串口外设的时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


        // 将USART Tx的GPIO配置为推挽复用模式
        GPIO_InitStructure.GPIO_Pin = USART_TX_GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);


        // 将USART Rx的GPIO配置为浮空输入模式
        GPIO_InitStructure.GPIO_Pin = USART_RX_GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        // 配置串口的工作参数
        // 配置波特率
        USART_InitStructure.USART_BaudRate = 115200;
        // 配置 针数据字长
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        // 配置停止位
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        // 配置校验位
        USART_InitStructure.USART_Parity = USART_Parity_No ;
        // 配置硬件流控制
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        // 配置工作模式,收发一起
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        // 完成串口的初始化配置
        USART_Init(USART2, &USART_InitStructure);


          NVIC_InitTypeDef NVIC_InitStructure;
  
        /* 嵌套向量中断控制器组选择 */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
         
        /* 配置USART为中断源 */
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        /* 抢断优先级*/
         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
        /* 子优先级 */
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
          /* 使能中断 */
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        /* 初始化配置NVIC */
          NVIC_Init(&NVIC_InitStructure);
       
        // 使能串口接收中断
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);       
        USART_ClearITPendingBit(USART2, USART_IT_RXNE);  //清楚中断标志
        // 使能串口
        USART_Cmd(USART2, ENABLE);               


   
        
        for(int i=0;i     {
            _rw_para._r_buf_status = empty;//清空缓存器
        
    }
}
数据接收结构体


#define  USART_TX_GPIO_PIN        GPIO_Pin_2
#define  USART_RX_GPIO_PIN        GPIO_Pin_3


//枚举类型
typedef enum data_ht {
        yes, no
} data_ht; //数据接收包头状态
typedef enum BufStatus {
        empty, full
} BufStatus; //数据缓存器状态 空还是满


//发送接收数据宏定义
#define r_BufNum 5  //数据接收缓存器个数
#define w_BufNum 5  //数据发送缓存器个数
#define r_BtyeNum 16 //数据接收缓存器长度
#define w_BtyeNum 16 //数据发送缓存器长度




//数据发送以及接受结构体
typedef struct _RW_Data {
        uint8_t _r_buf[r_BufNum][r_BtyeNum]; //数据接收缓存器
        uint8_t _w_buf[w_BufNum][r_BtyeNum]; //数据发送缓存器
        uint8_t _r_pos; //数据接收缓存器偏移地址 指在哪个缓存器
        uint8_t _w_pos; //数据发送缓存器偏移地址 指在哪个缓存器
        uint8_t _r_pos_byte; //数据接收缓存器字节偏移地址
        uint8_t _w_pos_byte; //数据发送缓存器字节偏移地址
        data_ht _r_header; //数据包头状态   yes=已经收到包头 no=未收到包头
        data_ht _r_first; //数据包头第一个字节状态  yes=已经收到第一个字节 no=未收到第一个字节
        BufStatus _r_buf_status[r_BufNum]; //数据接送缓存器状态 empty=空 full=满
        BufStatus _w_buf_status[w_BufNum]; //数据发送缓存器状态 empty=空 full=满
        uint8_t Cur_DealPackage_Pos; //当前数据包处理的位置


} _RW_Data;
中断接收函数


//中断接收
void USART2_IRQHandler(void)    //串口2中断服务程序
{
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中断
  {
    uint8_t Receivedata;
   
   
    //USART_ClearITPendingBit(USART2, USART_IT_RXNE);  //清楚中断标志
    USART_ClearFlag(USART2, USART_FLAG_RXNE);
   
    Receivedata  = USART_ReceiveData(USART2);
   
   
    uint8_t i;
    crc=0;
   
    if(_rw_para._r_header == no)//包头数据还未找到
    {
      if(_rw_para._r_first == yes)//第一个字节已经收到
      {
        if(Receivedata == 0x55)//如果数据是55 则说明包头数据接收成功
        {
          _rw_para._r_buf[_rw_para._r_pos][1] = 0x55;//存储数据
          _rw_para._r_pos_byte=2;        //数据储存位置为2
          _rw_para._r_header = yes;//包头数据已经找到
        }
        else//如果数据不对 则清除数据
        {
          _rw_para._r_pos_byte=0;        //数据储存位置清零
          _rw_para._r_first=no;//清空
          _rw_para._r_header = no;//包头数据清空
        }
      }
      else//还未收到第一个字节
      {
        if((uint8_t)Receivedata == 0xAA)//接收到包头数据
        {
          if(_rw_para._r_pos>=r_BufNum)//判断是否越界
            _rw_para._r_pos = 0;
         
          //判断缓存器是否是空的
          if(_rw_para._r_buf_status[_rw_para._r_pos] == empty)
          {
            _rw_para._r_buf[_rw_para._r_pos][0] = 0xAA;//存储数据
            _rw_para._r_pos_byte=1;        //数据储存位置为1
            _rw_para._r_first=yes;//第一个字节数据已经收到
          }
          else
          {
            //这里要做报警处理
          }
        }
        else//数据不对 则直接抛掉
        {
          _rw_para._r_pos_byte=0;        //数据储存位置清零
          _rw_para._r_first=no;//清空
          _rw_para._r_header = no;//包头数据清空
        }
      }
    }
    else//包头数据已经找到 开始接收数据
    {
      if(_rw_para._r_pos_byte>=r_BtyeNum)//如果越界的话
      {
        _rw_para._r_pos_byte = 0;
        //这里要添加报警
      }
      else//数据储存
      {
        _rw_para._r_buf[_rw_para._r_pos][_rw_para._r_pos_byte] = Receivedata;//存储数据
        //如果数据个数到达了 那么可以进行数据处理了
        if((_rw_para._r_buf[_rw_para._r_pos][2]+4) == _rw_para._r_pos_byte)
        {
          //判断包尾的数据是否正确 如果正确 则进行解析
          if(_rw_para._r_buf[_rw_para._r_pos][_rw_para._r_pos_byte] == 0xFF && _rw_para._r_buf[_rw_para._r_pos][_rw_para._r_pos_byte-1] == 0x55)
          {
            //这里要做CRC校验
            for(i=3;i<13;i++)
            {
              crc += _rw_para._r_buf[_rw_para._r_pos];//CRC
            }
            if(crc == _rw_para._r_buf[_rw_para._r_pos][13])//CRC校验成功
            {
              _rw_para._r_buf_status[_rw_para._r_pos] = full;//数据为满状态
              _rw_para._r_pos++;//缓存地址增加
              if(_rw_para._r_pos>=r_BufNum)//判断是否越界
                _rw_para._r_pos = 0;
              //这里开始进行数据处理 或者在中断外部处理 这里到时候看情况
              Deal_Package();//数据处理完后 状态要变成空
            }
            else;//这里发送CRC校验错误报警
          }
          else//如果数据包尾不正确 则需要进行报警
          {
            //这里添加报警
          }
          _rw_para._r_pos_byte=0;        //数据储存位置清零
          _rw_para._r_first=no;//清空
          _rw_para._r_header = no;//包头数据清空
        }
        else//数据个数没有到达 则继续接收
        {
          _rw_para._r_pos_byte++;//地址进行偏移
        }
      }
      
    }
   
  }
  
}
数据处理函数


//数据处理
void Deal_Package(void){
  
  if(_rw_para._r_buf_status[_rw_para.Cur_DealPackage_Pos] == full)
   
  {
   ................................................
  }
  _rw_para._r_buf_status[_rw_para.Cur_DealPackage_Pos] = empty;//数据为空状态
  _rw_para.Cur_DealPackage_Pos++;//偏移量增加
  
  if(_rw_para.Cur_DealPackage_Pos>=r_BufNum)//地址越界判断
  _rw_para.Cur_DealPackage_Pos = 0;
  
}
举报

更多回帖

×
20
完善资料,
赚取积分