原创 MCP2515驱动代码

2022-5-18 16:02 375 4 3 分类: MCU/ 嵌入式 文集: C语言
/*
 * @file    mcp2515.h 
 * @author  TanQi
 * @version V1.0.0
 * @date    2022-1-20
 * @brief   Header for mcp2515.c module
 */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MCP2515_H
#define __MCP2515_H

/* Includes ------------------------------------------------------------------*/
#include "board.h"

/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */

void MCP2515_Init(void);
void MCP2515_Poll(void);
void MCP2515_Poll_1ms(void);
void MCP2515_Reset(void);
void MCP2515_Read(uint8_t addr, uint8_t count, uint8_t * ptr);
void MCP2515_ReadRxBuf(uint8_t buf, uint8_t count, uint8_t * ptr);
void MCP2515_Write(uint8_t addr, uint8_t count, uint8_t * ptr);
void MCP2515_LoadTxBuf(uint8_t buf, uint8_t count, uint8_t * ptr);
void MCP2515_LoadTxDLC(uint8_t buf,uint8_t DLC);
void MCP2515_RTS(uint8_t txb);
uint8_t MCP2515_ReadStatus(void);
uint8_t MCP2515_RxStatus(void);
void MCP2515_BitModfye(uint8_t addr, uint8_t mask, uint8_t data);
void MCP2515_SetTxPriority(uint8_t txb, uint8_t priority);
void MCP2515_InitiateTx(uint8_t txb);
void MCP2515_SetRxMode(uint8_t rxb,uint8_t mode);
void MCP2515_BitTimingConfig(void);
void MCP2515_InterruptConfig(uint8_t bit_mask, uint8_t enable);
void MCP2515_LoadTxSID(uint8_t txb, uint32_t sid);
void MCP2515_LoadRxf(uint8_t rxf, uint32_t sid);
void MCP2515_LoadRxm(uint8_t rxm, uint32_t mask);
uint8_t MCP2515_ReadICOD(void);
void MCP2515_LoopBackMode(void);
void MCP2515_NormalOpMode(void);
#endif /* __MCP2515_H */
/*
 * @file    mcp2515.c
 * @author  TanQi
 * @version V1.0.0
 * @date    2022-1-20
 * @brief   mcp2515 driver
 */

#include "board.h"
#include "mcp2515.h"

#define RESET 0xc0 // 0b11000000
#define READ 0x03 // 0b00000011
#define READ_RX_BUF 0x90 // 0b10010nm0
#define WRITE 0x02 // 0b00000010
#define LOAD_TX_BUF 0x40 // 0b01000abc
#define RTS 0x80 // 0b10000nnn
#define READ_STATUS 0xa0 // 0b10100000
#define RX_STATUS 0xb0 // 0b10110000
#define BIT_MODIFY 0x05 // 0b00000101

void SPI_WriteByte(uint8_t byte)
{
// MSB first,rising edge clock in data
uint8_t i;
for(i = 0;i < 8;i++)
{
if(byte & (1<<7))
{
BOARD_SPI2_MOSI_SET();
}
else
{
BOARD_SPI2_MOSI_RESET();
}
byte <<= 1;
BOARD_SPI2_SCK_SET();
BOARD_SPI2_SCK_SET();
BOARD_SPI2_SCK_RESET();
BOARD_SPI2_SCK_RESET();
}
}

uint8_t SPI_ReadByte(void)
{
// MSB first,falling edge clock out data
uint8_t i;
uint8_t byte = 0;
for(i = 0;i < 8;i++)
{
byte <<= 1;
if(BOARD_MISO_READ())
{
byte |= 0x01;
}
else
{
byte &= ~0x01;
}
BOARD_SPI2_SCK_SET();
BOARD_SPI2_SCK_SET();
BOARD_SPI2_SCK_RESET();
BOARD_SPI2_SCK_RESET();
}
return byte;
}

void MCP2515_Reset(void)
{
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte(RESET);
BOARD_nSPI2_SS_INACTIVE();
}

void MCP2515_Read(uint8_t addr, uint8_t count, uint8_t * ptr)
{
uint8_t i;
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte(READ);
SPI_WriteByte(addr);
for(i = 0;i < count;i++)
{
*(ptr++) = SPI_ReadByte();
}
BOARD_nSPI2_SS_INACTIVE();
}

void MCP2515_ReadRxBuf(uint8_t buf, uint8_t count, uint8_t * ptr)
{
uint8_t i;
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte( READ_RX_BUF | (buf << 2) | (1 << 1) );
for(i = 0;i < count;i++)
{
*(ptr++) = SPI_ReadByte();
}
BOARD_nSPI2_SS_INACTIVE();
}

