基于51单片机SJA1000 CAN通讯实现(C语言程序)

您所在的位置:网站首页 can通讯芯片和主芯片引脚图 基于51单片机SJA1000 CAN通讯实现(C语言程序)

基于51单片机SJA1000 CAN通讯实现(C语言程序)

2024-07-10 13:45| 来源: 网络整理| 查看: 265

    经过一个星期的艰苦奋斗,终于将两个SJA1000通过51单片机成功通讯了!采用的是Pelican工作模式,扩展帧数据格式,验收滤波器是采用单滤波扩展帧模式。

发送和接收代码都全部相同样!

一 实物图

二 串口输出调试信息

三 以下是全部程序代码:包括1 main.c、2 uart.h、3 uart.c、4 sja1000.h、5 sja1000.c。

1main.c

#include "reg51.h" #include "uart.h" #include  "string.h" #include  "sja1000.h" sbit KEY=P2^5; void main(void) {  unsigned char init,state,num,i=0;  UART_Init();     if(SJA_Interface_Test())          {           UART_Send_String("\r\nSJA TO CPU Right!\r\n");          }          else          {           UART_Send_String("\r\nSJA TO CPU Error!\r\n");          }          init=SJA_Init();          if(init==0)         {            UART_Send_String("\r\nSJA Init OK!\r\n");         }         else          {           UART_Send_String("\r\nSJA Init Error!\r\n");           UART_Send_Byte(init);          }     while(1)     {      if(KEY==0)          {              DelayMs(10);              if(KEY==0)              {                CAN_Send_Str("ILoveY\r\n");               Display(num);               if(num++==14) num=0;                            }               DelayMs(200);                      }           SJA_BCANAdr = REG_STATUS;           state=*SJA_BCANAdr;        if((state&0x40)==0x40) { UART_Send_String("\r\nSJA Error count overflow!!\r\n"); SJA_Init(); }       if((state&0x20)==0x20)  UART_Send_String("SJA1000 CAN BUS is transmiting!\r\n");          } }

2uart.h

#ifndef  __UART_H__ #define  __UART_H__ #include "stdio.h" #include "reg51.h" #define reclength 8 extern bit recfinish; extern unsigned char recbuf[reclength]; void UART_Init(void); void UART_Send_Byte(unsigned char ch); void UART_Send_String(unsigned char *str); void Display( char num); void DelayMs(unsigned char t); #endif

3uart.c

#include "uart.h" unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; unsigned char reccount=0; bit recstart=0; bit recfinish=0; unsigned char recbuf[reclength]; void UART_Init(void) {  SCON=0X50;  TMOD|=0X20;  TH1=0XFD;  TL1=0XFD;  TR1=1;   EA=1;   ES=1; } void UART_Send_Byte(unsigned char ch) {     SBUF=ch;     while(!TI);//等到发送完成中断标志位置1     TI=0; } void UART_Send_String(unsigned char *str) {  while(*str)  {     UART_Send_Byte(*str);      str++;  } } void UART_ISR(void)  interrupt 4 {   //unsigned char temp;  if(RI)  {     if(recstart==0)     {         recstart=1;         reccount=0;         recfinish=0;     }     if(recstart)     {         recbuf[reccount++]=SBUF;         if((reccount==reclength)||(recbuf[reccount-1]=='z'))         {             recfinish=1;             reccount=0;                        recstart=0;         }     }  }  RI=0; } /*------------------------------------------------  uS延时函数,含有输入参数 unsigned char t,无返回值  unsigned char 是定义无符号字符变量,其值的范围是  0~255 这里使用晶振12M,精确延时请使用汇编,大致延时  长度如下 T=tx2+5 uS  ------------------------------------------------*/ void DelayUs2x(unsigned char t) {     while(--t); } /*------------------------------------------------  mS延时函数,含有输入参数 unsigned char t,无返回值  unsigned char 是定义无符号字符变量,其值的范围是  0~255 这里使用晶振12M,精确延时请使用汇编 ------------------------------------------------*/ void DelayMs(unsigned char t) {        while(t--)  {      //大致延时1mS      DelayUs2x(245); DelayUs2x(245);  } }

