piMCP2515
A library for controlling an MCP2515 on the Raspberry Pi and Raspberry Pi Pico
Loading...
Searching...
No Matches
pi_MCP2515.h
1/* Copyright 2026 Roos Catling-Tate
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any purpose with or
4 * without fee is hereby granted, provided that the above copyright notice and this permission
5 * notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
13 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */
15
16/* External Header.
17 *
18 * This is for including in projects that use the library. It must match up to the internal headers, which is currently
19 * done manually. I don't really like this approach, but it will do the job for now.
20 *
21 * TODO First draft. Tidy and finish the external header stuff.
22 */
23
24#ifndef PIMCP2515_PI_MCP2515_H
25#define PIMCP2515_PI_MCP2515_H
26
27#include <stdarg.h>
28#include <stdbool.h>
29#include <stdint.h>
30
31#define PI_MCP2515_CAN_FRAME_PAYLOAD_MAX 8
32
36typedef struct {
37 uint32_t id;
38 bool extended_id;
39 bool rtr;
40 uint8_t dlc;
41 uint8_t payload[PI_MCP2515_CAN_FRAME_PAYLOAD_MAX];
43
49typedef enum {
50 PI_MCP2515_RGSTR_RXF0SIDH = 0x00,
51 PI_MCP2515_RGSTR_RXF1SIDH = 0x04,
52 PI_MCP2515_RGSTR_RXF2SIDH = 0x08,
53 PI_MCP2515_RGSTR_RXF3SIDH = 0x10,
54 PI_MCP2515_RGSTR_RXF4SIDH = 0x14,
55 PI_MCP2515_RGSTR_RXF5SIDH = 0x18,
56 PI_MCP2515_RGSTR_RXM0SIDH = 0x20,
57 PI_MCP2515_RGSTR_RXM1SIDH = 0x24,
58 PI_MCP2515_RGSTR_CANSTAT = 0x0E,
59 PI_MCP2515_RGSTR_CANCTRL = 0x0F,
60 PI_MCP2515_RGSTR_CANINTE = 0x2B,
61 PI_MCP2515_RGSTR_CANINTF = 0x2C,
62 PI_MCP2515_RGSTR_EFLG = 0x2D,
63 PI_MCP2515_RGSTR_ECRX = 0x1D,
64 PI_MCP2515_RGSTR_ECTX = 0x1C,
65 PI_MCP2515_RGSTR_CNF1 = 0x2A,
66 PI_MCP2515_RGSTR_CNF2 = 0x29,
67 PI_MCP2515_RGSTR_CNF3 = 0x28,
68 PI_MCP2515_RGSTR_RXB0CTRL = 0x60,
69 PI_MCP2515_RGSTR_RXB0SIDH = 0x61,
70 PI_MCP2515_RGSTR_RXB0SIDL = 0x62,
71 PI_MCP2515_RGSTR_RXB0DATA = 0x66,
72 PI_MCP2515_RGSTR_RXB1CTRL = 0x70,
73 PI_MCP2515_RGSTR_RXB1SIDH = 0x71,
74 PI_MCP2515_RGSTR_RXB1SIDL = 0x72,
75 PI_MCP2515_RGSTR_RXB1DATA = 0x76,
76 PI_MCP2515_RGSTR_TXB0CTRL = 0x30,
77 PI_MCP2515_RGSTR_TXB0SIDH = 0x31,
78 PI_MCP2515_RGSTR_TXB0SIDL = 0x32,
79 PI_MCP2515_RGSTR_TXB0EID8 = 0x33,
80 PI_MCP2515_RGSTR_TXB0EID0 = 0x34,
81 PI_MCP2515_RGSTR_TXB0DLC = 0x35,
82 PI_MCP2515_RGSTR_TXB0DATA = 0x36,
83 PI_MCP2515_RGSTR_TXB1CTRL = 0x40,
84 PI_MCP2515_RGSTR_TXB1SIDH = 0x41,
85 PI_MCP2515_RGSTR_TXB1SIDL = 0x42,
86 PI_MCP2515_RGSTR_TXB1EID8 = 0x43,
87 PI_MCP2515_RGSTR_TXB1EID0 = 0x44,
88 PI_MCP2515_RGSTR_TXB1DLC = 0x45,
89 PI_MCP2515_RGSTR_TXB1DATA = 0x46,
90 PI_MCP2515_RGSTR_TXB2CTRL = 0x50,
91 PI_MCP2515_RGSTR_TXB2SIDH = 0x51,
92 PI_MCP2515_RGSTR_TXB2SIDL = 0x52,
93 PI_MCP2515_RGSTR_TXB2EID8 = 0x53,
94 PI_MCP2515_RGSTR_TXB2EID0 = 0x54,
95 PI_MCP2515_RGSTR_TXB2DLC = 0x55,
96 PI_MCP2515_RGSTR_TXB2DATA = 0x56,
97} mcp2515_rgstr_t;
99
105#define PI_MCP2515_INSTR_WRITE 0x02
106#define PI_MCP2515_INSTR_READ 0x03
107#define PI_MCP2515_INSTR_BITMOD 0x05
108#define PI_MCP2515_INSTR_READ_STATUS 0xA0
109#define PI_MCP2515_INSTR_RX_STATUS 0xB0
110#define PI_MCP2515_INSTR_RESET 0xC0
111
112#define PI_MCP2515_INSTR_LOAD_TX0 0x40
113#define PI_MCP2515_INSTR_LOAD_TX1 0x42
114#define PI_MCP2515_INSTR_LOAD_TX2 0x44
115
116#define PI_MCP2515_INSTR_READ_RX0 0x90
117#define PI_MCP2515_INSTR_READ_RX1 0x94
118
119/* These can be `|`'d together to apply the RTS instruction to multiple buffers. */
120#define PI_MCP2515_INSTR_RTS_TX0 0x81
121#define PI_MCP2515_INSTR_RTS_TX1 0x82
122#define PI_MCP2515_INSTR_RTS_TX2 0x84
124
138#define PI_MCP2515_REQOP_MASK 0xE0
140
141/* CTRL Definitions */
142#define PI_MCP2515_CTRL_RTR 0x08
143#define PI_MCP2515_CTRL_TXREQ 0x08
144#define PI_MCP2515_CTRL_TXERR 0x10
145#define PI_MCP2515_CTRL_MLOA 0x20
146#define PI_MCP2515_CTRL_ABTF 0x40
147#define PI_MCP2515_RXBCTRL_STDEXT_MASK 0x60
148
154#define PI_MCP2515_EFLG_EWARN 0x01
155#define PI_MCP2515_EFLG_RXWAR 0x02
156#define PI_MCP2515_EFLG_TXWAR 0x04
157#define PI_MCP2515_EFLG_RXEP 0x08
158#define PI_MCP2515_EFLG_TXEP 0x10
159#define PI_MCP2515_EFLG_TXBO 0x20
160#define PI_MCP2515_EFLG_RX0OVR 0x40
161#define PI_MCP2515_EFLG_RX1OVR 0x80
162#define PI_MCP2515_EFLG_MASK 0xF8
164
165#define PI_MCP2515_RXBSIDL_IDE 0x08
166#define PI_MCP2515_RXBSIDL_SRR 0x10
167
173#define PI_MCP2515_RX_STATUS_RCV_RXB0 0x40
174#define PI_MCP2515_RX_STATUS_RCV_RXB1 0x80
175#define PI_MCP2515_RX_STATUS_RCV_ALL 0xc0
176#define PI_MCP2515_RX_STATUS_RTR 0x08
177#define PI_MCP2515_RX_STATUS_EID 0x10
179
180/* Status Definitions */
181#define PI_MCP2515_STATUS_RX0BF 0x01
182#define PI_MCP2515_STATUS_RX1BF 0x02
183#define PI_MCP2515_STATUS_TX0IF 0x08
184#define PI_MCP2515_STATUS_TX1IF 0x20
185#define PI_MCP2515_STATUS_TX2IF 0x80
186
192#define PI_MCP2515_CANINTF_RX0 0x01
193#define PI_MCP2515_CANINTF_RX1 0x02
194#define PI_MCP2515_CANINTF_TX0IF 0x04
195#define PI_MCP2515_CANINTF_TX1IF 0x08
196#define PI_MCP2515_CANINTF_TX2IF 0x10
197#define PI_MCP2515_CANINTF_ERRIF 0x20
199
200typedef enum {
201 PI_MCP2515_TXB0 = 0,
202 PI_MCP2515_TXB1 = 1,
203 PI_MCP2515_TXB2 = 2,
204} mcp2515_txb_t;
205
206typedef enum {
207 PI_MCP2515_RXB0 = 0,
208 PI_MCP2515_RXB1 = 1,
209} mcp2515_rxb_t;
210
211typedef enum {
212 PI_MCP2515_RXM0 = 0,
213 PI_MCP2515_RXM1 = 1,
214} mcp2515_rxm_t;
215
216typedef enum {
217 PI_MCP2515_RXF0 = 0,
218 PI_MCP2515_RXF1 = 1,
219 PI_MCP2515_RXF2 = 2,
220 PI_MCP2515_RXF3 = 3,
221 PI_MCP2515_RXF4 = 4,
222 PI_MCP2515_RXF5 = 5,
223} mcp2515_rxf_t;
224
225/* CAN frame Mask Definitions */
226#define PI_MCP2515_CAN_ID_SFF_MASK 0x000007FFUL
227#define PI_MCP2515_CAN_ID_EFF_MASK 0x1FFFFFFFUL
228#define PI_MCP2515_CAN_DLC_RTR_FLAG 0x40
229#define PI_MCP2515_CAN_DLC_RTR_MASK 0x0F
230
231#define MCP2515_REQOP_CHANGE_SLEEP_CYCLES 128
232
233typedef struct pi_mcp2515 pi_mcp2515_t;
234
235uint32_t mcp2515_can_id_build(uint32_t, bool);
236int mcp2515_can_clear_txif(pi_mcp2515_t *, uint8_t);
237int mcp2515_can_message_send(pi_mcp2515_t *, const pi_mcp2515_can_frame_t *);
239int mcp2515_can_message_read_rxb(pi_mcp2515_t *, mcp2515_rxb_t, pi_mcp2515_can_frame_t *);
240bool mcp2515_can_message_received(pi_mcp2515_t *);
241void mcp2515_rts(pi_mcp2515_t *, uint8_t);
242
243uint8_t mcp2515_interrupts_get(pi_mcp2515_t *);
244uint8_t mcp2515_interrupts_mask(pi_mcp2515_t *);
245void mcp2515_interrupts_clear(pi_mcp2515_t *);
246
247int mcp2515_filter(pi_mcp2515_t *, mcp2515_rxf_t, uint32_t, bool);
248int mcp2515_filter_mask(pi_mcp2515_t *, mcp2515_rxm_t, uint32_t, bool);
249int mcp2515_filter_enable(pi_mcp2515_t *, bool);
250int mcp2515_filter_enable_rxb(pi_mcp2515_t *, mcp2515_rxb_t, bool);
251
252int mcp2515_register_read(pi_mcp2515_t *, uint8_t *, uint8_t, mcp2515_rgstr_t);
253int mcp2515_register_write(pi_mcp2515_t *, uint8_t[], uint8_t, mcp2515_rgstr_t);
254int mcp2515_register_bitmod(pi_mcp2515_t *, uint8_t, uint8_t, mcp2515_rgstr_t);
255
256int mcp2515_reset(pi_mcp2515_t *);
257int mcp2515_reqop(pi_mcp2515_t *, mcp2515_reqop_t);
258mcp2515_reqop_t mcp2515_reqop_get(pi_mcp2515_t *);
259
260uint8_t mcp2515_status(pi_mcp2515_t *);
261uint8_t mcp2515_error_tx_count(pi_mcp2515_t *);
262uint8_t mcp2515_error_rx_count(pi_mcp2515_t *);
263uint8_t mcp2515_error_flags(pi_mcp2515_t *);
264bool mcp2515_error(pi_mcp2515_t *);
265int mcp2515_error_clear_errif(pi_mcp2515_t *);
266
267void mcp2515_micro_sleep(uint64_t micro_s);
268uint64_t mcp2515_osc_time(const pi_mcp2515_t *, uint32_t);
269
270int mcp2515_bitrate_default_16mhz_1000kbps(pi_mcp2515_t *);
271int mcp2515_bitrate_default_8mhz_500kbps(pi_mcp2515_t *);
272int mcp2515_bitrate_simplified(pi_mcp2515_t *, uint16_t);
273int mcp2515_bitrate_full_optional(pi_mcp2515_t *, uint16_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t,
274 bool, bool, bool, bool);
275int mcp2515_reset(pi_mcp2515_t *);
276
277void mcp2515_free(pi_mcp2515_t *);
278int mcp2515_init(pi_mcp2515_t **, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint32_t, uint8_t);
279int mcp2515_cnf_set(pi_mcp2515_t *, uint8_t, uint8_t, uint8_t);
280uint8_t mcp2515_cnf_get(pi_mcp2515_t *, uint8_t);
281
282void mcp2515_conf_spi_devpath(pi_mcp2515_t *, char *);
283void mcp2515_conf_gpio_devpath(pi_mcp2515_t *, char *);
284
285void mcp2515_debug_enable(pi_mcp2515_t *, void (*)(char *, va_list));
286
287#endif /* PIMCP2515_PI_MCP2515_H */
int mcp2515_can_message_read(pi_mcp2515_t *, pi_mcp2515_can_frame_t *)
Read a CAN bus message.
Definition can.c:173
int mcp2515_can_message_send(pi_mcp2515_t *, const pi_mcp2515_can_frame_t *)
Send a CAN bus message.
Definition can.c:112
bool mcp2515_can_message_received(pi_mcp2515_t *)
Check if there is a CAN bus message received.
Definition can.c:244
int mcp2515_init(pi_mcp2515_t **, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint32_t, uint8_t)
Setup and prepare a pi_mcp2515_t structure based on the parameters provided.
Definition pi_MCP2515.c:199
uint8_t mcp2515_cnf_get(pi_mcp2515_t *, uint8_t)
Get the value of a CNF register.
Definition pi_MCP2515.c:157
int mcp2515_bitrate_simplified(pi_mcp2515_t *, uint16_t)
A simplified bitrate setting function.
Definition pi_MCP2515.c:40
int mcp2515_cnf_set(pi_mcp2515_t *, uint8_t, uint8_t, uint8_t)
Set the values of all CNF register.
Definition pi_MCP2515.c:135
void mcp2515_conf_gpio_devpath(pi_mcp2515_t *, char *)
Override the default path for the gpio device (ex /dev/gpio0).
Definition pi_MCP2515.c:268
int mcp2515_bitrate_full_optional(pi_mcp2515_t *, uint16_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, bool, bool, bool, bool)
Configure the bitrate and all other CNF register stored parameters.
Definition pi_MCP2515.c:70
void mcp2515_free(pi_mcp2515_t *)
Cleanup after everything.
Definition pi_MCP2515.c:283
void mcp2515_conf_spi_devpath(pi_mcp2515_t *, char *)
Override the default path for the spi device (ex /dev/spi0).
Definition pi_MCP2515.c:246
int mcp2515_error_clear_errif(pi_mcp2515_t *)
Clear error interrupt flag.
Definition status_error.c:116
uint8_t mcp2515_status(pi_mcp2515_t *)
Check status via the STATUS instruction.
Definition status_error.c:34
uint8_t mcp2515_error_rx_count(pi_mcp2515_t *)
Check the value of the 'receive' (RX) error counter.
Definition status_error.c:72
uint8_t mcp2515_error_tx_count(pi_mcp2515_t *)
Check the value of the 'transmit' (TX) error counter.
Definition status_error.c:56
bool mcp2515_error(pi_mcp2515_t *)
Check error flags in the EFLG register.
Definition status_error.c:104
uint8_t mcp2515_error_flags(pi_mcp2515_t *)
Fetch the contents of the error flag (EFLG) register.
Definition status_error.c:88
int mcp2515_filter_mask(pi_mcp2515_t *, mcp2515_rxm_t, uint32_t, bool)
Set the filter mask. The MCP2515 must be in config mode to use this (see mcp2515_reqop/mcp2515_reqop_...
Definition filter.c:85
int mcp2515_filter(pi_mcp2515_t *, mcp2515_rxf_t, uint32_t, bool)
Set one of the filters specified by its register.
Definition filter.c:38
uint8_t mcp2515_interrupts_mask(pi_mcp2515_t *)
Retrieve the interrupt mask.
Definition interrupt.c:50
void mcp2515_interrupts_clear(pi_mcp2515_t *)
Clear all interrupts.
Definition interrupt.c:65
uint8_t mcp2515_interrupts_get(pi_mcp2515_t *)
Check for interrupts.
Definition interrupt.c:34
int mcp2515_register_bitmod(pi_mcp2515_t *, uint8_t, uint8_t, mcp2515_rgstr_t)
Change the value of a register via an SPI bit modify.
Definition registers.c:94
int mcp2515_register_read(pi_mcp2515_t *, uint8_t *, uint8_t, mcp2515_rgstr_t)
Read a value from a specified register.
Definition registers.c:35
int mcp2515_register_write(pi_mcp2515_t *, uint8_t[], uint8_t, mcp2515_rgstr_t)
Write a value to the specified register.
Definition registers.c:64
mcp2515_reqop_t mcp2515_reqop_get(pi_mcp2515_t *)
Get the current operating mode.
Definition reqop.c:100
int mcp2515_reqop(pi_mcp2515_t *, mcp2515_reqop_t)
Change the operating mode.
Definition reqop.c:81
int mcp2515_reset(pi_mcp2515_t *)
Issue a reset command to the MCP2515 via the SPI interface.
Definition reqop.c:34
mcp2515_reqop_t
Definition pi_MCP2515.h:130
@ PI_MCP2515_REQOP_CONFIG
Config operating mode.
Definition pi_MCP2515.h:135
@ PI_MCP2515_REQOP_SLEEP
Sleep operating mode.
Definition pi_MCP2515.h:132
@ PI_MCP2515_REQOP_POWERUP
Powerup operating mode.
Definition pi_MCP2515.h:136
@ PI_MCP2515_REQOP_LOOPBACK
Loopback operating mode.
Definition pi_MCP2515.h:133
@ PI_MCP2515_REQOP_NORMAL
Normal operating mode.
Definition pi_MCP2515.h:131
@ PI_MCP2515_REQOP_LISTENONLY
Listenonly operating mode.
Definition pi_MCP2515.h:134
CAN bus frame data structure.
Definition pi_MCP2515.h:36