void MCP2515_Write(uint8_t addr, uint8_t count, uint8_t * ptr)
{
uint8_t i;
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte(WRITE);
SPI_WriteByte(addr);
for(i = 0;i < count;i++)
{
SPI_WriteByte(*(ptr++));
}
BOARD_nSPI2_SS_INACTIVE();
}

void MCP2515_LoadTxBuf(uint8_t buf, uint8_t count, uint8_t * ptr)
{
uint8_t i;
BOARD_nSPI2_SS_ACTIVE();
buf *= 2;
buf += 1;
SPI_WriteByte( LOAD_TX_BUF | buf );
for(i = 0;i < count;i++)
{
SPI_WriteByte(*(ptr++));
}
BOARD_nSPI2_SS_INACTIVE();
}

void MCP2515_LoadTxDLC(uint8_t buf,uint8_t DLC)
{
uint8_t addr;
if(buf == 0)
{
addr = 0x35;
}
else if(buf == 1)
{
addr = 0x45;
}
else if(buf == 2)
{
addr = 0x55;
}
MCP2515_Write(addr,1,&DLC);
}

static uint8_t read_out;

void MCP2515_RTS(uint8_t txb)
{
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte( RTS | (1<
BOARD_nSPI2_SS_INACTIVE();
MCP2515_Read(0x30, 1, &read_out); // debug
}

uint8_t MCP2515_ReadStatus(void)
{
uint8_t status;
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte(READ_STATUS);
status = SPI_ReadByte();
BOARD_nSPI2_SS_INACTIVE();
return status;
}

uint8_t MCP2515_RxStatus(void)
{
uint8_t status;
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte(RX_STATUS);
status = SPI_ReadByte();
BOARD_nSPI2_SS_INACTIVE();
return status;
}

void MCP2515_BitModfye(uint8_t addr, uint8_t mask, uint8_t data)
{
BOARD_nSPI2_SS_ACTIVE();
SPI_WriteByte(BIT_MODIFY);
SPI_WriteByte(addr);
SPI_WriteByte(mask);
SPI_WriteByte(data);
BOARD_nSPI2_SS_INACTIVE();
}

void MCP2515_SetTxPriority(uint8_t txb, uint8_t priority)
{
uint8_t start_addr;
if(txb == 0)
{
start_addr = 0x30;
}
else if(txb == 1)
{
start_addr = 0x40;
}
else if(txb == 2)
{
start_addr = 0x50;
}
MCP2515_BitModfye(start_addr, 0x03, priority);
}

void MCP2515_InitiateTx(uint8_t txb)
{
uint8_t addr;
if(txb == 0)
{
addr = 0x30;
}
else if(txb == 1)
{
addr = 0x40;
}
else if(txb == 2)
{
addr = 0x50;
}
MCP2515_BitModfye(addr, 1<<3, 1<<3);
MCP2515_BitModfye(0x0f, 1<<4, 0<<4);
}

/*
 * rxm : 11 = Turns mask/filters off; receives any message
 * 00 = Receives all valid messages using either Standard or Extended Identifiers that meet filter criteria;
 * Extended ID Filter registers, RXFnEID8:RXFnEID0, are applied to the first two bytes of data in
 * the messages with standard IDs
 */
void MCP2515_SetRxMode(uint8_t rxb,uint8_t mode)
{
uint8_t addr;
if(rxb == 0)
{
addr = 0x60;
}
else if(rxb == 1)
{
addr = 0x70;
}
MCP2515_BitModfye(addr, 0x03<<6, mode);
}

void MCP2515_ConfigMode(void)
{
uint8_t byte;
MCP2515_BitModfye(0x0f, 0x7<<5, 4<<5);
do
{
MCP2515_Read(0x0e, 1, &byte);
byte &= (0x07 << 5);
}
while(byte != (4<<5));
}

void MCP2515_LoopBackMode(void)
{
uint8_t byte;
MCP2515_BitModfye(0x0f, 0x7<<5, 2<<5);
do
{
MCP2515_Read(0x0e, 1, &byte);
byte &= (0x07 << 5);
}
while(byte != (2<<5));
}

void MCP2515_NormalOpMode(void)
{
uint8_t byte;
MCP2515_BitModfye(0x0f, 0x7<<5, 0<<5);
do
{
MCP2515_Read(0x0e, 1, &byte);
byte &= (0x07 << 5);
}
while(byte != (0<<5));
}

void MCP2515_BitTimingConfig(void)
{
/*
MCP2515_ConfigMode();
MCP2515_BitModfye(0x2a, 0xff, (0<<6) | (1<<0)); // 125KHz @ 8MHz,SJW = 1T_q, T_q = 2*(1 + 1)/8MHz = 0.5us
MCP2515_BitModfye(0x29, 0xff, (6<<3) | (1<<0)); // PS1 = 7T_q, ProgSeg = 2T_q
MCP2515_BitModfye(0x28, 0xff, (5<<0)); // PS2 = 6T_q
MCP2515_NormalOpMode();
*/
MCP2515_ConfigMode();
MCP2515_BitModfye(0x2a, 0xff, (0<<6) | (3<<0)); // 125KHz @ 8MHz,SJW = 1T_q, T_q = 2*(3 + 1)/8MHz = 1us
MCP2515_BitModfye(0x29, 0xff, (1<<7) | (2<<3) | (0<<0)); // PS1 = 3T_q, ProgSeg = 1T_q
MCP2515_BitModfye(0x28, 0xff, (2<<0)); // PS2 = 3T_q
MCP2515_NormalOpMode();
}

void MCP2515_InterruptConfig(uint8_t bit_mask, uint8_t enable)
{
MCP2515_ConfigMode();
if(enable)
{
MCP2515_BitModfye(0x2b, bit_mask, 0xff);
}
else
{
MCP2515_BitModfye(0x2b, bit_mask, 0x00);
}
MCP2515_NormalOpMode();
}

void MCP2515_LoadTxSID(uint8_t txb, uint32_t sid)
{
uint8_t addr;
uint8_t sid_array[2];
sid_array[0] = sid>>3;
sid_array[1] = (sid<<5);
if(txb == 0)
{
addr = 0x31;
}
else if(txb == 1)
{
addr = 0x41;
}
else if(txb == 2)
{
addr = 0x51;
}
// MCP2515_ConfigMode();
MCP2515_Write(addr, 2, sid_array);
}

void MCP2515_LoadRxf(uint8_t rxf, uint32_t sid)
{
uint8_t addr;
uint8_t sid_array[2];
sid_array[0] = sid>>3;
sid_array[1] = (sid<<5);
MCP2515_ConfigMode();
if(rxf == 0)
{
addr = 0x00;
}
else if(rxf == 1)
{
addr = 0x04;
}
else if(rxf == 2)
{
addr = 0x08;
}
else if(rxf == 3)
{
addr = 0x10;
}
else if(rxf == 4)
{
addr = 0x14;
}
else if(rxf == 5)
{
addr = 0x18;
}
MCP2515_Write(addr, 2, sid_array);
MCP2515_NormalOpMode();
}

void MCP2515_LoadRxm(uint8_t rxm, uint32_t mask)
{
uint8_t addr;
uint8_t mask_array[2];
mask_array[0] = mask>>3;
mask_array[1] = mask<<5;
MCP2515_ConfigMode();
if(rxm == 0)
{
addr = 0x20;
}
else if(rxm == 1)
{
addr = 0x24;
}
MCP2515_Write(addr, 2, mask_array);
MCP2515_NormalOpMode();
}

uint8_t MCP2515_ReadICOD(void)
{
uint8_t ret_val = 0;
MCP2515_Read(0x0e, 1, &ret_val);
ret_val >>= 1;
ret_val &= 0x07;
return ret_val;
}

作者: Qeecoda, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-1099225.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

给作者打赏,鼓励TA抓紧创作!

赞赏支持
点赞 4
赞赏0

文章评论0条评论)

登录后参与讨论
相关推荐阅读
Qeecoda 2021-06-19 17:37
实用可靠的干接点消抖滤波算法
[code]/* * * 干接点常用于实现各种电气设备开关停控制的弱电接口,两个触点可以组合出无动作、开、停和关4种状态。 * 干接点信号可以由手控面板发出,也可以由中控设备发出。 * 在手动应用中常...
Qeecoda 2020-06-11 22:56
一个让人头痛而又有趣的软件bug
这是我前几天遇到的bug,RS485协议程序我已经做过无数次了,有无数个成功的先例。当开始做这个小程序的时候,我认为对我而言这只是小菜一碟,我挥挥手就可以把它搞定。但是事情出乎我的意料!程序工作不正常...
Qeecoda 2020-05-17 16:02
电子产品常见故障现象、原因分析及改进措施(一)
1. 故障现象:通电无反应。原因分析:(1)接插件接不良;(2)470压敏电阻击穿;(3)开关电源的高压整流桥击穿;(4)开关电源的高压整理滤波电容损坏;(5)开关电源的开关管损坏;(6)开关电源的高...
Qeecoda 2020-03-28 11:11
欧姆定律的推导过程
...
Qeecoda 2020-03-23 18:18
环环紧扣,从傅里叶级数到Z变换的推导过程(六)
...
我要评论
0
4
1
2
3
4
5
6
7
8
9
0
关闭 热点推荐上一条 /3 下一条