Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mcp2515 by
mcp2515.cpp@0:d8f50b1e384f, 2010-01-30 (annotated)
- Committer:
- tecnosys
- Date:
- Sat Jan 30 08:46:04 2010 +0000
- Revision:
- 0:d8f50b1e384f
- Child:
- 1:dbc44582f2f8
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| tecnosys | 0:d8f50b1e384f | 1 | /****************************************************************************** |
| tecnosys | 0:d8f50b1e384f | 2 | * |
| tecnosys | 0:d8f50b1e384f | 3 | * Controller Area Network (CAN) Demo-Application |
| tecnosys | 0:d8f50b1e384f | 4 | * Atmel AVR with Microchip MCP2515 |
| tecnosys | 0:d8f50b1e384f | 5 | * |
| tecnosys | 0:d8f50b1e384f | 6 | * Copyright (C) 2005 Martin THOMAS, Kaiserslautern, Germany |
| tecnosys | 0:d8f50b1e384f | 7 | * <eversmith@heizung-thomas.de> |
| tecnosys | 0:d8f50b1e384f | 8 | * http://www.siwawi.arubi.uni-kl.de/avr_projects |
| tecnosys | 0:d8f50b1e384f | 9 | * |
| tecnosys | 0:d8f50b1e384f | 10 | ***************************************************************************** |
| tecnosys | 0:d8f50b1e384f | 11 | * |
| tecnosys | 0:d8f50b1e384f | 12 | * File : mcp2515.c |
| tecnosys | 0:d8f50b1e384f | 13 | * Version : 0.9 |
| tecnosys | 0:d8f50b1e384f | 14 | * |
| tecnosys | 0:d8f50b1e384f | 15 | * Summary : MCP2515 "low-level" driver |
| tecnosys | 0:d8f50b1e384f | 16 | * |
| tecnosys | 0:d8f50b1e384f | 17 | * Parts of this code are adapted from a MCP2510 sample-application |
| tecnosys | 0:d8f50b1e384f | 18 | * by KVASER AB, http://www.kvaser.com (KVASER-code is marked as free) |
| tecnosys | 0:d8f50b1e384f | 19 | * |
| tecnosys | 0:d8f50b1e384f | 20 | * This code-module is free to use but you have to keep the copyright |
| tecnosys | 0:d8f50b1e384f | 21 | * notice. |
| tecnosys | 0:d8f50b1e384f | 22 | * |
| tecnosys | 0:d8f50b1e384f | 23 | * |
| tecnosys | 0:d8f50b1e384f | 24 | ***************************************************************************** |
| tecnosys | 0:d8f50b1e384f | 25 | * |
| tecnosys | 0:d8f50b1e384f | 26 | * File : mcp2515.cpp (mbed LPC1768 version) |
| tecnosys | 0:d8f50b1e384f | 27 | * Version : 0.1 |
| tecnosys | 0:d8f50b1e384f | 28 | * |
| tecnosys | 0:d8f50b1e384f | 29 | * All credits to the nerds above, this source has been adapted for the |
| tecnosys | 0:d8f50b1e384f | 30 | * LPC1768 platform by J.Engelman. And does'nt require and of the copyrighted |
| tecnosys | 0:d8f50b1e384f | 31 | * SPI or AVR controller code that Martin or co have excluded copyright. |
| tecnosys | 0:d8f50b1e384f | 32 | * This module remains free. |
| tecnosys | 0:d8f50b1e384f | 33 | * |
| tecnosys | 0:d8f50b1e384f | 34 | * |
| tecnosys | 0:d8f50b1e384f | 35 | *****************************************************************************/ |
| tecnosys | 0:d8f50b1e384f | 36 | |
| tecnosys | 0:d8f50b1e384f | 37 | #include "mcp2515.h" |
| tecnosys | 0:d8f50b1e384f | 38 | |
| tecnosys | 0:d8f50b1e384f | 39 | #include <mbed.h> |
| tecnosys | 0:d8f50b1e384f | 40 | #include "mcp2515_can.h" |
| tecnosys | 0:d8f50b1e384f | 41 | #include "mcp2515_defs.h" |
| tecnosys | 0:d8f50b1e384f | 42 | #include "mcp2515_bittime.h" |
| tecnosys | 0:d8f50b1e384f | 43 | |
| tecnosys | 0:d8f50b1e384f | 44 | #define SPI_NULL (0x00) |
| tecnosys | 0:d8f50b1e384f | 45 | |
| tecnosys | 0:d8f50b1e384f | 46 | |
| tecnosys | 0:d8f50b1e384f | 47 | |
| tecnosys | 0:d8f50b1e384f | 48 | mcp2515::mcp2515(PinName mosi, PinName miso, PinName clk, PinName ncs) |
| tecnosys | 0:d8f50b1e384f | 49 | : _spi(mosi, miso, clk), _ncs(ncs) { |
| tecnosys | 0:d8f50b1e384f | 50 | |
| tecnosys | 0:d8f50b1e384f | 51 | // _spi.format(8,0); |
| tecnosys | 0:d8f50b1e384f | 52 | // _spi.frequency(10000000); |
| tecnosys | 0:d8f50b1e384f | 53 | //_spi.frequency(5000000); |
| tecnosys | 0:d8f50b1e384f | 54 | |
| tecnosys | 0:d8f50b1e384f | 55 | } |
| tecnosys | 0:d8f50b1e384f | 56 | |
| tecnosys | 0:d8f50b1e384f | 57 | |
| tecnosys | 0:d8f50b1e384f | 58 | void mcp2515::_reset() { |
| tecnosys | 0:d8f50b1e384f | 59 | |
| tecnosys | 0:d8f50b1e384f | 60 | _select(); |
| tecnosys | 0:d8f50b1e384f | 61 | _spi_readwrite(MCP_RESET); |
| tecnosys | 0:d8f50b1e384f | 62 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 63 | wait(0.001); |
| tecnosys | 0:d8f50b1e384f | 64 | } |
| tecnosys | 0:d8f50b1e384f | 65 | |
| tecnosys | 0:d8f50b1e384f | 66 | void mcp2515::setRegister(const uint8_t address, const uint8_t value) |
| tecnosys | 0:d8f50b1e384f | 67 | { |
| tecnosys | 0:d8f50b1e384f | 68 | _select(); |
| tecnosys | 0:d8f50b1e384f | 69 | _spi_readwrite(MCP_WRITE); |
| tecnosys | 0:d8f50b1e384f | 70 | _spi_readwrite(address); |
| tecnosys | 0:d8f50b1e384f | 71 | _spi_readwrite(value); |
| tecnosys | 0:d8f50b1e384f | 72 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 73 | } |
| tecnosys | 0:d8f50b1e384f | 74 | |
| tecnosys | 0:d8f50b1e384f | 75 | uint8_t mcp2515::configRate(const uint8_t canSpeed) |
| tecnosys | 0:d8f50b1e384f | 76 | { |
| tecnosys | 0:d8f50b1e384f | 77 | uint8_t set, cfg1, cfg2, cfg3; |
| tecnosys | 0:d8f50b1e384f | 78 | |
| tecnosys | 0:d8f50b1e384f | 79 | set = 0; |
| tecnosys | 0:d8f50b1e384f | 80 | |
| tecnosys | 0:d8f50b1e384f | 81 | switch (canSpeed) { |
| tecnosys | 0:d8f50b1e384f | 82 | case (CAN_125KBPS) : |
| tecnosys | 0:d8f50b1e384f | 83 | cfg1 = MCP_4MHz_125kBPS_CFG1 ; |
| tecnosys | 0:d8f50b1e384f | 84 | cfg2 = MCP_4MHz_125kBPS_CFG2 ; |
| tecnosys | 0:d8f50b1e384f | 85 | cfg3 = MCP_4MHz_125kBPS_CFG3 ; |
| tecnosys | 0:d8f50b1e384f | 86 | set = 1; |
| tecnosys | 0:d8f50b1e384f | 87 | break; |
| tecnosys | 0:d8f50b1e384f | 88 | case (CAN_20KBPS) : |
| tecnosys | 0:d8f50b1e384f | 89 | cfg1 = MCP_4MHz_20kBPS_CFG1 ; |
| tecnosys | 0:d8f50b1e384f | 90 | cfg2 = MCP_4MHz_20kBPS_CFG2 ; |
| tecnosys | 0:d8f50b1e384f | 91 | cfg3 = MCP_4MHz_20kBPS_CFG3 ; |
| tecnosys | 0:d8f50b1e384f | 92 | set = 1; |
| tecnosys | 0:d8f50b1e384f | 93 | break; |
| tecnosys | 0:d8f50b1e384f | 94 | default: |
| tecnosys | 0:d8f50b1e384f | 95 | set = 0; |
| tecnosys | 0:d8f50b1e384f | 96 | break; |
| tecnosys | 0:d8f50b1e384f | 97 | } |
| tecnosys | 0:d8f50b1e384f | 98 | |
| tecnosys | 0:d8f50b1e384f | 99 | if (set) { |
| tecnosys | 0:d8f50b1e384f | 100 | setRegister(MCP_CNF1, cfg1); |
| tecnosys | 0:d8f50b1e384f | 101 | setRegister(MCP_CNF2, cfg2); |
| tecnosys | 0:d8f50b1e384f | 102 | setRegister(MCP_CNF3, cfg3); |
| tecnosys | 0:d8f50b1e384f | 103 | return MCP2515_OK; |
| tecnosys | 0:d8f50b1e384f | 104 | } |
| tecnosys | 0:d8f50b1e384f | 105 | else { |
| tecnosys | 0:d8f50b1e384f | 106 | return MCP2515_FAIL; |
| tecnosys | 0:d8f50b1e384f | 107 | } |
| tecnosys | 0:d8f50b1e384f | 108 | } |
| tecnosys | 0:d8f50b1e384f | 109 | |
| tecnosys | 0:d8f50b1e384f | 110 | uint8_t mcp2515::readRegister(const uint8_t address) |
| tecnosys | 0:d8f50b1e384f | 111 | { |
| tecnosys | 0:d8f50b1e384f | 112 | uint8_t ret; |
| tecnosys | 0:d8f50b1e384f | 113 | |
| tecnosys | 0:d8f50b1e384f | 114 | _select(); |
| tecnosys | 0:d8f50b1e384f | 115 | _spi_readwrite(MCP_READ); |
| tecnosys | 0:d8f50b1e384f | 116 | _spi_readwrite(address); |
| tecnosys | 0:d8f50b1e384f | 117 | ret = _spi_read(); |
| tecnosys | 0:d8f50b1e384f | 118 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 119 | |
| tecnosys | 0:d8f50b1e384f | 120 | return ret; |
| tecnosys | 0:d8f50b1e384f | 121 | } |
| tecnosys | 0:d8f50b1e384f | 122 | |
| tecnosys | 0:d8f50b1e384f | 123 | void mcp2515::readRegisterS(const uint8_t address, |
| tecnosys | 0:d8f50b1e384f | 124 | uint8_t values[], const uint8_t n) |
| tecnosys | 0:d8f50b1e384f | 125 | { |
| tecnosys | 0:d8f50b1e384f | 126 | uint8_t i; |
| tecnosys | 0:d8f50b1e384f | 127 | |
| tecnosys | 0:d8f50b1e384f | 128 | _select(); |
| tecnosys | 0:d8f50b1e384f | 129 | _spi_readwrite(MCP_READ); |
| tecnosys | 0:d8f50b1e384f | 130 | _spi_readwrite(address); |
| tecnosys | 0:d8f50b1e384f | 131 | // mcp2515 has auto-increment of address-pointer |
| tecnosys | 0:d8f50b1e384f | 132 | for (i=0; i<n; i++) { |
| tecnosys | 0:d8f50b1e384f | 133 | values[i] = _spi_read(); |
| tecnosys | 0:d8f50b1e384f | 134 | } |
| tecnosys | 0:d8f50b1e384f | 135 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 136 | } |
| tecnosys | 0:d8f50b1e384f | 137 | |
| tecnosys | 0:d8f50b1e384f | 138 | void mcp2515::modifyRegister(const uint8_t address, |
| tecnosys | 0:d8f50b1e384f | 139 | const uint8_t mask, const uint8_t data) |
| tecnosys | 0:d8f50b1e384f | 140 | { |
| tecnosys | 0:d8f50b1e384f | 141 | _select(); |
| tecnosys | 0:d8f50b1e384f | 142 | _spi_readwrite(MCP_BITMOD); |
| tecnosys | 0:d8f50b1e384f | 143 | _spi_readwrite(address); |
| tecnosys | 0:d8f50b1e384f | 144 | _spi_readwrite(mask); |
| tecnosys | 0:d8f50b1e384f | 145 | _spi_readwrite(data); |
| tecnosys | 0:d8f50b1e384f | 146 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 147 | } |
| tecnosys | 0:d8f50b1e384f | 148 | |
| tecnosys | 0:d8f50b1e384f | 149 | |
| tecnosys | 0:d8f50b1e384f | 150 | uint8_t mcp2515::readXXStatus_helper(const uint8_t cmd) |
| tecnosys | 0:d8f50b1e384f | 151 | { |
| tecnosys | 0:d8f50b1e384f | 152 | uint8_t i; |
| tecnosys | 0:d8f50b1e384f | 153 | |
| tecnosys | 0:d8f50b1e384f | 154 | _select(); |
| tecnosys | 0:d8f50b1e384f | 155 | _spi_readwrite(cmd); |
| tecnosys | 0:d8f50b1e384f | 156 | i = _spi_read(); |
| tecnosys | 0:d8f50b1e384f | 157 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 158 | |
| tecnosys | 0:d8f50b1e384f | 159 | return i; |
| tecnosys | 0:d8f50b1e384f | 160 | } |
| tecnosys | 0:d8f50b1e384f | 161 | |
| tecnosys | 0:d8f50b1e384f | 162 | uint8_t mcp2515::readStatus(void) |
| tecnosys | 0:d8f50b1e384f | 163 | { |
| tecnosys | 0:d8f50b1e384f | 164 | return readXXStatus_helper(MCP_READ_STATUS); |
| tecnosys | 0:d8f50b1e384f | 165 | } |
| tecnosys | 0:d8f50b1e384f | 166 | |
| tecnosys | 0:d8f50b1e384f | 167 | uint8_t mcp2515::RXStatus(void) |
| tecnosys | 0:d8f50b1e384f | 168 | { |
| tecnosys | 0:d8f50b1e384f | 169 | return readXXStatus_helper(MCP_RX_STATUS); |
| tecnosys | 0:d8f50b1e384f | 170 | } |
| tecnosys | 0:d8f50b1e384f | 171 | |
| tecnosys | 0:d8f50b1e384f | 172 | // read-modify-write - better: Bit Modify Instruction |
| tecnosys | 0:d8f50b1e384f | 173 | uint8_t mcp2515::setCANCTRL_Mode(uint8_t newmode) |
| tecnosys | 0:d8f50b1e384f | 174 | { |
| tecnosys | 0:d8f50b1e384f | 175 | uint8_t i; |
| tecnosys | 0:d8f50b1e384f | 176 | |
| tecnosys | 0:d8f50b1e384f | 177 | i = readRegister(MCP_CANCTRL); |
| tecnosys | 0:d8f50b1e384f | 178 | i &= ~(MODE_MASK); |
| tecnosys | 0:d8f50b1e384f | 179 | i |= newmode; |
| tecnosys | 0:d8f50b1e384f | 180 | setRegister(MCP_CANCTRL, i); |
| tecnosys | 0:d8f50b1e384f | 181 | |
| tecnosys | 0:d8f50b1e384f | 182 | // verify as advised in datasheet |
| tecnosys | 0:d8f50b1e384f | 183 | i = readRegister(MCP_CANCTRL); |
| tecnosys | 0:d8f50b1e384f | 184 | i &= MODE_MASK; |
| tecnosys | 0:d8f50b1e384f | 185 | if ( i == newmode ) { |
| tecnosys | 0:d8f50b1e384f | 186 | return MCP2515_OK; |
| tecnosys | 0:d8f50b1e384f | 187 | } |
| tecnosys | 0:d8f50b1e384f | 188 | else { |
| tecnosys | 0:d8f50b1e384f | 189 | return MCP2515_FAIL; |
| tecnosys | 0:d8f50b1e384f | 190 | } |
| tecnosys | 0:d8f50b1e384f | 191 | } |
| tecnosys | 0:d8f50b1e384f | 192 | |
| tecnosys | 0:d8f50b1e384f | 193 | |
| tecnosys | 0:d8f50b1e384f | 194 | void mcp2515::setRegisterS(const uint8_t address, |
| tecnosys | 0:d8f50b1e384f | 195 | const uint8_t values[], const uint8_t n) |
| tecnosys | 0:d8f50b1e384f | 196 | { |
| tecnosys | 0:d8f50b1e384f | 197 | uint8_t i; |
| tecnosys | 0:d8f50b1e384f | 198 | |
| tecnosys | 0:d8f50b1e384f | 199 | _select(); |
| tecnosys | 0:d8f50b1e384f | 200 | _spi_readwrite(MCP_WRITE); |
| tecnosys | 0:d8f50b1e384f | 201 | _spi_readwrite(address); |
| tecnosys | 0:d8f50b1e384f | 202 | // mcp2515 has auto-increment of address-pointer |
| tecnosys | 0:d8f50b1e384f | 203 | for (i=0; i<n; i++) { |
| tecnosys | 0:d8f50b1e384f | 204 | _spi_readwrite(values[i]); |
| tecnosys | 0:d8f50b1e384f | 205 | } |
| tecnosys | 0:d8f50b1e384f | 206 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 207 | } |
| tecnosys | 0:d8f50b1e384f | 208 | |
| tecnosys | 0:d8f50b1e384f | 209 | void mcp2515::read_can_id( const uint8_t mcp_addr, |
| tecnosys | 0:d8f50b1e384f | 210 | uint8_t* ext, uint32_t* can_id ) |
| tecnosys | 0:d8f50b1e384f | 211 | { |
| tecnosys | 0:d8f50b1e384f | 212 | uint8_t tbufdata[4]; |
| tecnosys | 0:d8f50b1e384f | 213 | |
| tecnosys | 0:d8f50b1e384f | 214 | *ext = 0; |
| tecnosys | 0:d8f50b1e384f | 215 | *can_id = 0; |
| tecnosys | 0:d8f50b1e384f | 216 | |
| tecnosys | 0:d8f50b1e384f | 217 | readRegisterS( mcp_addr, tbufdata, 4 ); |
| tecnosys | 0:d8f50b1e384f | 218 | |
| tecnosys | 0:d8f50b1e384f | 219 | *can_id = (tbufdata[MCP_SIDH]<<3) + (tbufdata[MCP_SIDL]>>5); |
| tecnosys | 0:d8f50b1e384f | 220 | |
| tecnosys | 0:d8f50b1e384f | 221 | if ( (tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M ) { |
| tecnosys | 0:d8f50b1e384f | 222 | // extended id |
| tecnosys | 0:d8f50b1e384f | 223 | *can_id = (*can_id<<2) + (tbufdata[MCP_SIDL] & 0x03); |
| tecnosys | 0:d8f50b1e384f | 224 | *can_id <<= 16; |
| tecnosys | 0:d8f50b1e384f | 225 | *can_id = *can_id +(tbufdata[MCP_EID8]<<8) + tbufdata[MCP_EID0]; |
| tecnosys | 0:d8f50b1e384f | 226 | *ext = 1; |
| tecnosys | 0:d8f50b1e384f | 227 | } |
| tecnosys | 0:d8f50b1e384f | 228 | } |
| tecnosys | 0:d8f50b1e384f | 229 | |
| tecnosys | 0:d8f50b1e384f | 230 | |
| tecnosys | 0:d8f50b1e384f | 231 | // Buffer can be MCP_RXBUF_0 or MCP_RXBUF_1 |
| tecnosys | 0:d8f50b1e384f | 232 | void mcp2515::read_canMsg( const uint8_t buffer_sidh_addr, |
| tecnosys | 0:d8f50b1e384f | 233 | CANMessage* msg) |
| tecnosys | 0:d8f50b1e384f | 234 | { |
| tecnosys | 0:d8f50b1e384f | 235 | /* |
| tecnosys | 0:d8f50b1e384f | 236 | uint8_t mcp_addr, ctrl; |
| tecnosys | 0:d8f50b1e384f | 237 | |
| tecnosys | 0:d8f50b1e384f | 238 | mcp_addr = buffer_sidh_addr; |
| tecnosys | 0:d8f50b1e384f | 239 | |
| tecnosys | 0:d8f50b1e384f | 240 | read_can_id( mcp_addr, &(msg->extended_identifier), |
| tecnosys | 0:d8f50b1e384f | 241 | &(msg->identifier) ); |
| tecnosys | 0:d8f50b1e384f | 242 | |
| tecnosys | 0:d8f50b1e384f | 243 | ctrl = readRegister( mcp_addr-1 ); |
| tecnosys | 0:d8f50b1e384f | 244 | msg->dlc = readRegister( mcp_addr+4 ); |
| tecnosys | 0:d8f50b1e384f | 245 | |
| tecnosys | 0:d8f50b1e384f | 246 | //if ((*dlc & RTR_MASK) || (ctrl & 0x08)) { |
| tecnosys | 0:d8f50b1e384f | 247 | if ((ctrl & 0x08)) { |
| tecnosys | 0:d8f50b1e384f | 248 | msg->rtr = 1; |
| tecnosys | 0:d8f50b1e384f | 249 | } else { |
| tecnosys | 0:d8f50b1e384f | 250 | msg->rtr = 0; |
| tecnosys | 0:d8f50b1e384f | 251 | } |
| tecnosys | 0:d8f50b1e384f | 252 | |
| tecnosys | 0:d8f50b1e384f | 253 | msg->dlc &= MCP_DLC_MASK; |
| tecnosys | 0:d8f50b1e384f | 254 | readRegisterS( mcp_addr+5, &(msg->dta[0]), msg->dlc ); |
| tecnosys | 0:d8f50b1e384f | 255 | */ |
| tecnosys | 0:d8f50b1e384f | 256 | } |
| tecnosys | 0:d8f50b1e384f | 257 | |
| tecnosys | 0:d8f50b1e384f | 258 | |
| tecnosys | 0:d8f50b1e384f | 259 | void mcp2515::write_can_id( const uint8_t mcp_addr, |
| tecnosys | 0:d8f50b1e384f | 260 | const uint8_t ext, const uint32_t can_id ) |
| tecnosys | 0:d8f50b1e384f | 261 | { |
| tecnosys | 0:d8f50b1e384f | 262 | uint16_t canid; |
| tecnosys | 0:d8f50b1e384f | 263 | uint8_t tbufdata[4]; |
| tecnosys | 0:d8f50b1e384f | 264 | |
| tecnosys | 0:d8f50b1e384f | 265 | canid = (uint16_t)(can_id & 0x0FFFF); |
| tecnosys | 0:d8f50b1e384f | 266 | |
| tecnosys | 0:d8f50b1e384f | 267 | if ( ext == 1) { |
| tecnosys | 0:d8f50b1e384f | 268 | tbufdata[MCP_EID0] = (uint8_t) (canid & 0xFF); |
| tecnosys | 0:d8f50b1e384f | 269 | tbufdata[MCP_EID8] = (uint8_t) (canid / 256); |
| tecnosys | 0:d8f50b1e384f | 270 | canid = (uint16_t)( can_id / 0x10000L ); |
| tecnosys | 0:d8f50b1e384f | 271 | tbufdata[MCP_SIDL] = (uint8_t) (canid & 0x03); |
| tecnosys | 0:d8f50b1e384f | 272 | tbufdata[MCP_SIDL] += (uint8_t) ((canid & 0x1C )*8); |
| tecnosys | 0:d8f50b1e384f | 273 | tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M; |
| tecnosys | 0:d8f50b1e384f | 274 | tbufdata[MCP_SIDH] = (uint8_t) (canid / 32 ); |
| tecnosys | 0:d8f50b1e384f | 275 | } |
| tecnosys | 0:d8f50b1e384f | 276 | else { |
| tecnosys | 0:d8f50b1e384f | 277 | tbufdata[MCP_SIDH] = (uint8_t) (canid / 8 ); |
| tecnosys | 0:d8f50b1e384f | 278 | tbufdata[MCP_SIDL] = (uint8_t) ((canid & 0x07 )*32); |
| tecnosys | 0:d8f50b1e384f | 279 | tbufdata[MCP_EID0] = 0; |
| tecnosys | 0:d8f50b1e384f | 280 | tbufdata[MCP_EID8] = 0; |
| tecnosys | 0:d8f50b1e384f | 281 | } |
| tecnosys | 0:d8f50b1e384f | 282 | setRegisterS( mcp_addr, tbufdata, 4 ); |
| tecnosys | 0:d8f50b1e384f | 283 | } |
| tecnosys | 0:d8f50b1e384f | 284 | |
| tecnosys | 0:d8f50b1e384f | 285 | // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2 |
| tecnosys | 0:d8f50b1e384f | 286 | void mcp2515::write_canMsg( const uint8_t buffer_sidh_addr, |
| tecnosys | 0:d8f50b1e384f | 287 | CANMessage* msg) |
| tecnosys | 0:d8f50b1e384f | 288 | { |
| tecnosys | 0:d8f50b1e384f | 289 | uint8_t mcp_addr, dlc; |
| tecnosys | 0:d8f50b1e384f | 290 | |
| tecnosys | 0:d8f50b1e384f | 291 | mcp_addr = buffer_sidh_addr; |
| tecnosys | 0:d8f50b1e384f | 292 | dlc = msg->len; |
| tecnosys | 0:d8f50b1e384f | 293 | |
| tecnosys | 0:d8f50b1e384f | 294 | setRegisterS(mcp_addr+5, &(msg->data[0]), dlc ); // write data bytes |
| tecnosys | 0:d8f50b1e384f | 295 | write_can_id( mcp_addr, msg->format, |
| tecnosys | 0:d8f50b1e384f | 296 | msg->id ); // write CAN id |
| tecnosys | 0:d8f50b1e384f | 297 | if ( msg->type == 1) dlc |= MCP_RTR_MASK; // if RTR set bit in byte |
| tecnosys | 0:d8f50b1e384f | 298 | setRegister( (mcp_addr+4), dlc ); // write the RTR and DLC |
| tecnosys | 0:d8f50b1e384f | 299 | } |
| tecnosys | 0:d8f50b1e384f | 300 | |
| tecnosys | 0:d8f50b1e384f | 301 | void mcp2515::start_transmit(const uint8_t buffer_sidh_addr) |
| tecnosys | 0:d8f50b1e384f | 302 | { |
| tecnosys | 0:d8f50b1e384f | 303 | // TXBnCTRL_addr = TXBnSIDH_addr - 1 |
| tecnosys | 0:d8f50b1e384f | 304 | modifyRegister( buffer_sidh_addr-1 , MCP_TXB_TXREQ_M, |
| tecnosys | 0:d8f50b1e384f | 305 | MCP_TXB_TXREQ_M ); |
| tecnosys | 0:d8f50b1e384f | 306 | } |
| tecnosys | 0:d8f50b1e384f | 307 | |
| tecnosys | 0:d8f50b1e384f | 308 | uint8_t mcp2515::getNextFreeTXBuf(uint8_t *txbuf_n) |
| tecnosys | 0:d8f50b1e384f | 309 | { |
| tecnosys | 0:d8f50b1e384f | 310 | uint8_t res, i, ctrlval; |
| tecnosys | 0:d8f50b1e384f | 311 | uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL }; |
| tecnosys | 0:d8f50b1e384f | 312 | |
| tecnosys | 0:d8f50b1e384f | 313 | res = MCP_ALLTXBUSY; |
| tecnosys | 0:d8f50b1e384f | 314 | *txbuf_n = 0x00; |
| tecnosys | 0:d8f50b1e384f | 315 | |
| tecnosys | 0:d8f50b1e384f | 316 | // check all 3 TX-Buffers |
| tecnosys | 0:d8f50b1e384f | 317 | for (i=0; i<MCP_N_TXBUFFERS; i++) { |
| tecnosys | 0:d8f50b1e384f | 318 | ctrlval = readRegister( ctrlregs[i] ); |
| tecnosys | 0:d8f50b1e384f | 319 | if ( (ctrlval & MCP_TXB_TXREQ_M) == 0 ) { |
| tecnosys | 0:d8f50b1e384f | 320 | |
| tecnosys | 0:d8f50b1e384f | 321 | *txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer |
| tecnosys | 0:d8f50b1e384f | 322 | res = MCP2515_OK; |
| tecnosys | 0:d8f50b1e384f | 323 | return res; /* ! function exit */ |
| tecnosys | 0:d8f50b1e384f | 324 | } |
| tecnosys | 0:d8f50b1e384f | 325 | } |
| tecnosys | 0:d8f50b1e384f | 326 | |
| tecnosys | 0:d8f50b1e384f | 327 | return res; |
| tecnosys | 0:d8f50b1e384f | 328 | } |
| tecnosys | 0:d8f50b1e384f | 329 | |
| tecnosys | 0:d8f50b1e384f | 330 | void mcp2515::initCANBuffers(void) |
| tecnosys | 0:d8f50b1e384f | 331 | { |
| tecnosys | 0:d8f50b1e384f | 332 | uint8_t i, a1, a2, a3; |
| tecnosys | 0:d8f50b1e384f | 333 | |
| tecnosys | 0:d8f50b1e384f | 334 | // TODO: check why this is needed to receive extended |
| tecnosys | 0:d8f50b1e384f | 335 | // and standard frames |
| tecnosys | 0:d8f50b1e384f | 336 | // Mark all filter bits as don't care: |
| tecnosys | 0:d8f50b1e384f | 337 | write_can_id(MCP_RXM0SIDH, 0, 0); |
| tecnosys | 0:d8f50b1e384f | 338 | write_can_id(MCP_RXM1SIDH, 0, 0); |
| tecnosys | 0:d8f50b1e384f | 339 | // Anyway, set all filters to 0: |
| tecnosys | 0:d8f50b1e384f | 340 | write_can_id(MCP_RXF0SIDH, 1, 0); // RXB0: extended |
| tecnosys | 0:d8f50b1e384f | 341 | write_can_id(MCP_RXF1SIDH, 0, 0); // AND standard |
| tecnosys | 0:d8f50b1e384f | 342 | write_can_id(MCP_RXF2SIDH, 1, 0); // RXB1: extended |
| tecnosys | 0:d8f50b1e384f | 343 | write_can_id(MCP_RXF3SIDH, 0, 0); // AND standard |
| tecnosys | 0:d8f50b1e384f | 344 | write_can_id(MCP_RXF4SIDH, 0, 0); |
| tecnosys | 0:d8f50b1e384f | 345 | write_can_id(MCP_RXF5SIDH, 0, 0); |
| tecnosys | 0:d8f50b1e384f | 346 | |
| tecnosys | 0:d8f50b1e384f | 347 | // Clear, deactivate the three transmit buffers |
| tecnosys | 0:d8f50b1e384f | 348 | // TXBnCTRL -> TXBnD7 |
| tecnosys | 0:d8f50b1e384f | 349 | a1 = MCP_TXB0CTRL; |
| tecnosys | 0:d8f50b1e384f | 350 | a2 = MCP_TXB1CTRL; |
| tecnosys | 0:d8f50b1e384f | 351 | a3 = MCP_TXB2CTRL; |
| tecnosys | 0:d8f50b1e384f | 352 | for (i = 0; i < 14; i++) { // in-buffer loop |
| tecnosys | 0:d8f50b1e384f | 353 | setRegister(a1, 0); |
| tecnosys | 0:d8f50b1e384f | 354 | setRegister(a2, 0); |
| tecnosys | 0:d8f50b1e384f | 355 | setRegister(a3, 0); |
| tecnosys | 0:d8f50b1e384f | 356 | a1++; |
| tecnosys | 0:d8f50b1e384f | 357 | a2++; |
| tecnosys | 0:d8f50b1e384f | 358 | a3++; |
| tecnosys | 0:d8f50b1e384f | 359 | } |
| tecnosys | 0:d8f50b1e384f | 360 | |
| tecnosys | 0:d8f50b1e384f | 361 | // and clear, deactivate the two receive buffers. |
| tecnosys | 0:d8f50b1e384f | 362 | setRegister(MCP_RXB0CTRL, 0); |
| tecnosys | 0:d8f50b1e384f | 363 | setRegister(MCP_RXB1CTRL, 0); |
| tecnosys | 0:d8f50b1e384f | 364 | } |
| tecnosys | 0:d8f50b1e384f | 365 | |
| tecnosys | 0:d8f50b1e384f | 366 | uint8_t mcp2515::init(const uint8_t canSpeed) |
| tecnosys | 0:d8f50b1e384f | 367 | { |
| tecnosys | 0:d8f50b1e384f | 368 | uint8_t res; |
| tecnosys | 0:d8f50b1e384f | 369 | |
| tecnosys | 0:d8f50b1e384f | 370 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 371 | //MCP_CS_DDR |= ( 1 << MCP_CS_BIT ); |
| tecnosys | 0:d8f50b1e384f | 372 | |
| tecnosys | 0:d8f50b1e384f | 373 | _reset(); |
| tecnosys | 0:d8f50b1e384f | 374 | |
| tecnosys | 0:d8f50b1e384f | 375 | res = setCANCTRL_Mode(MODE_CONFIG); |
| tecnosys | 0:d8f50b1e384f | 376 | |
| tecnosys | 0:d8f50b1e384f | 377 | if ( res == MCP2515_FAIL ){ |
| tecnosys | 0:d8f50b1e384f | 378 | printf("FAIL here"); |
| tecnosys | 0:d8f50b1e384f | 379 | return res; /* function exit on error */ |
| tecnosys | 0:d8f50b1e384f | 380 | } |
| tecnosys | 0:d8f50b1e384f | 381 | res = configRate(canSpeed); |
| tecnosys | 0:d8f50b1e384f | 382 | |
| tecnosys | 0:d8f50b1e384f | 383 | if ( res == MCP2515_OK ) { |
| tecnosys | 0:d8f50b1e384f | 384 | initCANBuffers(); |
| tecnosys | 0:d8f50b1e384f | 385 | |
| tecnosys | 0:d8f50b1e384f | 386 | |
| tecnosys | 0:d8f50b1e384f | 387 | // enable both receive-buffers to receive messages |
| tecnosys | 0:d8f50b1e384f | 388 | // with std. and ext. identifiers |
| tecnosys | 0:d8f50b1e384f | 389 | // and enable rollover |
| tecnosys | 0:d8f50b1e384f | 390 | modifyRegister(MCP_RXB0CTRL, |
| tecnosys | 0:d8f50b1e384f | 391 | MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, |
| tecnosys | 0:d8f50b1e384f | 392 | MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK ); |
| tecnosys | 0:d8f50b1e384f | 393 | modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, |
| tecnosys | 0:d8f50b1e384f | 394 | MCP_RXB_RX_STDEXT); |
| tecnosys | 0:d8f50b1e384f | 395 | |
| tecnosys | 0:d8f50b1e384f | 396 | } |
| tecnosys | 0:d8f50b1e384f | 397 | |
| tecnosys | 0:d8f50b1e384f | 398 | return res; |
| tecnosys | 0:d8f50b1e384f | 399 | } |
| tecnosys | 0:d8f50b1e384f | 400 | |
| tecnosys | 0:d8f50b1e384f | 401 | /* |
| tecnosys | 0:d8f50b1e384f | 402 | * Select function |
| tecnosys | 0:d8f50b1e384f | 403 | */ |
| tecnosys | 0:d8f50b1e384f | 404 | |
| tecnosys | 0:d8f50b1e384f | 405 | void mcp2515::_select() { |
| tecnosys | 0:d8f50b1e384f | 406 | //printf("{"); |
| tecnosys | 0:d8f50b1e384f | 407 | _ncs = 0; |
| tecnosys | 0:d8f50b1e384f | 408 | } |
| tecnosys | 0:d8f50b1e384f | 409 | |
| tecnosys | 0:d8f50b1e384f | 410 | |
| tecnosys | 0:d8f50b1e384f | 411 | /* |
| tecnosys | 0:d8f50b1e384f | 412 | * Deselect function |
| tecnosys | 0:d8f50b1e384f | 413 | */ |
| tecnosys | 0:d8f50b1e384f | 414 | |
| tecnosys | 0:d8f50b1e384f | 415 | void mcp2515::_deselect() { |
| tecnosys | 0:d8f50b1e384f | 416 | _ncs = 1; |
| tecnosys | 0:d8f50b1e384f | 417 | //printf("}"); |
| tecnosys | 0:d8f50b1e384f | 418 | } |
| tecnosys | 0:d8f50b1e384f | 419 | |
| tecnosys | 0:d8f50b1e384f | 420 | int mcp2515::status() { |
| tecnosys | 0:d8f50b1e384f | 421 | int status = 0; |
| tecnosys | 0:d8f50b1e384f | 422 | _select(); |
| tecnosys | 0:d8f50b1e384f | 423 | _spi.write(0xd7); |
| tecnosys | 0:d8f50b1e384f | 424 | status = (_spi.write(0x00) << 8 ); |
| tecnosys | 0:d8f50b1e384f | 425 | status |= _spi.write(0x00); |
| tecnosys | 0:d8f50b1e384f | 426 | _deselect(); |
| tecnosys | 0:d8f50b1e384f | 427 | return status; |
| tecnosys | 0:d8f50b1e384f | 428 | } |
| tecnosys | 0:d8f50b1e384f | 429 | |
| tecnosys | 0:d8f50b1e384f | 430 | void mcp2515::_pollbusy() { |
| tecnosys | 0:d8f50b1e384f | 431 | volatile int busy = 1; |
| tecnosys | 0:d8f50b1e384f | 432 | while (busy) { |
| tecnosys | 0:d8f50b1e384f | 433 | // if bit 7 is set, we can proceed |
| tecnosys | 0:d8f50b1e384f | 434 | if ( status() & 0x80 ) { |
| tecnosys | 0:d8f50b1e384f | 435 | busy = 0; |
| tecnosys | 0:d8f50b1e384f | 436 | } |
| tecnosys | 0:d8f50b1e384f | 437 | } |
| tecnosys | 0:d8f50b1e384f | 438 | } |
| tecnosys | 0:d8f50b1e384f | 439 | |
| tecnosys | 0:d8f50b1e384f | 440 | |
| tecnosys | 0:d8f50b1e384f | 441 | uint8_t mcp2515::_spi_readwrite(uint8_t data) |
| tecnosys | 0:d8f50b1e384f | 442 | { |
| tecnosys | 0:d8f50b1e384f | 443 | //printf("W0x%x ", data); |
| tecnosys | 0:d8f50b1e384f | 444 | uint8_t ret = _spi.write(data); |
| tecnosys | 0:d8f50b1e384f | 445 | // printf("R0x%x,", ret); |
| tecnosys | 0:d8f50b1e384f | 446 | return ret; |
| tecnosys | 0:d8f50b1e384f | 447 | } |
| tecnosys | 0:d8f50b1e384f | 448 | |
| tecnosys | 0:d8f50b1e384f | 449 | uint8_t mcp2515::_spi_read(void) |
| tecnosys | 0:d8f50b1e384f | 450 | { |
| tecnosys | 0:d8f50b1e384f | 451 | return _spi_readwrite(SPI_NULL); |
| tecnosys | 0:d8f50b1e384f | 452 | } |
