#include #include #include

can总线多机通讯 接收

  • 格式:doc
  • 大小:49.50 KB
  • 文档页数:10

#include"SJA1000REG_1.h"#include<reg52.h>#include<stdio.h>#include<string.h>#include<intrins.h>#define STD_FRAMEID_LENTH 2 //标准帧ID长度#define EXT_FRAMEID_LENTH 4 //扩展帧ID长度#define LOW_BYTE(x) (unsigned char)(x)#define HIGH_BYTE(x) (unsigned char)((unsigned int)(x)>>8)#define OSCCLK 11059200UL#define CPUCLK (OSCCLK/12)#define SJA_BASE_ADDR 0X7E00#define T0_MASK 0x0fsbit LED=P2^5;sbit SJA1000_RST=P2^6;unsigned char xdata *SJA_CS_Point=(unsigned char xdata*)SJA_BASE_ADDR;void SJA1000_Init(unsigned char btr0,unsigned char btr1,unsigned char *filter);void WriteSJAReg(unsigned char RegAdr,unsigned char Value); //写寄存器unsigned char ReadSJAReg(unsigned char RegAdr); //读寄存器char SetBitMask(unsigned char RegAdr,unsigned char BitValue); //设置寄存器特定位char ClearBitMask(unsigned char RegAdr,unsigned char BitValue); //清除寄存器特定位char WriteSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len);//连续写寄存器char ReadSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len);//连续读寄存器char SetSJASendCmd(unsigned char cmd); //发送模式cmd 0为正常发送1为单次发送2为自发自收char SJASendData(unsigned char *databuf,unsigned char cmd); //sja1000发送函数,将数据写入sja1000发送缓冲区,再将其发到总线上char SJARcvData(unsigned char *databuf); //SJA1000接收函数读取接收缓冲区的CAN报文//void SJA1000_Config_Filter(char mode,char *Filter); //配置滤波器模式和滤波参数mode大于0为双滤波器,其他为单滤波unsigned char SJA_CAN_Filter[8]={ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff};typedef struct //结构定义{unsigned long ID;unsigned char FF;unsigned char RTR;unsigned char DLC;unsigned char CanData[8];}CanFrame_t;CanFrame_t UserRecData;unsigned char UserData[8];unsigned char UserID[4];unsigned char UserFF,UserRTR,UserDLC;void UserDataDeal(){unsigned char temp2;temp2=UserData[0];P1=temp2;}void NumDataDeal(){UserID[0]=((UserRecData.ID<<5)>>8)&0xff;UserID[1]=(UserRecData.ID<<5)&0xf0;UserRTR=UserRecData.RTR;UserFF=UserRecData.FF;UserDLC=UserRecData.DLC;UserData[0]=UserRecData.CanData[0];UserData[1]=UserRecData.CanData[1];UserData[2]=UserRecData.CanData[2];UserData[3]=UserRecData.CanData[3];UserData[4]=UserRecData.CanData[4];UserData[5]=UserRecData.CanData[5];UserData[6]=UserRecData.CanData[6];UserData[7]=UserRecData.CanData[7];}void timerInit(void) //串口初始化{TMOD&=~T0_MASK; //清除旧的设置(#define T0_MASK 0x0f)TMOD|=0x01;}void timerDelay(unsigned int n) //延时0.01×ndo{TL0=LOW_BYTE(65536UL-CPUCLK/100);TH0=HIGH_BYTE(65536UL-CPUCLK/100);TR0=1;while(!TF0);TR0=0;TF0=0;}while(--n!=0);}void SJA1000_Init(unsigned char btr0,unsigned char btr1,unsigned char *filter){SetBitMask(REG_CAN_MOD,RM_RR_BIT); //进入复位模式WriteSJAReg(REG_CAN_CDR,0x48); //配置时钟分频,选择peliCAN模式WriteSJAReg(REG_CAN_MOD,0x09); //配置模式寄存器,选择单滤波、正常模式WriteSJARegBlock(REG_CAN_ACR0,filter,8); //配置验收代码/屏蔽寄存器WriteSJAReg(REG_CAN_BTR0,btr0); //配置总线定时器0WriteSJAReg(REG_CAN_BTR1,btr1); //配置总线定时器1WriteSJAReg(REG_CAN_OCR,0x1A); //配置输出引脚TX0与RX0,推挽输出ClearBitMask(REG_CAN_MOD,RM_RR_BIT); //推出复位模式}void WriteSJAReg(unsigned char RegAdr,unsigned char Value) //写SJA1000寄存器{*(SJA_CS_Point+RegAdr)=Value;return;}unsigned char ReadSJAReg(unsigned char RegAdr) //读SJA1000寄存器{return(*(SJA_CS_Point+RegAdr));}char SetBitMask(unsigned char RegAdr,unsigned char BitValue) //设置指定寄存器指定位为1{char status=0;unsigned char temp;temp=ReadSJAReg(RegAdr);temp=temp|BitValue;WriteSJAReg(RegAdr,temp);if(ReadSJAReg(RegAdr)==temp){status=1;}else{status=0;}return(status);}char ClearBitMask(unsigned char RegAdr,unsigned char BitValue) //将指定寄存器的指定位清零{char status=0;unsigned char temp;temp=ReadSJAReg(RegAdr);temp=temp&(~BitValue);WriteSJAReg(RegAdr,temp);if(ReadSJAReg(RegAdr)==temp){status=1;}else{status=0;}return(status);}char WriteSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len) //连续写多个寄存器RegAdr寄存器起始地址len要连续写入的寄存器数{unsigned char i;if(len!=0){for(i=0;i<len;i++){WriteSJAReg(RegAdr+i,ValueBuf[i]);}}return len;}char ReadSJARegBlock(unsigned char RegAdr,unsigned char *ValueBuf,unsigned char len) //连续读多个寄存器RegAdr寄存器起始地址len要读取的寄存器数{unsigned char i;if(len!=0){for(i=0;i<len;i++){ValueBuf[i]=ReadSJAReg(RegAdr+i);}}return len;}char SetSJASendCmd(unsigned char cmd) //发送模式cmd 0为正常发送1为单次发送2为自发自收{unsigned char ret;switch(cmd){default:case 0:ret=SetBitMask(REG_CAN_CMR,TR_BIT);break;case 1:ret=SetBitMask(REG_CAN_CMR,TR_BIT|AT_BIT);break;case 2:ret=SetBitMask(REG_CAN_CMR,TR_BIT|SRR_BIT);break;case 0xff:ret=SetBitMask(REG_CAN_CMR,A T_BIT);break;}return ret;}char SJASendData(unsigned char *databuf,unsigned char cmd) //sja1000发送函数,将数据写入sja1000发送缓冲区,再将其发到总线上{char status=1;unsigned char len;unsigned char dlc;if((ReadSJAReg(REG_CAN_SR)&(TBS_BIT|TCS_BIT))!=(TBS_BIT|TCS_BIT)){status=0;}else{dlc=(*databuf&0x0f);if(dlc>8){dlc=8;}switch(*databuf&0xc0){case 0x00:len=STD_FRAMEID_LENTH+dlc+1;break;case 0x40:len=STD_FRAMEID_LENTH+1;break;case 0x80:len=EXT_FRAMEID_LENTH+dlc+1;break;case 0xc0:len=EXT_FRAMEID_LENTH+1;break;default:len=0;status=0;break;}if(len>0){WriteSJARegBlock(REG_CAN_TXFMINFO,databuf,len);SetSJASendCmd(cmd);status=1;}}return(status);}char SJARcvData(unsigned char *databuf) //SJA1000接收函数读取接收缓冲区的CAN报文{char status=1;unsigned char len;unsigned char dlc;if((ReadSJAReg(REG_CAN_SR)&RBS_BIT)==0){status=0;}else{*databuf=ReadSJAReg(REG_CAN_RXFMINFO);dlc=(*databuf&0x0f);if(dlc>8){dlc=8;}switch(*databuf&0xC0){case 0x00:len=STD_FRAMEID_LENTH+dlc;break;case 0x40:len=STD_FRAMEID_LENTH;break;case 0x80:len=EXT_FRAMEID_LENTH+dlc;break;case 0xC0:len=EXT_FRAMEID_LENTH;break;default:len=0;status=0;break;}if(len>0){ReadSJARegBlock(REG_CAN_RXBUF1,databuf+1,len);status=SetBitMask(REG_CAN_CMR,RRB_BIT);}}return(status);}/*void SJA1000_Config_Filter(char mode,char *Filter) //配置滤波器模式和滤波参数mode大于0为双滤波器,其他为单滤波{SetBitMask(REG_CAN_MOD,RM_RR_BIT);if(mode>0){SetBitMask(REG_CAN_MOD,AFM_BIT);}else{ClearBitMask(REG_CAN_MOD,AFM_BIT);}WriteSJARegBlock(REG_CAN_ACR0,Filter,8);ClearBitMask(REG_CAN_MOD,RM_RR_BIT);}*/int Hal_CanMsgSend(CanFrame_t *pCanFrame) //CAN控制器报文发送接口{unsigned char snd_buf[13];unsigned long id;snd_buf[0]=(pCanFrame->DLC&0xf);if(pCanFrame->FF){snd_buf[0]=(1<<7);}if(pCanFrame->RTR){snd_buf[0]|=(1<<6);}if(pCanFrame->FF){id=(pCanFrame->ID<<3);snd_buf[1]=(id>>24)&0xff;snd_buf[2]=(id>>16)&0xff;snd_buf[3]=(id>>8)&0xff;snd_buf[4]=(id>>0)&0xff;memcpy(&snd_buf[5],pCanFrame->CanData,pCanFrame->DLC);}else{id=(pCanFrame->ID<<5);snd_buf[1]=(id>>8)&0xff;snd_buf[2]=id&0xff;memcpy(&snd_buf[3],pCanFrame->CanData,pCanFrame->DLC);}return SJASendData(snd_buf,0);}int Hal_CanMsgRecive(CanFrame_t *pCanFrame) //CAN控制器报文接收接口{unsigned char rcv_buf[13];if(SJARcvData(rcv_buf)){pCanFrame->DLC=(rcv_buf[0]&0xf);if(rcv_buf[0]&(1<<7)){pCanFrame->FF=1;}else{pCanFrame->FF=0;}if(rcv_buf[0]&(1<<6)){pCanFrame->RTR=1;}else{pCanFrame->RTR=0;}if(rcv_buf[0]&(1<<7)){pCanFrame->ID=rcv_buf[1];pCanFrame->ID<<=8;pCanFrame->ID+=rcv_buf[2];pCanFrame->ID<<=8;pCanFrame->ID+=rcv_buf[3];pCanFrame->ID<<=8;pCanFrame->ID+=rcv_buf[4];pCanFrame->ID>>=3;memcpy(pCanFrame->CanData,&rcv_buf[5],pCanFrame->DLC);}else{pCanFrame->ID=rcv_buf[1]<<8;pCanFrame->ID|=rcv_buf[2]<<0;pCanFrame->ID>>=5;memcpy(pCanFrame->CanData,&rcv_buf[3],pCanFrame->DLC);}return 1;}else{return 0;}}int Hal_CanInit(void) //初始化SJA1000{SJA1000_RST=1;timerDelay(50);SJA1000_RST=0;SJA1000_Init( 0x00,0x14, SJA_CAN_Filter);return 1;}void main(){timerInit();Hal_CanInit();while(1){if(Hal_CanMsgRecive(&UserRecData)){NumDataDeal();UserDataDeal();LED=!LED;timerDelay(10);}else{LED=!LED;timerDelay(5);}}}。