今天 CAN总线调试成功。 算起来做CAN总线这部分主要时间都花在软件上了. 代码写了五天,调了四天. 一共用了差不多10天的时间. 说说一些应该要注意的地方.
1 尽量用结构体定义CAN的帧格式和接收发送缓冲格式.
比如下面的形式:
/*发送帧数据结构*/
typedef struct
{
uint32 TxFrameInfo; //发送帧信息结构,隐含了CAN协议的控制段.
uint32 TxCANID; //发送帧信息ID
uint32 CANTDA; //发送数据1~4字节
uint32 CANTDB; //发送数据5~8字节
}*PTxBuf,TxBuf_t;
注意我的结构体里的成员都是uint32(unsigned int)类型的. CAN的协议实际上是以bit为单位组织的. 在网上找的一些参考代码,发现有些定义帧格式时也是用bit为单位,个人觉得操作很不方便,反而觉得用字节比较不容易出错. 而且ARM7里的寄存器都是32bit的,直接定义uint32不是更好.
2 自测模式下设置寄存器要注意延时.
我刚开始调试时就是因为没有注意到这个吃了大亏. 发出去的数据帧怎么都不到收回来. 谁会想到设置几个寄存器还要用延时,难道ARM7的速度还不够快? 我之前认为只有LCD/flash的操作才对时序要求比较高. 这个问题我调了一个上午都没结果. 后来去网上搜了一下, 有人以前遇到过类似的问题,说可能是延时的问题. 建议设置几个关键寄存器时加延时. 后来我索性就延时也不要了,就用while一直等到它有效为止,代码如下:
while( !(CAN1MOD&0x01) ) /*确保RM置位*/
{
CAN1MOD |= 0x01; /*RM = 1, 软件复位,写寄存器*/
}
while( !(CAN1MOD&0x04) )
{
CAN1MOD |= (1 << 2); /*STM = 1, 自测模式*/
}
while( (CAN1MOD&0x01) )
{
CAN1MOD &= ~(1 << 0); /*RM = 0*/
}
3 关于帧ID过滤. 帧ID的接收过滤特性是CAN总线一个非常重要的概念. CAN的许多应用层协议是基于它的.比如可以用工控领域里的modus类似的上层协议作为CAN的应用层协议论,而帧ID就可以当作是地址, 并利用过滤原理实现主从式的通信. CANAFMR寄存器是接收过滤设置的寄存器,关于它的设置手册上说的不是很清楚. 搞的我调这个的时候也犯了一些错误, 去网上找了一下,发现还真有不少人弄错. 寄存器的位组合是下面这样的:
******定义验收寄存器的各个位******/
#define AccOff 0
#define AccBP 1
#define eFCAN 2
/************************************************
AccBP AccOff
0 0 :接收过滤起作用,可以根据ID屏蔽
0 1 :接收过滤器关闭,接收不到任何数据
1 0 :可以接收所有的数据
1 1 :关闭接收过滤器,置位accBp以便修改LUT
**************************************************/