串口收发处理——编程方法(原创)

对于通信相关代码编程,保证 及时、稳定、处理效率高,是很关键的。所以通常采用中断接收方式,并且中断处理函数尽量简短。
然而在我的工作中看到些:在中断中做很多工作,比如处理包的错误处理,解析,最终又将正确的有用信息拷贝到全局变量中,甚至还处理其他应用层的东西。
其实这样对于裸跑的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 }

 

posted @ 2016-02-29 18:09  小温点秋香  阅读(1044)  评论(0编辑  收藏  举报