1
Dependents: yezhong_main_controller_copy yezhong_main_controller_copy_1 yezhong_main_controller_copy yezhong_main_controller_copy-
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 | } |