CAN总线控制器-SJA1000源程序(c语言)解读复习进程
- 格式:doc
- 大小:69.50 KB
- 文档页数:20
SJA1000程序给你提供一些思路1、sja1000初始化2、发送子程序3、中断方式接收下面是一些程序段你参考下(已用于产品)/**********SJA1000初始化***********//void Init_SJA1000(void){uchar state;uchar ACRR[4]={0XAA,0XFF,0X22,0X11};// 接收代码寄存器uchar AMRR[4]={0xff,0xff,0xff,0xff};// 接收屏蔽寄存器//uchar AMRR[4]={0x00,0x00,0xff,0xff};// 接收屏蔽寄存器do// 使用do--while语句确保进入复位模式{MODR = 0x09; // 设置MOD.0=1--进入复位模式,以便设置相应的寄存器state = MODR;}while( !(state & 0x01) );// 对SJA1000部分寄存器进行初始化设置CDR = 0x88; // CDR为时钟分频器,CDR.3=1--时钟关闭, CDR.7=0---basic CAN, CDR.7=1---Peli CANBTR0 = 0x04;//0x31; // 总线定时寄存器0 ;总线波特率设定BTR1 = 0x1c;//0x1c; // 总线定时寄存器1 ;总线波特率设定IER = 0x01; // IER.0=1--接收中断使能;IER.1=0--关闭发送中断使能OCR = 0xaa; // 配置输出控制寄存器CMR = 0x04; // 释放接收缓冲器ACR0 = ACRR[0];// 初始化接收代码寄存器ACR1 = ACRR[1];ACR2 = ACRR[2];ACR3 = ACRR[3];AMR0 = AMRR[0];// 初始化接收屏蔽寄存器AMR1 = AMRR[1];AMR2 = AMRR[2];AMR3 = AMRR[3];do// 使用do--while语句确保退出复位模式{MODR = 0x08; //MOD.3=0--双滤波器模式state = MODR;}while( state & 0x01 );}////////////////////////////////////////**********CAN发送数据到CAN-Bus***********//void CAN_TXD(void){uchar state;//初始化标示码头信息TX_buffer[0] = 0x88; //.7=0--扩展帧;.6=0--数据帧; .0-.3=100--数据长度为8字节// TX_buffer[1] = 0xFF; //本帧信息的ID//TX_buffer[2] = 0xFF;TX_buffer[3] = 0xFF;TX_buffer[4] = 0xFF;do //查询SJA1000是否处于接收状态,当SJA1000不处于接收状态时才可继续执行{state = SR; //SR为SJA1000的状态寄存器}while( state & 0x10 ); //SR.4=1 正在接收,等待do //查询SJA1000是否处于发送完毕状态{state = SR;}while(!(state & 0x08)); //SR.3=0,发送请求未处理完,等待直到SR.3=1do //查询发送缓冲器状态{state = SR;}while(!(state & 0x04)); //SR.2=0,发送缓冲器被锁。
文库资料 ©2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd.第3章 CAN 控制器驱动1.1 SJA1000初始化1.1.1 初始化流程SJA10000在上电复位后处于复位模式,要使SJA1000能正常收发CAN 帧数据,必须对SJA1000进行初始化,SJA1000初始化流程详见图3.1。
1. 进入复位模式SJA1000的配置寄存器只有在复位模式下才能访问,所以必须首先置位模式寄存器的0位,以进入复位模式。
2. 设置模式寄存器模式寄存器用于设置SJA1000工作模式,定义详见表3.1。
表3.1 SJA1000模式寄存器定义RM :复位模式位,置位该位将使SJA1000进入复位模式,清零该位则退出复位模式返回工作模式。
LOM :只听模式位,设置该位后,SJA1000处于只听模式。
只听模式只从CAN 总线接收数据,不能向总线上发送数据也不会产生错误帧。
只听模式常用于自动波特率检测功能,例如在软件里预先定义一个包含所有可能的位频率以及它们的位时序参数的表格,使能SJA1000接收和错误中断,依次尝试表格中的位时序参数,如果在CAN 总线上产生了错误,软件转向下一个位时序参数,在一条信息的成功地接收后,表明软件已经检测到正确的位时序参数。
STM :只检测模式位,设置该位后,SJA1000在发送CAN 帧时不检查应答位,可以实现单个CAN 节点的发送功能。
AFM :验收滤波器模式,设置该位时使用单滤波功能;清零该位时使用双滤波功能。
SM :睡眠模式位,设置该位时,SJA1000进入睡眠模式,降低功耗。
3. 设置时钟分频寄存器时钟分频寄存器用于选择BasicCAN 模式还是PeliCAN 模式、CLKOUT 管脚控制、CAN 输入比较器控制,寄存器的位定义详见表3.2。
表3.2 SJA1000时钟分频寄存器定义4. 设置CAN 波特率波特率是异步串行通信中的重要参数,指每秒钟能发送的数据位元数量,只有相同波特率图3.1 SJA1000初始化流程图文库资料 ©2017 Guangzhou ZHIYUAN Electronics Stock Co., Ltd.的设备才能互相通信,CAN-bus 使用异步串行通信技术,同样需要遵守该规则。
CAN总线学习笔记二:CAN自收发程序解读花了一整个下午的时间,彻头彻尾的把PIAE小组提供的CAN自收发源程序解读了一遍。
解读别人的程序是一件挺费时费力的一件事,但是在对某项技术或者说某个芯片的入门阶段参考别人的程序又是一项必不可少的任务。
对于这个程序,头一个任务当然是把头文件先浏览一遍,能弄明白的还是先弄明白,对后面程序的解读有好处。
C文件里给出了三个头文件:#include#include#include第一个reg52.h我就不废话了,下一个intrins.h我在上一篇日志里也详细的作了说明,这里也不提了。
can_selfdef.h是程序员自己定义的一个头文件,在这个头文件里除了一些宏定义和管脚的一些说明外,最重要的就是要弄明白“CAN总线SJA1000寄存器地址定义”。
这个我开始也没弄明白,后来反复琢磨,才发现作者在这个程序里吧SJA1000的寄存器作为单片机的外部扩展RAM寻址了,从而省去了编写一些底层的驱动程序,这就让大家连SJA1000的datasheet的时序图都不用看了(不过下一步我想用驱动程序来控制SJA1000)。
看完头文件,可不能从第一个程序依次往下看。
应该直接找到主程序main()解读:void main(void){//MCU初始化(主要是各中断寄存器的初始化)SJA_RST = 1; //CAN总线复位管脚复位无效SJA_CS = 0; //CAN总线片选有效EX1 = 1; //开MCU外部中断INT1IT1 = 0;//MCU外部中断INT1为电平触发,也是CAN总线接收中断口IT0 = 1;//MCU外部中断INT0为下降沿触发EX0 = 1; //开MCU外部中断INT0EA = 1; //开MCU总中断SJA_CS = 1; //CAN总线片选无效,使得对数据总线的操作不会影响SJA1000。
//SJA1000初始化CAN_init(); //对SJA1000寄存器的读写是采用外部寄存器寻址方式,//所以不需要程序单独控制片选有效无效_nop_();_nop_();//主循环while(1){_nop_();_nop_();Rxd_deal(); //接收处理程序Txd_deal(); //发送处理程序led_seg7(0,Txd_data); //数码管1-2显示发送数据子程序led_seg7(1,Rxd_data+3); //数码管3-4显示接收数据子程序}}上面的注释是本人详细做了加工的,先是单片机中断寄存器的初始化,打开了单片机的INT0和INT1两个外部中断。
第3章 CAN 控制器驱动1.1 SJA1000编程基础1.1.1 MCU 访问SJA1000SJA1000使用并行总线接口与MCU 连接,对MCU 来说,SJA1000可以认为是1个外扩的RAM 芯片,51系列MCU 通过地址线、数据线和控制线与SJA1000连接,如图3.1所示。
AD[0:7]是低8位地址与数据总线复用的,MCU 在操作总线时,在该接口上先输出低8位地址线,然后再进行数据操作(读或写)。
SJA1000内部带有地址锁存器,由ALE 信号实现数据与地址的分离。
因为SJA1000的地址宽度为8位,所以寻址空间范围是0x00~0xFF 。
假如每个地址都对应一个寄存器,那么SJA1000最多支持256个寄存器。
而实际上SJA1000在BasicCAN (CAN2.0A )模式下只有32个寄存器,在FullCAN (CAN2.0B )模式下则有128个寄存器。
虽然SJA1000寄存器的访问地址会因为硬件设计不同而不同,但SJA1000内部寄存器的位置关系是固定的。
如果我们给SJA1000每个内部寄存器的地址都定义绝对地址(如程序清单3.1所示),那么在硬件设计发生变化时,特别是器件编址变化时,要修改的寄存器地址定义将会非常多。
为了提高驱动的可移植性,在实际访问SJA1000内部寄存器时,常采用基地址加偏移量的方式进行寄存器访问(如程序清单3.2所示)。
如果把SJA1000内部寄存器看做数组的话,那基地址就是这个数组的首地址,偏移量就是数组的下标,即成员在数组中的位置。
程序清单3.1 采用绝对编址的寄存器定义1 #define REG_CAN_MOD 0xA000 // 内部控制寄存器2 #define REG_CAN_CMR 0xA001 // 命令寄存器3 #define REG_CAN_SR 0xA002 // 状态寄存器4 #define REG_CAN_IR 0xA003 // 中断寄存器5 #define REG_CAN_IER0xA004// 中断使能寄存器6......程序清单3.2 采用基地址加偏移量方式的寄存器定义7 #define REG_BASE_ADD0xA000// SJA1000寄存器基地址 8 #defineREG_CAN_MOD 0x00 // 内部控制寄存器 9 #define REG_CAN_CMR 0x01 // 命令寄存器 10 #define REG_CAN_SR 0x02 // 状态寄存器 11 #define REG_CAN_IR 0x03 // 中断寄存器 12 #define REG_CAN_IER0x04// 中断使能寄存器13......通常MCU 的总线上会挂载很多器件,除了SJA1000外,可能还有RAM 和ROM 等器件。
一、以下是我做的CAN节点的测试程序, 实现两个节点传送数据,程序主要分三部分SJA1000 的初始化,接收数据,发送数据./******************************************************函数原型:bit Sja_1000_Init(void)**功能:初始化SJA10000**入口参数: 无**返回值:0:初始化成功1:复位失败2: 测试sja1000失败3:设置失败4:设置验收滤波器失败5:设置波特率失败*****************************************************/unsigned char Sja_1000_Init(void){bit s;EA=0;s=BCAN_ENTER_RETMODEL();if (s==1) return 1;s=BCAN_CREATE_COMMUNATION();if (s==1) return 2;s=BCAN_SET_OUTCLK(0xc0);//Pelicanif (s==1) return 3;s=BCAN_SET_OBJECT(0xFF,0x4E,0x16,0x00,0xff,0x00,0x00,0x00);if (s==1) return 4;s=BCAN_SET_BANDRATE(CAN_BPS_1M);if (s==1) return 5;SJA_BCANAdr=REG_OCR ;*SJA_BCANAdr=0x1a;SJA_BCANAdr=REG_IER;*SJA_BCANAdr=0x03;s=BCAN_SET_CONTROL(0x08);if (s==1) return 6;EA=1;return 0;}}/*********************************************************************函数原型: bit BCAN_SET_OUTCLK( unsigned char Clock_Out) **参数说明: ** Clock_Out:存放时钟分频寄存器(CDR)的参数设置**返回值: ** 0 ;设置成功** 1 ;设置失败**说明:设置SJA1000的时钟分频。