bg2bkk 发表于 2011-6-6 20:17:51

我在做TTL-CAN的一个转换板,使用stc12C5A,sja1000和82C250,不知道如何在单片机串口收到

对总线挂接的各部件分别分配ID号为0x01、0x02、0x03、0x04、0x05,相应的CAN通信模块ID与外设一致。报文的通信协议定为:ID、ID、ID、ID、EF、FE、内容一、内容二、内容三、校验内容四、校验内容五、EE(均为十六进制),发送至总线上时还应加上0x88这个帧信息标志,所以一个报文是13个字节。
判断整帧问题实质是当外设将一个整帧报文发送给CAN通信模块时,判断如何进行帧定界。在速率极高的总线通信中如何将从串口收到的报文完整无误的写入SJA1000并发送,或从总线接收并从SJA1000读出再发送给相连的设备,对软件的编写有很高要求。系统使用的通信速率是串口9600bps,CAN总线100kbps,通过提高硬件发送速率是一个方法,但是通过软件才是最通用的解决办法。在串口9600bps的速率下发送一个字节须约1ms,发送一帧须10ms以上,若同时进行收发,且共用一个串口的情况下至少须20ms才能保证同时收发各一帧数据。
有以下的方法可判断收到的12个字节为整帧,降低误码率。
方法一:直接发送
设置数组和计数器,收到12个字节后判断第12个字节是否等于0xee,若等于则认定是一帧并发送,否则计数器归零。
方法二:边接收边校验
设置一个数组,并设置两个标志位flag1和flag2。若收到一个字节等于EF则使flag1置1。若收到一个字节等于FE且flag1==1时使flag1归零,置flag2为1,否则如果flag2为1则开始接收报文。算法如下:
if(t == 0xef)
                { R_flag1=1;}               
                if(t == 0xfe && R_flag1==1)
                        {R_flag2=1;
                        R_flag1=0; }
                        else if(R_flag2 == 1)
        接收报文,如果收到一个字节是EE且为第6个字节,认定为一帧,发送且置计数器为0
                                }
方法三:使用循环数组
针对一帧为数据为12个字节,设置一个容量为32的大数组,设置计数器,若收到一个字节为0xee则判断前数第6个是否为fe、第7个是否为ef。这里采用循环链表的思想,限于硬件只能采用其想法不能使用数据结构。计数器大于32时对32取模,因为一个报文远远小于32字节所以数组的前几个字节是过时报文所以可以覆盖。算法如下:
        if(t == 0xee)
        {
          if(temp[(R_count+25)%32]==0xef &&temp[(R_count+26)%32] ==0xfe)
                  {       //R_count-11+32= R_count+21(报文的第一个字节在数组中地址)
//收到这个字节是ee后,认定前11个字节为报文数据,在数组中首地址应//为R_count-11+32
认定为一帧,发送报文
                  }
                  R_count=0;                          
        }
        else
        {
                temp = t;
                R_count++;
                if(R_count>200) R_count=0;
        }
方法四:状态机法
状态转换图如图。软件实现大量使用switch语句进行状态转换,编制较复杂。

bg2bkk 发表于 2011-6-6 20:25:13

我的问题在于如何使单片机知道串口中断了12次后是一个整帧,而不是假如这次少收了一个字节,就把下一帧的第一个字节当作上一个帧的最后一个字节。通过设置串口中断最高优先级似乎可以保证单片机每次都能响应串口接收中断,但是还有个问题是写sja1000要遵循它的读写规则,在PELICAN模式下发送缓冲器和接收缓冲器公用一个地址,这说明在写入发送缓存器的时候不能读取,读取接收缓冲器的时候不能写入发送缓冲器,不知道这个问题如何解决。sja1000内部有个缓冲的FIFO,这样的话用起来涉及到共享的问题,好像mcp2515有多个邮箱,这样可以想写写,想收收,感觉这点比sja要好一点,sja的优点,我能用到的优点仅仅是比较大的报文缓冲器而已。不知道大家有没有好招让我准确的从串口收数,然后还能准确的判断一帧12个自节。我一会把程序发上来。单片机从串口收到12字节,然后加上报头写入sja的ram里然后通过它发送,通过读取sja内部的缓冲器从总线收取报文,然后通过串口发送给所挂接的节点。串口9600bps,sja是100kbps,在100ms对发的实验中丢帧现象会发生,我想着是能让它在100ms对发的时候不丢帧。大家有什么好招吗,小弟抛砖引玉了

bg2bkk 发表于 2011-6-6 20:27:34

重点在于如何使串口收到一帧的12字节,而不是串帧、丢数。所以51或者avr什么的,不是重点

shennaijun0433 发表于 2011-6-7 13:20:35

顶啊!回复【2楼】bg2bkk
-----------------------------------------------------------------------

顶啊!

machao 发表于 2011-6-10 13:17:31

2楼说对了一点,这个对于51或者avr不重要,重要的方法。在我的教程中有这个方面讲解和例子,尽管是在AVR上实现的,但思想和方法不受AVR的局限。

51不是说已经退出历史,只是现在市面上大量51的教材应该退出历史,如果你手上有本我编写的教材,哪怕你不使用AVR,但我相信里面的思路和方法肯定会给你很多的帮助和受益。

其实你的思路中还有点问题,尽管串口可以工作在双工方式下,但实际应用中,通常基本上还是按半双工的模式工作。因为作为通信的一方,在没确定对方传来数据的具体意义的前提下,通常是不会发送数据的,因为它不知道应该发送什么(除了主动发送,开始一次新的数据交换过程)。(多任务OS下的应用除外)

关于具体的方法和思路,建议你先借本我编写的教程看一下,里面有关于串口应用的例子,接收、发送、以及LZ位的问题,里面都涉及到的。

bg2bkk 发表于 2011-6-10 17:30:49

回复【4楼】machao
-----------------------------------------------------------------------

谢谢马老师,我就知道放在这个区会有结果,我这里有您的书,我再看看您的书

改版没改好 发表于 2012-4-24 03:48:06

我的ID啊啊啊

改版没改好 发表于 2012-7-9 18:36:54

我还是想说这是我的ID,我会多发精华来找回ID的
页: [1]
查看完整版本: 我在做TTL-CAN的一个转换板,使用stc12C5A,sja1000和82C250,不知道如何在单片机串口收到