700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > sja1000编程c语言 基于51单片机SJA1000 CAN通讯实现(C语言程序)

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

时间:2022-09-16 20:29:45

相关推荐

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

经过一个星期的艰苦奋斗,终于将两个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

#defineREG_CONTROL SJA_BaseAdr+0x00 //内部控制寄存器

#defineREG_COMMAND SJA_BaseAdr+0x01 //命令寄存器 只写

#defineREG_STATUS SJA_BaseAdr+0x02 //状态寄存器 只读

#defineREG_INTERRUPT SJA_BaseAdr+0x03 //中断寄存器 只读

#defineREG_INTENABLE SJA_BaseAdr+0x04 //中断使能寄存器 可读可写

#defineREG_RESVER0 SJA_BaseAdr+0x05 //保留0

#defineREG_BTR0SJA_BaseAdr+0x06 //总线定时寄存器0 复位模式读写

//定义了波特率预设值BRP 和同步跳转宽度SJW 的值

#defineREG_BTR1SJA_BaseAdr+0x07 //总线定时寄存器1 复位模式读写

//总线定时寄存器1 定义了每个位周期的长度采样点的位置和在每个采样点的采样数目

#defineREG_OCRSJA_BaseAdr+0x08 //输出控制寄存器 复位模式读写

//输出控制寄存器实现了由软件控制不同输出驱动配置的建立

#defineREG_TESTSJA_BaseAdr+0x09 //测试寄存器

#defineREG_RESVER1 SJA_BaseAdr+0x0A //保留1

#defineREG_ARBITRATE SJA_BaseAdr+0x0B //仲裁丢失捕捉 只读

#defineREG_ERRCATCH SJA_BaseAdr+0x0C //错误代码捕捉 只读

#defineREG_ERRLIMIT SJA_BaseAdr+0x0D //错误报警限额 工作模式只读 复位模式可读写

#defineREG_RXERRSJA_BaseAdr+0x0E//接收错误计数器工作模式只读 复位模式可读写

#defineREG_TXERRSJA_BaseAdr+0x0F//发送错误计数器工作模式只读 复位模式可读写

#defineREG_ACR0SJA_BaseAdr+0x10 //验收代码寄存器

#defineREG_ACR1SJA_BaseAdr+0x11 //验收代码寄存器

#defineREG_ACR2SJA_BaseAdr+0x12 //验收代码寄存器

#defineREG_ACR3SJA_BaseAdr+0x13 //验收代码寄存器

#defineREG_AMR0SJA_BaseAdr+0x14 //验收屏蔽寄存器

#defineREG_AMR1SJA_BaseAdr+0x15 //验收屏蔽寄存器

#defineREG_AMR2SJA_BaseAdr+0x16 //验收屏蔽寄存器

#defineREG_AMR3SJA_BaseAdr+0x17 //验收屏蔽寄存器

// 发送缓冲区寄存器 (发送缓冲区长13字节,在CAN地址是16-28即0x10-0x1c)

#defineREG_TXBuffer1 SJA_BaseAdr+0x10//发送缓冲区1

#defineREG_TXBuffer2 SJA_BaseAdr+0x11//发送缓冲区2

#defineREG_TXBuffer3 SJA_BaseAdr+0x12//发送缓冲区3

#defineREG_TXBuffer4 SJA_BaseAdr+0x13//发送缓冲区4

#defineREG_TXBuffer5 SJA_BaseAdr+0x14//发送缓冲区5

#defineREG_TXBuffer6 SJA_BaseAdr+0x15//发送缓冲区6

#defineREG_TXBuffer7 SJA_BaseAdr+0x16//发送缓冲区7

#defineREG_TXBuffer8 SJA_BaseAdr+0x17//发送缓冲区8

#defineREG_TXBuffer9 SJA_BaseAdr+0x18//发送缓冲区9

#defineREG_TXBuffer10 SJA_BaseAdr+0x19//发送缓冲区10

#defineREG_TXBuffer11 SJA_BaseAdr+0x1A//发送缓冲区11

#defineREG_TXBuffer12 SJA_BaseAdr+0x1B//发送缓冲区12

#defineREG_TXBuffer13 SJA_BaseAdr+0x1C//发送缓冲区13

// 接收缓冲区寄存器 (接收缓冲区长13字节,在CAN地址是16-28即0x10-0x1c)

#defineREG_RXBuffer1 SJA_BaseAdr+0x10 //接收缓冲区1

#defineREG_RXBuffer2 SJA_BaseAdr+0x11 //接收缓冲区2

