1、CAN总线之saj1000与82c250应用源程序CAN总线之saj1000与82c250应用源程序,基于c8051f340单片机平台。2009年04月19日 星期日 10:58定义头文件:s.hvoid CanInit();void CanSend(unsigned char *bufDATA,unsigned char datalen);void Port_IO_Init();void Oscillator_Init();void Init_Device(void);void WR_SJA(unsigned char sja_addr,unsigned char sja_data);uns
2、igned char RD_SJA(unsigned char sja_addr);/*SJA1000内部寄存器地址(初始化复位模式) PeliCAN模式的地址表./*标准帧格式(SFF)与扩展帧格式(EFF).#define SJA_MOD 0 /*模式寄存器 可以定义过滤模式 MOD.3=AFM 00H*/#define SJA_CMR 1 /命令寄存器#define SJA_SR 2 /状态寄存器 #define SJA_IR 3 / 中断标志 03#define SJA_IER 4 /*中断允许 04H */#define SJA_BTR0 6 /*总线定时器0 06H*/#defin
3、e SJA_BTR1 7 /*总线定时器1 07H*/#define SJA_OCR 8 /*输出控制 08H*/#define SJA_ALC 11 / 仲裁丢失捕捉 11 #define SJA_ECC 12 /*错误代码捕捉 0CH*/#define SJA_EWLR 13 /错误报警限制寄存器#define SJA_RXERR 14 /错误计数寄存器#define SJA_TXERR 15 /*发送错误记数 0FH*/以下为复位模式定义#define SJA_ACR0 16 /*验收代码 即ID ?16*/ #define SJA_ACR1 17 /*验收代码 即ID 17*/#def
4、ine SJA_ACR2 18 /*验收代码 即ID 18*/#define SJA_ACR3 19 /*验收代码 即ID 19*/#define SJA_AMR0 20 /*验收屏蔽 初地址20*/ #define SJA_AMR1 21 /*验收屏蔽 初地址21*/ #define SJA_AMR2 22 /*验收屏蔽 初地址22*/ #define SJA_AMR3 23 /*验收屏蔽 初地址23*/SJA1000内部寄存器地址(工作模式)#define SJA_EFF 16 /RX和TX结构信息 扩展帧/标准帧#define SJA_ID1 17 /识别码#define SJA_ID2
5、 18 /识别码#define SJA_ID3 19 /识别码,标准帧无#define SJA_ID4 20 /识别码,标准帧无#define SJA_D1 21 /#define SJA_D2 22 #define SJA_D3 23 #define SJA_D4 24 #define SJA_D5 25 #define SJA_D6 26 #define SJA_D7 27 #define SJA_D8 28 / / / / / / /单片机程序如下:#include #include #include s.h/模块程序测试-CAN主动发送与中断接收。/版本号:V1.2/ c8051f34
6、0/ -/ (低有效) led1|P2.0 P3.0|-P1继电器(低有效) 上/ led2|P2.1 P3.1|-P2继电器 下/ SDA|P2.2 I2C |/ SCL|P2.3 |/ | |/ AD0|P1.0 |/ * | * |/(CAN通信) * | * |/ AD7|P1.7 |/ | |/ CS_CAN|P0.3 |/ ALE|P0.0 |/ RD|P0.1 |/ WR|P2.7 |/ INTCAN|P0.2 |/ | |/sbit led1 = P20;sbit led2 = P21;sbit SDA = P22;sbit SCL = P23;sbit J1 = P30;sb
7、it J2 = P31;sbit st1 = P04;sbit ALE_CAN = P00;sbit RD_CAN = P01;sbit INT_CAN = P02;sbit CS_CAN = P03;sbit WR_CAN = P27;#define WriteDeviceAddress 0xa0 /地址以及读写方向,本设备中只有一个IIC设备地址为0#define ReadDviceAddress 0xa1#define uchar unsigned char#define uint unsigned int#define nop _nop_ uchar c116=0X00,0X01,0X
8、02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0a,0X0b,0X0c, 0X0d,0X0e,0X0f;uchar c216;uchar c38 =0X00,0X01,0X02,0X03,0X04,0X05,0X06,0X07;unsigned int idata MaxLenCanRxBuf=440;unsigned char xdata CanRxBuf440; /40个CAN帧缓冲区unsigned char idata CanTempBuf11; /单个can报文的缓冲区。unsigned char idata CanTxData8; /CAN发送数据
9、缓冲区unsigned char data_flag=0;unsigned int idata CanRxAddr=0;unsigned char CanRxcompleteFlag=0;unsigned char idata cfgbuf32;unsigned char SendBufId2=0x07,0x20;/这个值要自己设定,现在只是测试程序代码假 设的一个值11位标示符的格式,后3位可选值为20,60,40,80,a0,e0unsigned char SendBufInfo;unsigned int xdata mSendDelay=0;unsigned char *h_pointe
10、r;unsigned char *l_pointer;unsigned char i=0;unsigned char j=0;uint LedFlag1=0;void DelayMs(unsigned int number)unsigned int temp;for(;number!=0;number-) for(temp=3066;temp!=0;temp-) ;/for c8051void delay(int num)int value;unsigned char jj;value=num*5;for(jj=0;jjvalue;jj+);void delay2(int num)unsign
11、ed char jj=0;for(jj=0;jjnum;jj+);/*函数名:CanInit(void)*功能描述:CAN的初始化设置,在复位模式下设置CAN为单滤波,正常模式,PeliCAN模式,不屏蔽,8* 字节数据位*函数说明: 通过ALE,RD,CS的配合控制完成*调用函数:NONE*全局变量:NONE*输入:*返回:*设计者:*/ void CanInit(void)unsigned char tempMode;unsigned char temp7=0;unsigned char temp8=0;tempMode =0x01; /复位模式tempMode |=0x08; /设置CA
12、N为单滤波 ,选择单个验收滤波器(32位长度)tempMode |=0x00; /正常模式,这句话貌似没有实际意义? WR_SJA(SJA_MOD,tempMode); /模式寄存器 进入复位模式 temp7=RD_SJA(SJA_MOD); /设置的变量用来查看前面的写入是否成功。 WR_SJA(SJA_CDR , 0x0C8); /时钟分频 选择PeliCAN模式 终止can输入比较器 关闭时钟输出CLKOUT temp8=RD_SJA(SJA_CDR);WR_SJA(SJA_AMR0 , 0xff); /验收屏蔽位设置,不影响WR_SJA(SJA_AMR1 , 0xff);WR_SJA(
13、SJA_AMR2 , 0xff);WR_SJA(SJA_AMR3 , 0xff);WR_SJA(SJA_ACR0 , 0x80); /验收代码位设置 扩展祯 数据 8字节WR_SJA(SJA_ACR1 , 0x00);WR_SJA(SJA_ACR2 , 0x00);WR_SJA(SJA_ACR3 , 0x00);WR_SJA(SJA_BTR0,0x00); /设置CAN波特率为500k 通过波特率计算器可以算出该值WR_SJA(SJA_BTR1,0x1c); temp7=RD_SJA(SJA_BTR0);temp8=RD_SJA(SJA_BTR1);mSendDelay=1000;WR_SJA
14、(SJA_IER , 0x01); /中断允许 打开接收中断使能WR_SJA(SJA_OCR , 0x0da); /输出控制 驱动上拉 正常输出模式 WR_SJA(SJA_MOD , tempMode & 0xFE);/模式寄存器 退出复位模式/*函数名:void can_rx_isr(void) interrupt 0*功能描述:sja1000 CAN接收中断函数*函数说明:在响应接收中断的时候,完成数据的接收。问题是现在sja的数据根本读不出来RD_SJA()函数问题。*调用函数:NONE*全局变量:NONE*输入:*返回:*设计者:*/ void can_rx_isr(void) int
15、errupt 0 /sja1000 CAN接收中断unsigned char k=0;unsigned char sja_addr;EA = 0;/*!RD_SJA(SJA_IR)读出来的值为0xff,所以也可以通过进入读环节。*/ /关CPU中断if(RD_SJA(SJA_IR)& 0x01)=0x01 ) /IR中断寄存器,当接收FIFO不空和接收中断使能时置位此位 sja_addr=SJA_EFF; /register 17. data start address if(CanRxAddr=MaxLenCanRxBuf)/unsigned int idata MaxLenCanRxBuf
16、=440. CanRxAddr=0; for(k=0;k11;k+) /完成11位标准帧数据的接收过程。 CanRxBufCanRxAddr+k = RD_SJA(sja_addr); sja_addr+; WR_SJA(SJA_CMR,0x04); /释放接收缓冲区 CanRxAddr+=11; CanRxcompleteFlag += 1; /接收完一次完整的数据报文以后该标志位加1.EA = 1;/打开CPU中断/*函数名:CanSend(unsigned char *bufDATA,unsigned char datalen)*功能描述:Can设备数据发送函数*函数说明:*调用函数:N
17、ONE*全局变量:NONE*输入:*返回:*设计者:*/ void CanSend(unsigned char *bufDATA,unsigned char datalen)unsigned int sja_addr;unsigned char j=0;unsigned char temp; /局部变量unsigned int n;/CanLedFlag=1;sja_addr=SJA_EFF; /取SJA的ID号的首地址地址,ID0的地址。SendBufInfo=datalen; /填入数据长度信息WR_SJA(sja_addr+,SendBufInfo); /以标准帧发送消息for(j=0;
18、j2;j+) WR_SJA(sja_addr+j,*(SendBufId+j); /发送两字节的id信息。for(j=0;jdatalen;j+) WR_SJA(sja_addr+2+j,*(bufDATA+j); /发送data区数据。WR_SJA(SJA_CMR, 0x03); /打开发送请求位与终止发送位,Send 正常发送for(n=0;nmSendDelay;n+) temp=RD_SJA(SJA_SR); /读取状态寄存器SR.3-TCS发送完毕状态 1(完毕) if(temp &0x08)=0x08) /发送完毕 for(n=0;n300;n+); /延时 break; /*函数
19、名:WR_SJA(unsigned char sja_addr,unsigned char sja_data)*功能描述: 完成先准备相应sja_addr地址,再在相应的sja_addr地址操作送sja_data数据的 过程*函数说明: 通过ALE切换地址与数据位的操作*调用函数:NONE*全局变量:NONE*输入:*返回:*设计者:*/ void WR_SJA(unsigned char sja_addr,unsigned char sja_data)ALE_CAN=1; /置高开启地址锁存允许,将io口的地址数据锁存。P1=sja_addr;delay2(3); ALE_CAN=0; /置
20、低关闭地址锁存允许,改为发送数据有效。delay2(1);CS_CAN=0;WR_CAN=0;P1=sja_data;delay2(4);/*/WR_CAN=1;CS_CAN=1; /恢复到操作前的状态,避免影响单片机对sja1000误操作。ALE_CAN=1;/*/*函数名:RD_SJA(unsigned char sja_addr)*功能描述: 完成先准备相应sja_addr地址,再将该地址的数据读出到sja_data的过程*函数说明: 通过ALE,RD,CS的配合控制完成*调用函数:NONE*全局变量:NONE*输入:*返回:*设计者:*/ /*unsigned char RD_SJA(
21、unsigned char sja_addr)unsigned char sja_data=0;CS_CAN=0; /使能片选ALE_CAN=1;/置高开启地址锁存允许,将io口的地址数据锁存。delay2(2);P1 = sja_addr;ALE_CAN=0;/置低关闭地址锁存允许,改为发送数据有效。delay2(4);RD_CAN=0; /使能读有效sja_data = P1;/*ALE_CAN=1;RD_CAN=1;/此处的3个使能一起操作,前面的写地址与写命令一样的原理CS_CAN=1;/*return sja_data;*/unsigned char RD_SJA(unsigned char sja_addr)unsigned char sja_data;ALE_CAN=1;/置高开启地址锁存允许,将io口的地址数据锁存。P1=sja_addr;delay2(3);ALE_CAN=0;/置低关闭地址锁存允许,改为发送数据有效。delay2(1);CS_CAN=0; /使能片选P1=0xFF; /端口初始化RD_CAN=0; /使能读有效delay2(4);sja_data=P1;/*/RD_CAN=1;/此处的3
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1