串口收发处理——编程方法(原创)
对于通信相关代码编程,保证 及时、稳定、处理效率高,是很关键的。所以通常采用中断接收方式,并且中断处理函数尽量简短。
然而在我的工作中看到些:在中断中做很多工作,比如处理包的错误处理,解析,最终又将正确的有用信息拷贝到全局变量中,甚至还处理其他应用层的东西。
其实这样对于裸跑的mcu来说,main中的主循环就不高效了。
下面代码,将只对串口接收处理接收操作哦,在main的主循环去解析接收的内容;
comm_deal() 中以状态机的方式处理:等待接收(包头判断)、接收中(长度符合或有包尾、加接收超时)、接收处理(对包的正确性判断,以及应用处理、错误提示等);这样看是不是方便、高效很多呢!而且逻辑清晰!
对于包长固定的通讯格式,可以从接收长度上判断有没有收发完成;而对于多种格式的数据包结构,往往还是加个接收超时 T_WAST 判断较好(虽然这要求发送短包之间的间隔 T_WAST至少)
其实发送也可以采用中断的发送: 开启发送中断,讲发送内容放在buff_send[]中,在发送第一个字节。再跳到中断,在中断中发送其他内容。
1 #define MAX_CHAR_NUM 1064 2 3 struct USART{ 4 volatile unsigned short haveAcceptedLen;//接收字符数 5 unsigned short conIndex;//消费指针 6 unsigned short proIndex;//生产指针 7 unsigned long acceptTimer; 8 unsigned long readTimer; 9 unsigned char bufOverErr; 10 unsigned char acceptBuf[MAX_CHAR_NUM]; 11 }; 12 extern struct USART m1USART;//串口1的结构 13 14 /*------------------------ 15 brif:从接收缓存内读取一个字节 16 input: none 17 output: none 18 --------------------------*/ 19 struct USART m1USART;//串口的结构 20 unsigned char UartROneData(USART_TypeDef* USARTx,struct USART* pUSART ) 21 { 22 unsigned char val; 23 val=pUSART->acceptBuf[pUSART->conIndex]; 24 pUSART->conIndex =(pUSART->conIndex+1)%(MAX_CHAR_NUM); 25 /* Disable the USART0 Receive interrupt */ 26 USART_ITConfig(USARTx, USART_IT_RXNE, DISABLE); 27 pUSART->haveAcceptedLen =pUSART->haveAcceptedLen -1; 28 /* ENABLE the USART0 Receive interrupt */ 29 USART_ITConfig(USARTx, USART_IT_RXNE, ENABLE); 30 return val; 31 } 32 unsigned char UartRData(USART_TypeDef* USARTx ,struct USART* pUSART,unsigned char *mRBuf,unsigned short needRNum)// unsigned char needRNum 33 { 34 unsigned short rlen; 35 36 pUSART->readTimer = Tick_1ms; 37 rlen = 0; 38 while(1) 39 { 40 if(pUSART->haveAcceptedLen) 41 { 42 *(mRBuf+rlen) =UartROneData(USARTx,pUSART); 43 rlen++; 44 if(rlen>=needRNum) 45 break; 46 } 47 if((Tick_1ms-pUSART->readTimer)>100) 48 {//超时,发送超时错误 49 return 1;//err 50 } 51 } 52 return 0; 53 } 54 void UART_ClearRxBuf(struct USART *pUSART) 55 { 56 pUSART->haveAcceptedLen=0; 57 pUSART->proIndex=0; 58 pUSART->conIndex=0; 59 } 60 61 /** 62 * @brief This function handles USART1 interrupt request. 63 * @param None 64 * @retval None 65 */ 66 void USART1_IRQHandler(void) 67 { 68 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) 69 { 70 USART_ClearITPendingBit(USART1, USART_IT_RXNE); 71 m1USART.acceptBuf[m1USART.proIndex] = (uint8_t)USART_ReceiveData(USART1); 72 m1USART.proIndex =(m1USART.proIndex+1)%MAX_CHAR_NUM; 73 m1USART.haveAcceptedLen = m1USART.haveAcceptedLen+1; 74 if(m1USART.haveAcceptedLen> MAX_CHAR_NUM) 75 { 76 m1USART.bufOverErr = 1; 77 m1USART.haveAcceptedLen = 0; 78 m1USART.conIndex = m1USART.proIndex; 79 } 80 m1USART.acceptTimer=Tick_1ms; 81 } 82 } 83 84 /************应用部分 main.c*************/ 85 KeyData g_keydatabuf[MAX_KEY_NUM]={0}; 86 u8 CMD_status=CMD_WAIT; 87 u32 CMD_delay; 88 u8 bufData[MAX_CHAR_NUM];// 用于中转 89 u16 g_len; 90 void comm_deal(void) 91 { 92 u16 i; 93 u8 n,cmd1,cmd2; 94 u16 sum; 95 u16 tmp16; 96 u8 pool[4]={0}; 97 char Pstr[6]="\0"; 98 switch(CMD_status) 99 { 100 case CMD_WAIT: 101 if(m1USART.haveAcceptedLen>=2) 102 { 103 cmd1=UartROneData(USART1, &m1USART); 104 cmd2=UartROneData(USART1, &m1USART); 105 if(cmd1==HEAD1&&cmd2==HEAD2) 106 { 107 CMD_status=CMD_RECV; 108 CMD_delay=Tick_1ms; 109 //? Usart1_SendByte(0xDD); 110 } 111 else 112 { 113 UART_ClearRxBuf( &m1USART); 114 //? Usart1_SendByte(0xEE); 115 } 116 } 117 break; 118 case CMD_RECV: 119 if((m1USART.haveAcceptedLen+2)>=4) 120 { 121 g_len=m1USART.acceptBuf[m1USART.conIndex+1];//高8bit 122 g_len=(g_len<<8)+m1USART.acceptBuf[m1USART.conIndex];//低8bit 123 if((m1USART.haveAcceptedLen+2)>=g_len) 124 { 125 UartRData(USART1, &m1USART, bufData, g_len-2);//从包长度开始读取 126 CMD_status=CMD_DEAL; 127 } 128 } 129 else if(Tick_1ms-m1USART.acceptTimer>150)//超过50Ms, 没有接收,清空重新接收 130 { 131 UART_ClearRxBuf( &m1USART); 132 CMD_status=CMD_WAIT; 133 //? Usart1_SendByte(0xAA); 134 } 135 break; 136 case CMD_DEAL: 137 sum = GetSum(bufData,(g_len-4)); 138 sum=0xFFFF-(sum + HEAD1 +HEAD2); 139 tmp16 = (bufData[g_len-3]<<8) + bufData[g_len-4]; 140 if(sum==tmp16)//校验和正确 141 { 142 switch(bufData[2]) 143 { 144 case CMD_READ:145 //? Usart1_SendByte(0xBB);147 break; 148 case CMD_SET:149 //? Usart1_SendByte(0xCC);151 setting_save(); 152 break; 153 case CMD_ERR://错误码, 表示上控收到错误的下控包 154 if(bufData[3]==E_CMD)//下控发送包错误 155 { 156 //? Usart1_SendByte(0xEF); 157 my_memset(pool, 0, 4); 158 setting_sendback(CMD_READ, (u8 *)pool, 4); 159 } 160 else ; 161 break; 162 default: 163 break; 164 } 165 } 166 else//校验和错误,上控包错误 167 { 168 //? Usart1_SendByte(0xED); 169 my_memset(pool, 0, 4); 170 setting_sendback(CMD_ERR, (u8 *)pool, 4); 171 } 172 UART_ClearRxBuf(&m1USART); 173 CMD_status=CMD_WAIT; 174 break; 175 } 176 }