我一个用的PCA82c200,一个用的SJA1000的,可是两个不能通信啊,下面贴出我的程序
#include <reg52.h>
#include <intrins.h>
#include <can_selfdef.h>
void INT0_Counter( void ) interrupt 0 using 1
{//INT0按键为计数按键
EA = 0;
Txd_data++; //存储计数结果,并为待发送的数据
TXD_flag = 1;//要发送数据标志位
EA = 1;
}
void CAN_TX( void ) interrupt 2
{//发送数据函数,在中断服务程序中调用
uchar data Judge;
EA = 0;//关CPU中断
IE1 = 0;
Rxd_data++;
Judge = IR;
if( Judge & 0x02)
{
CMR = 0X04;
}
CR = 0x04;// .1=1--发送中断使能;
EA = 1;//打开CPU中断
}
void main(void)
{
CPU_init( ); //CPU初始化
CAN_init( ); //SJA1000初始化,对 SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效
_nop_();
_nop_();
while(1)
{
_nop_();
_nop_();
Txd_deal();//发送处理程序
led_seg7(1,Txd_data);
led_seg7(3,Rxd_data);
}
}
//*********************CPU初始化函数********************************
void CPU_init(void)
{//初始化CPU
SJA_RST = 0;//CAN总线复位管脚有效
Delay( 20 );
SJA_RST = 1;//CAN总线复位管脚无效
SJA_CS = 0;//CAN总线片选有效
EX1 = 1;
IT1 = 0;//CAN总线接收中断
IT0 = 1;//外部中断0负边沿触发
EX0 = 1;//打开外部中断0
EA = 1; //打开总中断
SJA_CS = 1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。
}
void Txd_deal(void)
{//发送处理函数,主要是准备数据,并且调用发送函数
if( TXD_flag == 1 )
{
_nop_();
TXD_flag = 0;
TX_buffer[2] = Txd_data;//
CAN_TXD();
_nop_();
_nop_();
}
}
//*********************处理函数********************************
//*********************CAN子函数***********************
void CAN_init( void )
{//SJA1000 的初始化
uchar bdata Judge;
do
{// .0=1---reset MODRe,进入复位模式,以便设置相应的寄存器
//防止未进入复位模式,重复写入
CR = 0x05;
Judge = CR ;
}
while( !(Judge & 0x01) );
CDR = 0x04;// CDR.3=1--时钟关闭, .7=0---basic CAN, .7=1---Peli CAN
BTR0 = 0xcf;
BTR1 = 0xff;//总线波特率设定
OCR = 0xaa;// 配置输出控制寄存器
CMR = 0x04;//释放接收缓冲器
ACR = 0xaa;
AMR = 0xff;
do
{
CR = 0x04;
Judge = CR;
}
while( !(Judge & 0x04) );
}//SJA1000 的初始化
void CAN_TXD( void )
{
uchar data Judge;
uchar data TX_buffer[3];
//初始化标识符头信息
TX_buffer[0] = 0xab;//报文信息;.7=1扩展帧;.6=0数据帧; .3~0=1数据长度
TX_buffer[1] = 0x01;//报文标识符
//初始化标识符头信息
//初始化发送数据单元
TX_buffer[2] = Txd_data;
// Judge=IR ;
//初始化数据信息
EA = 0; //关中断
// do
// {
// Judge = SR;
// LED_RED = 0;//
// }
// while( Judge & 0x10 ); //SR.4=1 正在接收,等待
do//第二次发送不成功,死循环
{
Judge = SR;
LED_RED = 0;//
}
while(!(Judge & 0x08)); //SR.3=0,发送请求未处理完,等待
LED_GRE = !LED_GRE;
do
{
Judge = SR;
LED_RED = 0;//
}
while(!(Judge & 0x04)); //SR.2=0,发送缓冲器被锁。等待
LED_RED = !LED_RED;
NOP5;
NOP5;
LED_GRE = !LED_GRE;//灯闪烁
TBSR = TX_buffer[0];
TBSR1 = TX_buffer[1];
TBSR2 = TX_buffer[2];
//CR=0X04;
EA = 1;
CMR = 0x03;//
}
void Delay(uchar delay_time)
{//延时程序
while(delay_time--)
{}
}
//*********************CAN子函数*************************
//*********************显示子函数*************************
void led_seg7(uchar from,uchar number) //from(1_4):数码管显示起始位置(从右到左),number:显示的数(数码管上采用10进制显示)
{
uchar digit,temp_l;
uchar temp_h=0x7f;
temp_h = _cror_(temp_h,from-1); //确定从哪一位开始显示,即确定高四位
temp_h = temp_h & 0xf0; //取高四位
temp_l = P2 & 0x0f; //取P2的低四位
P2 = temp_h | temp_l; //设定P2口
if(number==0)
{
P0 = led[0];
Delay(10);
P0 = 0xff;
}
else
{
while(number)
{
digit = number%10 ;
number /= 10;
P0 = led[digit] ;
Delay(10);
temp_h = P2 & 0xf0; //取P2的高四位
temp_h = temp_h | 0x0f; //拼装 temp_h,进行位选
temp_h = _cror_(temp_h,1);
temp_h = temp_h & 0xf0; //取高四位
temp_l = P2 & 0x0f; //取P2的低四位
P0 = 0xff;
P2 = temp_h | temp_l; //设定P2口
}
}
}
上面是发送的
#include <reg52.h>
#include <intrins.h>
#include <can_selfdef.h>
void CAN_RXD( void ) interrupt 2
{//接收数据函数,在中断服务程序中调用
uchar data Judge;
EA = 0;//关CPU中断
IE1 = 0;
Rxd_data=2;
Judge = IR;
if( Judge & 0x01)
{//IR.0 = 1 接收中断
RXD_flag = 1;//置有接收标志
RX_buffer[5]=RBSR2;
//CMR = 0X04;
}
CR = 0x02;// .1=1--接受中断使能;
EA = 1;//打开CPU中断
}
void main(void)
{
CPU_init( ); //CPU初始化
CAN_init( ); //SJA1000初始化,对 SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效
_nop_();
_nop_();
while(1)
{
_nop_();
_nop_();
Rxd_deal();//接收处理程序
led_seg7(3,Rxd_data);
led_seg7(1,d);
}
}
//*********************CPU初始化函数********************************
void CPU_init(void)
{//初始化CPU
SJA_RST = 0;//CAN总线复位管脚有效
Delay( 20 );
SJA_RST = 1;//CAN总线复位管脚无效
SJA_CS = 0;//CAN总线片选有效
EX1 = 1;
IT1 = 0;//CAN总线接收中断
// IT0 = 1;//外部中断0负边沿触发
// EX0 = 1;//打开外部中断0
EA = 1; //打开总中断
SJA_CS = 1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。
}
void Rxd_deal(void)
{//////// 接收处理程序//////////////
if( RXD_flag )
{
EA = 0;//关闭CPU中断
RXD_flag = 0;
Rxd_data = RX_buffer[5];
EA = 1;
}
}//////// 接收处理程序//////////////
//*********************处理函数********************************
//*********************CAN子函数***********************
void CAN_init( void )
{//SJA1000 的初始化
uchar bdata Judge;
do
{
TEST = 0xAA;
Judge = TEST ;
}
while( !(Judge & 0xAA) );
d=4;
do
{// .0=1---reset MODRe,进入复位模式,以便设置相应的寄存器
//防止未进入复位模式,重复写入
CR = 0x01;
Judge = CR ;
}
while( !(Judge & 0x01) );
CDR = 0x04;// CDR.3=1--时钟关闭, .7=0---basic CAN, .7=1---Peli CAN
BTR0 = 0xcf;
BTR1 = 0xff;//总线波特率设定
OCR = 0xaa;// 配置输出控制寄存器
CMR = 0x04;//释放接收缓冲器
ACR = 0xab;
AMR = 0xff;
do
{
CR = 0x02;
Judge = CR;
}
while( !(Judge & 0x02) );
}//SJA1000 的初始化
void Delay(uchar delay_time)
{//延时程序
while(delay_time--)
{}
}
//*********************CAN子函数*************************
//*********************显示子函数*************************
void led_seg7(uchar from,uchar number) //from(1_4):数码管显示起始位置(从右到左),number:显示的数(数码管上采用10进制显示)
{
uchar digit,temp_l;
uchar temp_h=0x7f;
temp_h = _cror_(temp_h,from-1); //确定从哪一位开始显示,即确定高四位
temp_h = temp_h & 0xf0; //取高四位
temp_l = P2 & 0x0f; //取P2的低四位
P2 = temp_h | temp_l; //设定P2口
if(number==0)
{
P0 = led[0];
Delay(10);
P0 = 0xff;
}
else
{
while(number)
{
digit = number%10 ;
number /= 10;
P0 = led[digit] ;
Delay(10);
temp_h = P2 & 0xf0; //取P2的高四位
temp_h = temp_h | 0x0f; //拼装 temp_h,进行位选
temp_h = _cror_(temp_h,1);
temp_h = temp_h & 0xf0; //取高四位
temp_l = P2 & 0x0f; //取P2的低四位
P0 = 0xff;
P2 = temp_h | temp_l; //设定P2口
}
}
}
上面是接受的
两者共用一个头文件
# define uchar unsigned char
# define uint unsigned int
# define NOP5 {_nop_();_nop_();_nop_();_nop_();_nop_();}/*延时5us*/
#define N_can 10//一帧字节数
bit TXD_flag = 0;// 若为1,要求发送处理
bit RXD_flag = 0;
uint d;
uchar code led[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92, // 0, 1, 2, 3, 4, 5
0x82,0xf8,0x80,0x90, 0xff}; // 6, 7, 8, 9, off
//编码规则是gfedcba ,其中g为小数点,控制dp,这里都设为1,不亮
uchar RX_buffer[13]; //接收的数据
uchar TX_buffer[13]; //接收的数据
uchar Txd_data = 0;//CAN总线要发送的数据,也是要在数码管1-2位置显示的数据
uchar Rxd_data= 0;//CAN总线要接收的数据,也是要在数码管3-4位置显示的数据
/*P2 口分配*/
sbit LED_RED = P2^1;
sbit LED_GRE = P2^2;
sbit SJA_RST = P2^3;//SJA1000复位管脚
sbit SJA_CS = P2^0;//SJA1000片选管脚
/*CAN总线SJA1000寄存器地址定义(用的是PeliCAN模式,扩展帧EFF模式)*/
#define CR (*(unsigned char volatile xdata *)0xFE00) // 控制寄存器
#define CMR (*(unsigned char volatile xdata *)0xFE01) // 命令寄存器
#define SR (*(unsigned char volatile xdata *)0xFE02) // 状态寄存器
#define IR (*(unsigned char volatile xdata *)0xFE03) // 中断寄存器
#define ACR (*(unsigned char volatile xdata *)0xFE04) // 验收代码
#define AMR (*(unsigned char volatile xdata *)0xFE05) // 验收屏蔽
#define BTR0 (*(unsigned char volatile xdata *)0xFE06) // 总线定时寄存器0 ;总线波特率的选择
#define BTR1 (*(unsigned char volatile xdata *)0xFE07) // 总线定时寄存器1 ;总线波特率的选择
#define OCR (*(unsigned char volatile xdata *)0xFE08) // 输出控制寄存器
#define TEST (*(unsigned char volatile xdata *)0xFE09)
#define CDR (*(unsigned char volatile xdata *)0xFE1F) // 时钟分频
#define TBSR (*(unsigned char volatile xdata *)0xFE0A) //发送缓冲器地址(0x0A_0x13)
#define TBSR1 (*(unsigned char volatile xdata *)0xFE0B) //
#define TBSR2 (*(unsigned char volatile xdata *)0xFE0C) //
#define TBSR3 (*(unsigned char volatile xdata *)0xFE0D) //
#define TBSR4 (*(unsigned char volatile xdata *)0xFE0E) //
#define TBSR5 (*(unsigned char volatile xdata *)0xFE0F) //
#define TBSR6 (*(unsigned char volatile xdata *)0xFE10) //
#define TBSR7 (*(unsigned char volatile xdata *)0xFE11) //
#define TBSR8 (*(unsigned char volatile xdata *)0xFE12) //
#define TBSR9 (*(unsigned char volatile xdata *)0xFE13) //
#define RBSR (*(unsigned char volatile xdata *)0xFE14) //接收缓冲器首地址(0x14_0x1D)
#define RBSR1 (*(unsigned char volatile xdata *)0xFE15) //
#define RBSR2 (*(unsigned char volatile xdata *)0xFE16) //
#define RBSR3 (*(unsigned char volatile xdata *)0xFE17) //
#define RBSR4 (*(unsigned char volatile xdata *)0xFE18) //
#define RBSR5 (*(unsigned char volatile xdata *)0xFE19) //
#define RBSR6 (*(unsigned char volatile xdata *)0xFE1A) //
#define RBSR7 (*(unsigned char volatile xdata *)0xFE1B) //
#define RBSR8 (*(unsigned char volatile xdata *)0xFE1C) //
#define RBSR9 (*(unsigned char volatile xdata *)0xFE1D) //
void CPU_init(void); //CPU初始化子函数
void CAN_init( void ); //初始化CAN总线芯片
void CAN_TXD( void ); //CAN发送子函数
void Rxd_deal(void); //接收处理函数
void Txd_deal(void); //发送处理函数
void Delay(uchar delay_time);//延时子函数
void led_seg7(uchar from,uchar number);//显示子函数
对了,有一个想不通的问题,当我把发送程序下到2快板子是,发现SJA1000的不能进入发送中断,而PCA82C200是可以的,好奇怪啊 |
|