51单片机串口通信的发送与接收 字符串
样做过,但我这个绝对不是抄袭或者模仿来的。这样写的确可以避免前面提到过的bug,不过代价是多用了一个定时器的资源,而且中断函数里的内容更多了,占用了更多的时间。
要是能把第一种方法改进一下就好了,主要是那个校验不能为aa的那个bug,因为毕竟传输到一半突然断了的可能性是非常小的。后来我想第一个判断if(count==0&&receive[count]==0xaa)好像有点太严格了,考虑到第二字节的帧头,跟板选地址不可能为aa,于是把这个改写为if(count>=0&&count<=2&& receive[count]==0xaa),这样就把bug出现的几率降到了非常小,也只是在前一帧结尾数据恰好为 aa 55 板选 的时候才出现,几率是多少大家自己算一下吧,呵呵。这样我自己觉得,昨天写的那种方法改进到这个程度,应该算可以啦,反正我是很满意了。
实际上我还想过其他的方法,比如缓存的数组采用移位寄存的方式。拿前面的4个字节的协议为例。
- voidser()interrupt4
- {
- unsignedchari;
- RI=0;
- for(i=0;i<3;i++)
- {
- receive[i]=receive[i+1];
- }
- receive[3]=SBUF;
- if(reveive[0]==0xaa&&receive[1]==0x55&&receive[2]==receive[3])
- {
- ret_flag=1;
- ES=0;
- }
- }
这段代码看上去可是简单明了,这样判断可是不错啊,同时判断帧头跟校验不会产生前面提到的bug。说实话当时我刚想出这种方法并写出来的时候,马上就被我给否了。那个for循环可真是很占时间的啊,延时函数都是这样写的。每次都循环一下,这延时太长,通信速度太快的话就不能接收到下一字节数据了。最要命的是这个时间的长度是随着通信协议帧的字节数增加而增加的,如果一次要接收几十个字节,肯定就玩完了。这种方法我一次都没用过。
不过我居然又想出来了这种方法的改良措施,是前两天刚想出来的,呵呵,还没有实践过呢。
下面代码的协议就按第二段程序(定时器清零的那个协议,一共10字节)
全局变量
- bitret_flag;
- unsignedcharreceive[256]={0};
- unsignedcharboardaddress;
- 中断函数
- voidser()interrupt4
- {
- staticunsignedchari=0;
- staticunsignedchartotal=0;
- RI=0;
- receive[i]=SBUF;
- total=total-receive[i-7]+receive[i-1];
- if(receive[i-9]==0xaa&&receive[i-8]==0x55
- &&receive[i-7]==boardaddress&&receive[i]==total
- )
- {
- ret_flag=1;
- ES=0;
- }
- i++;
- }
之所以要定义256个长度的数组,就是为了能够让数组“首尾相接”。因为0 -1 = 255 , 255+1 = 0。而且我在计算校验的时候也改进了算法,不会因为数据长度的增加而增加计算校验值的时间。这种方法也是我不久前才想出来的,所以还没有经过实际的验证。上面的代码可能会有逻辑上的错误,如果真有错误,有网友看出来的话,请在下面留言告诉我。这个方法也是我原创的哦,别人也肯能会想到,不过我这个绝对不是抄袭别人的。
上面的代码最大的缺点就是变量定义的太多了,太占ram资源了,编译的时候可能会出现错误,毕竟51单片机才128字节的ram(有的资源也很丰富的,比如c8051系列的),这一下子就是256字节的变量。不过对于资源多一些的单片机,这样写还是可以的。要是能有4bit在一起的数据类型就好了,呵呵,verilog代码里面是可以的,C语言里貌似不行啊。
要想能在例如51单片机上运行,只能按照下面的折中方式了,也就是把i相关的量都与一个0x0f
- 全局变量
- bitret_flag;
- unsignedcharreceive[16]={0};//可以考虑在定义时加上idata,毕竟还可能是32
- //或者64长度的数组呢unsignedcharidatareceive[16]={0};
- unsignedcharboardaddress;
- 中断函数
- voidser()interrupt4
- {
- staticunsignedchari=0;
- staticunsignedchartotal=0;
- RI=0;
- receive[i&0x0f]=SBUF;
- total=total-receive[(i-7)&0x0f]+receive[(i-1)&0x0f];
- if(receive[(i-9)&0x0f]==0xaa&&receive[(i-8)&0x0f]==0x55
- &&receive[(i-7)&0x0f]==boardaddress&&receive[i&0x0f]==total
- )
- {
- ret_flag=1;
- ES=0;
- }
- i++;
- }
51单片机串口通信发送与接收字符 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)