SJA1000初始化成功!当想发送数据的时候,先检测了状态寄存器,REG_STATUS寄存器 = 0x44,第四位为0,表示正在发送,可我还没发送呢?所以在下面标记 1 的循环里跳不出来,原因是出在标记 2 的地方。<br />既然SJA1000初始化成功,那还出现这个问题,真是想了几天都没想不通。只能麻烦一下高手们了。下面附了小弟的程序,挺长,真是麻烦大家了。<br />#include <reg51.h><br />#include "SJA_BCANCONF.H"<br />#include <string.h><br />void delay(unsigned int t);<br />bit Sja_1000_Init(void);<br />sbit LED = P1^0;<br />unsigned char data send_data[10] = {0xaa,0x08,2,3,4,5,6,7,8,9};<br /><br />main()<br />{<br /> while(Sja_1000_Init());<br /> while(1)<br /> {<br /> while(BCAN_DATA_WRITE(send_data));/*老是跳不出来*/<br /> while(BCAN_CMD_PRG(0x01));<br /> delay(1000);<br /> LED = ~LED;<br /> }<br />}<br /><br />/************************************************************************<br />* delay()<br />* 延时函数<br />*************************************************************************/<br />void delay(unsigned int t)<br />{<br /> unsigned char i;<br /> while(t--)<br /> {<br /> for(i=0;i<125;i++);<br /> }<br />}<br /><br />/************************************************************************<br />* Sja_1000_Init()<br />* SJA1000初始化<br />*************************************************************************/<br />bit Sja_1000_Init(void)<br />{<br /> if(BCAN_CREATE_COMMUNATION()) //通信测试;<br /> return 1;<br /> if(BCAN_ENTER_RETMODEL()) //申请进入复位模式<br /> return 1;<br /> if(BCAN_SET_BANDRATE()) //设置波特率为50K<br /> return 1;<br /> if(BCAN_SET_OBJECT(0xaa,0xFF)) //设置ACK、AMR<br /> return 1;<br /> if(BCAN_SET_OUTCLK(0xaa,0x48)) //设置输出方式禁止clkout<br /> return 1;<br /> if(BCAN_QUIT_RETMODEL()) //退出复位状态<br /> return 1;<br /> SJA_BCANAdr = REG_CONTROL; //送控制寄存器地址<br /> *SJA_BCANAdr |= 0x0A; //开放错误中断和接收中断<br /> return 0;<br />}<br /><br />/************************************************************************<br />*函数原型: bit BCAN_CREATE_COMMUNATION(void) * <br />*参数说明: 无 *<br />*返回值: *<br />* 0 ; 表示SJA1000接口正常 *<br />* 1 ; 表示SJA1000与处理器接口不正常 *<br />* * <br />*说明:该函数用于检测CAN控制器的接口是否正常 *<br />************************************************************************/<br />bit BCAN_CREATE_COMMUNATION(void)<br />{ <br /> SJA_BCANAdr=REG_TEST; //访问测试寄存器 <br /> <br /> *SJA_BCANAdr =0xaa; //写入测试值<br /> if(*SJA_BCANAdr == 0xaa)<br /> {<br /> return 0; //读测试正确<br /> }<br /> else<br /> { <br /> return 1;<br /> } <br />} <br /><br />/************************************************************************<br />*函数原型: bit BCAN_ENTER_RETMODEL(void) *<br />*参数说明: 无 *<br />*返回值: *<br />* 0 ; 表示成功进入复位工作模式 *<br />* 1 ; 表示不能进入复位工作模式 *<br />* * <br />*说明: CAN控制器进入复位工作模式 *<br />************************************************************************/ <br />bit BCAN_ENTER_RETMODEL(void)<br />{<br /> unsigned char TempData;<br /> SJA_BCANAdr = REG_CONTROL; //访问地址指向控制寄存器 <br /> TempData= *SJA_BCANAdr; //保存原始值<br /> *SJA_BCANAdr=(TempData|0x01); //置位复位请求<br /> if((*SJA_BCANAdr&0x01) == 1)<br /> {<br /> return 0;<br /> }<br /> else<br /> {<br /> return 1;<br /> }<br /> <br />}<br /><br />/************************************************************************<br />*函数原型: bit BCAN_QUIT_RETMODEL(void) *<br />*参数说明: 无 *<br />*返回值: *<br />* 0 ; 表示成功退出复位工作模式 *<br />* 1 ; 表示不能退出复位工作模式 *<br />* * <br />*说明: CAN控制器退出复位工作模式 *<br />************************************************************************/ <br />bit BCAN_QUIT_RETMODEL(void)<br />{<br /> unsigned char TempData;<br /> SJA_BCANAdr = REG_CONTROL; //访问地址指向控制寄存器 <br /> TempData = *SJA_BCANAdr; //保存原始值<br /> *SJA_BCANAdr=(TempData&0xfe); //清除复位请求<br /> if((*SJA_BCANAdr&0x01) == 0)<br /> {<br /> return 0; //<br /> }<br /> else<br /> {<br /> return 1; //退出成功<br /> }<br /><br />}<br /><br />/************************************************************************<br />;*函数原型: bit BCAN_SET_BANDRATE(unsigned char CAN_ByteRate) *<br />;*参数说明: R7 波特率(Kbit/s) BTR0 BTR1 *<br />;* 50Kbit/s 0xC9 0xA7 *<br />;*返回值: *<br />;* 0 ;波特率设置成功 *<br />;* 1 ;波特率设置失败 *<br />;* * <br />;*说明:设置CAN控制器SJA1000通讯波特率.SJA1000的晶振为必须为12MHZ, *<br />;* 其它晶体的频率的值的波特率,需自己计算 。该子程序只能用于 *<br />;* 复位模式 * <br />;************************************************************************/<br /><br /><br />bit BCAN_SET_BANDRATE(void)<br />{<br /> unsigned char BTR0_num,BTR1_num;<br /> BTR0_num = 0xC9;<br /> BTR1_num = 0xA7;<br /> //将波特率的的预设值装入sja1000的总线定时器<br /> SJA_BCANAdr=REG_BTR0; //访问地址指向总线定时寄存器0<br /> *SJA_BCANAdr=BTR0_num; //写入参数<br /> if(*SJA_BCANAdr != BTR0_num) //校验写入值<br /> {<br /> return 1; <br /> }<br /> SJA_BCANAdr=REG_BTR1; //访问地址指向总线定时寄存器0<br /> *SJA_BCANAdr=BTR1_num; //写入参数<br /> if(*SJA_BCANAdr != BTR1_num) //校验写入值<br /> {<br /> return 1; <br /> }<br /><br /> return 0;<br />} <br /><br /><br />/************************************************************************<br />;*函数原型: BCAN_SET_OBJECT *<br />*参数说明: *<br />* BCAN_ACR:存放验收代码寄存器(ACR)的参数设置 *<br />* BCAN_AMR:存放接收屏蔽寄存器(AMR)的参数设置 *<br />;*返回值: *<br />;* 0 ;通信对象设置成功 *<br />;* 1 ;通信对象设置失败 *<br />;* * <br />;*说明:设置CAN节点的通讯对象,允许接收的报文ID号的高8位(D10--D3) 。 *<br />;* 允许接收的报文,是由AMR和ACR共同决定的. * <br />;* 满足以下条件的ID号的报文才可以被接收 *<br />;*[(ID.10-ID.3)≡(AC.7-AC.0)]||(AM.7-AM.0)≡11111111 *<br />;* 该子程序只能用于复位模式 * * <br />;************************************************************************/<br />bit BCAN_SET_OBJECT(unsigned char BCAN_ACR,unsigned char BCAN_AMR)<br />{<br /> SJA_BCANAdr=REG_ACR; //访问地址指向验收代码寄存器(ACR)<br /> *SJA_BCANAdr=BCAN_ACR; //写入参数<br /> if(*SJA_BCANAdr != BCAN_ACR) //校验写入值<br /> {<br /> return 1; <br /> }<br /> SJA_BCANAdr=REG_AMR; //访问地址指向验收屏蔽寄存器(AMR)<br /> *SJA_BCANAdr=BCAN_AMR; //写入参数<br /> if(*SJA_BCANAdr != BCAN_AMR) //校验写入值<br /> {<br /> return 1; <br /> }<br /><br /> return 0;<br />}<br /><br />/************************************************************************<br />;*函数原型: bit BCAN_SET_OUTCLK (unsigned char Out_Control, *<br /> unsigned char Clock_Out); *<br />;*参数说明: *<br />* Out_Control:存放输出控制寄存器 (OC) 的参数设置 *<br />* Clock_Out:存放时钟分频寄存器 (CDR) 的参数设置 *<br />* * <br />;*返回值: *<br />;* 0 ;设置成功 *<br />;* 1 ;设置失败 *<br />;* * <br />;*说明:设置SJA1000的输出模式和时钟分频 。该子程序只能用于复位模式 * * <br />;************************************************************************/<br />bit BCAN_SET_OUTCLK (unsigned char Out_Control, <br /> unsigned char Clock_Out)<br />{<br /> SJA_BCANAdr=REG_OCR ; //访问地址指向输出控制寄存器<br /> *SJA_BCANAdr=Out_Control; //写入参数<br /> if(*SJA_BCANAdr != Out_Control) //校验写入值<br /> {<br /> return 1; <br /> } <br /> SJA_BCANAdr=REG_CDR; //访问地址指向输出控制寄存器<br /> *SJA_BCANAdr=Clock_Out; //写入参数<br /> return 0;<br />}<br /><br />/************************************************************************<br />*函数原型: bit BCAN_DATA_WRITE(unsigned char *SendDataBuf)*<br />*参数说明: 特定帧各式的数据? *<br />*返回值: *<br />* 0 ; 表示将数据成功的送至发送缓冲区 *<br />* 1 ; 表示上一次的数据正在发送, *<br />* ; 表示发送缓冲区被锁定,不能写入数据 *<br />* ; 表示写入数据错误 * <br />*说明: 将待发送特定帧各式的数据,送入SJA1000发送缓存区中,然后启动 *<br />* SJA1000发送。 *<br />* 特定帧格式为:开始的两个字节存放 '描述符' ,以后的为数据 *<br />* 描述符包括11位长的ID(标志符)\1位RTR\4位描述数据长度的DLC共16位 *<br />* *<br />*注:本函数的返回值仅指示,将数据正确写入SJA1000发送缓存区中与否。 *<br />* 不指示SJA1000将该数据正确发送到CAN总线上完毕与否 *<br />************************************************************************/ <br />bit BCAN_DATA_WRITE(unsigned char *SendDataBuf)<br />{<br /> unsigned char TempCount;<br /> SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器<br /> if((*SJA_BCANAdr&0x08) == 0) //判断上次发送是否完成<br /> {<br /> return 1; //???????? 总是进来,此时的STATUS = 0x44 ??????????<br /> }<br /><br /> if((*SJA_BCANAdr&0x04)==0) //判断发送缓冲区是否锁定<br /> {<br /> return 1;<br /> } <br /><br /> SJA_BCANAdr = REG_TxBuffer1; //访问地址指向发送缓冲区1<br /> if((SendDataBuf[1]&0x10)==0) //判断RTR,从而得出是数据帧还是远程帧<br /> { <br /> TempCount =(SendDataBuf[1]&0x0f)+2; //输入数据帧<br /> }<br /><br /> else<br /> {<br /> TempCount =2; //远程帧<br /> }<br /><br /> memcpy(SJA_BCANAdr,SendDataBuf,TempCount);<br /> return 0;<br />}<br /><br />/************************************************************************<br />*函数原型: bit BCAN_CMD_PRG(unsigned char cmd) *<br />*参数说明: cmd:sja1000运行的命令字 *<br />* 01:发送请求 *<br />* 02:中止发送 *<br />* 04:释放接收缓冲区 *<br />* 08:清除超载状态 *<br />* 0x10:进入睡眠状态 *<br />* *<br />*返回值: *<br />* 0 ; 表示命令执行成功 *<br />* 1 ; 表示命令执行失败 *<br />* * <br />*说明: 执行sja1000命令 * <br />************************************************************************/ <br />bit BCAN_CMD_PRG(unsigned char cmd)<br />{<br /> SJA_BCANAdr=REG_COMMAND; //访问地址指向命令寄存器<br /> *SJA_BCANAdr=cmd; //启动命令字<br /> switch(cmd)<br /> {<br /> case TR_CMD: //发送请求命令<br /> return 0;<br /> break;<br /> case AT_CMD: //夭折发送命令 <br /> SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器 <br /> if((*SJA_BCANAdr & 0x20)==0)//判断是否正在发送<br /> {<br /> return 0;<br /> }<br /> else<br /> {<br /> return 1;<br /> } <br /> break; <br /> case RRB_CMD: //释放接收缓冲区 <br /> SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器 <br /> if((*SJA_BCANAdr & 0x01)==1)//判断是否释放成功<br /> {<br /> return 1;<br /> }<br /> else<br /> {<br /> return 0;<br /> } <br /> break; <br /> <br /> case COS_CMD: //清除超载状态<br /> SJA_BCANAdr = REG_STATUS; //访问地址指向状态寄存器 <br /> if((*SJA_BCANAdr & 0x02)==0)//判断清除超载是否成功<br /> {<br /> return 0;<br /> }<br /> else<br /> {<br /> return 1;<br /> } <br /> break; <br /> <br /> case GTS_CMD: //进入睡眠状态命令 <br /> return 0;<br /> break; <br /> default:<br /> return 1;<br /> break; <br /> }<br /><br />}<br /><br /><br /><br /> |
|