//共阳数码管显示 调试的时候用到 ,本程序最终没有用到。 void Display( char num) {     P1=table[num]; }

4sja1000.h

#ifndef  __SJA1000_H__ #define  __SJA1000_H__ #include  "string.h" #include "uart.h" #define  SJA_BaseAdr  0XFE00     //定义SJA RAM基址                                     //P2口为地址线高八位 P0口为地址线低八位                                  // CS接P2.0 地址线 1111 1110 0000 0000 即为0XFE00                                  // CS接P2.7 地址线 0111 1111 0000 0000     0x7F00                             #define         REG_CONTROL       SJA_BaseAdr+0x00       //内部控制寄存器 #define         REG_COMMAND       SJA_BaseAdr+0x01       //命令寄存器      只写 #define         REG_STATUS        SJA_BaseAdr+0x02       //状态寄存器      只读 #define         REG_INTERRUPT     SJA_BaseAdr+0x03       //中断寄存器      只读 #define         REG_INTENABLE     SJA_BaseAdr+0x04       //中断使能寄存器   可读可写 #define         REG_RESVER0       SJA_BaseAdr+0x05       //保留0                                                          #define         REG_BTR0          SJA_BaseAdr+0x06       //总线定时寄存器0  复位模式读写                                                          //定义了波特率预设值BRP 和同步跳转宽度SJW 的值 #define         REG_BTR1          SJA_BaseAdr+0x07       //总线定时寄存器1  复位模式读写 //总线定时寄存器1 定义了每个位周期的长度采样点的位置和在每个采样点的采样数目 #define         REG_OCR           SJA_BaseAdr+0x08       //输出控制寄存器  复位模式读写 //输出控制寄存器实现了由软件控制不同输出驱动配置的建立 #define         REG_TEST          SJA_BaseAdr+0x09       //测试寄存器 #define         REG_RESVER1       SJA_BaseAdr+0x0A       //保留1 #define         REG_ARBITRATE     SJA_BaseAdr+0x0B       //仲裁丢失捕捉    只读 #define         REG_ERRCATCH      SJA_BaseAdr+0x0C       //错误代码捕捉    只读 #define         REG_ERRLIMIT      SJA_BaseAdr+0x0D       //错误报警限额    工作模式只读 复位模式可读写 #define         REG_RXERR         SJA_BaseAdr+0x0E         //接收错误计数器工作模式只读 复位模式可读写 #define         REG_TXERR         SJA_BaseAdr+0x0F         //发送错误计数器工作模式只读 复位模式可读写 #define         REG_ACR0          SJA_BaseAdr+0x10       //验收代码寄存器 #define         REG_ACR1          SJA_BaseAdr+0x11       //验收代码寄存器 #define         REG_ACR2          SJA_BaseAdr+0x12       //验收代码寄存器 #define         REG_ACR3          SJA_BaseAdr+0x13       //验收代码寄存器 #define         REG_AMR0          SJA_BaseAdr+0x14       //验收屏蔽寄存器 #define         REG_AMR1          SJA_BaseAdr+0x15       //验收屏蔽寄存器 #define         REG_AMR2          SJA_BaseAdr+0x16       //验收屏蔽寄存器 #define         REG_AMR3          SJA_BaseAdr+0x17       //验收屏蔽寄存器 // 发送缓冲区寄存器  (发送缓冲区长13字节,在CAN地址是16-28即0x10-0x1c) #define         REG_TXBuffer1     SJA_BaseAdr+0x10         //发送缓冲区1 #define         REG_TXBuffer2     SJA_BaseAdr+0x11         //发送缓冲区2 #define         REG_TXBuffer3     SJA_BaseAdr+0x12         //发送缓冲区3 #define         REG_TXBuffer4     SJA_BaseAdr+0x13         //发送缓冲区4 #define         REG_TXBuffer5     SJA_BaseAdr+0x14         //发送缓冲区5 #define         REG_TXBuffer6     SJA_BaseAdr+0x15         //发送缓冲区6 #define         REG_TXBuffer7     SJA_BaseAdr+0x16         //发送缓冲区7 #define         REG_TXBuffer8     SJA_BaseAdr+0x17         //发送缓冲区8 #define         REG_TXBuffer9     SJA_BaseAdr+0x18         //发送缓冲区9 #define         REG_TXBuffer10    SJA_BaseAdr+0x19         //发送缓冲区10 #define         REG_TXBuffer11    SJA_BaseAdr+0x1A         //发送缓冲区11 #define         REG_TXBuffer12    SJA_BaseAdr+0x1B         //发送缓冲区12 #define         REG_TXBuffer13    SJA_BaseAdr+0x1C         //发送缓冲区13  // 接收缓冲区寄存器   (接收缓冲区长13字节,在CAN地址是16-28即0x10-0x1c) #define         REG_RXBuffer1     SJA_BaseAdr+0x10       //接收缓冲区1 #define         REG_RXBuffer2     SJA_BaseAdr+0x11       //接收缓冲区2 #define         REG_RXBuffer3     SJA_BaseAdr+0x12        //接收缓冲区3 #define         REG_RXBuffer4     SJA_BaseAdr+0x13       //接收缓冲区4 #define         REG_RXBuffer5     SJA_BaseAdr+0x14        //接收缓冲区5 #define         REG_RXBuffer6     SJA_BaseAdr+0x15         //接收缓冲区6 #define         REG_RXBuffer7     SJA_BaseAdr+0x16         //接收缓冲区7 #define         REG_RXBuffer8     SJA_BaseAdr+0x17         //接收缓冲区8 #define         REG_RXBuffer9     SJA_BaseAdr+0x18         //接收缓冲区9 #define         REG_RXBuffer10    SJA_BaseAdr+0x19        //接收缓冲区10 #define         REG_RXBuffer11    SJA_BaseAdr+0x1A        //接收缓冲区11 #define         REG_RXBuffer12    SJA_BaseAdr+0x1B        //接收缓冲区12 #define         REG_RXBuffer13    SJA_BaseAdr+0x1C        //接收缓冲区13 #define         REG_RXCOUNT       SJA_BaseAdr+0x1D         //RX报文计数器  只读 RX信息计数器(RMC)反应RXFIFO中可用的信息数目 #define         REG_RBSA          SJA_BaseAdr+0x1E         //RX缓冲器起始地址寄存器(RBSA)可读写 复位模式只写                                                            //反映了当前可用来存储位于接收缓冲器窗口中的信息的内部RAM地址 #define         REG_CDR           SJA_BaseAdr+0x1F         //时钟分频寄存器 //时钟分频寄存器为微控制器控制CLKOUT 的频率以及屏蔽CLKOUT 引脚而且它还控制着TX1上 //的专用接收中断脉冲接收比较通道和BasicCAN 模式与PeliCAN 模式的选择 /* 功能说明:   CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为16MHZ*/ #define         BTR0_Rate_20k      0x53          //20KBPS的预设值 #define         BTR1_Rate_20k      0x2F          //20KBPS的预设值 #define         BTR0_Rate_40k      0x87          //40KBPS的预设值 #define         BTR1_Rate_40k      0xFF          //40KBPS的预设值 #define         BTR0_Rate_50k      0x47          //50KBPS的预设值 #define         BTR1_Rate_50k      0x2F          //50KBPS的预设值 #define         BTR0_Rate_80k      0x83          //80KBPS的预设值 #define         BTR1_Rate_80k      0xFF          //80KBPS的预设值 #define         BTR0_Rate_100k     0x43          //100KBPS的预设值 #define         BTR1_Rate_100k     0x2f          //100KBPS的预设值 #define         BTR0_Rate_125k     0x03          //125KBPS的预设值 #define         BTR1_Rate_125k     0x1c          //125KBPS的预设值 #define         BTR0_Rate_200k     0x81          //200KBPS的预设值 #define         BTR1_Rate_200k     0xFA          //200KBPS的预设值 #define         BTR0_Rate_250k     0x01          //250KBPS的预设值 #define         BTR1_Rate_250k     0x1c          //250KBPS的预设值 #define         BTR0_Rate_400k     0x43          //400KBPS的预设值 #define         BTR1_Rate_400k     0x11          //400KBPS的预设值 #define         BTR0_Rate_500k     0x81          //500KBPS的预设值 #define         BTR1_Rate_500k     0x23          //500KBPS的预设值 #define         BTR0_Rate_666k     0x41          //666KBPS的预设值 #define         BTR1_Rate_666k     0x12          //666KBPS的预设值 #define         BTR0_Rate_800k     0x41          //800KBPS的预设值 #define         BTR1_Rate_800k     0x11          //800KBPS的预设值 #define         BTR0_Rate_1000k    0x40          //1000KBPS的预设值 #define         BTR1_Rate_1000k    0x23          //1000KBPS的预设值 //BPS //功能说明:   CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为24MHZ*/ #define         BTR0_Rate_10k      0xEF          //20KBPS的预设值 #define         BTR1_Rate_10k      0xFF          //20KBPS的预设值 #define         ByteRate_10k       10  #define         ByteRate_20k       20 #define         ByteRate_40k       40 #define         ByteRate_50k       50 #define         ByteRate_80k       80 #define         ByteRate_100k      100 #define         ByteRate_125k      125 #define         ByteRate_200k      200 #define         ByteRate_250k      250 #define         ByteRate_400k      400 #define         ByteRate_500k      500 #define         ByteRate_800k      800 #define         ByteRate_1000k     1000 //命令字 #define    TR_CMD     0X01  //CMR.0发送请求位 #define    AT_CMD     0X02  //CMR.1中止发送位 #define    RRB_CMD    0X04  //CMR.2释放接收缓冲器   #define    COS_CMD    0X08  //CMR.3清除数据溢出 #define    SRR_CMD    0X10  //CMR.4自接收模式 #define    GTS_CMD    0X10  //????CMR.5.CMR7保留位 //错误字 #define CAN_INTERFACE_OK      0     //CAN总线接口OK #define CAN_BUS_OK            0     //CAN总线OK #define CAN_INTERFACE_ERR     0XFF  //CAN总线接口错误 #define CAN_ENTERSET_ERR      0XFE  //CAN总线初始化错误 #define CAN_QUITSET_ERR       0XFD  //CAN总线退出复位模式错误 #define CAN_INITOBJECT_ERR    0XFC  //CAN总线初始化对象错误 #define CAN_INITBTR_ERR       0XFB  //?     #define CAN_INITOUTCTL_ERR    0XFA  //?? #define CAN_INTCLKDIV_ERR     0XF9  //?? #define CAN_BUS_ERR           0XF8  //CAN总线错误 #define ID28_21    0X0A; #define ID20_13    0X4A; #define ID12_5     0X6B; #define ID4_0      0XE8; //低三位不影响设为0 //定义扩展模式数据帧ID //Basic CAN模式标准帧格式 :帧信息,TX识别码1-2,TX数据字节1-8 //Pelican模式扩展帧格式   :帧信息,TX识别码1-4,TX数据字节1-8 extern unsigned char xdata *SJA_BCANAdr;  bit SJA_Interface_Test(void); bit Set_OutClock(unsigned char outclock);//只能用于复位模式 bit SET_ACR(unsigned char BCAN_ACR0,unsigned char BCAN_ACR1,unsigned char BCAN_ACR2,unsigned char BCAN_ACR3); bit SET_AMR(unsigned char BCAN_AMR0,unsigned char BCAN_AMR1,unsigned char BCAN_AMR2,unsigned char BCAN_AMR3); bit Set_Bandrate(unsigned char bandrate);//只能用于复位模式 bit Set_ContrREG(unsigned char CMD);//设置控制(模式)寄存器 bit Enter_RST_Mode(void); bit Quit_RST_Mode(void); bit CAN_CMD_PRG(unsigned char cmd);//命令请求 bit Set_IntEnable(unsigned char CMD); unsigned char CAN_Write(unsigned char *SendDataBuf); void CAN_Send_onebyte(unsigned char CAN_TX_data); unsigned char SJA_Init(void); void CAN_Send_Str(unsigned char *str); #endif