#defineREG_RXBuffer3 SJA_BaseAdr+0x12 //接收缓冲区3

#defineREG_RXBuffer4 SJA_BaseAdr+0x13 //接收缓冲区4

#defineREG_RXBuffer5 SJA_BaseAdr+0x14 //接收缓冲区5

#defineREG_RXBuffer6 SJA_BaseAdr+0x15//接收缓冲区6

#defineREG_RXBuffer7 SJA_BaseAdr+0x16//接收缓冲区7

#defineREG_RXBuffer8 SJA_BaseAdr+0x17//接收缓冲区8

#defineREG_RXBuffer9 SJA_BaseAdr+0x18//接收缓冲区9

#defineREG_RXBuffer10 SJA_BaseAdr+0x19 //接收缓冲区10

#defineREG_RXBuffer11 SJA_BaseAdr+0x1A //接收缓冲区11

#defineREG_RXBuffer12 SJA_BaseAdr+0x1B //接收缓冲区12

#defineREG_RXBuffer13 SJA_BaseAdr+0x1C //接收缓冲区13

#defineREG_RXCOUNT SJA_BaseAdr+0x1D//RX报文计数器 只读 RX信息计数器(RMC)反应RXFIFO中可用的信息数目

#defineREG_RBSASJA_BaseAdr+0x1E//RX缓冲器起始地址寄存器(RBSA)可读写 复位模式只写

//反映了当前可用来存储位于接收缓冲器窗口中的信息的内部RAM地址

#defineREG_CDRSJA_BaseAdr+0x1F//时钟分频寄存器

//时钟分频寄存器为微控制器控制CLKOUT 的频率以及屏蔽CLKOUT 引脚而且它还控制着TX1上

//的专用接收中断脉冲接收比较通道和BasicCAN 模式与PeliCAN 模式的选择

/*

功能说明: CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为16MHZ*/

#defineBTR0_Rate_20k 0x53//20KBPS的预设值

#defineBTR1_Rate_20k 0x2F//20KBPS的预设值

#defineBTR0_Rate_40k 0x87//40KBPS的预设值

#defineBTR1_Rate_40k 0xFF//40KBPS的预设值

#defineBTR0_Rate_50k 0x47//50KBPS的预设值

#defineBTR1_Rate_50k 0x2F//50KBPS的预设值

#defineBTR0_Rate_80k 0x83//80KBPS的预设值

#defineBTR1_Rate_80k 0xFF//80KBPS的预设值

#defineBTR0_Rate_100k 0x43//100KBPS的预设值

#defineBTR1_Rate_100k 0x2f//100KBPS的预设值

#defineBTR0_Rate_125k 0x03//125KBPS的预设值

#defineBTR1_Rate_125k 0x1c//125KBPS的预设值

#defineBTR0_Rate_200k 0x81//200KBPS的预设值

#defineBTR1_Rate_200k 0xFA//200KBPS的预设值

#defineBTR0_Rate_250k 0x01//250KBPS的预设值

#defineBTR1_Rate_250k 0x1c//250KBPS的预设值

#defineBTR0_Rate_400k 0x43//400KBPS的预设值

#defineBTR1_Rate_400k 0x11//400KBPS的预设值

#defineBTR0_Rate_500k 0x81//500KBPS的预设值

#defineBTR1_Rate_500k 0x23//500KBPS的预设值

#defineBTR0_Rate_666k 0x41//666KBPS的预设值

#defineBTR1_Rate_666k 0x12//666KBPS的预设值

#defineBTR0_Rate_800k 0x41//800KBPS的预设值

#defineBTR1_Rate_800k 0x11//800KBPS的预设值

#defineBTR0_Rate_1000k 0x40//1000KBPS的预设值

#defineBTR1_Rate_1000k 0x23//1000KBPS的预设值

//BPS

//功能说明: CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为24MHZ*/

#defineBTR0_Rate_10k 0xEF//20KBPS的预设值

#defineBTR1_Rate_10k 0xFF//20KBPS的预设值

#defineByteRate_10k 10

#defineByteRate_20k 20

#defineByteRate_40k 40

#defineByteRate_50k 50

#defineByteRate_80k 80

#defineByteRate_100k 100

#defineByteRate_125k 125

#defineByteRate_200k 200

#defineByteRate_250k 250

#defineByteRate_400k 400

#defineByteRate_500k 500

#defineByteRate_800k 800

#defineByteRate_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_OK0 //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_ERR0XF8 //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接收缓冲区,****已经修改

}

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。