CAN总线SJA1000测试程序
//********************************************************************
 //SJA1000测试程序
//在8位单片机P89LPC922上测试通过
//串口转CAN:内部时钟7.373MHz,串口115200,can口20k
 //协议:1、8位数据为1帧,是数据转发,双向
// 2、DB,01,目的地址,XX,XX,XX,0D,0A 改目的地址
// 3、DB,02,验收码 ,XX,XX,XX,0D,0A 改验收码
// 4、DB,03,验收屏蔽,XX,XX,XX,0D,0A 改验收屏蔽
// 5、DB,04,BTR0,BTR1,XX,XX,0D,0A 改波特率
//编写日期:2010.06.18
 //********************************************************************
#include<reg932.h> //单片机头文件
#include"sja.h"
unsigned char RBuf[8]; //接收区
unsigned char CBuf[8]; //发送区
unsigned char CL; //计数
unsigned char num; //
 unsigned char Inp; //串口接收计数
unsigned char Num2; //串口延时计数
bit Fir=0; //数据头标志,1-头
unsigned char ACN=0x00; //验收码
unsigned char AMN=0x00; //验收屏蔽
unsigned char TBN=0x00; //目标地址
unsigned char BTR0N=0x4E; //波特率,20k
 unsigned char BTR1N=0x2F;
 //--------------------------------------------------------------------
 //io_init:初始化IO子程序
//--------------------------------------------------------------------
void io_init(void)
 {
 P0M1=0x00; //P0准双向
P0M2=0x00;
 P1M1=0x00; //P1准双向
P1M2=0x00;
 P3M1=0x00; //P3准双向
P3M2=0x00;
 }
//-------------------------------------------------------------------
 //TIMER_init:初始化定时器
//-------------------------------------------------------------------
void TIMER_init(void)
 {
 TMOD=0x11; //定时器0和1配置为模式1
 TAMOD=0x00; 
 // ET0=1; //允许定时器0中断
 TH1=0xB7; //5ms,根据波特率和单片机计算出
TL1=0xFF; 
  ET1=1; //允许定时器1中断
 TR1=1; //打开定时器1
 }
//--------------------------------------------------
 //UART_init:初始化UART
 //--------------------------------------------------
 void UART_init(void)
 {
 SCON=0x50; //串口模式1,接收使能
SSTAT=0x00; //组合中断使能,停止位产生中断
BRGCON=0x00; //关闭BRG 
 BRGR0=0x30; //设置波特率为115200
 BRGR1=0x00; 
 BRGCON=0x03; //允许BRG
 ES=1; //允许串口中断
}
//------------------------------------------------------------------
//main:主函数
//------------------------------------------------------------------
void main(void)
 {
 io_init(); //端口初始化
TIMER_init(); //定时器0初始化
UART_init();
 SJA_init(ACN,AMN,BTR0N,BTR1N);
IT1=1; //外部中断1下降沿有效
EX1=1; //外部中断1有效
IP0H=0x16; //定时器0中断和外部中断1优先级设高3
 IP0=0x0E; //通信中断优先级设高2
 IP1H=0; //定时器1中断优先级设高1
 IP1=0; //键盘中断优先级设高0
EA=1;
 while(1); //
 }
 //-------------------------------------------------------------------
 //Timer1Int:定时中断子程序,通信间隔判断,5ms
 //-------------------------------------------------------------------
 void Timer1Int(void) interrupt 3
 { 
  TH1=0xB7; //5ms,根据波特率和单片机计算出
TL1=0xFF; 
 Num2++; //超时计数
if(Num2>4)Fir=0;
 }
//-------------------------------------------------------------------
 //ComInt:通信中断子程序,接收串口数据,发送到CAN口
//-------------------------------------------------------------------
void ComInt() interrupt 4
 {
 unsigned char IND; //临时量
unsigned char i; //循环量
if(RI) //有输入数据,执行以下程序,发送中断不响应
{ 
 IND=SBUF; //读入数据
RI=0;
 Num2=0;
 if(!Fir) 
 { 
  Fir=1; //新数据
 Inp=0; //清零
 RBuf[Inp]=IND;
 }
 else 
 { //数据
 Inp++; //数据位置加1 
  RBuf[Inp]=IND; //保存数据
 if(Inp==7) 
  {
  Fir=0; //8位数据
 if(RBuf[0]==0xDB&&RBuf[6]==0x0D&&RBuf[7]==0x0A) //命令处理
 {
  if(RBuf[1]==0x01) TBN=RBuf[2]; //改目的地址
 if(RBuf[1]==0x02) ACN=RBuf[2]; //改验收码
 if(RBuf[1]==0x03) AMN=RBuf[2]; //改验收屏蔽
 if(RBuf[1]==0x04) //改波特率
 {
  BTR0N=RBuf[2]; 
  BTR1N=RBuf[3]; 
  }
  SJA_init(ACN,AMN,BTR0N,BTR1N); //重新初始化
 }
  else //发送数据
 {
  SJA_write(TransBuffer1,TBN); //目的地址
 SJA_write(TransBuffer2,0x08); 
  for(i=0;i<8;i++) //写发送缓冲区
 {
  SJA_write(TransBuffer3+i,RBuf[i]);
  }
  SJA_write(CMR,0x01); //发送
 }
  }
 }
 }
}
 //-------------------------------------------------------------------
 //Int1Int:外部中断子程序,接收CAN总线数据并发送到串口
