C51模拟SPI对MCP2515没成功,总线上波形有时候有,有时候没有,CAN调试器没发现数据,CAN调试肯定耗用 #include "reg51.h" #include "MCP2515.H" #include "intrins.h"
sbit CS=P1^2; /*单片机P1.2为片选 可以改为你的实际引脚 */ sbit SO=P1^3;/*数据输出 */ sbit SK=P1^5; /* 时钟 */ sbit SI=P1^4; /* 数据输入*/
#define uint unsigned int #define uchar unsigned char
uchar can_boud=0x01;//修改8M下500K拨特率//MCP2515在16M晶振情况, //can_boud=0x00总线波特率为1M,0x01=500K,0x03=250K,0x07=125K;公式:16M/(16*(1+X))
uchar TID[2]={0,0}; //存放标准祯的ID号 uchar Tdate[10]={0}; //发送标准祯的数据, 2字节ID,8字节数据 uchar Rdate[8]={0}; //存放接收数据 uchar RESID[4]; //存放接收到的数据帧的ID号,标准帧只用到RESID[0],RESID[1],扩展帧全部用到
void Uart_init(void) //串口初始化,11。0592M-------------9600 { TMOD=0X22; SCON=0X40; TH1=0XFA; PCON=0X80; TR1=1; REN=1; } void putchar(uchar dat) //串口输出一字节函数 { SBUF=dat; while(!TI); TI=0; } void delay_ms(uint del) //延时 {
unsigned char j,k;
for(k=del;k>0;k--)
for(j=24;j>0;j--); }
void Exint0(void) //外部中断初始化 { EA=1; EX0=1; IT0=1; //下降沿触发 }
void WriteSPI(uchar cData) //模拟SPI发送数据 { uchar cLoop;
for(cLoop=0;cLoop<8;cLoop++) { SK=0; if((cData&0x80)==0) { SI=0; } else { SI=1; } SK=1; cData<<=1; } } unsigned char Read8(void) //模拟SPI 读1个字节 { bit bData; unsigned char cLoop; unsigned char cData; for(cLoop=0;cLoop<8;cLoop++) { SK=1; SK=0; bData=SO; cData<<=1; if(bData) { cData|=0x01; } } return cData; }
uchar Read_state(uchar order) //读命令状态 { uchar clear; CS=0; WriteSPI(order); clear=Read8(); CS=1; return clear; }
//**从2515指定地址Address读取一个字节数据Data**// uchar Read_Byte(uchar Address) {//uchar clear; uchar date; CS=0; //使能SPI器件 //SPDR=0x03; //送2515读指令为0x03 WriteSPI(0X03); // SPDR=Address; //送地址 WriteSPI(Address); date=Read8(); CS=1; //关SPI器件 return date; }
//**向2515指定地址Address写一个字节数据Data**// void Write_Byte(uchar Address,uchar Data) { CS=0; //使能SPI器件2515 WriteSPI(0X02); WriteSPI(Address); WriteSPI(Data); CS=1; //关SPI器件 }
void load_Standard_ID_dates(uchar num) //给标准祯装载ID号和数据 { uchar i,j,T0=0x36; uchar TIDH,TIDL; i=TID[1]>>3;j=TID[0]<<5;j=j+i;i=TID[1]<<5; TIDL=i;TIDH=j;//将数组TID中的值转化为TIDH,TIDL以便给TXB0SIDH,TXB0SIDL附值 Write_Byte(CANCTRL,0x80);//CAN工作在配置模式 Write_Byte(CNF1,can_boud); Write_Byte(TXB0SIDH,TIDH); Write_Byte(TXB0SIDL,TIDL); Write_Byte(TXB0DLC,num);// for(i=2;i<num+2;i++,T0++)Write_Byte(T0,Tdate); }
void CAN_Initialize(void) { WriteSPI(CAN_RESET); delay_ms(20); Write_Byte(CANCTRL,0x80);//CAN工作在配置模式 Write_Byte(CNF1,can_boud); Write_Byte(CNF2,0x80 | PHSEG1_3TQ | PRSEG_1TQ);//Set CNF2 Write_Byte(CNF3,PHSEG2_3TQ); //0x80+0x10+0x00,相位缓冲段2由CNF3确定,相位缓冲段1为3TQ,传播段为1TQ Write_Byte(RXB0CTRL,0xf0);//接收类型选择,接收所有报文 Write_Byte(CANINTF,0x00);//接收完一次必须对中断标志位清0 Write_Byte(CANINTE,0x01);//接收缓冲器0满中断使能 Write_Byte(CANCTRL,0x00);//选定正常工作模式 }
void int0() interrupt 0 //外部中断处理程序 { putchar(0x55); }
void main(void) { uchar i; Uart_init(); Exint0(); CAN_Initialize(); CAN_Initialize(); CAN_Initialize(); TID[0]=0X00;TID[1]=0X01; //ID号 for(i=0;i<8;i++) { Tdate=i; //要发送的数据 } SK=1; SK=1; SK=1; CS=1; while(1)
{ load_Standard_ID_dates(8); Write_Byte(CANCTRL,0x00);//选定工作模式 WriteSPI(CAN_RTS_TXB0);//发送缓冲器0请求发送 delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000); delay_ms(60000);
for(i=0;i<8;i++) { putchar(Tdate); } } } |