5.sja1000.c

#include "sja1000.h" sbit LED=P1^0; unsigned char xdata *SJA_BCANAdr;  unsigned char RevceData[8]; //C语言指针说明以 * 为分隔符, //“*” 前面的存储类型修饰—指针所指向的对象数据的存储位置; //“*” 后面的存储类型修饰—指针本身所分配的存储位置。 // //unsigned char xdata *P说明指针指向的对象是一个处于Xdata的元素,比如数组. //xdata unsigned char *p表明指针本身位于Xdata,至于指向什么类型的地址,自由变换. //所以unsigned char xdata *p; 和xdata unsigned char *p   不一样。说明的是2回事。 //而:xdata unsigned char *p; 和 unsigned char  * xdata p; 完全一样。 //因为C写法中允许“最前面的存储类型修饰符修饰最后面的对象。” /***************************************************************** 函数功能:检测SJA1000与CPU数据接口是否正确连接 入口参数: 返回参数:1正确 0错误 说明: ******************************************************************/ bit SJA_Interface_Test(void) {    SJA_BCANAdr=REG_TEST;    *SJA_BCANAdr=0xAA;    if(*SJA_BCANAdr==0XAA)    return 1;    else return 0; } /***************************************************************** 函数功能:设置分频系数  工作模式  入口参数: 返回参数:1设置成功 0失败 说明:此处设置为PeliCAN模式,终止CAN输入比较器(复位模式),关闭时钟输出 ******************************************************************/ bit Set_OutClock(unsigned char outclock) {    SJA_BCANAdr=REG_CDR ;    *SJA_BCANAdr=outclock;    if(*SJA_BCANAdr==outclock)    return 1;    else return 0; } /***************************************************************** 函数功能:设置验收验收代码寄存器和接收屏蔽码寄存器 只有在复位模式下才能访问该寄存器 入口参数:各个寄存器的写入值 返回参数:1设置成功 0 设置失败 说明:设置CAN节点的通讯对象,允许接收的报文,是由AMR和ACR共同决定的.  PeliCAN工作模式下滤波模式分为:  1.单滤波器模式 模式寄存器(MOD.3=1)     这种滤波模式可以定义一个4字节长虑波器 。虑波器字节和信息字节之位的对应关系取决于当前接收帧的格式。 标准帧:11位标识符、RTR位、数据场前连个字节参与滤波。对于参与滤波的数据,所有AMR为0的位所对应的ACR位 和参与滤波数据的对应位必须相同才算验收通过。如果由于置位RTR位而没有数据字节,或因为设置相应的数据长度代码 而没有或只有一个数据字节,报文也会被接收。ACR1和AMR1的低四位是不用的,此时可将AMR1.3-AMR1.0设为1,定为不影响 扩展帧:29位标识符和RTR位参与滤波。此时ACR3和AMR3的最低两位是不用的。将AMR3.1、AMR3.0置1,定为不影响。 2.双滤波器模式 模式寄存器(MOD.3=0)至少有一个滤波器验收通过,数据才能正常接收。 接收标准帧:第一个滤波器由ACR0、ACR1、AMR0、AMR1及ACR3、AMR3的低四位组成。11位标识符、RTR位和数据场的第一个字节参与滤波 在RTR位置位1或数据长度代码是0,表示没有数据字节存在时,只要从开始到RTR位的部分都表示接收。信息就可以通过滤波器1 第二个滤波器由ACR2、AMR2及ACR3、AMR3的高四位组成。11位标识符和RTR位参与滤波。 如果没有数据字节向滤波器请求过滤,AMR1和AMR3的低四位必须被置1,表示不影响。此时两个滤波器的识别工作都是验证 包括RTR在内的整个标准识别码。 接收扩展帧:定义的两个滤波器是相同的 第一个滤波器由ACR0、ACR1和AMR0、AMR1构成 第二个滤波器由ACR2、ACR3和AMR2、AMR3构成 两个滤波器都只比较扩展识别码的前两个字节即29位识别码中的搞16位 ******************************************************************/ bit SET_ACR(unsigned char BCAN_ACR0,unsigned char BCAN_ACR1,unsigned char BCAN_ACR2,unsigned char BCAN_ACR3) {     SJA_BCANAdr=REG_ACR0;    *SJA_BCANAdr=BCAN_ACR0;     SJA_BCANAdr=REG_ACR1;    *SJA_BCANAdr=BCAN_ACR1;     SJA_BCANAdr=REG_ACR2;    *SJA_BCANAdr=BCAN_ACR2;     SJA_BCANAdr=REG_ACR3;    *SJA_BCANAdr=BCAN_ACR3;     if(*SJA_BCANAdr!=BCAN_ACR3)  return 0;     return 1; } bit SET_AMR(unsigned char BCAN_AMR0,unsigned char BCAN_AMR1,unsigned char BCAN_AMR2,unsigned char BCAN_AMR3) {  SJA_BCANAdr=REG_AMR0;    *SJA_BCANAdr=BCAN_AMR0;     SJA_BCANAdr=REG_AMR1;    *SJA_BCANAdr=BCAN_AMR1;     SJA_BCANAdr=REG_AMR2;    *SJA_BCANAdr=BCAN_AMR2;     SJA_BCANAdr=REG_AMR3;    *SJA_BCANAdr=BCAN_AMR3;     if(*SJA_BCANAdr!=BCAN_AMR3) return 0;      return 1; } /***************************************************************** 函数功能:设置CAN总线通信波特率 入口参数:波特率 返回参数:1设置成功 0设置失败 说明:该子程序只能用于复位模式         因为总线定时器BTRO-BTR1只有在复位模式下才能读写操作,工作模式只读                                  ******************************************************************/ bit Set_Bandrate(unsigned char bandrate) {     unsigned char BR_Num= bandrate,BTR0_num,BTR1_num;     switch (BR_Num)     {         case ByteRate_10k:              BTR0_num=BTR0_Rate_10k;              BTR1_num=BTR0_Rate_10k;              break;         case ByteRate_20k:              BTR0_num=BTR0_Rate_20k;              BTR1_num=BTR0_Rate_20k;              break;         case ByteRate_40k:              BTR0_num=BTR0_Rate_20k;              BTR1_num=BTR0_Rate_20k;              break;         case ByteRate_50k:              BTR0_num=BTR0_Rate_50k;              BTR1_num=BTR0_Rate_50k;              break;         case ByteRate_80k:              BTR0_num=BTR0_Rate_80k;              BTR1_num=BTR0_Rate_80k;              break;         case ByteRate_100k:              BTR0_num=BTR0_Rate_100k;              BTR1_num=BTR0_Rate_100k;              break;         case ByteRate_125k:              BTR0_num=BTR0_Rate_125k;              BTR1_num=BTR0_Rate_125k;              break;         case ByteRate_200k:              BTR0_num=BTR0_Rate_200k;              BTR1_num=BTR0_Rate_200k;              break;         case ByteRate_250k:              BTR0_num=BTR0_Rate_250k;              BTR1_num=BTR0_Rate_250k;              break;         case ByteRate_400k:              BTR0_num=BTR0_Rate_400k;              BTR1_num=BTR0_Rate_400k;              break;         case ByteRate_500k:              BTR0_num=BTR0_Rate_500k;              BTR1_num=BTR0_Rate_500k;              break;         case ByteRate_1000k:              BTR0_num=BTR0_Rate_1000k;              BTR1_num=BTR0_Rate_1000k;              break;         default :return 0;break;     }     SJA_BCANAdr=REG_BTR0;     *SJA_BCANAdr=BTR0_num;     if(*SJA_BCANAdr!=BTR0_num) return 0;     SJA_BCANAdr=REG_BTR1;     *SJA_BCANAdr=BTR1_num;     if(*SJA_BCANAdr!=BTR1_num) return 0;     return 1; } /***************************************************************** 函数功能:设置控制(模式)寄存器 入口参数:写入的命令 返回参数: 说明:模式寄存器的内容是用来改变CAN 控制器的行为 ******************************************************************/ bit Set_ContrREG(unsigned char CMD) {     SJA_BCANAdr  = REG_CONTROL;//控制寄存器        *SJA_BCANAdr=CMD;     if(*SJA_BCANAdr==CMD) return 1;     else return 0; } /***************************************************************** 函数功能:设置复位请求和单滤波工作模式 入口参数: 返回参数: 说明: ******************************************************************/ bit Enter_RST_Mode(void) {     SJA_BCANAdr  = REG_CONTROL;//控制寄存器       *SJA_BCANAdr=0x09;           //置位复位请求 和单滤波模式     if((*SJA_BCANAdr&0x01) == 1)      return   1;     else      return   0; }/***************************************************************** 函数功能: 入口参数: 返回参数: 说明: ******************************************************************/ bit Quit_RST_Mode(void) {     SJA_BCANAdr=REG_CONTROL;            //退出 复位模式     *SJA_BCANAdr=*SJA_BCANAdr&0xfe;     if((*SJA_BCANAdr&0X01)==0)         return 1;     else return 0; } /***************************************************************** 函数功能:发送命令请求,并返回请求结果 入口参数: 返回参数:0请求成功 1请求失败 说明: ******************************************************************/ bit  CAN_CMD_PRG(unsigned char cmd)  {    SJA_BCANAdr=REG_COMMAND;            //访问地址指向命令寄存器    *SJA_BCANAdr=cmd;                   //启动命令字    switch(cmd)    {          case  TR_CMD:    //发送请求                            return    1;            break;      case  SRR_CMD:     //CMR.4自接收模式            return 1;            break;      case  AT_CMD:      //CMR.1中止发送位                       SJA_BCANAdr = REG_STATUS;   //访问地址指向状态寄存器               if((*SJA_BCANAdr & 0x20)==0) //判断是否正在发送 (0正在发送 1等待空闲)              return  1;            else              return  0;                          break;       case  RRB_CMD:   // CMR.2释放接收缓冲器                             SJA_BCANAdr = REG_STATUS;   //访问地址指向状态寄存器               if((*SJA_BCANAdr & 0x01)==1) //判断接收缓冲器是否为空 (0为空 1不为空)               return  0;//若不为空 则释放接收缓冲器失败            else                          return  1;                           break;        case  COS_CMD:  //CMR.3清除数据溢出                            SJA_BCANAdr = REG_STATUS;               if((*SJA_BCANAdr & 0x02)==0)//判断清除溢出是否成功              return  1;             else              return  0;                         break;       default:              return  0;              break;     } } /***************************************************************** 函数功能:设置中断使能寄存器 入口参数: 返回参数: 说明: ******************************************************************/ bit Set_IntEnable(unsigned char CMD) {   SJA_BCANAdr=REG_INTENABLE;   //SJA_BaseAdr+0x00  控制寄存器   *SJA_BCANAdr=CMD;     if (*SJA_BCANAdr == CMD)     return 1;   else     return 0; } unsigned char CAN_Write(unsigned char *SendDataBuf)  {       unsigned char temp;     SJA_BCANAdr = REG_STATUS;         temp=*SJA_BCANAdr;     if ((temp&0x08)==0) return  1;    //上次发送未完成     if ((temp&0x04)==0) return  2;    //发送缓冲区是否锁定      if ((temp&0x10)==0x10) return 3;  //判断是否正在接收        SJA_BCANAdr = REG_RXBuffer1;      //访问地址指向发送缓冲区1,修改成头文件     memcpy(SJA_BCANAdr,SendDataBuf,4); //将SendDataBuf起始地址的的4个字节数据拷贝到 SJA_BCANAdr 发送缓冲区中      CAN_CMD_PRG(TR_CMD);             //请求发送              return 0; }   //CAN发送一个字节 void CAN_Send_onebyte(unsigned char CAN_TX_data) { unsigned char temptt; loop:     SJA_BCANAdr = REG_STATUS;              temptt=*SJA_BCANAdr;  //temptt=Read_SJA1000(REG_STATUS); if((temptt&0x04)==0x00)  goto loop;//循环检测等待                        //可以向发送缓冲器写数据     SJA_BCANAdr = REG_RXBuffer1;           *SJA_BCANAdr=0x01;       SJA_BCANAdr = REG_RXBuffer2;          *SJA_BCANAdr=0x28;        SJA_BCANAdr = REG_RXBuffer3;     *SJA_BCANAdr=0x00;     SJA_BCANAdr = REG_RXBuffer4;       *SJA_BCANAdr=CAN_TX_data;  //数据发送请求     CAN_CMD_PRG(TR_CMD);           } void CAN_Send_Str(unsigned char *str) {     unsigned char temptt,length; loop:     SJA_BCANAdr = REG_STATUS;              temptt=*SJA_BCANAdr;  //temptt=Read_SJA1000(REG_STATUS); if((temptt&0x04)==0x00)  goto loop;//循环检测等待                        //可以向发送缓冲器写数据     length=strlen(str);     SJA_BCANAdr = REG_TXBuffer1;           *SJA_BCANAdr=0x80|length; //设置发送信息帧位扩展数据帧 和发送的数据字节长度      SJA_BCANAdr = REG_TXBuffer2;          *SJA_BCANAdr=ID28_21;        SJA_BCANAdr = REG_TXBuffer3;     *SJA_BCANAdr=ID20_13;     SJA_BCANAdr = REG_TXBuffer4;       *SJA_BCANAdr=ID12_5;      SJA_BCANAdr =REG_TXBuffer5;       *SJA_BCANAdr=ID4_0;      SJA_BCANAdr = REG_TXBuffer6;       memcpy(SJA_BCANAdr,str,length); //数据发送请求     CAN_CMD_PRG(TR_CMD);       } /***************************************************************** 函数功能:SJA1000初始化 入口参数: 返回参数: 说明: ******************************************************************/ unsigned char SJA_Init(void) {     bit s;      EA=0;//关总中断     if (!Enter_RST_Mode()) return 1; //设置模式(控制)寄存器 置位复位请求位 和验收滤波模式位(单滤波模式)     if (!SJA_Interface_Test()) return 2; //!!!!!我觉得此处逻辑上应先测试SJA1000再进行复位操作        //0XC8=1100 0000 最高位CDR.7(CANmode位)=1=Pelican模式(=0=BasicCAN模式)     //置位CDR.6 可以中止CAN 输入比较器 CDR.3置位关闭external CLKOUT CD2-CD0 设置时钟分频      //设置为PeliCAN模式,终止CAN输入比较器(复位模式),关闭时钟输出      if (!Set_OutClock(0XC8)) return 3;     //设置滤波器滤波条件     SET_ACR(0x0A,0x4A,0x6B,0x78);         s=SET_AMR(0x00,0x00,0x00,0x03);                                                                 if (s==0) return 4;     if (!Set_Bandrate(ByteRate_1000k)) return 5;//设置通信波特率     if (!Set_IntEnable(0x1D)) return 6;      SJA_BCANAdr=REG_OCR ;               //输出控制寄存器       *SJA_BCANAdr=0x1a;                  //设置为正常输出模式      if(!Quit_RST_Mode()) return 7;      EA=1;      PX0=1;//外部中断0定义为高优先级中断      EX0=1;//开启外部中断      IT0=0;//外部中断0触发方式选择位 此处设置为低电平触发      return 0;    } void Int0_ISR() interrupt 0 {  unsigned char tt,length;  SJA_BCANAdr=REG_INTERRUPT;//中断寄存器  if((*SJA_BCANAdr)&0x01)   //产生了接收中断  {       UART_Send_String("SJA1000 Has recieved data!\r\n");     SJA_BCANAdr=REG_RXBuffer1;//CAN地址16  TX帧信息 低四位DLC.3-DLC.0数据长度代码为      tt=*SJA_BCANAdr;     length=tt&0x0F;//获取数据长度代码      if ((tt&0x40)!=0x40)                 //最高位为帧格式位=0数据帧   =1 为远程帧      {        SJA_BCANAdr=REG_RXBuffer6;           //宏定义的变量不能memcpy(RevceData,REG_RXBuffer4,8);             memcpy(RevceData,SJA_BCANAdr,length);//功能:由src所指内存区域复制count个字节到dest所指内存区域                                           //测试用的主要是把接收到的数据在发出去,验证数据的正确                                           //以下代码是发送到串      UART_Send_String(RevceData);      }      CAN_CMD_PRG(RRB_CMD);                //释放SJA1000接收缓冲区,****已经修改  } }



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3