搜索
bottom↓
回复: 37

菜鸟发一个自认为不错的串口接收指令的程序!!严重欢迎拍砖、指教!!!

[复制链接]

出0入0汤圆

发表于 2011-7-5 16:28:06 | 显示全部楼层 |阅读模式
main()
{   
    while(1){
    if(Receiver_Count>0)         //如果串口中断接收到数据,侧马上进入接收剩余数据的等待
       {       
        Time20msCnt=0;
        while(Time20msCnt<5)     //根据要接收的数据多少和波特率,确定大概的等待时间
             {
               if((Data_Buffer[0]==0x12)&&(Data_Buffer[1]==0x21)){      //收到固定的指令数据0x12 0x21后,
                                                                                               //给指令标志ack赋特定的值 并且马上结束等待
                    ack=1;
                    Data_Buffer[0]=0;
                    Data_Buffer[1]=0;
                    break;
                  }
               if(Data_Buffer[0]==0x30&Data_Buffer[1]==0x31){
                    ack=2;
                    Data_Buffer[0]=0;
                    Data_Buffer[1]=0;
                    break;
                  }       
             }
       Receiver_Count=0;
      }
   }
}

void UARTInterrupt(void) interrupt 4            //串口中断  
{
  if(RI)
    {        
      if(Receiver_Count<5)
        {
             Data_Buffer[Receiver_Count++]=SBUF;
        }
      RI = 0;
    }
  else    return;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2011-7-5 16:39:21 | 显示全部楼层
应该先判断帧头后再存数组要好点吧

出0入0汤圆

 楼主| 发表于 2011-7-5 16:40:19 | 显示全部楼层
if((Data_Buffer[0]==0x12)&&(Data_Buffer[1]==0x21)){      //收到固定的指令数据0x12 0x21后,
                                                                                               //给指令标志ack赋特定的值 并且马上结束等待
    ack=1;
    SendOneBiyt(0xce);    //测试用
    Data_Buffer[0]=0;
    Data_Buffer[1]=0;
            break;
  }
有个疑问就是 如果把这段程序改成这样:

if((Data_Buffer[0]==0x12)&&(Data_Buffer[1]==0x21)){      //收到固定的指令数据0x12 0x21后,
                                                                                               //给指令标志ack赋特定的值 并且马上结束等待
    ack=1;
    SendOneBiyt(0xce);   //测试用
    break;
  }
侧响应速度没那么快了,如果有Data_Buffer[0]=0; Data_Buffer[1]=0; 侧至少以5MS的间隔给单片机发送16进制0x12、0x21单片机都能响应,并返回0xce,但如果没有Data_Buffer[0]=0; Data_Buffer[1]=0; 侧响应速度连10MS达不到,不知道怎么回事呢???

出0入0汤圆

 楼主| 发表于 2011-7-5 16:41:08 | 显示全部楼层
回复【1楼】zhanglu1990 杨工
-----------------------------------------------------------------------

你说是在中断里面判断吗??

出0入0汤圆

发表于 2011-7-5 16:45:45 | 显示全部楼层
回复【3楼】jdzjk06
-----------------------------------------------------------------------

是啊,其实完全可以在中断里判断是否是一帧有用的数据,有就置标志

出0入0汤圆

 楼主| 发表于 2011-7-5 16:52:44 | 显示全部楼层
回复【4楼】zhanglu1990 杨工
-----------------------------------------------------------------------

哪也顶多判断个帧头吧??

出0入0汤圆

发表于 2011-7-5 16:55:54 | 显示全部楼层
回复【5楼】jdzjk06
-----------------------------------------------------------------------

呵呵这要看你的协议怎么样了,里面要是有帧命令对应一定帧长度,加上校验字和结束符,这样就能判断完整的一帧了

出0入0汤圆

 楼主| 发表于 2011-7-5 17:01:30 | 显示全部楼层
在中断里面判断一帧数据的完整性好呢   还是先接受过来再在主程序中判断数据帧的完整性好呢?

出0入0汤圆

发表于 2011-7-5 18:19:13 | 显示全部楼层
看不懂。。

出0入0汤圆

发表于 2011-7-5 18:25:01 | 显示全部楼层
找个mp3文件,中间插入一个有用帧,以57600bps的速度发送,如果你的单片机能在数MB的杂乱数据中发现这一帧,并正确解析,那么就强大了。

出0入0汤圆

发表于 2011-7-5 23:14:06 | 显示全部楼层
关注,会用到!

出0入0汤圆

发表于 2011-7-5 23:56:40 | 显示全部楼层
楼主没弄过协议。。

出0入0汤圆

发表于 2011-7-6 00:32:05 | 显示全部楼层
MARK下,会用到的!!

出0入0汤圆

发表于 2011-7-6 00:36:45 | 显示全部楼层
标记下!!!

出0入0汤圆

发表于 2011-7-6 01:01:36 | 显示全部楼层
找个mp3文件,中间插入一个有用帧,以57600bps的速度发送,如果你的单片机能在数MB的杂乱数据中发现这一帧,并正确解析,那么就强大了。


呵呵,这个好像很容易的,下一个3D AND ZEN 高清的那种,然后在里面搞一帧正确的数据,把他找出来就OK了

出0入0汤圆

发表于 2011-7-6 01:14:08 | 显示全部楼层
无协议,浮云就是神马的说!!!

出0入0汤圆

发表于 2011-7-6 10:09:06 | 显示全部楼层
回复【11楼】huayuliang 花生
楼主没弄过协议。。
-----------------------------------------------------------------------

额 比较同意。楼主可以看看modbus之类协议的接收例程学习下。

出0入0汤圆

发表于 2011-7-6 10:18:28 | 显示全部楼层
自己定个协议要好些

出0入0汤圆

发表于 2011-7-6 11:29:07 | 显示全部楼层
协议一般情况下是[帧头][ID][功能][数据长度][若干数据][校验][帧尾]
中断里判断帧头,ID,功能,长度就可以了,另外收到帧尾和校验通过都要把相应的标志置位,其他的事情就在主程序处理

出0入0汤圆

 楼主| 发表于 2011-7-6 13:41:22 | 显示全部楼层
回复【11楼】huayuliang 花生
楼主没弄过协议。。
-----------------------------------------------------------------------

没弄过协议,望指教啊!!!

出0入0汤圆

 楼主| 发表于 2011-7-6 13:47:55 | 显示全部楼层
回复【18楼】trent5145
协议一般情况下是[帧头][id][功能][数据长度][若干数据][校验][帧尾]
中断里判断帧头,id,功能,长度就可以了,另外收到帧尾和校验通过都要把相应的标志置位,其他的事情就在主程序处理
-----------------------------------------------------------------------

您说的够清楚了,可能是我比较笨,这句话明白了“中断里判断帧头,id,功能,长度就可以了”,下半句还是没明白“另外收到帧尾和校验通过都要把相应的标志置位”,把相应标志置位是在中断里面完成吗?还是在主程序中完成?

出0入0汤圆

发表于 2011-7-6 20:52:45 | 显示全部楼层
回复【20楼】jdzjk06
回复【18楼】trent5145  
协议一般情况下是[帧头][id][功能][数据长度][若干数据][校验][帧尾]  
中断里判断帧头,id,功能,长度就可以了,另外收到帧尾和校验通过都要把相应的标志置位,其他的事情就在主程序处理
-----------------------------------------------------------------------
您说的够清楚了,可能是我比较笨,这句话明白了“中断里判断帧头,id,功能,长度就可以了”,下半句还是没明白“另外收到帧尾和校验通过都要把相应的标志置位”,把相应标志置位是在中断里面完成吗?还是在主程序中完成?
-----------------------------------------------------------------------

为了确保接收的帧都是正确且完整的,每个人的方法都不同,总的原则是中断里的程序尽量想办法精简,比如收到帧尾了和校验位通过了可以让接收成功的标志位置位,然后在主程序里判断标志位后接着处理这一个正确且完整的数据帧

出0入0汤圆

发表于 2011-7-6 21:12:01 | 显示全部楼层
回复【20楼】jdzjk06  
-----------------------------------------------------------------------

接收尽量在中断中完成,这样时间利用率比较高。

简单说吧,你一般都会定义一个全局数组变量吧?和一个下标变量x。还需要几个变量为你的协议用,比如长度...再用一个数组保存内容数据。

假定数组 ary[n字节]
假定帧头 2 字节,分别为 0x55 0xAA(哦,这是俺常用的),那么一旦收到第一个字节为 0x55,就可以开始判断了:
ary[x] = 缓冲
if (ary[0]!==0x55)
    return;
if (ary[1]!=0xAA)
    return;
id = ary[2]
len = ary[?]
再根据长度依次取内容数据放到另一个数组里,由主程序处理它(如果功能简单,在中断里处理也可以)。。。
收完校验字节后,计算比较。。。
最后判断帧尾,虽然用途不大,不过可以表明数据是否接收完毕以及通讯是否完整。
俺一般是把 功能(用途)字节和数据放在一起。

出0入0汤圆

发表于 2011-7-6 22:02:01 | 显示全部楼层
回复【21楼】trent5145
-----------------------------------------------------------------------

同意。
中断程序尽量简短,否则会影响其他中断的响应速度,从而影响实时性。

出0入0汤圆

 楼主| 发表于 2011-7-6 22:28:53 | 显示全部楼层
非常感谢楼上两位的指教!!谢了!!!

出0入0汤圆

发表于 2011-7-6 22:36:12 | 显示全部楼层
拍!!!
呵呵:)

