STM32串口中断接收一个完整的数据帧

发布时间 2023-07-21 08:45:13作者: SymPny

代码运行条件:
(1) 大端发送;
(2) 上位机发送一帧数据的时间间隔不能大于主循环周期;

(3)数据帧满足下面格式: 

帧头部(Head)

类型(Type)

长度(Length)

值(Value)

CRC校验

2字节

1字节

1字节

X字节

2字节

     0xaa  0x55

 

       X

 

 

  1. void USART6_Init (void)
  2. {
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. USART_InitTypeDef USART_InitStructure;
  5. NVIC_InitTypeDef NVIC_InitStructure;
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE);
  7. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //修改
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//修改
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  10. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  11. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  12. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13. GPIO_Init(GPIOC,&GPIO_InitStructure);//修改
  14. GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_USART6);//修改
  15. GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_USART6); //修改
  16. NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
  17. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  18. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  19. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  20. NVIC_Init(&NVIC_InitStructure);
  21. USART_InitStructure.USART_BaudRate = 115200;
  22. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  23. USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;
  24. USART_InitStructure.USART_Parity = USART_Parity_No;
  25. USART_InitStructure.USART_StopBits = USART_StopBits_1;
  26. USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  27. USART_Init(USART6,&USART_InitStructure);
  28. USART_ITConfig(USART6,USART_IT_RXNE,ENABLE);//打开接收中断
  29. USART_Cmd(USART6,ENABLE);
  30. }
  31. void USART6_IRQHandler()
  32. {
  33. unsigned char rCh;
  34. static char rCnt = 0;
  35. if(USART_GetITStatus(USART6,USART_IT_RXNE) != RESET)
  36. {
  37. rCh = USART_ReceiveData(USART6);
  38. COM6_RecvBuf[rCnt] = rCh;
  39. if(rCnt == 0) //帧头0xAA
  40. {
  41. rCnt = (0xAA != rCh)?0:rCnt+1;
  42. }
  43. else if(rCnt == 1) //帧头0x55
  44. {
  45. rCnt = (0x55 != rCh)?0:rCnt+1;
  46. }
  47. else if(rCnt == 2) //类型type
  48. {
  49. //这里可以根据类型的范围进行如上的处理
  50. rCnt++;
  51. }
  52. else if(rCnt == 3) //长度len
  53. {
  54. rCnt++;
  55. }
  56. else if(rCnt > 3) //值value
  57. {
  58. rCnt++;
  59. if(rCnt == 6+COM6_RecvBuf[3])
  60. {
  61. rCnt = 0;
  62. memcpy(COM6_RecvBufBck,COM6_RecvBuf,RECV_BUF_SZ);//缓冲
  63. COM6_RecvFin = 1; //通知主循环处理
  64. }
  65. }
  66. }
  67. }
  68. int main(void)
  69. {
  70. int i;
  71. //代码段1
  72. while(1)//该循环不能太慢,否则数据缓冲区会被部分修改
  73. {
  74. //代码段2
  75. if(COM6_RecvFin == 1)
  76. {
  77. COM6_RecvFin = 0;
  78. CMD_Analysis();//分析接收到的这帧数据
  79. }
  80. //代码段3
  81. }
  82. return 0;
  83. }
  84. //在以后再仔细分析数据接收较快而处理较慢的问题吧,本课题主要讨论的是如何完整的接收一个数据帧,在数据源正确的情况下不丢帧