//-------------------------------------------------------------------
void Int1Int(void) interrupt 2
 { 
 unsigned char tmp; //临时量
tmp=SJA_read(IR); //读中断寄存器
tmp&=0x01;
 if(tmp==0x01) //判断是接收中断
{
 for(tmp=0;tmp<8;tmp++) 
 {
  CBuf[tmp]=SJA_read(RxBuffer3+tmp); //读缓冲器数据
 SBUF = CBuf[tmp]; //发送数据到串口
 while(TI==0);
  TI = 0;
 }
 SJA_write(CMR,0x04); //清缓冲器,等下次数据来 
 }
 }
/*CAN 总线SJA1000寄存器地址定义(用的是PeliCAN 模式,扩展帧EFF 模式)*/
#include<reg932.h> //单片机头文件
#include"sja.h" //
//-----------------------------------------------------------------
 //SJA1000读
//参数:寄存器地址addr
 //返回:读取到数据
//-----------------------------------------------------------------
unsigned char SJA_read(unsigned char addr)
 {
 unsigned char dat;
 ALE=1;
 P0=addr;
 ALE=0;
 P0=0xFF;
 CS=0;
 RD=0;
 dat=P0;
 RD=1;
 CS=1;
 return dat;
 }
//-----------------------------------------------------------------
 //SJA1000写
//参数:寄存器地址addr,待写入数据dat
 //返回:无
//-----------------------------------------------------------------
void SJA_write(unsigned char addr,unsigned char dat)
 {
 ALE=1;
 P0=addr;
 ALE=0;
 CS=0;
 WR=0;
 P0=dat;
 WR=1;
 CS=1;
 }
//-----------------------------------------------------------------
 //SJA1000初始化
//参数:验收代码AC,验收屏蔽AM,波特率参数BTO\BT1
 //返回:无
//-----------------------------------------------------------------
void SJA_init(unsigned char AC,unsigned char AM,unsigned char BT0,unsigned char BT1)
 {
 unsigned int i;
 unsigned char c;
 RESET=0;
 ALE=0;
 WR=1;
 RD=1;
 CS=1;
 INT=1;
 for(i=0;i<8000;i++);
 RESET=1;
SJA_write(CDR,0x40); //时钟分频寄存器,默认0x40(BasicCAN) PeliCAN 模式0xC0
 c=SJA_read(IR); //中断寄存器
SJA_write(CR,0x61); //进入复位模式
SJA_write(OCR,0xFA); //输出控制寄存器,默认0xfa
 SJA_write(BTR0,BT0); //波特率设置 20kHz
 SJA_write(BTR1,BT1); //BTRO=0x0E,SJW=1,BTR1=0x2F,SAM=0单倍
SJA_write(ACR,AC); //验收代码寄存器
SJA_write(AMR,AM); //验收屏蔽寄存器
SJA_write(CR,0x06); //进入工作模式,使能发送、接收中断
}
//SJA1000测试,BasicCAN模式
//模拟时序选intel模式
//sja.h
 #ifndef __SJA_H__
 #define __SJA_H__
#define CR 0x00 // 控制寄存器地址
#define CMR 0x01 // 命令寄存器地址
#define SR 0x02 // 状态寄存器地址
#define IR 0x03 // 中断寄存器地址
#define ACR 0x04 // 验收码寄存器地址
#define AMR 0x05 // 验收屏蔽寄存器地址
#define BTR0 0x06 // 总线定时寄存器0地址
#define BTR1 0x07 // 总线定时寄存器1地址
#define OCR 0x08 // 输出控制寄存器地址
#define TR 0x09 // 测试寄存器地址
#define TransBuffer1 0x0a // 发送缓冲器
#define TransBuffer2 0x0b
 #define TransBuffer3 0x0c
 #define TransBuffer4 0x0d
 #define TransBuffer5 0x0e
 #define TransBuffer6 0x0f
 #define TransBuffer7 0x10
 #define TransBuffer8 0x11
 #define TransBuffer9 0x12
 #define TransBuffer10 0x13
#define RxBuffer1 0x14 // 接收缓冲器
#define RxBuffer2 0x15
 #define RxBuffer3 0x16
 #define RxBuffer4 0x17
 #define RxBuffer5 0x18
 #define RxBuffer6 0x19
 #define RxBuffer7 0x1a
 #define RxBuffer8 0x1b
 #define RxBuffer9 0x1c
 #define RxBuffer10 0x1d
#define CDR 0x1f // 时钟频分寄存器
//管脚定义:PO数据
sbit RESET=P1^3; //复位
sbit INT=P1^4; //中断
sbit ALE=P3^0; //写地址使能
sbit RD=P1^6; //写数据
sbit WR=P1^7; //读数据
sbit CS=P3^1; //片选
unsigned char SJA_read(unsigned char addr); //SJA读
void SJA_write(unsigned char addr,unsigned char dat); //SJA写
void SJA_init(unsigned char AC,unsigned char AM,unsigned char BT0,unsigned char BT1); //SJA初始化
#endif