数据包长度为NBYTE,起始字节为STARTBYTE1,STARTBYTE2,最后一个字节为检验和,中间字节不可能出现连续出现STARTBYTE1,STARTBYTE2。
unsigned char Buf[NBYTE-2];bit GetRight=0;void comm(void) interrupt 4//"串行口中断"{static unsigned char Sum,Flag=0,i;unsigned char temp;if(RI==1){RI=0;temp=SBUF;switch(Flag){case 0:if(temp==STARTBYTE1){Flag=1;}break;case 1:if(temp==STARTBYTE2){Sum=STARTBYTE1+STARTBYTE2;i=0;Flag=2;break;}if(temp==STARTBYTE1) break;Flag=0;break;case 2:if(temp==STARTBYTE1){Flag=3;break;}Sum+=temp;if((i>=(NBYTE-3))&&Sum==0){GetRight=1;Flag=0;break;}Buf[i++]=temp;break;case 3:if(temp==STARTBYTE2){Sum=STARTBYTE1+STARTBYTE2;Flag=2;i=0;break;}Sum+=STARTBYTE1;if((i>=(NBYTE-3))&&Sum==0){GetRight=1;Flag=0;break;}Buf[i++]=STARTBYTE1;if(temp==STARTBYTE1){break;}Sum+=temp;if((i>=(NBYTE-3))&&Sum==0){GetRight=1;Flag=0;break;}Buf[i++]=temp;Flag=2;break;}}}
第二种方法,使用队列中断函数:
void comm(void) interrupt 4//"串行口中断"{if(RI==1){RI=0;SBUF 入队;}}
主程序不断调用的函数:
unsigned char Buf[NBYTE-2];unsigned char ReadSerial(unsigned char *cp){unsigned char i;unsigned char temp,Sum;temp=队列中数据个数;if(temp<(NBYTE)) return 0;出队 temp;if(temp!=STARTBYTE1) return 0;temp=队列首字节;if(temp!=STARTBYTE2) return 0;出队 temp;sum=STARTBYTE1+STARTBYTE2;for(i=0;i{temp=队列首字节;if(temp==STARTBYTE1){temp=队列次首字节;if(temp==STARTBYTE2) return 0;}出队 temp;*cp++=temp;Sum+=temp;}temp=队列首字节;Sum+=temp;if(Sum!=0) return 0;出队 temp;return 1;}
第三种方法,使用RTOS中断函数:
void comm(void) interrupt 4//"串行口中断"{OS_INT_ENTER();if(RI==1){RI=0;OSIntSendSignal(RECIVE_TASK_ID);}OSIntExit();}ID为RECIVE_TASK_ID的任务void Recuve(void){unsigned char temp,temp1,Sum,i;OSWait(K_SIG,0);temp=SBUF;while(1){while(1){OSWait(K_SIG,0);temp1=SBUF;if((temp==STARTBYTE1)&&(temp1==STARTBYTE2)) break;temp=temp1;}Sum=STARTBYTE1+STARTBYTE2;OSWait(K_SIG,0);temp=SBUF;for(i=0;i{OSWait(K_SIG,0);temp1=SBUF;if((temp==STARTBYTE1)&&(temp1==STARTBYTE2)){OSWait(K_SIG,0);temp=SBUF;i=-1;Sum=STARTBYTE1+STARTBYTE2;continue;}Buf=temp;Sum+=temp;temp=temp1;}Sum+=temp1;if(Sum==0) OSSendSignal(命令解释任务 ID);}}
以下为这几种方法的比较:
可读性和编程容易性方面,第三钟方法最好(如果允许使用goto语句,程序更加简单易读),第二种次之(因为要编队列程序),第一种最差。如果协议更加复杂,这方面更加明显。程序简单易读,自然出错机会小了。
RAM占用方面,第三种方法较少,第二种最多(因为队列占用大量空间),第一种最少。
中断执行时间方面,第三种方法最长,第二种最短,第一种较长。
从功能方面,第三种方法最强,它还可以进行超时处理(虽然例子程序没有),其它方法均不行。
如果数据来的太快,命令处理程序来不及处理,三种方法处理方式不太一样,第一种和第三种方法类似:丢弃以前数据,第二种则是丢弃后到的数据。而且,第二种方法必须等命令处理程序完成后才处理下一个数据包,而第一种和第三种方只需命令处理程序将数据收取后就可处理下一个数据包。也就是说,第一种和第三种与命令处理程序并行处理,第二种方法为串行处理。
现在,一般情况下,开发的效率第一,执行的效率(包括执行时间和资源占用)第二。在这种情况下,降低些许效率换取开发的效率的较大提高,何乐而不为?何况,单个模块的执行的效率高不等于整个程序执行效率高。例如,如果程序需要等待一段时间,一般用程序延时或定时器延时。无论何种方法,CPU不再处理其它工作,效率很低。而用RTOS,等待的时候CPU可以处理其它工作,效率得到提高。
以下摘自《uC/OS-II--源码公开的实时嵌入式操作系统》
“实时内核也称为实时操作系统或RTOS。使用它使得实时应用程序的设计和扩展变得容易。不需要大的改动就可以增加新的功能。通过应用程序分割为若干独立的任务,RTOS使得应用程序的设计过程大为简化。使用可剥夺性的内核时,所有时间要求苛刻的事件都得到了尽可能快捷、有效的处理。通过有效的服务;如信号量、邮箱、队列、延时、超时等;RTOS使得资源得到更好的利用。
“如果应用项目对额外的需求可以承受,应该考虑使用实时内核。这些额外的需求是:内核的价格,额外ROM/RAM开销,2至4百分点的CPU额外负担。
“还有没提到的一个因素是使用实时内核增加的价格成本。在一些应用中,价格就是一切,以至于对使用RTOS连想都不敢想。”
总而言之,适用的就是最好的,不要拒绝RTOS,在它适用的情况下,它工作得很好