From 94b454765086cfaddee63921ac1f2d9b5598a762 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Fri, 3 Oct 2025 17:33:55 -0400 Subject: mcp2515 spi functions --- fw/can.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- fw/can.h | 4 ++ 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/fw/can.c b/fw/can.c index b005fc2..b311383 100644 --- a/fw/can.c +++ b/fw/can.c @@ -2,14 +2,30 @@ #include +#include "system.h" #include "types.h" +#include "spi.h" #include "can.h" +// Oscillator startup timeout +#define STARTUP_TIME 128u + // Register addresses enum { - // Pin control and status - REG_BFPCTRL = 0x0C, + // Config + REG_BFPCTRL = 0x0C, // pin control and status + REG_CANCTRL = 0x0F, // CAN control + REG_CANSTAT = 0x0E, // CAN status + + // Bit timing + REG_CNF1 = 0x2A, + REG_CNF2 = 0x29, + REG_CNF3 = 0x28, + + // Interrupts + REG_CANINTE = 0x2B, // CAN interrupt enable + REG_CANINTF = 0x2C, // CAN interrupt flag // Filter 0 REG_RXF0SIDH = 0x00, // standard ID high @@ -48,7 +64,7 @@ enum { REG_RXF5EID0 = 0x1B, // extended ID low // Mask 0 - REG_RXM0SIDH = 0x20, standard ID high + REG_RXM0SIDH = 0x20, // standard ID high REG_RXM0SIDL = 0x21, // standard ID low REG_RXM0EID8 = 0x22, // extended ID high REG_RXM0EID0 = 0x23, // extended ID low @@ -56,7 +72,7 @@ enum { // Mask 1 REG_RXM1SIDH = 0x24, // standard ID high REG_RXM1SIDL = 0x25, // standard ID low - REG_RXM1EID8 = 0x26. // extended ID high + REG_RXM1EID8 = 0x26, // extended ID high REG_RXM1EID0 = 0x27, // extended ID low // Receive buffer 0 @@ -77,3 +93,110 @@ enum { REG_RXB1DLC = 0x75, // data length code REG_RXB1DM = 0x76, // data byte [76h+0, 76h+7] }; + +// Modes of operation +typedef enum { + MODE_NORMAL = 0x0, + MODE_SLEEP = 0x1, + MODE_LOOPBACK = 0x2, + MODE_LISTEN_ONLY = 0x3, + MODE_CONFIG = 0x4, +} Mode; + +// Instructions +enum { + CMD_RESET = 0xC0, + CMD_READ = 0x03, + CMD_READ_RX = 0x90, + CMD_WRITE = 0x02, + CMD_LOAD_TX = 0x40, + CMD_RTS = 0x80, + CMD_READ_STATUS = 0xA0, + CMD_RX_STATUS = 0xB0, + CMD_BIT_MODIFY = 0x05, +}; + +// Receive buffer identifiers +typedef enum { + RXB0 = 0, + RXB1 = 1, +} RxBuf; + +// Send RESET instruction. +static void +reset(void) { + CAN_CS = 0; + (void)spiTx(CMD_RESET); + CAN_CS = 1; +} + +// Read n registers into data, starting at the specified address. +static void +read(U8 addr, U8 *data, U8 n) { + CAN_CS = 0; + (void)spiTx(CMD_READ); + (void)spiTx(addr); + while (n--) { + *data = spiTx(0x00); + data++; + } + CAN_CS = 1; +} + +// Read the DATA field of one of the RX buffers. +static void +readRxData(RxBuf bufNum, U8 data[8u]) { + U8 i; + + CAN_CS = 0; + (void)spiTx(CMD_READ_RX | (U8)(bufNum << 2u) | 1u); // start at RXBnD0 + for (i = 0u; i < 8u; i++) { + data[i] = spiTx(0x00); + } + CAN_CS = 1; +} + +// Write to a register. +static void +write(U8 addr, U8 data) { + CAN_CS = 0; + (void)spiTx(CMD_WRITE); + (void)spiTx(addr); + (void)spiTx(data); + CAN_CS = 1; +} + +// Read RX status. +static U8 +rxStatus(void) { + U8 status; + + CAN_CS = 0; + (void)spiTx(CMD_RX_STATUS); + status = spiTx(0x00); + CAN_CS = 1; + return status; +} + +// Write individual bits of a register with the BIT MODIFY instruction. +static void +bitModify(U8 addr, U8 mask, U8 data) { + CAN_CS = 0; + (void)spiTx(CMD_BIT_MODIFY); + (void)spiTx(addr); + (void)spiTx(mask); + (void)spiTx(data); + CAN_CS = 1; +} + +void +canInit(void) { + CAN_CS_TRIS = OUT; + CAN_CS = 1; + + _delay(STARTUP_TIME); // wait for MCP2515 to power on + reset(); // send RESET command + _delay(STARTUP_TIME); // wait to power on again + + // TODO +} diff --git a/fw/can.h b/fw/can.h index 320c020..833a7c4 100644 --- a/fw/can.h +++ b/fw/can.h @@ -12,6 +12,10 @@ * #include "can.h" */ +// Pin mapping +#define CAN_CS_TRIS TRISAbits.TRISA5 +#define CAN_CS LATAbits.LATA5 + // Bit timings (CNF1, CNF2, CNF3) #define CAN_TIMINGS_10K 0xDE, 0xAD, 0x06 // BRP=30, PropSeg=6, PS1=6, PS2=7, SP=65%, SJW=4 #define CAN_TIMINGS_20K 0xCF, 0xAD, 0x06 // BRP=15, PropSeg=6, PS1=6, PS2=7, SP=65%, SJW=4 -- cgit v1.2.3