1、第1章 CAN接口应用1.1 概述CAN,全称为“Controller Area Network”,即控制器局域网,是一种用于连接电子控制单元(ECU)的多主站共用型串行总线标准,并成为国际上应用最广泛的现场总线之一。CAN特别适用于电磁干扰和其它电子噪声强的环境,它可以使用像RS-485这样的平衡差分线或者更稳定可靠的双绞线。最初,CAN被设计作为汽车环境中的微控制器通讯,在车载各电子控制装置ECU之间交换信息,形成汽车电子控制网络。后来也使用在许多嵌入式控制应用中(比如:工业和医疗)。当总线长度小于40米时位速率可高达1Mbps。位速率会随着节点之间距离的增加而降低(例如:总线长度为500
2、米时位速率为125 Kbps)。Luminary公司的LM3S2000/5000/8000 系列ARM Cortex-M3处理器内建13( 详细配置请参考芯片手册) 路CAN控制器,可同时支持多路CAN总线的操作,使器件可用作网关、开关、工业或汽车应用中多个CAN总线的路由器。1.2 特性Stellaris CAN 模块具有以下特性: 支持CAN2.0 A/B协议; 位速率可编程(高达1 Mbps); 具有32个报文对象; 每个报文对象都具有自己的标识符屏蔽码(过滤器使用后方能使用); 包含可屏蔽中断; 在时间触发的CAN(TTCAN)应用中禁止自动重发送模式; 自测试操作具有可编程的回环模式
3、; 具有可编程的FIFO模式; 数据长度从0到8字节; 通过 CAN0Tx 和 CAN0Rx 管脚与外部CAN PHY无缝连接。1.3 外设驱动库函数说明Stellaris Peripheral Driver Library为用户提供了完整可靠的CAN通信底层API函数,用户通过调用API 函数即可完成CAN控制器配置、报文对象配置及 CAN中断管理等CAN模块开发工作。使用Stellaris Peripheral Driver Library提供的API函数开发CAN模块应用,必须了解相关的数据结构及枚举类型,下面就先介绍CAN模块API 函数所涉及的数据结构及枚举类型。注:在can.h 和
4、hw_can.h中我们一直要应用,所有的结构体都是在can.h中已经定义1.3.1 数据结构 1 tCANBitClkParms tCANBitClkParms是CAN位时钟设置参数的结构类型,其原型定义如程序清单1.1所示。注:后文中将讲到对CAN波特率真设置时,就要对CAN的位时间寄存器进行操作,虽然在驱动库里面已经对其进行了封装,但是我们还要了解它的工作原理.程序清单1.1 tCANBitClkParms结构原型typedef struct unsigned int uSyncPropPhase1Seg; / 这个成员用于保存位时间中的传输段及相位缓冲段1 / 的和,取值范围216 un
5、signed int uPhase2Seg; / 这个成员用于保存位时间中的相位缓冲段2的值, / 取值范围为18 unsigned int uSJW; / 这个成员用于保存位时间中的同步跳转宽度,取值范围14 unsigned int uQuantumPrescaler; / CAN波特率预分频值,取值范围为11023 tCANBitClkParms;2 tCANMsgObject tCANMsgObject结构用于组织配置报文对象的所有参数,其原型定义如程序清单 1.2所示。程序清单1.2 tCANMsgObject结构原型typedef struct unsigned long ulMs
6、gID; / 11或29位的CAN报文标识符 unsigned long ulMsgIDMask; / 报文滤波器使能后的标识符掩码 ,如果不使能报文滤波器的话,可以不用这个数据unsigned long ulFlags; / 由tCANObjFlags列举的配置参数 unsigned long ulMsgLen; / 报文数据域长度 unsigned char *pucMsgData; / 指向配置报文对象数据域数据的指针tCANMsgObject;1.3.2 枚举类型 1 tCANObjFlags 枚举类型tCANObjFlags中定义的常量将在调用 CANMessageSet( )和CA
7、NMessageGet( )函数时的tCANMsgObject型变量中用到,tCANObjFlags的原型定义如程序清单1.3所示。程序清单1.3 tCANObjFlags枚举类型typedef enum MSG_OBJ_TX_INT_ENABLE = 0x00000001, / 表示将使能或已使能发送中断 MSG_OBJ_RX_INT_ENABLE = 0x00000002, / 表示将使能或已使能接收中断 MSG_OBJ_EXTENDED_ID = 0x00000004, / 表示报文对象将使用或已使用扩展标识符 MSG_OBJ_USE_ID_FILTER = 0x00000008, /
8、表示将使用或已使用报文标识符滤波 MSG_OBJ_NEW_DATA = 0x00000080, / 表示报文对象中有可用的新数据 MSG_OBJ_DATA_LOST = 0x00000100, / 表示自上次读取数据后报文对象丢失了数据 MSG_OBJ_USE_DIR_FILTER = (0x00000010 | MSG_OBJ_USE_ID_FILTER),/ 表示报文对象将使用或已使用传输方向滤波, 如果使用方向滤波,则必须同时使用报文标识符滤波 MSG_OBJ_USE_EXT_FILTER = (0x00000020 | MSG_OBJ_USE_ID_FILTER), / 表示报文对象将
9、使用或已使用扩展标识符滤波, 如果使用扩展标识符滤波,则必须同时使用报文标识符滤波 MSG_OBJ_REMOTE_FRAME = 0x00000040, / 表示这个报文对象是一个远程帧 MSG_OBJ_NO_FLAGS = 0x00000000 / 表示这个报文对象不设置任何标志位tCANObjFlags;2 tCANIntStsReg tCANIntStsReg所列举的类型在调用函数CANIntStatus( )时用到,tCANIntStsReg的原型定义如程序清单1.4所示。程序清单1.4 tCANIntStsReg枚举类型typedef enum CAN_INT_STS_CAUSE,
10、/ 读取CAN中断寄存器 CAN_INT_STS_OBJECT / 读取CAN报文中断挂起标志. tCANIntStsReg;3 tCANStsReg tCANStsReg所列举的类型在调用函数CANStatusGet( )时用到,tCANStsReg 的原型定义如程序清单1.5所示。程序清单1.5 tCANStsReg枚举类型typedef enum CAN_STS_CONTROL, / 读取CAN控制器状态 CAN_STS_TXREQUEST, / 读取32个报文对象的发送请求位 CAN_STS_NEWDAT, / 读取32个报文对象的NewDat位 CAN_STS_MSGVAL / 读取
11、32个报文对象的MsgVal位tCANStsReg;4 tCANIntFlags tCANIntFlags所列举的类型在调用函数CANIntEnable( )和CANIntDisable( )时用到,tCANIntFlags的原型定义如程序清单1.6所示。程序清单1.6 tCANIntFlags枚举类型typedef enum CAN_INT_ERROR = 0x00000008, / 表示CAN控制器允许产生错误中断 CAN_INT_STATUS = 0x00000004, / 表示CAB控制器允许产生状态中断 CAN_INT_MASTER = 0x00000002 / 表示允许产生任何CA
12、N 中断,如果这位没设置, / 则不会产生任何中断tCANIntFlags;5 tMsgObjType tMsgObjType所列举的类型在调用API 函数CANMessageSet( )时用到,用于确定报文对象将被配置的类型,tMsgObjType的原型定义如程序清单1.7 所示。程序清单1.7 tMsgObjType枚举类型typedef enum MSG_OBJ_TYPE_TX, / 发送报文对象 MSG_OBJ_TYPE_TX_REMOTE, / 发送远程帧报文对象 MSG_OBJ_TYPE_RX, / 接收数据帧报文对象 MSG_OBJ_TYPE_RX_REMOTE, / 接收远程帧
13、报文对象 MSG_OBJ_TYPE_RXTX_REMOTE / 自动应答远程帧报文对象tMsgObjType;6 tCANStatusCtrl tCANStatusCtrl所列举的类型为调用函数CANStatusGet( )时的返回值的可能情况,包含所有的错误类型及总线状态,tCANStatusCtrl的原型定义如程序清单 1.8所示。程序清单1.8 tCANStatusCtrl枚举类型typedef enum CAN_STATUS_BUS_OFF = 0x00000080, / 脱离总线状态 CAN_STATUS_EWARN = 0x00000040, / 错误计数器已达到警告值 CAN_S
14、TATUS_EPASS = 0x00000020, / 错误计数器已达到被动错误值 CAN_STATUS_RXOK = 0x00000010, / 自上次读此状态以来,CAN控制器成功收到一帧数据 CAN_STATUS_TXOK = 0x00000008, / 自上次读此状态以来,CAN控制器成功发送一帧数据 CAN_STATUS_LEC_MSK = 0x00000007, / This is the mask for the last error code field. CAN_STATUS_LEC_NONE = 0x00000000, / 没有任何错误 CAN_STATUS_LEC_STU
15、FF= 0x00000001, / 位填充错误 CAN_STATUS_LEC_FORM = 0x00000002, / 格式错误 CAN_STATUS_LEC_ACK = 0x00000003, / 应答错误 CAN_STATUS_LEC_BIT1 = 0x00000004, / 总线1错误 CAN_STATUS_LEC_BIT0 = 0x00000005, / 总线0错误 CAN_STATUS_LEC_CRC = 0x00000006, / CRC效验错误 CAN_STATUS_LEC_MASK = 0x00000007 / This is the mask for the CAN Last
16、 Error Code (LEC). tCANStatusCtrl;注:以上为 can.h 中所有的结构体类型和枚举型类型的 CAN 有关的数据位类型1.3.3 接口函数 CAN控制器的初始化非常简单,直接调用CANInit( )即可,如表1.1所示。使用 CANBitTimingSet( )设置 CAN 通信波特率及位时钟等参数,如表 1.2 所示。注:后文中将专门介绍关于 can 通信波特率及位时钟等参数的设置情况.调用 CANBitTimingGet( )函数可以得到当前的位时钟配置信息,如表 1.3 所示。表 1.3 CANBitTimingGet( )函数配置好通信波特率后,可以调用
17、 CANEnable( )函数,使能 CAN 控制器,调用 CANEnable( )函数后,CAN 控制器自动接入总线并开始处理报文,如发送挂起的报文、从总线上接收报文等。CANEnable( )函数如表 1.4 所示。调用 CANDisable( )函数,将使 CAN 控制器停止报文处理,但对应报文对象中的配置信息及状态信息将不会因此改变,CANDisable( )函数如表 1.5 所示。通过调用 CANErrCntrGet( )函数可以读取 CAN 控制器当前的发送错误计数器值及接收错误计数器值,CANErrCntrGet( )函数如表 1.6 所示.通过调用 CANIntClear( )
18、函数则可以清除相应的中断标志,如表 1.9 所示。CAN 中断服务函数的设置也相当简单,通过调用 CANIntRegister( )函数可以将普通的 C 函数注册为 CAN 的中断服务函数,而不用去理会 ROM 中断向量表的配置 a,CANIntRegister( )函数如表 1.10 所示。注a:使用RAM中的向量表时须将VTABLE进行向量表对齐,否 则无法进入中断,解决方法可以采用以下任一种: 1.在链接配置文件(LM3S.icf )中“place in SRAM readwrite, block HEAP ;”的上一行添加“place at start of SRAM readwrit
19、e section VTABLE ;”。需要注意的是,当不需要将中断向量表重映射至RAM中时,若添加了上面那句“段定位”语句将会产生链接错误,所以上面那句“段定位”语 句只在有需要的工程中适用! 2.向量表数组定义的地方使用“编译器关键字”进行向量表对齐;具体方法为:将驱动库源程序文件 interrupt.c文件中的定义语句,如程序清单 1.9 所示,替换成如程序清单 1.10 所示的语句,然后重新编译生成新的驱动库文件,并替换工程中原来的驱动库文件即可。表 1.16 CANRetrySet( )函数调用 CANStatusGet( )函数可以读取 CAN 控制器的状态信息,CANStatusGet( )函数如表 1.18 所示。