出0入0汤圆

 楼主| 发表于 2011-7-6 22:39:44 | 显示全部楼层
回复【25楼】mitchell
-----------------------------------------------------------------------

欢迎!!哈!

出0入0汤圆

发表于 2011-7-7 09:12:00 | 显示全部楼层
我也在研究基于RS232接口的通信指令,希望能学习呀!

出0入0汤圆

发表于 2011-7-8 10:08:10 | 显示全部楼层
9600的波特率传输一个一节用0.833ms。挺长的…

出0入0汤圆

发表于 2011-7-8 13:25:22 | 显示全部楼层
不错...
mark一下...
学习ing

出0入0汤圆

发表于 2011-7-8 23:06:24 | 显示全部楼层
9600bps N 8 1方式,每字节有1起始位,8数据位,1停止位,1字节需传10位,所以一个字节0.96ms。3MB需3019.89888S,差不多一个钟……

出0入0汤圆

发表于 2011-7-9 13:42:17 | 显示全部楼层
好好看看modbus是啥就OK

出0入0汤圆

发表于 2011-7-9 14:12:31 | 显示全部楼层
看了好多高手的讨论,学到了很多!

出0入0汤圆

 楼主| 发表于 2011-7-10 13:31:25 | 显示全部楼层
回复【楼主位】jdzjk06
main()
{   
    while(1){
    if(receiver_count>0)         //如果串口中断接收到数据,侧马上进入接收剩余数据的等待
       {
time20mscnt=0;
while(time20mscnt<5)     //根据要接收的数据多少和波特率,确定大概的等待时间
     {
       if((data_buffer[0]==0x12)&&(data_buffer[1]==0x21)){      //收到固定的指令数据0x12 0x21后,
                                                                                               //给指令标志ack赋特定的值 并且马上结束等待......
-----------------------------------------------------------------------

对于这个程序,最近又发现问题了。 如果串口收到任意一个干扰数据的话,都会使主函数中等待接收数据的while(time20mscnt<<5)达到最大的等待时间,而影响主函数的运行速度,所以现在看来还是应该在串口中断函数中进行接收数据的判断! 有一个很好的通信协议很重要!

出0入0汤圆

发表于 2012-2-28 19:54:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-28 20:45:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-3 11:10:47 | 显示全部楼层
看看

出0入0汤圆

发表于 2013-12-4 09:22:11 | 显示全部楼层
trent5145 发表于 2011-7-6 20:52
回复【20楼】jdzjk06
回复【18楼】trent5145  
协议一般情况下是[帧头][功能][数据长度][若干数据][校验][ ...

我觉得在中断里面验证校验 比较耗时间吧   收完后,最后的校验放在主程序中验证,通过就处理这个帧,没通过就丢掉
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 14:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表