82C250
基于CAN总线的分布式控制系统
sja1000与m128 的连接方式 可按外扩RAM 操作方式即可
SJA1000是作为外部RAM扩展来使用的
AD0-AD7是地址/数据复用总线(其他端口也可以用模拟的写)。先补一下外部扩展RAM的知识,然后再谈这个电路就容易多了:51单片机外部RAM的扩展最多是可以寻址64KB的,也就是最多可以有16条地址线来寻址,P0口是低八位地址扩展口,P2口是高八位地址扩展口。如果外部RAM不需要用到全部16条地址线(SJA1000就只有8条地址线),那么只要把低位地址线和外部RAM的相应地址线连接,高位的地址线在寻址时都默认为1,比如这里的SJA1000,它的8条地址线是和P0口相连接的,所以对SJA1000的寄存器寻址时的地址应该是FF00H-FFFFH,但是为什么PIAE提供的程序里的地址定义却是FE00H-FEFFH呢?这就要讨论CS信号的连接问题了,我们知道,CS是片选输入信号,只有当它是低电平时才能访问SJA1000。再看看它和谁连了?是P2.0口,正好是地址线高八位的最低位,如果按常理来说,寻址FF00H,那么P2.0就是高电平,SJA1000就不能被访问。所以寻址FE00H时才选通SJA1000,这时才是SJA1000寄存器的地址。
M128可以只用低8位,高八位地址口做普通端口用。
还有,SJA1000的内部寄存器的地址,作用,名称等等。资料书籍都很多的很好找。如果需要对SJA1000有详细的了解,可参阅周立功翻译过的SJA1000中文说明和sja1000应用指南。都是很好很强大的必备资料。
在对SJA1000有了基本的了解之后,接下来就是编程啦。网上的程序实在太多,各种稀奇古怪的功能也加了不少,调试时最需要的是一个只有最基本的功能的程序,不要什么指示灯,什么按键……那么,就按着自己的需求,写PeliCAN吧,可以作为SJA1000的驱动使用哦~(rr的说,其实是根据一个不知道什么时候存在电脑里的程序改的,不过那个源程序实在是漏洞百出,我花了很大的功夫修改,所以,只好感谢无名原作者,顺致痛恨之意)
顺大便说一下注意事项,需要注意的是公共寄存器的配置(即CDR,BTR和OCR)!大家调试时可以用模拟软件看看各个端口的变化时否正确(最易发现问题了)
给一个初始化的一段程序:
#define SJA1000_BASE 0x00//7f00
#define MOD SJA1000_BASE + 0x00
#define CMR SJA1000_BASE + 0x01
#define SR SJA1000_BASE + 0x02
#define IR SJA1000_BASE + 0x03
#define IER SJA1000_BASE + 0x04
#define BTR0 SJA1000_BASE + 0x06
#define BTR1 SJA1000_BASE + 0x07
#define OCR SJA1000_BASE + 0x08
#define ECC SJA1000_BASE + 0x0C //错误代码捕捉寄存器
#define EWLR SJA1000_BASE + 0x0D
#define RXERR SJA1000_BASE + 0x0E
#define TXERR SJA1000_BASE + 0x000F
#define ACR0 SJA1000_BASE + 0x10
#define ACR1 SJA1000_BASE + 0x11
#define ACR2 SJA1000_BASE + 0x12
#define ACR3 SJA1000_BASE + 0x13
#define ACM0 SJA1000_BASE + 0x14
#define ACM1 SJA1000_BASE + 0x15
#define ACM2 SJA1000_BASE + 0x16
#define ACM3 SJA1000_BASE + 0x17
#define CDR SJA1000_BASE + 0x1F
#define TXF SJA1000_BASE + 0x10
#define TXI1 SJA1000_BASE + 0x11
#define TXI2 SJA1000_BASE + 0x12
#define TXI3 SJA1000_BASE + 0x13
#define TXI4 SJA1000_BASE + 0x14
#define TXD1 SJA1000_BASE + 0x15
#define TXD2 SJA1000_BASE + 0x16
#define TXD3 SJA1000_BASE + 0x17
#define TXD4 SJA1000_BASE + 0x18
#define TXD5 SJA1000_BASE + 0x19
#define TXD6 SJA1000_BASE + 0x1A
#define TXD7 SJA1000_BASE + 0x1B
#define TXD8 SJA1000_BASE + 0x1C
#define RXF SJA1000_BASE + 0x10
#define RXI1 SJA1000_BASE + 0x11
#define RXI2 SJA1000_BASE + 0x12
#define RXI3 SJA1000_BASE + 0x13
#define RXI4 SJA1000_BASE + 0x14
#define RXD1 SJA1000_BASE + 0x15
#define RXD2 SJA1000_BASE + 0x16
#define RXD3 SJA1000_BASE + 0x17
#define RXD4 SJA1000_BASE + 0x18
#define RXD5 SJA1000_BASE + 0x19
#define RXD6 SJA1000_BASE + 0x1A
#define RXD7 SJA1000_BASE + 0x1B
#define RXD8 SJA1000_BASE + 0x1C
#define BSA SJA1000_BASE + 0x1E
。
。
。
。
。
。
。
。
void CAN_init(void)
{
int data,k ;
CLI();
Write_SJA1000(MOD,0x09);
Read_SJA1000(IR); //读取CAN的中断标识
while(!(Read_SJA1000(MOD)&0x01)) //检测SJA1000是否达到复位工作模式
{
Write_SJA1000(MOD,0x01); //进入复位工作模式
}
for(k=0;k<6;k++); //延时约5us
Write_SJA1000(CDR,0x88); //PeliCAN 模式,禁能CLOCKOUT引脚C8
for(k=0;k<6;k++); //延时约5us
Write_SJA1000(BTR0,0x31); // 09 53 //设置时钟分频器,50kff
Write_SJA1000(BTR1,0x1c); //1c00 2f
Write_SJA1000(OCR,0x1a ); // 0x0a //输出控制????????????(0x1a)????????????///??????????????????????????????????aa
Write_SJA1000(RXERR,0x00);
Write_SJA1000(TXERR,0x00);
Write_SJA1000(ECC,0x00);/
Write_SJA1000(BSA,0x00); //缓存器起始地址寄存器设置为0
Write_SJA1000(ACR0,0x11); //acceptcode default ffffffff
Write_SJA1000(ACR1,0x22);
Write_SJA1000(ACR2,0x33);
Write_SJA1000(ACR3,0x44); ///(0x01)Write_SJA1000
Write_SJA1000(ACM0,0x00); //acceptmask default ffffffff
Write_SJA1000(ACM1,0xff);
Write_SJA1000(ACM2,0xff);
Write_SJA1000(ACM3,0xff);
Write_SJA1000(IR,0x03);//f
Write_SJA1000(BSA,0x00);
Write_SJA1000(IER,0x01); /// //开放接收中断()0x00
Write_SJA1000(CMR,0x0c); //清除数据溢出和释放接收缓冲器;()0x0c4
do
{
Write_SJA1000(MOD,0x08); //设置SJA1000 工作模式,单滤波接收工作模式
}
while((Read_SJA1000(MOD)&0x01)); //确认复位标志是否被删除
//write_sja(MOD,0x02);/
SEI();
}
绝对是对的!