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