eeprom adding

Fork of SEEED_CAN by Sophie Dexter

Committer:
Just4pLeisure
Date:
Tue Nov 05 22:37:35 2013 +0000
Revision:
0:f5d099885d3d
Child:
1:ad71faa09868
Beta release of a CAN-BUS library for Seeed Studios' CAN BUS Shield

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Just4pLeisure 0:f5d099885d3d 1 /* seeed_can_api.cpp
Just4pLeisure 0:f5d099885d3d 2 * Copyright (c) 2013 Sophie Dexter
Just4pLeisure 0:f5d099885d3d 3 *
Just4pLeisure 0:f5d099885d3d 4 * Licensed under the Apache License, Version 2.0 (the "License");
Just4pLeisure 0:f5d099885d3d 5 * you may not use this file except in compliance with the License.
Just4pLeisure 0:f5d099885d3d 6 * You may obtain a copy of the License at
Just4pLeisure 0:f5d099885d3d 7 *
Just4pLeisure 0:f5d099885d3d 8 * http://www.apache.org/licenses/LICENSE-2.0
Just4pLeisure 0:f5d099885d3d 9 *
Just4pLeisure 0:f5d099885d3d 10 * Unless required by applicable law or agreed to in writing, software
Just4pLeisure 0:f5d099885d3d 11 * distributed under the License is distributed on an "AS IS" BASIS,
Just4pLeisure 0:f5d099885d3d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Just4pLeisure 0:f5d099885d3d 13 * See the License for the specific language governing permissions and
Just4pLeisure 0:f5d099885d3d 14 * limitations under the License.
Just4pLeisure 0:f5d099885d3d 15 */
Just4pLeisure 0:f5d099885d3d 16
Just4pLeisure 0:f5d099885d3d 17 #include "seeed_can_api.h"
Just4pLeisure 0:f5d099885d3d 18
Just4pLeisure 0:f5d099885d3d 19 /** Initialise the MCP2515 and set the bit rate
Just4pLeisure 0:f5d099885d3d 20 */
Just4pLeisure 0:f5d099885d3d 21 uint8_t mcpInit(can_t *obj, const uint32_t bitRate)
Just4pLeisure 0:f5d099885d3d 22 {
Just4pLeisure 0:f5d099885d3d 23 union { // Access CANMsg as:
Just4pLeisure 0:f5d099885d3d 24 CANMsg x; // the organised struct
Just4pLeisure 0:f5d099885d3d 25 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 26 };
Just4pLeisure 0:f5d099885d3d 27 uint8_t maskFilt[8] = { MCP_RXM0SIDH, MCP_RXM1SIDH, MCP_RXF0SIDH, MCP_RXF1SIDH, MCP_RXF2SIDH, MCP_RXF3SIDH, MCP_RXF4SIDH, MCP_RXF5SIDH };
Just4pLeisure 0:f5d099885d3d 28 uint8_t canBufCtrl[5] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL, MCP_RXB0CTRL, MCP_RXB1CTRL };
Just4pLeisure 0:f5d099885d3d 29 uint8_t canBuffer[3] = { MCP_TXB0CTRL+1, MCP_TXB1CTRL+1, MCP_TXB2CTRL+1 };
Just4pLeisure 0:f5d099885d3d 30
Just4pLeisure 0:f5d099885d3d 31 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 32 printf("Reseting MCP2515\r\n");
Just4pLeisure 0:f5d099885d3d 33 #endif
Just4pLeisure 0:f5d099885d3d 34 mcpReset(obj);
Just4pLeisure 0:f5d099885d3d 35 for (uint32_t i = 0; i < 8; i++) { // Clear all CAN id masks and filters
Just4pLeisure 0:f5d099885d3d 36 mcpWriteId(obj, maskFilt[i], NULL, NULL);
Just4pLeisure 0:f5d099885d3d 37 }
Just4pLeisure 0:f5d099885d3d 38 for (uint32_t i = 0; i < 5; i++) { // Clear all CAN buffer control registers
Just4pLeisure 0:f5d099885d3d 39 mcpWrite(obj, canBufCtrl[i], NULL);
Just4pLeisure 0:f5d099885d3d 40 }
Just4pLeisure 0:f5d099885d3d 41 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise empty CAN message buffer
Just4pLeisure 0:f5d099885d3d 42 for (uint32_t i = 0; i < 3; i++) { // Clear all CAN TX buffers
Just4pLeisure 0:f5d099885d3d 43 mcpWriteMultiple(obj, canBuffer[i], y, sizeof(x) ); // using empty CAN message (as an array)
Just4pLeisure 0:f5d099885d3d 44 }
Just4pLeisure 0:f5d099885d3d 45 mcpWrite(obj, MCP_CANINTE, MCP_RX0IF | MCP_RX1IF); // RX buffers can generate a interrupt
Just4pLeisure 0:f5d099885d3d 46 #if (DEBUG_RXANY==1)
Just4pLeisure 0:f5d099885d3d 47 // enable both receive-buffers to receive any message and enable rollover
Just4pLeisure 0:f5d099885d3d 48 mcpBitModify(obj, MCP_RXB0CTRL, MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
Just4pLeisure 0:f5d099885d3d 49 mcpBitModify(obj, MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_ANY);
Just4pLeisure 0:f5d099885d3d 50 #else
Just4pLeisure 0:f5d099885d3d 51 // enable both receive-buffers to receive messages with std. and ext. identifiers and enable rollover
Just4pLeisure 0:f5d099885d3d 52 mcpBitModify(obj, MCP_RXB0CTRL, MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
Just4pLeisure 0:f5d099885d3d 53 mcpBitModify(obj, MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT);
Just4pLeisure 0:f5d099885d3d 54 #endif
Just4pLeisure 0:f5d099885d3d 55 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 56 printf("Setting bit rate\r\n");
Just4pLeisure 0:f5d099885d3d 57 #endif
Just4pLeisure 0:f5d099885d3d 58 return (mcpSetBitRate(obj, bitRate)) ? 1 : 0; // set baudrate and return
Just4pLeisure 0:f5d099885d3d 59 }
Just4pLeisure 0:f5d099885d3d 60
Just4pLeisure 0:f5d099885d3d 61 /** set MCP2515 operation mode
Just4pLeisure 0:f5d099885d3d 62 *
Just4pLeisure 0:f5d099885d3d 63 * Configuration, Normal, Sleep, Listen-only or Loopback
Just4pLeisure 0:f5d099885d3d 64 */
Just4pLeisure 0:f5d099885d3d 65 uint8_t mcpSetMode(can_t *obj, const uint8_t newmode)
Just4pLeisure 0:f5d099885d3d 66 {
Just4pLeisure 0:f5d099885d3d 67 mcpBitModify(obj, MCP_CANCTRL, MODE_MASK, newmode);
Just4pLeisure 0:f5d099885d3d 68 for (uint32_t i = 0; i<10; i++) {
Just4pLeisure 0:f5d099885d3d 69 if ((mcpRead(obj, MCP_CANSTAT) & MODE_MASK) == newmode) {
Just4pLeisure 0:f5d099885d3d 70 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 71 printf("Successfully entered mode: %02x time: %dms\r\n", newmode, i);
Just4pLeisure 0:f5d099885d3d 72 printf("CANCTRL:%02x CANSTAT:%02x TXB0:%02x TXB1:%02x TXB2:%02x\r\n", mcpRead(obj, MCP_CANCTRL), mcpRead(obj, MCP_CANSTAT), mcpRead(obj, MCP_TXB0CTRL), mcpRead(obj, MCP_TXB1CTRL), mcpRead(obj, MCP_TXB2CTRL));
Just4pLeisure 0:f5d099885d3d 73 #endif
Just4pLeisure 0:f5d099885d3d 74 return 1;
Just4pLeisure 0:f5d099885d3d 75 }
Just4pLeisure 0:f5d099885d3d 76 wait_ms(1);
Just4pLeisure 0:f5d099885d3d 77 }
Just4pLeisure 0:f5d099885d3d 78 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 79 printf("Failed to enter mode: %02x\r\n", newmode);
Just4pLeisure 0:f5d099885d3d 80 printf("CANCTRL:%02x CANSTAT:%02x TXB0:%02x TXB1:%02x TXB2:%02x\r\n", mcpRead(obj, MCP_CANCTRL), mcpRead(obj, MCP_CANSTAT), mcpRead(obj, MCP_TXB0CTRL), mcpRead(obj, MCP_TXB1CTRL), mcpRead(obj, MCP_TXB2CTRL));
Just4pLeisure 0:f5d099885d3d 81 #endif
Just4pLeisure 0:f5d099885d3d 82 return 0;
Just4pLeisure 0:f5d099885d3d 83 }
Just4pLeisure 0:f5d099885d3d 84
Just4pLeisure 0:f5d099885d3d 85 /** set the CAN bus bitrate
Just4pLeisure 0:f5d099885d3d 86 *
Just4pLeisure 0:f5d099885d3d 87 * Calculate suitable BTR register values.
Just4pLeisure 0:f5d099885d3d 88 * The Bit Rate Pre-scaler (BRP) can be in the range of 1-64.
Just4pLeisure 0:f5d099885d3d 89 * According to CANopen, Bit Time can be be between 25 and 8 Time Quanta (TQU).
Just4pLeisure 0:f5d099885d3d 90 * Bit Time = SyncSeg(1 TQU) + PropSeg(1-8 TQU) + PhaseSeg1(1-8 TQU) + PhaseSeg2(2-8 TQU).
Just4pLeisure 0:f5d099885d3d 91 * SyncSeg is always 1TQU, PhaseSeg2 must be at least 2TQU to be longer than the processing time.
Just4pLeisure 0:f5d099885d3d 92 * Opinions vary on when to take a sample but a point roughly 2/3 of Bit Time seems OK.
Just4pLeisure 0:f5d099885d3d 93 * Synchronisation Jump width can be 1-4 TQU, a value of 1 seems to be normal.
Just4pLeisure 0:f5d099885d3d 94 *
Just4pLeisure 0:f5d099885d3d 95 * All register values are -1, e.g. PropSeg can range from 1-8 TQU, so values are 0-7 (0-63 for BRP).
Just4pLeisure 0:f5d099885d3d 96 *
Just4pLeisure 0:f5d099885d3d 97 * This table has the sampling points as close to 2/3 (66.7%) as possible.
Just4pLeisure 0:f5d099885d3d 98 * The first value is PropSeg, 2nd PhaseSeg1.
Just4pLeisure 0:f5d099885d3d 99 * PhaseSeg2 will be the same as PhaseSeg1 when btlmode bit is initialised to 0.
Just4pLeisure 0:f5d099885d3d 100 */
Just4pLeisure 0:f5d099885d3d 101 static const uint8_t timing_pts[18][2] = {
Just4pLeisure 0:f5d099885d3d 102 {0x0, 0x2}, // 8, 62.5%
Just4pLeisure 0:f5d099885d3d 103 {0x1, 0x2}, // 9, 66.7%
Just4pLeisure 0:f5d099885d3d 104 {0x2, 0x2}, // 10, 70.0%
Just4pLeisure 0:f5d099885d3d 105 {0x1, 0x3}, // 11, 63.6%
Just4pLeisure 0:f5d099885d3d 106 {0x2, 0x3}, // 12, 66.7%
Just4pLeisure 0:f5d099885d3d 107 {0x3, 0x3}, // 13, 69.2%
Just4pLeisure 0:f5d099885d3d 108 {0x2, 0x4}, // 14, 64.3%
Just4pLeisure 0:f5d099885d3d 109 {0x3, 0x4}, // 15, 66.7%
Just4pLeisure 0:f5d099885d3d 110 {0x4, 0x4}, // 16, 68.75%
Just4pLeisure 0:f5d099885d3d 111 {0x3, 0x5}, // 17, 64.7%
Just4pLeisure 0:f5d099885d3d 112 {0x4, 0x5}, // 18, 66.7%
Just4pLeisure 0:f5d099885d3d 113 {0x5, 0x5}, // 19, 63.2%
Just4pLeisure 0:f5d099885d3d 114 {0x4, 0x6}, // 20, 65.0%
Just4pLeisure 0:f5d099885d3d 115 {0x5, 0x6}, // 21, 66.7%
Just4pLeisure 0:f5d099885d3d 116 {0x6, 0x6}, // 22, 68.2%
Just4pLeisure 0:f5d099885d3d 117 {0x5, 0x7}, // 23, 65.2
Just4pLeisure 0:f5d099885d3d 118 {0x6, 0x7}, // 24, 66.7%
Just4pLeisure 0:f5d099885d3d 119 {0x7, 0x7}, // 25, 68.0%
Just4pLeisure 0:f5d099885d3d 120 };
Just4pLeisure 0:f5d099885d3d 121
Just4pLeisure 0:f5d099885d3d 122 uint8_t mcpSetBitRate(can_t *obj, const uint32_t bitRate)
Just4pLeisure 0:f5d099885d3d 123 {
Just4pLeisure 0:f5d099885d3d 124 union { // Access CANtiming as:
Just4pLeisure 0:f5d099885d3d 125 CANtiming x; // the organised struct
Just4pLeisure 0:f5d099885d3d 126 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 127 };
Just4pLeisure 0:f5d099885d3d 128 uint32_t bestBRP = 0;
Just4pLeisure 0:f5d099885d3d 129 uint32_t bestTQU = 0;
Just4pLeisure 0:f5d099885d3d 130 uint32_t bestCanRate = 0;
Just4pLeisure 0:f5d099885d3d 131 uint32_t minBRP = (MCP_CLOCK_FREQ / (2 * MCP_MAX_TIME_QUANTA * bitRate));
Just4pLeisure 0:f5d099885d3d 132 uint32_t maxBRP = (MCP_CLOCK_FREQ / (2 * MCP_MIN_TIME_QUANTA * bitRate));
Just4pLeisure 0:f5d099885d3d 133
Just4pLeisure 0:f5d099885d3d 134 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 135 printf("Setting configuration mode\r\n");
Just4pLeisure 0:f5d099885d3d 136 #endif
Just4pLeisure 0:f5d099885d3d 137 if(!mcpSetMode(obj, MODE_CONFIG)) { // Go into configuration mode
Just4pLeisure 0:f5d099885d3d 138 return 0;
Just4pLeisure 0:f5d099885d3d 139 }
Just4pLeisure 0:f5d099885d3d 140
Just4pLeisure 0:f5d099885d3d 141 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise CANtiming (btlmode, sjw and sam all = 0)
Just4pLeisure 0:f5d099885d3d 142 if ((bitRate < CAN_MIN_RATE) || (bitRate > CAN_MAX_RATE)) {
Just4pLeisure 0:f5d099885d3d 143 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 144 printf("FAILED!! The requested Bit Rate is too high or too low: %d\r\n", bitRate);
Just4pLeisure 0:f5d099885d3d 145 #endif
Just4pLeisure 0:f5d099885d3d 146 return 0; // Cannot set the requested bit rate!
Just4pLeisure 0:f5d099885d3d 147 }
Just4pLeisure 0:f5d099885d3d 148 minBRP = (minBRP == 0) ? MCP_MIN_PRESCALER : minBRP;
Just4pLeisure 0:f5d099885d3d 149 maxBRP = (maxBRP > MCP_MAX_PRESCALER) ? MCP_MAX_PRESCALER : maxBRP;
Just4pLeisure 0:f5d099885d3d 150 for (uint32_t BRP = minBRP; BRP < (maxBRP + 1); BRP++) {
Just4pLeisure 0:f5d099885d3d 151 uint32_t timeQuanta = (MCP_CLOCK_FREQ / (2 * BRP * bitRate));
Just4pLeisure 0:f5d099885d3d 152 if ((timeQuanta >= MCP_MIN_TIME_QUANTA) && (timeQuanta <= MCP_MAX_TIME_QUANTA)) {
Just4pLeisure 0:f5d099885d3d 153 for (uint32_t TQU = timeQuanta; TQU <= MCP_MAX_TIME_QUANTA; TQU++) {
Just4pLeisure 0:f5d099885d3d 154 uint32_t thisCanRate = MCP_CLOCK_FREQ / (2 * BRP * TQU);
Just4pLeisure 0:f5d099885d3d 155 if ( abs((int)bitRate - (int)thisCanRate) < abs((int)bitRate - (int)bestCanRate)) {
Just4pLeisure 0:f5d099885d3d 156 bestCanRate = thisCanRate;
Just4pLeisure 0:f5d099885d3d 157 bestBRP= BRP;
Just4pLeisure 0:f5d099885d3d 158 bestTQU= TQU;
Just4pLeisure 0:f5d099885d3d 159 }
Just4pLeisure 0:f5d099885d3d 160 }
Just4pLeisure 0:f5d099885d3d 161 }
Just4pLeisure 0:f5d099885d3d 162 }
Just4pLeisure 0:f5d099885d3d 163 x.brp = (bestBRP - 1);
Just4pLeisure 0:f5d099885d3d 164 x.prseg = (timing_pts[bestTQU - 8][0]);
Just4pLeisure 0:f5d099885d3d 165 x.phseg1 = (timing_pts[bestTQU - 8][1]);
Just4pLeisure 0:f5d099885d3d 166 mcpWriteMultiple(obj, MCP_CNF3, y, sizeof(x) ); // Copy CANtiming to the MCP2515 (as an array)
Just4pLeisure 0:f5d099885d3d 167 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 168 printf("minBRP %d maxBRP %d\r\n", minBRP, maxBRP);
Just4pLeisure 0:f5d099885d3d 169 printf("Bitrate: %d\tactualBitRate: %d\t Error: %1.2f percent.\r\n", bitRate, bestCanRate, (100-(100*(float)bitRate/(float)bestCanRate)));
Just4pLeisure 0:f5d099885d3d 170 printf("TimeQuanta: %d\tbitRatePrescaler: %d\tSamplePoint: %2.2f percent\r\n", bestTQU, bestBRP, 100*(float)(3 + x.prseg + x.phseg1)/(float)bestTQU ) ;
Just4pLeisure 0:f5d099885d3d 171 printf("Syncseg: 1\tPropSeg: %d\tPhaseSeg1: %d\tPhaseSeg2: %d\r\n", (x.prseg+1), (x.phseg1+1), (x.phseg1+1));
Just4pLeisure 0:f5d099885d3d 172 printf("Setting normal mode\r\n");
Just4pLeisure 0:f5d099885d3d 173 #endif
Just4pLeisure 0:f5d099885d3d 174 return (mcpSetMode(obj, MODE_NORMAL)) ? 1 : 0; // desired bit rate set enter normal mode and return
Just4pLeisure 0:f5d099885d3d 175 }
Just4pLeisure 0:f5d099885d3d 176
Just4pLeisure 0:f5d099885d3d 177 /** write a CAN id to a mask, filter or transmit buffer
Just4pLeisure 0:f5d099885d3d 178 */
Just4pLeisure 0:f5d099885d3d 179 void mcpWriteId(can_t *obj, const uint8_t mcp_addr, const uint8_t ext, const uint32_t id )
Just4pLeisure 0:f5d099885d3d 180 {
Just4pLeisure 0:f5d099885d3d 181 union { // Access CANid as:
Just4pLeisure 0:f5d099885d3d 182 CANid x; // the organised struct
Just4pLeisure 0:f5d099885d3d 183 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 184 };
Just4pLeisure 0:f5d099885d3d 185
Just4pLeisure 0:f5d099885d3d 186 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise CANid structure
Just4pLeisure 0:f5d099885d3d 187 x.ide = ext; // Extended Identifier Flag
Just4pLeisure 0:f5d099885d3d 188 if (x.ide == CANExtended) {
Just4pLeisure 0:f5d099885d3d 189 x.sid10_3 = (uint8_t) (id >> 21); // SID10..3
Just4pLeisure 0:f5d099885d3d 190 x.sid2_0 = (uint8_t) (id >> 18) & 0x07; // SID2..0
Just4pLeisure 0:f5d099885d3d 191 x.eid17_16 = (uint8_t) (id >> 16) & 0x03; // EID17..16
Just4pLeisure 0:f5d099885d3d 192 x.eid15_8 = (uint8_t) (id >> 8); // EID15..8
Just4pLeisure 0:f5d099885d3d 193 x.eid7_0 = (uint8_t) id; // EID7..0
Just4pLeisure 0:f5d099885d3d 194 } else {
Just4pLeisure 0:f5d099885d3d 195 x.sid10_3 = (uint8_t) (id >> 3); // SID10..3
Just4pLeisure 0:f5d099885d3d 196 x.sid2_0 = (uint8_t) (id & 0x07); // SID2..0
Just4pLeisure 0:f5d099885d3d 197 }
Just4pLeisure 0:f5d099885d3d 198 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 199 printf("sizeof CanIdStruct: %d bytes\r\n", sizeof(x));
Just4pLeisure 0:f5d099885d3d 200 printf("sid10_3: %x\r\n", x.sid10_3);
Just4pLeisure 0:f5d099885d3d 201 printf("eid17_16: %x\r\n", x.eid17_16);
Just4pLeisure 0:f5d099885d3d 202 printf("ide: %x\r\n", x.ide);
Just4pLeisure 0:f5d099885d3d 203 printf("srtr: %x\r\n", x.srtr);
Just4pLeisure 0:f5d099885d3d 204 printf("sid2_0: %x\r\n", x.sid2_0);
Just4pLeisure 0:f5d099885d3d 205 printf("eid15_8: %x\r\n", x.eid15_8);
Just4pLeisure 0:f5d099885d3d 206 printf("eid7_0: %x\r\n", x.eid7_0);
Just4pLeisure 0:f5d099885d3d 207 #endif
Just4pLeisure 0:f5d099885d3d 208 mcpWriteMultiple(obj, mcp_addr, y, sizeof(x) ); // Copy CANid to the MCP2515 (as an array)
Just4pLeisure 0:f5d099885d3d 209 }
Just4pLeisure 0:f5d099885d3d 210
Just4pLeisure 0:f5d099885d3d 211 /** write a CAN message to the MCP2515
Just4pLeisure 0:f5d099885d3d 212 */
Just4pLeisure 0:f5d099885d3d 213 uint8_t mcpCanWrite(can_t *obj, CAN_Message msg)
Just4pLeisure 0:f5d099885d3d 214 {
Just4pLeisure 0:f5d099885d3d 215 union { // Access CANMsg as:
Just4pLeisure 0:f5d099885d3d 216 CANMsg x; // the organised struct
Just4pLeisure 0:f5d099885d3d 217 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 218 };
Just4pLeisure 0:f5d099885d3d 219 uint8_t bufferCommand[] = {MCP_WRITE_TX0, MCP_WRITE_TX1, MCP_WRITE_TX2};
Just4pLeisure 0:f5d099885d3d 220 uint8_t rtsCommand[] = {MCP_RTS_TX0, MCP_RTS_TX1, MCP_RTS_TX2};
Just4pLeisure 0:f5d099885d3d 221 uint8_t status = mcpStatus(obj);
Just4pLeisure 0:f5d099885d3d 222 uint32_t num = 0;
Just4pLeisure 0:f5d099885d3d 223 // Check if there is a free message buffer
Just4pLeisure 0:f5d099885d3d 224 if (!(status & MCP_STAT_TX0REQ)) { // TX Message Buffer 0 free?
Just4pLeisure 0:f5d099885d3d 225 num = 0;
Just4pLeisure 0:f5d099885d3d 226 } else if (!(status & MCP_STAT_TX1REQ)) { // TX Message Buffer 1 free?
Just4pLeisure 0:f5d099885d3d 227 num = 1;
Just4pLeisure 0:f5d099885d3d 228 } else if (!(status & MCP_STAT_TX2REQ)) { // TX Message Buffer 2 free?
Just4pLeisure 0:f5d099885d3d 229 num = 2;
Just4pLeisure 0:f5d099885d3d 230 } else {
Just4pLeisure 0:f5d099885d3d 231 return 0; // No free transmit buffers in the MCP2515 CAN controller chip
Just4pLeisure 0:f5d099885d3d 232 }
Just4pLeisure 0:f5d099885d3d 233 // populate CANMsg structure
Just4pLeisure 0:f5d099885d3d 234 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise CANMsg structure
Just4pLeisure 0:f5d099885d3d 235 x.id.ide = msg.format; // Extended Identifier Flag
Just4pLeisure 0:f5d099885d3d 236 if (x.id.ide == CANExtended) {
Just4pLeisure 0:f5d099885d3d 237 x.id.sid10_3 = (uint8_t) (msg.id >> 21); // SID10..3
Just4pLeisure 0:f5d099885d3d 238 x.id.sid2_0 = (uint8_t) (msg.id >> 18) & 0x07; // SID2..0
Just4pLeisure 0:f5d099885d3d 239 x.id.eid17_16 = (uint8_t) (msg.id >> 16) & 0x03; // EID17..16
Just4pLeisure 0:f5d099885d3d 240 x.id.eid15_8 = (uint8_t) (msg.id >> 8); // EID15..8
Just4pLeisure 0:f5d099885d3d 241 x.id.eid7_0 = (uint8_t) msg.id; // EID7..0
Just4pLeisure 0:f5d099885d3d 242 } else {
Just4pLeisure 0:f5d099885d3d 243 x.id.sid10_3 = (uint8_t) (msg.id >> 3); // SID10..3
Just4pLeisure 0:f5d099885d3d 244 x.id.sid2_0 = (uint8_t) (msg.id & 0x07); // SID2..0
Just4pLeisure 0:f5d099885d3d 245 }
Just4pLeisure 0:f5d099885d3d 246 x.dlc = msg.len & 0x0f; // Number of bytes in can message
Just4pLeisure 0:f5d099885d3d 247 x.ertr = msg.type; // Data or remote message
Just4pLeisure 0:f5d099885d3d 248 memcpy(x.data,msg.data,x.dlc); // Get the Data bytes
Just4pLeisure 0:f5d099885d3d 249 // write CANmsg to the specified TX buffer 'num'
Just4pLeisure 0:f5d099885d3d 250 mcpWriteBuffer(obj, bufferCommand[num], y, sizeof(x)); // Write the message ,CANMsg, to the MCP2515's Tx buffer 'num' (as an array)
Just4pLeisure 0:f5d099885d3d 251 mcpBufferRTS(obj, rtsCommand[num]);
Just4pLeisure 0:f5d099885d3d 252 return 1; // Indicate that message has been transmitted
Just4pLeisure 0:f5d099885d3d 253 }
Just4pLeisure 0:f5d099885d3d 254
Just4pLeisure 0:f5d099885d3d 255 /** read a CAN message from the MCP2515
Just4pLeisure 0:f5d099885d3d 256 */
Just4pLeisure 0:f5d099885d3d 257 uint8_t mcpCanRead(can_t *obj, CAN_Message *msg)
Just4pLeisure 0:f5d099885d3d 258 {
Just4pLeisure 0:f5d099885d3d 259 union { // Access CANMsg as:
Just4pLeisure 0:f5d099885d3d 260 CANMsg x; // the organised struct
Just4pLeisure 0:f5d099885d3d 261 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 262 };
Just4pLeisure 0:f5d099885d3d 263 uint8_t bufferCommand[] = {MCP_READ_RX0, MCP_READ_RX1};
Just4pLeisure 0:f5d099885d3d 264 uint8_t status = mcpReceiveStatus(obj);
Just4pLeisure 0:f5d099885d3d 265 bool num = 0;
Just4pLeisure 0:f5d099885d3d 266 // Check if there is a message the buffers
Just4pLeisure 0:f5d099885d3d 267 if (status & MCP_RXSTAT_RXB0) { // Msg in Buffer 0?
Just4pLeisure 0:f5d099885d3d 268 num = 0;
Just4pLeisure 0:f5d099885d3d 269 } else if (status & MCP_RXSTAT_RXB1) { // Msg in Buffer 1?
Just4pLeisure 0:f5d099885d3d 270 num = 1;
Just4pLeisure 0:f5d099885d3d 271 } else {
Just4pLeisure 0:f5d099885d3d 272 return 0; // No messages waiting
Just4pLeisure 0:f5d099885d3d 273 }
Just4pLeisure 0:f5d099885d3d 274 mcpReadBuffer(obj, bufferCommand[0], y, sizeof(x)); // Read the message into CANMsg (as an array)
Just4pLeisure 0:f5d099885d3d 275 mcpBitModify(obj, MCP_CANINTF, (!num ? MCP_RX0IF : MCP_RX1IF), 0); // Free the message buffer
Just4pLeisure 0:f5d099885d3d 276 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 277 printf("sizeof CanMsgStruct: %d bytes\r\n", sizeof(x));
Just4pLeisure 0:f5d099885d3d 278 printf("sizeof CanMsgArray: %d bytes\r\n", sizeof(y));
Just4pLeisure 0:f5d099885d3d 279 printf("sid10_3: %x\r\n", x.id.sid10_3);
Just4pLeisure 0:f5d099885d3d 280 printf("eid17_16: %x\r\n", x.id.eid17_16);
Just4pLeisure 0:f5d099885d3d 281 printf("ide: %x\r\n", x.id.ide);
Just4pLeisure 0:f5d099885d3d 282 printf("srtr: %x\r\n", x.id.srtr);
Just4pLeisure 0:f5d099885d3d 283 printf("sid2_0: %x\r\n", x.id.sid2_0);
Just4pLeisure 0:f5d099885d3d 284 printf("eid15_8: %x\r\n", x.id.eid15_8);
Just4pLeisure 0:f5d099885d3d 285 printf("eid7_0: %x\r\n", x.id.eid7_0);
Just4pLeisure 0:f5d099885d3d 286 printf("dlc: %x\r\n", x.dlc);
Just4pLeisure 0:f5d099885d3d 287 printf("ertr: %x\r\n", x.ertr);
Just4pLeisure 0:f5d099885d3d 288 printf("data: ");
Just4pLeisure 0:f5d099885d3d 289 for (char i=0; i<8; i++)
Just4pLeisure 0:f5d099885d3d 290 printf("%02x,", x.data[i]);
Just4pLeisure 0:f5d099885d3d 291 printf("\r\n");
Just4pLeisure 0:f5d099885d3d 292 #endif
Just4pLeisure 0:f5d099885d3d 293 msg->format = (status & MCP_RXSTAT_IDE) ? CANExtended : CANStandard;// Extended CAN id Flag
Just4pLeisure 0:f5d099885d3d 294 if (msg->format == CANExtended) { // Assemble the Extended CAN id
Just4pLeisure 0:f5d099885d3d 295 msg->id = (x.id.sid10_3 << 21) |
Just4pLeisure 0:f5d099885d3d 296 (x.id.sid2_0 << 18) |
Just4pLeisure 0:f5d099885d3d 297 (x.id.eid17_16 << 16) |
Just4pLeisure 0:f5d099885d3d 298 (x.id.eid15_8 << 8) |
Just4pLeisure 0:f5d099885d3d 299 (x.id.eid7_0);
Just4pLeisure 0:f5d099885d3d 300 } else { // Assemble the Standard CAN id
Just4pLeisure 0:f5d099885d3d 301 msg->id = (x.id.sid10_3 << 3) |
Just4pLeisure 0:f5d099885d3d 302 (x.id.sid2_0);
Just4pLeisure 0:f5d099885d3d 303 }
Just4pLeisure 0:f5d099885d3d 304 msg->len = x.dlc; // Number of bytes in CAN message
Just4pLeisure 0:f5d099885d3d 305 msg->type = (status & MCP_RXSTAT_RTR) ? CANRemote : CANData; // Determine if a Remote or Data message type
Just4pLeisure 0:f5d099885d3d 306 memcpy(msg->data,x.data,x.dlc); // Get the Data bytes
Just4pLeisure 0:f5d099885d3d 307 return 1; // Indicate that message has been retrieved
Just4pLeisure 0:f5d099885d3d 308 }
Just4pLeisure 0:f5d099885d3d 309
Just4pLeisure 0:f5d099885d3d 310 /** initialise an Acceptance Mask
Just4pLeisure 0:f5d099885d3d 311 */
Just4pLeisure 0:f5d099885d3d 312 uint8_t mcpInitMask(can_t *obj, uint8_t num, uint32_t ulData, bool ext)
Just4pLeisure 0:f5d099885d3d 313 {
Just4pLeisure 0:f5d099885d3d 314 uint8_t mask[2] = { MCP_RXM0SIDH, MCP_RXM1SIDH };
Just4pLeisure 0:f5d099885d3d 315
Just4pLeisure 0:f5d099885d3d 316 if (num > 1) {
Just4pLeisure 0:f5d099885d3d 317 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 318 printf("Trying to set an invalid Mask number: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 319 #endif
Just4pLeisure 0:f5d099885d3d 320 return 0;
Just4pLeisure 0:f5d099885d3d 321 }
Just4pLeisure 0:f5d099885d3d 322 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 323 printf("Begin to set Mask!!\r\n");
Just4pLeisure 0:f5d099885d3d 324 #endif
Just4pLeisure 0:f5d099885d3d 325 if(!mcpSetMode(obj, MODE_CONFIG)) {
Just4pLeisure 0:f5d099885d3d 326 return 0;
Just4pLeisure 0:f5d099885d3d 327 }
Just4pLeisure 0:f5d099885d3d 328 mcpWriteId(obj, mask[num], ext, ulData);
Just4pLeisure 0:f5d099885d3d 329 if(!mcpSetMode(obj, MODE_NORMAL)) {
Just4pLeisure 0:f5d099885d3d 330 return 0;
Just4pLeisure 0:f5d099885d3d 331 }
Just4pLeisure 0:f5d099885d3d 332 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 333 printf("Successfully set Mask number: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 334 #endif
Just4pLeisure 0:f5d099885d3d 335 return 1;
Just4pLeisure 0:f5d099885d3d 336 }
Just4pLeisure 0:f5d099885d3d 337
Just4pLeisure 0:f5d099885d3d 338 /** initialise an Acceptance Filter
Just4pLeisure 0:f5d099885d3d 339 */
Just4pLeisure 0:f5d099885d3d 340 uint8_t mcpInitFilter(can_t *obj, uint8_t num, uint32_t ulData, bool ext)
Just4pLeisure 0:f5d099885d3d 341 {
Just4pLeisure 0:f5d099885d3d 342 uint8_t filter[6] = { MCP_RXF0SIDH, MCP_RXF1SIDH, MCP_RXF2SIDH, MCP_RXF3SIDH, MCP_RXF4SIDH, MCP_RXF5SIDH };
Just4pLeisure 0:f5d099885d3d 343
Just4pLeisure 0:f5d099885d3d 344 if (num > 5) {
Just4pLeisure 0:f5d099885d3d 345 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 346 printf("Trying to set an invalid Filter number: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 347 #endif
Just4pLeisure 0:f5d099885d3d 348 return 0;
Just4pLeisure 0:f5d099885d3d 349 }
Just4pLeisure 0:f5d099885d3d 350 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 351 printf("Begin to set Filter!!\r\n");
Just4pLeisure 0:f5d099885d3d 352 #endif
Just4pLeisure 0:f5d099885d3d 353 if(!mcpSetMode(obj, MODE_CONFIG)) {
Just4pLeisure 0:f5d099885d3d 354 return 0;
Just4pLeisure 0:f5d099885d3d 355 }
Just4pLeisure 0:f5d099885d3d 356 mcpWriteId(obj, filter[num], ext, ulData);
Just4pLeisure 0:f5d099885d3d 357 if(!mcpSetMode(obj, MODE_NORMAL)) {
Just4pLeisure 0:f5d099885d3d 358 return 0;
Just4pLeisure 0:f5d099885d3d 359 }
Just4pLeisure 0:f5d099885d3d 360 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 361 printf("Successfully set Filter: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 362 #endif
Just4pLeisure 0:f5d099885d3d 363 return 1;
Just4pLeisure 0:f5d099885d3d 364 }
Just4pLeisure 0:f5d099885d3d 365
Just4pLeisure 0:f5d099885d3d 366 /* Number of message reception errors
Just4pLeisure 0:f5d099885d3d 367 */
Just4pLeisure 0:f5d099885d3d 368 uint8_t mcpReceptionErrorCount(can_t *obj)
Just4pLeisure 0:f5d099885d3d 369 {
Just4pLeisure 0:f5d099885d3d 370 return (mcpRead(obj, MCP_REC));
Just4pLeisure 0:f5d099885d3d 371 }
Just4pLeisure 0:f5d099885d3d 372
Just4pLeisure 0:f5d099885d3d 373 /* Number of message transmission errors
Just4pLeisure 0:f5d099885d3d 374 */
Just4pLeisure 0:f5d099885d3d 375 uint8_t mcpTransmissionErrorCount(can_t *obj)
Just4pLeisure 0:f5d099885d3d 376 {
Just4pLeisure 0:f5d099885d3d 377 return (mcpRead(obj, MCP_TEC));
Just4pLeisure 0:f5d099885d3d 378 }
Just4pLeisure 0:f5d099885d3d 379
Just4pLeisure 0:f5d099885d3d 380 /* Select between monitor (silent = 1) and normal (silent = 0) modes
Just4pLeisure 0:f5d099885d3d 381 */
Just4pLeisure 0:f5d099885d3d 382 void mcpMonitor(can_t *obj, const bool silent)
Just4pLeisure 0:f5d099885d3d 383 {
Just4pLeisure 0:f5d099885d3d 384 silent ? mcpSetMode(obj, MODE_LISTENONLY) : mcpSetMode(obj, MODE_NORMAL);
Just4pLeisure 0:f5d099885d3d 385 }
Just4pLeisure 0:f5d099885d3d 386
Just4pLeisure 0:f5d099885d3d 387 /* Change CAN operation to the specified mode
Just4pLeisure 0:f5d099885d3d 388 */
Just4pLeisure 0:f5d099885d3d 389 uint8_t mcpMode(can_t *obj, const CANMode mode)
Just4pLeisure 0:f5d099885d3d 390 {
Just4pLeisure 0:f5d099885d3d 391 uint8_t which[] = { MODE_NORMAL, MODE_SLEEP, MODE_LOOPBACK, MODE_LISTENONLY, MODE_CONFIG, MODE_CONFIG};
Just4pLeisure 0:f5d099885d3d 392
Just4pLeisure 0:f5d099885d3d 393 if (mode == _RESET) {
Just4pLeisure 0:f5d099885d3d 394 mcpReset(obj);
Just4pLeisure 0:f5d099885d3d 395 }
Just4pLeisure 0:f5d099885d3d 396 if (mcpSetMode(obj, which[mode])) {
Just4pLeisure 0:f5d099885d3d 397 return 1;
Just4pLeisure 0:f5d099885d3d 398 }
Just4pLeisure 0:f5d099885d3d 399 return 0;
Just4pLeisure 0:f5d099885d3d 400 }