📄 mcp2515.c
字号:
#include "msp430x14x.h"
#include "mcp2515.h"
//u8_t temp;
u8_t TxFrameID[2]; //发送帧ID
u8_t TxFrameDLC;
u8_t TxFrameData[8];
extern void delay(u32_t delaytime);
/* MCP2515 复位 */
void MCP2515_Reset(void)
{
P3OUT &= 0xfe; // P3.0 CS 拉低,片选mcp2515
TXBUF0=CMD_RESET; // 复位指令,TXBUF0即为U0TXBUF,是430的USART0的发送缓冲寄存器
while(!(U0TCTL & TXEPT)); // U0TCTL为USART0的发送控制寄存器。TXEPT=0,表示UTXBUF有数据或正在传;
// TXEPT=1,UTXBUF空或SWRST=1,TXEPT=1,继续下一句
P3OUT|=0x01; // P3.0 CS 拉高
delay(100);
}
/* MCP2515 读寄存器 */
u8_t MCP2515_ReadReg(u8_t addr)
{
P3OUT &= 0xfe; // P3.0 CS 拉低
TXBUF0 = CMD_READ;
while(!(U0TCTL & TXEPT));
TXBUF0 = addr; // 发送地址
while(!(U0TCTL & TXEPT));
TXBUF0 = 0x00; // 据读指令,此字节为任意状态,这里定义为0x00
while(!(U0TCTL & TXEPT));
P3OUT |= 0x01; // P3.0 CS 拉高
return RXBUF0; // RXBUF0即为U0RXBUF,是430的USART0的接收缓冲寄存器
}
/* MCP2515 写寄存器 */
void MCP2515_WriteReg(u8_t addr, u8_t data)
{
P3OUT &= 0xfe; // P3.0 CS 拉低
TXBUF0 = CMD_WRITE;
while(!(U0TCTL & TXEPT));
TXBUF0 = addr;
while(!(U0TCTL & TXEPT));
TXBUF0 = data;
while(!(U0TCTL & TXEPT));
P3OUT |= 0x01; // P3.0 CS 拉高
}
/* 顺序读寄存器 */
void MCP2515_ReadSeqReg(u8_t addr, u8_t *data, u8_t num)
{
P3OUT &= 0xfe; // P3.0 CS 拉低
TXBUF0 = CMD_READ;
while(!(U0TCTL & TXEPT));
TXBUF0 = addr;
while(!(U0TCTL & TXEPT));
for(u8_t i = 0; i < num; i++)
{
TXBUF0 = 0x00;
while(!(U0TCTL & TXEPT));
*data++ = RXBUF0; //此语句即为以下两个语句 *data = RXBUF0;
// data = data+1;
}
P3OUT |= 0x01; // P3.0 CS 拉高
}
/* 顺序写寄存器 */
void MCP2515_WriteSeqReg(u8_t addr, u8_t *data, u8_t num)
{
P3OUT &= 0xfe; // P3.0 CS 拉低
TXBUF0 = CMD_WRITE;
while(!(U0TCTL & TXEPT));
TXBUF0 = addr;
while(!(U0TCTL & TXEPT));
for(u8_t i = 0; i < num; i++)
{
TXBUF0 = *data++; //此语句即为以下两个语句 TXBUF0 = *data;
// data = data+1;
while(!(U0TCTL & TXEPT));
}
P3OUT |= 0x01; // P3.0 CS 拉高
}
/* MCP2515 请求发送TX中内容 (cmd=0x81,请求发TXB0;cmd=0x82,请求发TXB1;cmd=0x84,请求发TXB2) */
void MCP2515_SndRequest(u8_t cmd)
{
//u8_t temp;
P3OUT &= 0xfe; // P3.0 CS 拉低
TXBUF0 = cmd;
while(!(U0TCTL & TXEPT));
//temp = MCP2515_ReadReg(CANINTF); // 读CAN状态寄存器内容
P3OUT |= 0x01; // P3.0 CS 拉高
}
/* 修改后的发送标准帧函数 */
void sendStandardFrame(u8_t bufn, u8_t btPri, u8_t btFrameType, u8_t btModuleId, u8_t btChnId,u8_t btCommandType, u8_t btDlc, u8_t *data)
{
u8_t size = btDlc & 0x0f;
TxFrameID[0] = (btPri | (btFrameType << 1) | btModuleId );
TxFrameID[1] = ((btChnId <<5 )& 0xf7);
TxFrameDLC = btDlc;
TxFrameData[0] = btCommandType;
for(u8_t i=1;i<size;i++)
{
TxFrameData[i]=data[i-1];
}
switch(bufn){
case 0:
MCP2515_WriteSeqReg(TXB0SIDH, TxFrameID, 2); // 发送id,2字节,分别写入TXB0SIDH,TXB0SIDL
MCP2515_WriteReg(TXB0DLC, TxFrameDLC); // 发送数据长度,1字节,写入TXB0DLC
MCP2515_WriteSeqReg(TXB0D0, TxFrameData, size); // Can数据发送
MCP2515_SndRequest(CMD_REQUEST0); // 开始发送
break;
case 1:
MCP2515_WriteSeqReg(TXB1SIDH, TxFrameID, 2);
MCP2515_WriteReg(TXB1DLC, TxFrameDLC);
MCP2515_WriteSeqReg(TXB1D0, TxFrameData, size);
MCP2515_SndRequest(CMD_REQUEST1);
break;
case 2:
MCP2515_WriteSeqReg(TXB2SIDH, TxFrameID, 2);
MCP2515_WriteReg(TXB2DLC, TxFrameDLC);
MCP2515_WriteSeqReg(TXB2D0, TxFrameData, size);
MCP2515_SndRequest(CMD_REQUEST2);
}
}
/* MCP2515 位修改 0 屏蔽*/
void MCP2515_BitModify(u8_t addr, u8_t mask, u8_t data)
{
P3OUT &= 0xfe;
TXBUF0 = CMD_BITMODIFY; // 位修改指令
while(!(U0TCTL & TXEPT));
TXBUF0 = addr; // 地址字节
while(!(U0TCTL & TXEPT));
TXBUF0 = mask; // 屏蔽字节
while(!(U0TCTL & TXEPT));
TXBUF0 = data; // 修改位
while(!(U0TCTL & TXEPT));
P3OUT |= 0x01;
}
/* MCP2515初始化 */
void MCP2515_Init(void) //只有在配置模式下,才能对器件进行初始化
{
u8_t temp1,temp2;
do{
MCP2515_Reset(); // 复位(在上电或复位时,器件会自动进入配置模式)
temp1 = MCP2515_ReadReg(CANSTAT); // 读CAN状态寄存器内容
temp1 = temp1 >> 5;
}while(temp1 != 0x04); // 是否进入配置模式(若没有进入配置模式,一直进行复位)
MCP2515_WriteReg(RXB0CTRL, 0x64); // 接收所有帧,允许滚存(RXB0CTRL为接收缓冲器0控制寄存器)
MCP2515_WriteReg(RXB1CTRL, 0x60); // 接收所有帧 (RXB1CTRL为接收缓冲器1控制寄存器)
MCP2515_WriteReg(RXM0SIDH, 0x00); // 全通,不滤波 (RXM0SIDL验收屏蔽滤波器0标准标识符高位)
MCP2515_WriteReg(RXM0SIDL, 0x00); // (RXM0SIDL验收屏蔽滤波器0标准标识符低位)
MCP2515_WriteReg(RXM1SIDH, 0x00); // (RXM1SIDL验收屏蔽滤波器1标准标识符高位)
MCP2515_WriteReg(RXM1SIDL, 0x00); // (RXM1SIDL验收屏蔽滤波器1标准标识符低位)
MCP2515_WriteReg(BFPCTRL, 0x0f); // 缓冲器满引脚使能 (BFPCTRL为RXnBF引脚控制寄存器和状态寄存器)
/* 125Kbps 8TQ*/
/*
MCP2515_WriteReg(CNF1, 0x07); // BRP = 7 ,8TQ
MCP2515_WriteReg(CNF2, 0x90); // 采样1次, PS1 = 2TQ, 传播段 = 2TQ
MCP2515_WriteReg(CNF3, 0x82); // CLKOUT 为SOF, PS2 = 2TQ
*/
/* 250Kbps 16TQ*/
MCP2515_WriteReg(CNF1, 0x01); // BRP = 1 ,16TQ (4TQ)
MCP2515_WriteReg(CNF2, 0xb1); // 采样1次, PS1 = 7TQ, 传播段 = 2TQ
MCP2515_WriteReg(CNF3, 0x85); // CLKOUT 为SOF, PS2 = 6TQ
/* 500Kbps 8TQ*/
/*
MCP2515_WriteReg(CNF1, 0x01); // BRP = 1 , 8TQ
MCP2515_WriteReg(CNF2, 0x90); // 采样1次, PS1 = 3TQ, 传播段 = 1TQ
MCP2515_WriteReg(CNF3, 0x82); // CLKOUT 为SOF, PS2 = 3TQ
*/
/* 500Kbps 16TQ*/
/*
MCP2515_WriteReg(CNF1, 0x00); // BRP = 0 ,16TQ
MCP2515_WriteReg(CNF2, 0xb1); // 采样1次, PS1 = 7TQ, 传播段 = 2TQ
MCP2515_WriteReg(CNF3, 0x85); // CLKOUT 为SOF, PS2 = 6TQ
*/
MCP2515_WriteReg(TXRTSCTRL, 0x00); // 禁掉发送请求引脚(TXRTSCTRL为TXnRTS引脚控制和状态寄存器)
_NOP();
do{
//MCP2515_WriteReg(CANCTRL,0x40); //for test
MCP2515_WriteReg(CANCTRL, 0x00); //正常工作模式(CANCTRL为CAN控制寄存器)
temp2 = MCP2515_ReadReg(CANSTAT);
temp2 = temp2 >> 5;
}while(temp2 != 0x00); // 是否进入正常模式
_NOP();
MCP2515_BitModify(TXB0CTRL, 0x03, 0x03); // 最高优先级(TXB0CTRL为发送缓冲器0控制寄存器)
//temp3 = MCP2515_ReadReg(TXB0CTRL); // TXB0CTRL=0x03
_NOP();
MCP2515_WriteReg(CANINTF, 0x00); // 清所有中断标志(CANINTF为中断标志寄存器)
MCP2515_WriteReg(EFLG, 0x00); //(EFLG为错误标志寄存器)
MCP2515_WriteReg(CANINTE, 0x03); // 中断使能 10100011 //enable rxe0 rxe1(CANINTE为中断使能寄存)
_NOP();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -