串口通信的无外乎两种方式:查询和中断 例如通信协议格式:AB + LEN + DATA1......+DATAN + SUM
LEN (DATA1.....SUM)
SUM(AB..........DATAN)
1.查询方式的应用:
bit WaitUART() { unsigned int xdata wait_j; for(wait_j=0;wait_j<4000;wait_j++) { if(RI1==1) { ClearRI1 return 1; } } return 0; }
void uart1_isr() interrupt 20 using 3 //UART1 INTERRUPT { register unsigned char Redata; unsigned char m; unsigned char CheckReSum=0; EA = 0; //disable all interrupt;
if(!WaitUART()) goto Exit; Redata = SBUF1; if(Redata != 0xab) // check receive flag { goto Exit; }
if(!WaitUART()) goto Exit; Redata = SBUF1; if(Redata == 0) { goto Exit; } iCmddata[0]=Redata; //data length CheckReSum = 0xef + iCmddata[0]; for(m=1;m<iCmddata[0];m++) { if(!WaitUART()) goto Exit; Redata = SBUF1; iCmddata[m] = Redata; CheckReSum += Redata; } if(!WaitUART()) goto Exit; Redata = SBUF1; iCmddata[m] = Redata; //sum if(CheckReSum != iCmddata[m]) //check transdata sum { goto Exit; }
ProcessOrder();
Exit: EA = 1; //enable all interrupt }
上面查询这个方法就是感觉很耗CPU,毕竟CPU总在等数据。
2.中断方式(采用队列)
(1)定义的一个数组用来接收数据,数据满的时候,最前面的数据会被最新的数据替换。
(2)有两个指针,一个头指针,由用户控制,用来查找符合包格式的数据包;一个尾指针永远指向队列的末尾处
如何查找:当发现头指针和尾指针不相等时,说明有新的数据,头指针向后移动,取出数据。
(1)如果数据不符合格式,头指针回到最初的位置+1
(2)如果数据符合格式,但未接收完,当头指针和尾指针相等,头指针返回最初的位置。
优点: 不占用CPU资源
缺点: 出现包误判。
问题:
假设发送 (1)第一个包发送 AB (错误包)
(2)第二个包发送 AB 02 10 01 (正确包)
队列的数据就为
AB AB 02 10 01
由于队列只是将接收的数据依次放在队列中,并不知道包和包间隔。当在队列取数据的时候,当取出AB后,会将后面的AB当成LEN,当取到最后值01时候,头指针会回到当初的EF头处 (认为数据没接收完),这样对第二个包就没有响应了。一直等到后面有AB个数据之后,才会再重新往后取第二个AB头。
大家是一般是怎么写的呀?谢谢!
|