#include "mcp2515.h"
#include "delay.h"
#include "spi.h"
#include "can_protocol_ywk.h"
#include "stdio.h"
#define CS PAout(4)// PA4
extern CAN_FRAME_STRUCT current_frame3; //CAN2
u8 dummy=0;
u8 number=0,number1=0,number2=0,j,number3=0,number4=0,number5=0,number6=0;
///*RXB0's data registers:*/
unsigned char RXB0D[8]={RXB0D0,RXB0D1,RXB0D2,RXB0D3,RXB0D4,RXB0D5,RXB0D6,RXB0D7};
///*TXB0's data registers:*/
unsigned char TXB0D[8]={TXB0D0,TXB0D1,TXB0D2,TXB0D3,TXB0D4,TXB0D5,TXB0D6,TXB0D7};
volatile int can3_rx_data_flag=0;
void MCP_2515_init()
{
SPIReset();
delay_ms(1);
//SPIByteWrite(CANCTRL,0x80);//CAN工作在配置模式
//设置波特率为10Kbps
//set CNF1,SJW=00,长度为1TQ,BRP=49,TQ=[2*(BRP+1)]/Fsoc=2*50/8M=12.5us
SPIByteWrite(CNF1,CAN_125Kbps);
//set CNF2,SAM=0,在采样点对总线进行一次采样,PHSEG1=(2+1)TQ=3TQ,PRSEG=(0+1)TQ=1TQ
SPIByteWrite(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ);
//set CNF3,PHSEG2=(2+1)TQ=3TQ,同时当CANCTRL.CLKEN=1时设定CLKOUT引脚为时间输出使能位
SPIByteWrite(CNF3,PHSEG2_3TQ);
SPIByteWrite(RXB0CTRL,0x20);//仅仅接收标准标识符的有效信息,FIILHIT0=0表示RXB0 ,采用FILHIT0
SPIByteWrite(RXF0SIDH,0xFF);//初始化接收滤波器0,待修改***
SPIByteWrite(RXF0SIDL,0xE0)
;
SPIByteWrite(RXF1SIDH,0xFD);//初始化接收滤波器0,待修改***
SPIByteWrite(RXF1SIDL,0xC0);
SPIByteWrite(RXM0SIDH,0x00);
SPIByteWrite(RXM0SIDL,0x00);
//set TXB0,设置发送缓冲器0的标识符和发送的数据,以及发送的数据长度
SPIByteWrite(TXB0SIDH,0xFF);//设置发送缓冲器0的标准标识符,待修改***
SPIByteWrite(TXB0SIDL,0xE0);//用到标准标识符
SPIByteWrite(RXB0DLC,DLC_8);//设置接收数据的长度为8个字节
//SPIByteWrite(TXB0D0,0x1E);//有待修改及确定是否使用
//SPIByteWrite(TXB0D1,0x10);//有待修改及确定是否使用
/*set TXB1
SPIByteWrite(TXB1SIDH,0x50); //Set TXB0 SIDH
SPIByteWrite(TXB1SIDL,0x00); //Set TXB0 SIDL
SPIByteWrite(TXB1DLC,0x40 | DLC_8); //Set DLC = 3 bytes and RTR bit*/
//设置接收缓冲器0中断
SPIByteWrite(CANINTF,0x00);//清空中断标志
SPIByteWrite(CANINTE,0x01);//接收缓冲器0满中断使能位
SPIByteWrite(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED);//设置正常模式
dummy=SPIByteRead(CANSTAT); //如果还处于配置模式,就进入工作模式配置
if(OPMODE_NORMAL!=(dummy&0xE0))
{
SPIByteWrite(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED);//判断进入正常工作模式
}
}
void SPIReset() //器件复位
{
CS=0;
SPI1_ReadWriteByte(CAN_RESET);
CS=1;
}
//初始化完全完全正确
//读指定地址的指令
u8 SPIByteRead(u8 addr)
{
u8 tempdata;
CS=0;
WriteSPI(CAN_READ);
WriteSPI(addr);
tempdata=ReadSPI();
CS=1;
return tempdata;
}
//功能:只修改寄存器中的某些位
//入口参数:Addr:寄存器地址 MASK:屏蔽字 dat:数据字节
void MODIFY_2515(unsigned char Addr, unsigned char MASK, unsigned char dat)
{
CS = 0 ;
//WriteSPI(0x05);
WriteSPI(CAN_BIT_MODIFY);
WriteSPI(Addr) ;
WriteSPI(MASK) ;
WriteSPI(dat) ;
CS = 1 ;
}
void SPIByteWrite(u8 addr,u8 value) //向2515指定一个地址写指令
{
CS=0;
WriteSPI(CAN_WRITE);
WriteSPI(addr);
WriteSPI(value);
CS=1;
}
/*******add zhang***********/
unsigned char ReadByte_MCP2515(unsigned char Addr)
{
unsigned char Data;
CS=0;
WriteSPI(CAN_READ);
WriteSPI(Addr);
Data = SPI1_ReadWriteByte(Addr);
CS=1;
return Data;
}
unsigned char SPI_CMD_MCP2515(unsigned char CMD)
{
unsigned char Data;
CS=0;
Data=SPI1_ReadWriteByte(CMD);
CS=1;
return Data;
}
//CAN发送任意长度字节
void CAN_Send_anylength(u8 *CAN_TX_Buf,u8 length1)
{
unsigned char tempdata,j;
tempdata=SPIByteRead(CAN_RD_STATUS);
SPIByteWrite(TXB0DLC,length1);
for(j=0;j<length1;j++)
{
SPIByteWrite(TXB0D0+j,CAN_TX_Buf[j]);
}
if(tempdata&0x04)//判断TXREQ标志位
{
delay_ms(1);
MODIFY_2515(TXB0CTRL,0x80,0x00);//clear TXREQ bit add zhang
//SPIByteWrite(TXB0CTRL,0);//清除TXREQ标志位 old code
while(SPIByteRead(CAN_RD_STATUS)&0x04);//等待TXREQ清零
delay_ms(1);
}
CS=0;
WriteSPI(CAN_RTS_TXB0);//发送缓冲器0请求发送
CS=1;
}
void WriteSPI(u8 ch) //写函数
{
SPI1_ReadWriteByte(ch);
}
u8 ReadSPI(void)
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 0xff);
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI1);
}
/********* ADD ***********
* @brief Send a byte to CAN bus by TXB0
* @param Data:data to be sent
* @retval none
*/
void CAN_SendOneByte(unsigned char Data)
{
unsigned char tempdata;
/*Test the driver between MCP2515 and the SPI periphere :tempdata<--------------*/
tempdata=SPI_CMD_MCP2515(CAN_RD_STATUS);
if(tempdata&0x04)//check the TXREQ bit
{
delay_ms(1);
MODIFY_2515(TXB0CTRL,0x08,0x00);//clear TXREQ bit
while(SPI_CMD_MCP2515(CAN_RD_STATUS)&0x04);//wait until TXREQ bit matchs 0
}
SPIByteWrite(TXB0D0,Data);
CS=0;
WriteSPI(CAN_RTS_TXB0);//TXB0 send-request
CS=1;
}
/********* Add
* @brief Receive a byte from MCP2515 RXB0
* @param none
* @retval Data:return the effectively data from RXB0
*/
unsigned char CAN_Receive_onebyte()
{
unsigned char tempdata;
tempdata=SPI_CMD_MCP2515(CAN_RD_STATUS);//confirm receive data=RXB0IF
if(tempdata&0x01)
{
tempdata=SPI_CMD_MCP2515(CAN_RX_STATUS);
if(tempdata&0x40)//true means RXB0's standard frame
{
tempdata=ReadByte_MCP2515(RXB0D0);
}
else
{tempdata=254;}//no standard frame receive
MODIFY_2515(CANINTF,0x01,0x00);
}
else
{tempdata=255;}//no frame receive
return tempdata;
}
/***************ADD ***********
* @brief Send n bytes with a given standard ID corresponding to frame type
* @param CAN_TX_Buf: data to be sent
* @param DLC
LC<=8
* @param SID:<=0x7FF
* @param CAN_FrameType:CAN_STD,CAN_RTR
* @retval None
*/
void CAN_SendData(unsigned char *CAN_TX_Buf,Frame_TypeDef *Frame )
{
unsigned char tempdata;
unsigned char HSID,LSID;
if(Frame->Type==CAN_STD)
{
/*Set the ID of the frame*/
HSID=(unsigned char)(Frame->SID>>3);
LSID=(unsigned char)((Frame->SID<<5)&0xE0);
SPIByteWrite(TXB0SIDH,HSID);
SPIByteWrite(TXB0SIDL,LSID);
/*Set the DLC and the type of the frame*/
SPIByteWrite(TXB0DLC,Frame->DLC|CAN_STD);
/*Write the data into the TXB0 data registers */
for(tempdata=0;tempdata<Frame->DLC;tempdata++)
SPIByteWrite(TXB0D[tempdata],CAN_TX_Buf[tempdata]);
}
else /*if(CAN_FrameType==CAN_RTR)*/
{
/*Set the ID of the frame*/
HSID=(unsigned char)(Frame->SID>>3);
LSID=(unsigned char)((Frame->SID<<5)&0xE0);
SPIByteWrite(TXB0SIDH,HSID);
SPIByteWrite(TXB0SIDL,LSID);
/*Set the type of the frame*/
SPIByteWrite(TXB0DLC,CAN_RTR);
}
tempdata=SPI_CMD_MCP2515(CAN_RD_STATUS);
if(tempdata&0x04)
{
delay_ms(1);
MODIFY_2515(TXB0CTRL,0x80,0x00);
while(SPI_CMD_MCP2515(CAN_RD_STATUS)&0x04);
}
/*Send the SPI_RTS_TXB0 request command to MCP2515 to send the data loaded in the data register*/
CS=0;
WriteSPI(CAN_RTS_TXB0);
CS=1;
}
/*********
* @brief Receive n bytes from MCP2515 RXB0
* @param none
* @retval Data:return the effectively data from RXB0
*/
unsigned char CAN_ReceiveData(unsigned char *CAN_RX_Buf,Frame_TypeDef *Frame)
{
unsigned char tempdata;
unsigned int CAN_ID;
unsigned int RXID[6];
tempdata=SPI_CMD_MCP2515(CAN_RD_STATUS);//check if it is received a frame
tempdata=SPI_CMD_MCP2515(CAN_RX_STATUS);
if(tempdata&0x40)//RXB0
{
RXID[0]=(unsigned int)(SPIByteRead(RXB0SIDH));
RXID[1]=(unsigned int)(SPIByteRead(RXB0SIDL)); //62h
RXID[4]=(unsigned int)(SPIByteRead(RXB0DLC)); //65h
Frame->DLC=RXID[4]&0x0f;
if((RXID[1]>>3)&1) //判断是否是扩展id
{
RXID[2]=(unsigned int)(SPIByteRead(RXB0EID8)); //63h
RXID[3]=(unsigned int)(SPIByteRead(RXB0EID0)); //64h
CAN_ID=((RXID[1]&0x03)<<16 ) +( RXID[2]<<8) + RXID[3]; //得到扩展id
Frame->SID=CAN_ID;
}
else
{
CAN_ID=RXID[0]<<8;
CAN_ID|= RXID[1]>>5; //是标准id
//CAN_ID>>=5;
Frame->SID=CAN_ID;
}
/*Check the CAN_ID you received that if it is matched with the SID you wish*/
if(Frame->DLC==0x08)//if(Frame->DLC==8)
{
for(tempdata=0;tempdata<Frame->DLC;tempdata++)
{
CAN_RX_Buf[tempdata]=SPIByteRead(RXB0D[tempdata]);
}
current_frame.id=CAN_ID;
current_frame.message_length=Frame->DLC;
current_frame.p_data_buf=CAN_RX_Buf;
Can_Protocol_Analizy(current_frame);
MODIFY_2515(CANINTF,0x01,0x00);
return 1;//receive ok
}
else
{
return 0;//ID is not correct
}
}
else
{
return 2;//no standard frame receive
}
}
一周热门 更多>