独立CAN芯片SJA1000的读写函数问题?
#define startadd 0x7F00 //SJA1000的首地址unsigned char read_sja(unsigned char addr) //读SJA1000状态寄存器子程序
{
unsigned char *sja_address = (unsigned char *)startadd;
sja_address = sja_address + addr;
return (*(sja_address));
}
void write_sja(unsigned char addr,unsigned char val) //写SJA1000控制寄存器子程序
{
unsigned char *sja_address = (unsigned char *)startadd;
sja_address = sja_address + addr;
*(sja_address) = val;
}
读写程序如上,原理图如下。 http://cache.amobbs.com/bbs_upload782111/files_23/ourdev_511797.jpg
(原文件名:243543656.jpg)
我是用ATMEGA128硬件访问的,AD接PA。外部存储器使能是对的,就是在初始化SJA1000时,程序停在while()循环内。 请路过的高手帮忙回答一下,谢谢!!!!!!!! 先这样定义好寄存器的地址
#define CAN_MOD (*(volatile unsigned char *)0xfb00) //模式寄存器
#define CAN_CMR (*(volatile unsigned char *)0xfb01) //命令寄存器 只写
#define CAN_SR (*(volatile unsigned char *)0xfb02) //状态寄存器 只读
#define CAN_IR (*(volatile unsigned char *)0xfb03) //中断寄存器 只读
#define CAN_IER (*(volatile unsigned char *)0xfb04) //中断使能寄存器
#define CAN_BTR0 (*(volatile unsigned char *)0xfb06) //总线定时寄存器0
#define CAN_BTR1 (*(volatile unsigned char *)0xfb07) //总线定时寄存器1
那么对它们的读写这样就可以了。
CAN_MOD=0x01;
CAN_CDR=0xc8; //配置时钟分频寄存器-Pelican,CBP=1,
//关闭TX1中断与时钟输出
CAN_AMR0=0xff; //配置验收屏蔽AMR0=0FFH
CAN_AMR1=0xff; //配置验收屏蔽AMR1=000H
CAN_AMR2=0xff; //配置验收屏蔽AMR2=0FFH
CAN_AMR3=0xff; //配置验收屏蔽AMR3=000H
CAN_ACR1=0x00; //配置验收代码ACR1=0:广播
CAN_ACR3=0x00; //配置验收代码ACR3=地址 =0 老大,你要写程序模拟intel时序吧,RD WR ALE你怎么没控制啊
好有楼上的方法是用51控制 的方法吧 LZ仔细研究下,把程序发上来参考参考啊 /*******************************************************************************功能说明: 计算SJA1000在电路中的实际地址:基址+内部寄存器地址
其它说明: 以下的定义为SJA1000的内部寄存器的地址,不可修改
各寄存器的具体功能清参阅sja1000的数据手册
*******************************************************************************/
#define startadd 0x7F00 //SJA1000的首地址
// 控制寄存器
#define MODE 0x00 //内部控制寄存器
#define CMR 0x01 //命令寄存器
#define SR 0x02 //状态寄存器
#define IR 0x03 //中断寄存器
#define IER 0x04 //中断使能寄存器
#define BTR0 0x06 //总线定时寄存器0
#define BTR1 0x07 //总线定时寄存器1
#define OCR 0x08 //输出控制寄存器
#define TEST 0x09 //测试寄存器
#define RESVER1 0x0A //保留1
#define ALC 0x0B //仲裁丢失捕捉
#define ECC 0x0C //错误代码捕捉
#define EWLR 0x0D //错误报警限额
#define RXERR 0x0E //接收错误计数器
#define TXERR 0x0F //发送错误计数器
#define ACR0 0x10 //验收代码寄存器
#define ACR1 0x11 //验收代码寄存器
#define ACR2 0x12 //验收代码寄存器
#define ACR3 0x13 //验收代码寄存器
#define AMR0 0x14 //验收屏蔽寄存器
#define AMR1 0x15 //验收屏蔽寄存器
#define AMR2 0x16 //验收屏蔽寄存器
#define AMR3 0x17 //验收屏蔽寄存器
// 发送缓冲区寄存器
#define TXD_FID 0x10 //发送缓冲区1
#define TXD_ID1 0x11 //发送缓冲区2
#define TXD_ID2 0x12 //发送缓冲区3
#define TXD_ID3 0x13 //发送缓冲区4
#define TXD_ID4 0x14 //发送缓冲区5
#define TXBuffer1 0x15 //发送缓冲区6
#define TXBuffer2 0x16 //发送缓冲区7
#define TXBuffer3 0x17 //发送缓冲区8
#define TXBuffer4 0x18 //发送缓冲区9
#define TXBuffer5 0x19 //发送缓冲区10
#define TXBuffer6 0x1A //发送缓冲区11
#define TXBuffer7 0x1B //发送缓冲区12
#define TXBuffer8 0x1C //发送缓冲区13
// 接收缓冲区寄存器
#define RXD_FID 0x10 //接收缓冲区1
#define RXD_ID1 0x11 //接收缓冲区2
#define RXD_ID2 0x12 //接收缓冲区3
#define RXD_ID3 0x13 //接收缓冲区4
#define RXD_ID4 0x14 //接收缓冲区5
#define RXBuffer1 0x15 //接收缓冲区6
#define RXBuffer2 0x16 //接收缓冲区7
#define RXBuffer3 0x17 //接收缓冲区8
#define RXBuffer4 0x18 //接收缓冲区9
#define RXBuffer5 0x19 //接收缓冲区10
#define RXBuffer6 0x1A //接收缓冲区11
#define RXBuffer7 0x1B //接收缓冲区12
#define RXBuffer8 0x1C //接收缓冲区13
#define RMC 0x1D //RX报文计数器
#define RBSA 0x1E //接收缓冲区起始地址
#define CDR 0x1F //时钟分频寄存器
/*******************************************************************************
功能说明: 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 0x80 //400KBPS的预设值
#define BTR1_Rate_400k 0xfa //400KBPS的预设值
#define BTR0_Rate_500k 0x00 //500KBPS的预设值
#define BTR1_Rate_500k 0x1c //500KBPS的预设值
#define BTR0_Rate_666k 0x80 //666KBPS的预设值
#define BTR1_Rate_666k 0xb6 //666KBPS的预设值
#define BTR0_Rate_800k 0x00 //800KBPS的预设值
#define BTR1_Rate_800k 0x16 //800KBPS的预设值
#define BTR0_Rate_1000k 0x00 //1000KBPS的预设值
#define BTR1_Rate_1000k 0x14 //1000KBPS的预设值
/*******************************************************************************
功能说明: 定义系统参数
其它说明: 无
*******************************************************************************/
// 本地的IP地址
#define Local_IP1 1 // IP地址最高位
#define Local_IP2 2
#define Local_IP3 3
#define Local_IP4 4 // IP地址最低位
// 本地的CAN标识
#define REG_ACR1_FIDLocal_IP4 // 滤波器的标识符最高位
#define REG_ACR2_FIDLocal_IP3
#define REG_ACR3_FIDLocal_IP2
#define REG_ACR4_FIDLocal_IP1 // 滤波器的标识符最低位
#define REG_AMR1_FID0x00 // 滤波器的屏蔽符最高位
#define REG_AMR2_FID0x00
#define REG_AMR3_FID0x03
#define REG_AMR4_FID0x07 // 滤波器的屏蔽符最低位
// 发往目标CAN标识
#define SEND_ACR1_FID Local_IP4 // 滤波器的最高位
#define SEND_ACR2_FID Local_IP3
#define SEND_ACR3_FID Local_IP2
#define SEND_ACR4_FID Local_IP1 // 滤波器的最低位
// 模式参数
#define REG_MODE_DATA 0x0C // 模式控制器: 单滤波器、自检测模式
#define REG_TEST_DATA 0xAA // 测试值
#define REG_CDR_DATA 0x88 // 时分控制的值: PeilCAN模式、CLOCK无效
#define REG_INTENABLE_DATA 0x83 // 中断使能控制的值: 总线错误中断、发送中断、接收中断
#define REG_OCR_DATA 0x1A // 输出控制的值:
// 定义命令字
#define TXD_ONE_CMD 0x03 // 产生一次报文发送,当错误时不再生发(单次发送)
#define TXD_CMD 0x01 // 发送请求命令,当错误时可重发
#define T_R_CMD 0x12 // 产生一次自接收性质的报文发送,发送错误时不会重发
#define AT_CMD 0x02 // 中止发送命令
#define RRB_CMD 0x04 // 释放接收缓冲区
#define COS_CMD 0x08 // 数据溢出清除命令
unsigned char TransBuffer;
unsigned char RxBuffer[];
unsigned char *sja_address=(unsigned char *)startadd;
unsigned char read_sja(unsigned char addr) //读SJA1000状态寄存器子程序
{
sja_address=(unsigned char *)startadd;
sja_address=sja_address+addr;
return (*(sja_address));
}
void write_sja(unsigned char addr,unsigned char val) //写SJA1000控制寄存器子程序
{
sja_address=(unsigned char *)startadd;
sja_address=sja_address+addr;
*(sja_address)=val;
}
void SJA1000_init(void)
{
//CLI();
write_sja(MODE,0x01);
read_sja(IR); //读取CAN的中断标识
while(!(read_sja(MODE)&0x01)) //检测SJA1000是否达到复位工作模式
{
write_sja(MODE,0x01); //进入复位工作模式
}
delay_us(5); //延时约5us
write_sja(CDR,0xC8); //PeliCAN 模式,禁能CLOCKOUT引脚
delay_us(5); //延时约5us
write_sja(BTR0,0x53); //设置时钟分频器,20k
write_sja(BTR1,0x2F);
write_sja(OCR,0x1a); //输出控制
write_sja(RXERR,0x00);
write_sja(TXERR,0x00);
write_sja(ECC,0x00);
write_sja(RBSA,0x00); //缓存器起始地址寄存器设置为0
write_sja(ACR0,0x00); //acceptcode default ffffffff
write_sja(ACR1,0x00);
write_sja(ACR2,0x00);
write_sja(ACR3,0x00); //配置验收代码ACR3地址
write_sja(AMR0,0xff); //acceptmask default ffffffff
write_sja(AMR1,0xff);
write_sja(AMR2,0xff);
write_sja(AMR3,0xff);
write_sja(IER,0x01); //接收中断使能
write_sja(CMR,0x0c); //清除数据溢出和释放接收缓冲器;
do
{
write_sja(MODE,0x00); //设置SJA1000工作模式,双滤波接收工作模式
}
while((read_sja(MODE)&0x01)); //确认复位标志是否被删除
//SEI();
}
void CanTransmit(void)
{
unsigned char status;
CLI(); //关中断
TransBuffer=0x88;
TransBuffer=0x00;
TransBuffer=0x00;
TransBuffer=0x00;
TransBuffer=0x00;
TransBuffer=0x01;
TransBuffer=0x02;
TransBuffer=0x03;
TransBuffer=0x04;
TransBuffer=0x05;
TransBuffer=0x06;
TransBuffer=0x07;
TransBuffer=0xaa;
while(!(read_sja(SR)&0x04)); //wait until reg2^2==1 ,即判断发送缓冲器的状态
write_sja(TXD_FID,TransBuffer); //扩展帧,数据长度为8个字节
write_sja(TXD_ID1,TransBuffer);
write_sja(TXD_ID2,TransBuffer);
write_sja(TXD_ID3,TransBuffer);
write_sja(TXD_ID4,TransBuffer);
write_sja(TXBuffer1,TransBuffer);
write_sja(TXBuffer2,TransBuffer);
write_sja(TXBuffer3,TransBuffer);
write_sja(TXBuffer4,TransBuffer);
write_sja(TXBuffer5,TransBuffer);
write_sja(TXBuffer6,TransBuffer);
write_sja(TXBuffer7,TransBuffer);
write_sja(TXBuffer8,TransBuffer);
write_sja(CMR,0x01); //发送请求命令
while(!(read_sja(SR) & 0x08));//检测SR.3位,判断发送是否完成
SEI(); //开中断
}
unsigned char Receive(void)
{
unsigned char result=0;
unsigned char status,number,sff,j;
unsigned char mp=RXD_FID;
status=read_sja(SR);
if((status&0xc3)!=0) //读取总线脱离、错误状态、接收溢出、有数据等位
{
if((status&0x80)==0x80)
{
write_sja(MODE,0x00);
return 0;
}
if((status&0x02)==0x02)
{
write_sja(CMR,0x0c);
return 0;
}
if((status&0x01)==0x01)
{
if((read_sja(RXD_FID)&0x40)==0x40)//如果RTR=1,为远程帧
{
write_sja(CMR,0x04); //则释放FXFIFO
}
else //为0,则是数据帧
{
sff=read_sja(RXD_FID)&0x80; //取第一个字节的最高位
number=(read_sja(RXD_FID)&0x0f);//取第一个字节的低四位,即数据长度
if ((sff&0x80)==0x80) //判断是标准帧还是扩展帧
number=number+5; //扩展帧,则帧的总长度加5(13字节)
else
number=number+3; //标准帧,则帧的总长度加3(11字节)
for(j=0;j<number;j++) //读取数据
{
RxBuffer=read_sja(RXD_FID);
mp++;
}
result=1; //读取到正确的数据则返回TRUE
write_sja(CMR,0x04); //最后释放FXFIFO
}
}
}
return result;
}
以上是“SJA1000.h”部分 基本上是修改这个帖子的程序。“http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=598348&bbs_page_no=1&search_mode=1&search_text=CAN调试成功,特上传资料与大家共享&bbs_id=1000”
下面是我整个的程序:
点击此处下载 ourdev_512166.rar(文件大小:42K) (原文件名:SJA1000.rar) 问题出现在SJA1000初始化子函数“void SJA1000_init(void) ”中的while查询语句:
while(!(read_sja(MODE)&0x01)) //检测SJA1000是否达到复位工作模式
{
write_sja(MODE,0x01); //进入复位工作模式
}
这句话始终为真!请各位大侠帮忙看看哈,谢谢!! 大侠,知道的加我QQ:752791687 不能进入复位模式,
1.检查SJA1000的时钟,CLKOUT 有脉冲输出不?有时候换换晶振就好了。
2.CPU与SJA1000的连接线是否正常,遇到过cpu的数据线因为焊接原因,导致数据一直不正常;
3.读写SJA1000的寄存器,参考3楼的写法就行,和51的一样,前提:开M128的总线; while(!(read_sja(MODE)&0x01)) //检测SJA1000是否达到复位工作模式
MODE的zui低位为1的时候,进入了复位模式。。((read_sja(MODE)&0x01))为1.
取反后为假,退出while语句,
正确啊,
还有问一下,你的自收发实验成功没?能否正确读出sja1000寄存器的值? 【回复】: erxun 老孟
老孟大侠,请您看一下我上面的原理图是否有错?缺少16M晶振,我已经加上了。现在,我怀疑我的硬件有误!请您指点…… mark mark 好东西 楼主的现在好了没有? 感谢楼主分享啊,对我这初学者用处很大
页:
[1]