基于51单片机的CAN通讯协议C语言程序
2017-01-11 09:05
253 查看
//-----------------------函数声明,变量定义-------------------------------------------------------- #include <reg52.h> sbit int0 = P3^2; //-----------------------定义寻址的基址-------------------------------------------------------- #define base_Adr 0x00 //-----------------------定义总线定时寄存器的值-------------------------------------------------------- #define SJA_BTR0 0x00 //该值需要用户根据实际需要的波特率进行计算 #define SJA_BTR1 0x16 //具体计算见文章说明 //-----------------------设置接收报文类型(标示符)-------------------------------------------------------- //该值需要用户根据实际需要重新配置 #define SJA_ACR 0x00 //验收代码寄存器的值 #define SJA_AMR 0x16 //验收屏蔽寄存器的值 //-----------------------设置输出始终类型-------------------------------------------------------- //该值需要用户根据实际需要重新配置 #define SJA_OCR 0x00 //输出控制寄存器的值 #define SJA_CDR 0x16 //始终分频寄存器的值 //-----------------------设置SJA中断,1为开中断-------------------------------------------------------- #define SJA_OIE 0 //溢出中断 #define SJA_EIE 0 //错误中断 #define SJA_TIE 0 //发送中断 #define SJA_RIE 0 //接收中断 //-----------------------定义地址指针,指向基址-------------------------------------------------------- unsigned char xdata *SJA_base_Adr = base_Adr; //-----------------------定义硬件故障标志位-------------------------------------------------------- bit bdata connect_OK=0; //connect_OK=1设备连接正常 //connect_OK=0设备连接故障 //-----------------------定义硬件故障标志位-------------------------------------------------------- bit bdata SJA_workmode=1; //SJA_workmode=1SJA工作在工作模式 //SJA_workmode=0工作在复位模式 //-----------------------定义SJA1000读写缓冲区的数据结构-------------------------------------------------------- struct BASICCAN_BUFstruct{ unsigned char FrameID_H; unsigned char FrameLENTH ; unsigned char FrameKIND ; unsigned char FrameID_L3 ; unsigned char Frame_Data[8]; }BASICCAN_FRAME,receive_BUF,send_BUF; //BASICCAN_BUFstruct send_BUF; //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 CANREG_write // 入口函数 SJAREG_ADR,setting // 出口函数 无 // 函数功能 写SJA1000的寄存器 //------------------------------------------------------------------------------------------------------ void CANREG_write(unsigned char SJAREG_ADR, unsigned char setting) { *(SJA_base_Adr+SJAREG_ADR)=setting; } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 CANREG_write // 入口函数 SJAREG_ADR // 出口函数 SJAREG_data // 函数功能 读SJA1000的寄存器 //------------------------------------------------------------------------------------------------------ unsigned char CANREG_read(unsigned char SJAREG_ADR) { unsigned char SJAREG_data; SJAREG_data=*(SJA_base_Adr+SJAREG_ADR); return(SJAREG_data); } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 SJAconnect_judge // 入口函数 无 // 出口函数 无 // 全局变量 connect_OK // 操作寄存器 测试寄存器(地址09) // 函数功能 判断SJA1000与控制器连接是否正常 //------------------------------------------------------------------------------------------------------ void SJAconnect_judge(void) { CANREG_write(0x09,0xAA); //写AA到测试寄存器(地址09) if(CANREG_read(0x09)==0xAA) { connect_OK=1; //连接正常 } else { connect_OK=0; //连接故障 } } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 setting_SJA_resetmode // 入口函数 无 // 出口函数 无 // 全局变量 SJA_workmode // 操作寄存器 控制寄存器(地址00) // 函数功能 设置SJA工作在复位模式 //------------------------------------------------------------------------------------------------------ void setting_SJA_resetmode(void) { unsigned char CONTROL_REGdata; CONTROL_REGdata=CANREG_read(0x00); CONTROL_REGdata=CONTROL_REGdata|0x01; CANREG_write(0x00,CONTROL_REGdata); if((CANREG_read(0x00)&0x01)==1) { SJA_workmode=0; //置复位模式成功 } else { SJA_workmode=1; //置复位模式失败 } } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 setting_SJA_resetmode // 入口函数 无 // 出口函数 无 // 全局变量 SJA_workmode // 操作寄存器 控制寄存器(地址00) // 函数功能 设置SJA工作在正常工作模式 //------------------------------------------------------------------------------------------------------ void setting_SJA_workingmode(void) { unsigned char CONTROL_REGdata; CONTROL_REGdata=CANREG_read(0x00); CONTROL_REGdata=CONTROL_REGdata&0xFE; CANREG_write(0x00,CONTROL_REGdata); if((CANREG_read(0x00)&0x01)==0) { SJA_workmode=1; //置工作模式成功 } else { SJA_workmode=0; //置工作模式失败 } } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 setting_SJA_rate // 入口函数 SJA_BTR0,SJA_BTR1 // 出口函数 setting_success // 操作寄存器 总线定时寄存器BTR1(地址07)和BTR0(地址06) // 函数功能 设置SJA波特率 // 特殊要求 只能在复位工作模式下设置 //------------------------------------------------------------------------------------------------------ bit setting_SJA_rate(void) { bit setting_success; while(SJA_workmode) { setting_SJA_resetmode(); //设置SJA工作在复位模式 } CANREG_write(0x06,SJA_BTR0); CANREG_write(0x07,SJA_BTR1); if((CANREG_read(0x06)==SJA_BTR0)&(CANREG_read(0x07)==SJA_BTR1)) { setting_success=1; //波特率设置成功 } else { setting_success=0; //波特率设置失败 } return(setting_success); } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 setting_SJA_dataselect // 入口函数 SJA_ACR,SJA_AMR // 出口函数 setting_success // 操作寄存器 验收代码寄存器ACR(地址04)和验收屏蔽寄存器AMR(地址05) // 函数功能 设置SJA接收数据类型 // 特殊要求 只能在复位工作模式下设置 //------------------------------------------------------------------------------------------------------ bit setting_SJA_dataselect(void) { bit setting_success; while(SJA_workmode) { setting_SJA_resetmode(); //设置SJA工作在复位模式 } CANREG_write(0x04,SJA_ACR); CANREG_write(0x05,SJA_AMR); if((CANREG_read(0x04)==SJA_ACR)&(CANREG_read(0x05)==SJA_AMR)) { setting_success=1; //滤波器设置成功 } else { setting_success=0; //滤波器设置失败 } return(setting_success); } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 setting_SJA_CLK // 入口函数 SJA_OCR,SJA_CDR // 出口函数 setting_success // 操作寄存器 输出控制寄存器OCR(地址08)和时钟分频寄存器CDR(地址31) // 函数功能 设置SJA输出始终类型 // 特殊要求 只能在复位工作模式下设置 //------------------------------------------------------------------------------------------------------ bit setting_SJA_CLK(void) { bit setting_success; while(SJA_workmode) { setting_SJA_resetmode(); //设置SJA工作在复位模式 } CANREG_write(0x08,SJA_OCR); CANREG_write(31,SJA_CDR); if((CANREG_read(0x08)==SJA_OCR)&(CANREG_read(31)==SJA_CDR)) { setting_success=1; //滤波器设置成功 } else { setting_success=0; //滤波器设置失败 } return(setting_success); } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 setting_SJA_interrupt // 入口函数 SJA_OIE,SJA_EIE,SJA_TIE,SJA_RIE // 出口函数 setting_success // 操作寄存器 控制寄存器(00) // 函数功能 设置SJA中断类型和中断状态 // 特殊要求 只能在复位工作模式下设置 //------------------------------------------------------------------------------------------------------ bit setting_SJA_interrupt(void) { bit setting_success; unsigned char CONT_buf,temp=0; while(SJA_workmode) { setting_SJA_resetmode(); //设置SJA工作在复位模式 } CONT_buf=CANREG_read(0x00); temp=SJA_OIE; temp=temp<<4; temp=temp|SJA_EIE; temp=temp<<3; temp=temp|SJA_TIE; temp=temp<<2; temp=temp|SJA_RIE; temp=temp<<1; CONT_buf=(temp&0x1E)|(CONT_buf&0x01); CANREG_write(0x00,CONT_buf); if(CANREG_read(0x00)==CONT_buf) { setting_success=1; //滤波器设置成功 } else { setting_success=0; //滤波器设置失败 } return(setting_success); } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 Write_SJAsendBUF // 入口函数 无 // 出口函数 setting_success // 操作寄存器 发送缓存器(10-19)状态寄存器02 // 函数功能 写发送缓存器 // 特殊要求 只能在工作模式下写 //------------------------------------------------------------------------------------------------------ bit Write_SJAsendBUF(void) { bit setting_success=0; unsigned char i; while(SJA_workmode==0) { setting_SJA_workingmode(); //设置SJA在工作模式 } if((CANREG_read(0x02)&0x10)==0) { if((CANREG_read(0x02)&0x04)!=0) { CANREG_write(0x10,send_BUF.FrameID_H); CANREG_write(0x11,(send_BUF.FrameLENTH<<4)||(send_BUF.FrameKIND<<3)||(send_BUF.FrameID_L3)); if(send_BUF.FrameKIND==0) {for(i=0;i<send_BUF.FrameLENTH,i<8;i++) CANREG_write(0x12+i,send_BUF.Frame_Data[i]); } setting_success=1; //发送寄存器写成功 } } return(setting_success); } //------------------------------------------------------------------------------------------------------ // 函数类别 SJA1000基本操作 // 函数名称 Write_SJAsendBUF // 入口函数 无 // 出口函数 setting_success // 操作寄存器 接收缓存器(20-29)状态寄存器02 // 函数功能 写发送缓存器 // 特殊要求 只能在工作模式下写 //------------------------------------------------------------------------------------------------------ bit read_SJAreceiveBUF(void) { bit setting_success=0; unsigned char i; while(SJA_workmode==0) { setting_SJA_workingmode(); //设置SJA在工作模式 } if((CANREG_read(0x02)&0x01)!=0) { if((CANREG_read(0x02)&0x10)==0) { receive_BUF.FrameID_H=CANREG_read(0x20); receive_BUF.FrameLENTH=((CANREG_read(0x21)&0xF0)>>4); receive_BUF.FrameKIND=((CANREG_read(0x21)&0x08)>>3); receive_BUF.FrameID_L3=(CANREG_read(0x21)&0x07); if(receive_BUF.FrameKIND==0) {for(i=0;i<receive_BUF.FrameLENTH,i<8;i++) receive_BUF.Frame_Data[i]=CANREG_read(0x22+i); } setting_success=1; //接收寄存器读成功 } } return(setting_success); } //------------------------------------------------------------------------------------------------------ // 函数类别 供调用子程序 // 函数名称 SJA1000_init // 入口函数 无 // 出口函数 无 // 操作寄存器 1)控制寄存器(地址00) // 2)收代码寄存器ACR(地址04) // 3)验收屏蔽寄存器AMR(地址05) // 4)总线定时寄存器BTR0(地址06) // 5)总线定时寄存器BTR1(地址07) // 6)输出控制寄存器OCR(地址08) // 7)测试寄存器(地址09) // 8)和时钟分频寄存器CDR(地址31) // 函数功能 SJA1000初始化设置 // 特殊要求 在复位模式进行,初始化结束进入工作状态 //------------------------------------------------------------------------------------------------------ void SJA1000_init(void) { while(connect_OK==0) { SJAconnect_judge(); //检测设备连接 } while(SJA_workmode) { setting_SJA_resetmode(); //置SJA1000为复位工作模式 } while(setting_SJA_rate()==0) { setting_SJA_rate(); //设置总线波特率 } while(setting_SJA_dataselect()==0) { setting_SJA_dataselect(); //设置SJA接收数据的格式(标示位) } while(setting_SJA_CLK()==0) { setting_SJA_CLK(); //设置SJA输出始终的形式 } } //------------------------------------------------------------------------------------------------------ // 函数类别 中断处理函数 // 函数名称 send_interrupt // 入口函数 无 // 出口函数 无 // 操作寄存器 // 函数功能 接收中断处理函数 //------------------------------------------------------------------------------------------------------ send_interrupt() { } //------------------------------------------------------------------------------------------------------ // 函数类别 发送中断处理函数 // 函数名称 receive_interrupt // 入口函数 // 出口函数 // 操作寄存器 // 函数功能 发送中断处理函数 //------------------------------------------------------------------------------------------------------ receive_interrupt() { } //------------------------------------------------------------------------------------------------------ // 函数类别 中断函数 // 函数名称 SJA_INTR // 入口函数 无 // 出口函数 无 // 操作寄存器 中断寄存器(地址03) // 函数功能 中断分析,判断是什么中断,调用相应的中断处理函数 //------------------------------------------------------------------------------------------------------ void SJA_INTR() interrupt 0 using 1 //CanBus接口芯片产生中断(INTR0) { unsigned char sta; unsigned char temp; EX0 = 0; sta = CANREG_read(3); //读中断寄存器 temp = sta & 0x20; if(temp == 0x20) SJA1000_init(); temp = sta & 0x04; if(temp == 0x04) SJA1000_init(); //消极错误中断,错误报警中断,均导致重启 temp = sta & 0x02; if(temp == 0x02) //发送中断处理 { send_interrupt(); } temp = sta & 0x01; if(temp == 0x01) //接收中断,接收数据 { receive_interrupt(); } EX0 = 1; } main() { } 本程序是基于51单片机的CAN(sja1000)通信协议的操作程序,利用51单片机的中断来操作,每个函数都有详细的注释,希望能帮助到初学者,在main函数中没有任何函数调用,自己可以根据需要进行调用。 |
相关文章推荐
- 基于51单片机列车车门自动开关测试台开发
- 基于51单片机的摇摇棒制作
- 一种基于51单片机的多任务机制及应用
- 基于proteus的51单片机仿真实例十一、51单片机的P0口控制实例--流水灯
- 基于51单片机-温度监控系统
- 基于51单片机及DS18B20温度传感器数码管显示程序
- 基于51单片机的直流电机驱动(L298…
- 基于proteus的51单片机仿真实例十二、51单片机的C语言程序结构
- 基于51单片机-智能红外遥控寻迹避障小车
- 基于51单片机的简易数字频率计
- 基于51单片机的数控电源设计
- 51单片机教程(从原理开始基于汇编)
- 基于51单片机的花样流水灯仿真(代码)
- 基于Java语言的51单片机串口通讯PC机程序
- 基于51单片机的简单方波发生器
- 基于51单片机实现模拟IIC总线时序
- 基于proteus的51单片机仿真实例十三、51单片机的C语言宏定义应用实例
- 基于51单片机的交通灯C语言程序设计
- 基于51单片机IIC通信的AT24C02学习笔记
- 基于DS1302芯片---使用51单片机C语言编制的电子时钟(液晶1602显示)