最近用到NXP的P89V51RD2做一个关于CAN通讯的小工程,碰到点问题,望大家指点一二。
情况是这样的,所用的KEIL的版本是:
硬件情况是:单片机外扩了一片SJA1000的CAN控制器,SJA1000的片选直接接GND
KEIL\Target设置如下:
意思就是告诉编译器,外扩了RAM
SJA1000的基地址定义为:
#define CAN1 0x0000 //cs_c1
其控制寄存器定义为(太长,没复制完全):
//第一片CAN地址/
unsigned char volatile CAN1_MOD _at_ (CAN1+0); //模式
unsigned char volatile CAN1_CMR _at_ (CAN1+1); //命令
unsigned char volatile CAN1_SR _at_ (CAN1+2); //状态
unsigned char volatile CAN1_IR _at_ (CAN1+3); //中断
unsigned char volatile CAN1_IER _at_ (CAN1+4); //中断使能
unsigned char volatile CAN1_BRT0 _at_ (CAN1+6); //总线定时0
//在复位模式中是可以被访问的(读/写),定义波特率预设值和同步跳转宽度
//pelican模式,在工作模式中是只读的
//basic模式中,总是0XFF
unsigned char volatile CAN1_BRT1 _at_ (CAN1+7); //总线定时1
//在复位模式中是可以被访问的(读/写),定义每个位周期的长度、采样点的位置和在每个采样点的采样数目
//pelican模式,在工作模式中是只读的
//basic模式中,总是0XFF
unsigned char volatile CAN1_OCR _at_ (CAN1+8); //输出控制
//在复位模式中是可以被访问的(读/写),实现了由软件控制不同输出驱动配置的建立
//pelican模式,在工作模式中是只读的
//basic模式中,总是0XFF
CAN初始化函数:
void can1_ini(void)
{
unsigned char can1_status;
EX0=0; //关INT0
can1_status=can1_interface_test(0x55); //a)检测硬件连接是否正确
if(can1_status==CAN1_INTERFACE_OK)
{
while((CAN1_MOD&0x01)!=0x01) CAN1_MOD=0x01; //b)进入复位状态
CAN1_CDR=0xc8; //c)设置时钟分频寄存器
CAN1_OCR=0xaa; //d)设置输出控制寄存器
CAN1_BRT0=Can12_BTR0_Rate_250k; //e)设置通讯波特率
CAN1_BRT1=Can12_BTR1_Rate_250k; //e)设置通讯波特率
CAN1_ACR0=0x00; //f)设置代码验收寄存器
CAN1_ACR1=0x01; //f)设置代码验收寄存器
CAN1_ACR2=0x00; //f)设置代码验收寄存器
CAN1_ACR3=0x01; //f)设置代码验收寄存器
CAN1_AMR0=0xff; //g)设置代码屏蔽寄存器
CAN1_AMR1=0xff; //g)设置代码屏蔽寄存器
CAN1_AMR2=0xff; //g)设置代码屏蔽寄存器
CAN1_AMR3=0xff; //g)设置代码屏蔽寄存器
CAN1_IER=0xff; //j)设置中断使能寄存器
//CAN1_IER=0x00; //j)设置中断使能寄存器
while((CAN1_MOD&0x01)!=0x00) CAN1_MOD=0x00; //h)退出复位状态
//i)设置工作模式,选择两个验收滤波器
//EX0=1;
LED_run=0;
DelayMs(1000);
LED_run=1;
DelayMs(1000);
LED_run=0;
DelayMs(1000);
}
else
{
//硬件连接不正常,以后再处理
}
}
CAN发送函数为:
void can_take(unsigned char id,unsigned char temp[8])
{
unsigned char temp1=0;
unsigned char temp2=0;
unsigned char temp3=0;
unsigned char temp4=0;
temp1=id;
temp2=id;
temp3=temp1>>3;
temp4=temp1<<5;
CAN1_CMR=0x0e; //清除数据溢出,释放接收缓冲器,中止发送
CAN1_TXB_0=0x08; //FF=0:标准桢 RTR=0:数据桢
CAN1_TXB_1=temp3; //ID.28--ID.21
CAN1_TXB_2=temp4&0xe0; //ID.20--ID.18
CAN1_TXB_3=temp[0];
CAN1_TXB_4=temp[1];
CAN1_TXB_5=0x30;
CAN1_TXB_6=0x31;
CAN1_TXB_7=0x33;
CAN1_TXB_8=0x34;
CAN1_TXB_9=0x35;
CAN1_TXB_10=0x36;
CAN1_CMR=0x09;
}
目前的现象是:
初始化函数运行正常,SJA1000能正常发出设定波特率的数据,且发送数据的后6个数据正常(写的是常数),但是前面的2个字节就不受控制了,像是随机数一样
CAN接收端收到的数据是:
正常在主程序里面调用CAN发送部分的程序为:
can_tr[0] = 0x10;
can_tr[1] = 0x11;
can_tr[2] = 0x22;
can_tr[3] = 0x23;
can_tr[4] = 0x24;
can_tr[5] = 0x25;
can_tr[6] = 0x26;
can_tr[7] = 0x27;
while(1)
{
can_take(0x38,can_tr);
//can_tr2[0]=1;
//can_tr2[1]=3;
//can_tr2[2]=5;
//can_tr2[3]=7;
//can_tr2[4]=9;
//can_tr2[5]=11;
//can_tr2[6]=13;
//can_tr2[7]=15;
//send_string_com(can_tr2,8);
//send_char_com(0x11);
//send_char_com(0x18);
DelayMs(500);
LED_run=~LED_run;
}
即CAN收到的第一个数据应该是0x10,第2个数据应该是0x11
因为这个CPU不能仿真,只能通过ISP的方式下载调试,所以现在很痛苦,不知道是哪里的问题。
肯定各位有知道,指点一下,谢谢谢谢了
|