经过一个星期的艰苦奋斗,终于将两个SJA1000通过51单片机成功通讯了!采用的是Pelican工作模式,扩展帧数据格式,验收滤波器是采用单滤波扩展帧模式。 发送和接收代码都全部相同样! 一 实物图 二 串口输出调试信息 三 以下是全部程序代码:包括1 main.c、2 uart.h、3 uart.c、4 sja1000.h、5 sja1000.c。 1main.c #include "reg51.h" 2uart.h #ifndef __UART_H__ 3uart.c #include "uart.h" //共阳数码管显示 调试的时候用到 ,本程序最终没有用到。 4sja1000.h #ifndef __SJA1000_H__ 5.sja1000.c #include "sja1000.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");
}
}
#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
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];
}
#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
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接收缓冲区,****已经修改
}
}
上一篇:基于C8051F040单片机的CAN总线通信
下一篇:STC89C52+SJA1000自收发程序记录
推荐阅读最新更新时间:2024-03-16 16:13