CAN总线之saj1000与82c250应用源程序.docx
《CAN总线之saj1000与82c250应用源程序.docx》由会员分享,可在线阅读,更多相关《CAN总线之saj1000与82c250应用源程序.docx(12页珍藏版)》请在冰豆网上搜索。
![CAN总线之saj1000与82c250应用源程序.docx](https://file1.bdocx.com/fileroot1/2023-2/9/ea3a3984-7a95-49d1-8f8e-9e8d56139624/ea3a3984-7a95-49d1-8f8e-9e8d561396241.gif)
CAN总线之saj1000与82c250应用源程序
CAN总线之saj1000与82c250应用源程序,基于c8051f340单片机平台。
2009年04月19日星期日10:
58
定义头文件:
s.h
voidCanInit();
voidCanSend(unsignedchar*bufDATA,unsignedchardatalen);
voidPort_IO_Init();
voidOscillator_Init();
voidInit_Device(void);
voidWR_SJA(unsignedcharsja_addr,unsignedcharsja_data);
unsignedcharRD_SJA(unsignedcharsja_addr);
//******SJA1000内部寄存器地址(初始化复位模式)PeliCAN模式的地址表.
//******标准帧格式(SFF)与扩展帧格式(EFF).
#defineSJA_MOD0 /*模式寄存器可以定义过滤模式MOD.3=AFM00H*/
#defineSJA_CMR1 //命令寄存器
#defineSJA_SR 2 //状态寄存器
#defineSJA_IR 3 //中断标志 03
#defineSJA_IER4 /*中断允许04H*/
#defineSJA_BTR06 /*总线定时器0 06H*/
#defineSJA_BTR17 /*总线定时器1 07H*/
#defineSJA_OCR 8 /*输出控制 08H*/
#defineSJA_ALC11 //仲裁丢失捕捉 11
#defineSJA_ECC12 /*错误代码捕捉0CH*/
#defineSJA_EWLR13 //错误报警限制寄存器
#defineSJA_RXERR14 //错误计数寄存器
#defineSJA_TXERR15 /*发送错误记数0FH*/
//以下为复位模式定义
#defineSJA_ACR016 /*验收代码即ID?
16*/
#defineSJA_ACR117 /*验收代码即ID 17*/
#defineSJA_ACR218 /*验收代码即ID 18*/
#defineSJA_ACR319 /*验收代码即ID 19*/
#defineSJA_AMR020 /*验收屏蔽初地址20*/
#defineSJA_AMR121 /*验收屏蔽初地址21*/
#defineSJA_AMR222 /*验收屏蔽初地址22*/
#defineSJA_AMR323 /*验收屏蔽初地址23*/
//SJA1000内部寄存器地址(工作模式)
#defineSJA_EFF16 //RX和TX结构信息扩展帧/标准帧
#defineSJA_ID117 //识别码
#defineSJA_ID218 //识别码
#defineSJA_ID319 //识别码,标准帧无
#defineSJA_ID420 //识别码,标准帧无
#defineSJA_D121 //
#defineSJA_D222
#defineSJA_D323
#defineSJA_D424
#defineSJA_D525
#defineSJA_D626
#defineSJA_D727
#defineSJA_D828 //////////////
单片机程序如下:
#include
#include
#include"s.h"
//模块程序测试--CAN主动发送与中断接收。
//版本号:
V1.2
// c8051f340
// -----------------
//(低有效)led1|P2.0 P3.0|-->P1继电器(低有效)上
// led2|P2.1 P3.1|-->P2继电器 下
// SDA|P2.2I2C |
// 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 |
// | |
//
//
sbitled1 =P2^0;
sbitled2 =P2^1;
sbitSDA =P2^2;
sbitSCL =P2^3;
sbitJ1 =P3^0;
sbitJ2 =P3^1;
sbitst1 =P0^4;
sbitALE_CAN=P0^0;
sbitRD_CAN =P0^1;
sbitINT_CAN=P0^2;
sbitCS_CAN =P0^3;
sbitWR_CAN =P2^7;
#defineWriteDeviceAddress0xa0//地址以及读写方向,本设备中只有一个IIC设备地址为0
#defineReadDviceAddress0xa1
#defineucharunsignedchar
#defineuintunsignedint
#definenop_nop_
ucharc1[16]={0X00,0X01,0X02,0X03,0X04,0X05,0X06,0X07,0X08,0X09,0X0a,0X0b,0X0c,
0X0d,0X0e,0X0f};
ucharc2[16];
ucharc3[8]={0X00,0X01,0X02,0X03,0X04,0X05,0X06,0X07};
unsignedintidataMaxLenCanRxBuf=440;
unsignedcharxdataCanRxBuf[440]; //40个CAN帧缓冲区
unsignedcharidataCanTempBuf[11]; //单个can报文的缓冲区。
unsignedcharidataCanTxData[8]; //CAN发送数据缓冲区
unsignedchardata_flag=0;
unsignedintidataCanRxAddr=0;
unsignedcharCanRxcompleteFlag=0;
unsignedcharidatacfgbuf[32];
unsignedcharSendBufId[2]={0x07,0x20};//这个值要自己设定,现在只是测试程序代码假设的一个值11位标示符的格式,后3位可选值为20,,60,40,80,a0,e0
unsignedcharSendBufInfo;
unsignedintxdatamSendDelay=0;
unsignedchar*h_pointer;
unsignedchar*l_pointer;
unsignedchari=0;
unsignedcharj=0;
uintLedFlag1=0;
voidDelayMs(unsignedintnumber)
{
unsignedinttemp;
for(;number!
=0;number--)
{
for(temp=3066;temp!
=0;temp--);//forc8051
}
}
voiddelay(intnum)
{
intvalue;
unsignedcharjj;
value=num*5;
for(jj=0;jj}
voiddelay2(intnum)
{
unsignedcharjj=0;
for(jj=0;jj}
/******************************************************************************************************************************************************
*函数名:
CanInit(void)
*功能描述:
CAN的初始化设置,在复位模式下设置CAN为单滤波,正常模式,PeliCAN模式,不屏蔽,8* 字节数据位
*函数说明:
通过ALE,RD,CS的配合控制完成
*调用函数:
NONE
*全局变量:
NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/
voidCanInit(void)
{
unsignedchartempMode;
unsignedchartemp7=0;
unsignedchartemp8=0;
tempMode=0x01; //复位模式
tempMode|=0x08; //设置CAN为单滤波,选择单个验收滤波器(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(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(SJA_IER,0x01); //中断允许打开接收中断使能
WR_SJA(SJA_OCR,0x0da); //输出控制驱动上拉正常输出模式
WR_SJA(SJA_MOD,tempMode&0xFE);//模式寄存器退出复位模式
}
/******************************************************************************************************************************************************
*函数名:
voidcan_rx_isr(void)interrupt0
*功能描述:
sja1000CAN接收中断函数
*函数说明:
在响应接收中断的时候,完成数据的接收。
问题是现在sja的数据根本读不出来RD_SJA()函数问题。
*调用函数:
NONE
*全局变量:
NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/
voidcan_rx_isr(void)interrupt0 //sja1000CAN接收中断
{
unsignedchark=0;
unsignedcharsja_addr;
EA=0;
/***!
!
!
RD_SJA(SJA_IR)读出来的值为0xff,所以也可以通过进入读环节。
****************************/ //关CPU中断
if((RD_SJA(SJA_IR)&0x01)==0x01) //IR中断寄存器,当接收FIFO不空和接收中断使能时置位此位
{
sja_addr=SJA_EFF; //register17.datastartaddress
if(CanRxAddr==MaxLenCanRxBuf)//unsignedintidataMaxLenCanRxBuf=440.
CanRxAddr=0;
for(k=0;k<11;k++) //完成11位标准帧数据的接收过程。
{
CanRxBuf[CanRxAddr+k]=RD_SJA(sja_addr);
sja_addr++;
}
WR_SJA(SJA_CMR,0x04); //释放接收缓冲区
CanRxAddr+=11;
CanRxcompleteFlag+=1; //接收完一次完整的数据报文以后该标志位加1.
}
EA=1;//打开CPU中断
}
/******************************************************************************************************************************************************
*函数名:
CanSend(unsignedchar*bufDATA,unsignedchardatalen)
*功能描述:
Can设备数据发送函数
*函数说明:
*调用函数:
NONE
*全局变量:
NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/
voidCanSend(unsignedchar*bufDATA,unsignedchardatalen)
{
unsignedintsja_addr;
unsignedcharj=0;
unsignedchartemp; //局部变量
unsignedintn;
//CanLedFlag=1;
sja_addr=SJA_EFF; //取SJA的ID号的首地址地址,ID0的地址。
SendBufInfo=datalen; //填入数据长度信息
WR_SJA(sja_addr++,SendBufInfo); //以标准帧发送消息
for(j=0;j<2;j++)
WR_SJA(sja_addr+j,*(SendBufId+j));//发送两字节的id信息。
for(j=0;j WR_SJA(sja_addr+2+j,*(bufDATA+j));//发送data区数据。
WR_SJA(SJA_CMR,0x03); //打开发送请求位与终止发送位,Send正常发送
for(n=0;n{
temp=RD_SJA(SJA_SR); //读取状态寄存器SR.3--TCS发送完毕状态1(完毕)
if((temp&0x08)==0x08) //发送完毕
{
for(n=0;n<300;n++); //延时
break;
}
}
}
/******************************************************************************************************************************************************
*函数名:
WR_SJA(unsignedcharsja_addr,unsignedcharsja_data)
*功能描述:
完成先准备相应sja_addr地址,再在相应的sja_addr地址操作送sja_data数据的 过程
*函数说明:
通过ALE切换地址与数据位的操作
*调用函数:
NONE
*全局变量:
NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/
voidWR_SJA(unsignedcharsja_addr,unsignedcharsja_data)
{
ALE_CAN=1;//置高开启地址锁存允许,将io口的地址数据锁存。
P1=sja_addr;
delay2(3);
ALE_CAN=0;//置低关闭地址锁存允许,改为发送数据有效。
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(unsignedcharsja_addr)
*功能描述:
完成先准备相应sja_addr地址,再将该地址的数据读出到sja_data的过程
*函数说明:
通过ALE,RD,CS的配合控制完成
*调用函数:
NONE
*全局变量:
NONE
*输入:
*返回:
*设计者:
******************************************************************************************************************************************************/
/*unsignedcharRD_SJA(unsignedcharsja_addr)
{
unsignedcharsja_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;
/***********************************************************
returnsja_data;
}*/
unsignedcharRD_SJA(unsignedcharsja_addr)
{
unsignedcharsja_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