eeprom adding

Fork of SEEED_CAN by Sophie Dexter

Committer:
sameera0824
Date:
Fri Mar 10 09:32:20 2017 +0000
Revision:
3:29448355ef3a
Parent:
2:fd026fcfde94
EEPROM chack

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 2:fd026fcfde94 21 uint8_t mcpInit(mcp_can_t *obj, const uint32_t bitRate, const CANMode mode)
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 1:ad71faa09868 45 // enable both receive-buffers, using filters to receive messages with std. and ext. identifiers that meet the filter criteria and enable rollover from RXB0 to RXB1 if RXB0 is full
Just4pLeisure 0:f5d099885d3d 46 mcpBitModify(obj, MCP_RXB0CTRL, MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
Just4pLeisure 0:f5d099885d3d 47 mcpBitModify(obj, MCP_RXB1CTRL, MCP_RXB_RX_MASK, MCP_RXB_RX_STDEXT);
Just4pLeisure 0:f5d099885d3d 48 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 49 printf("Setting bit rate\r\n");
Just4pLeisure 0:f5d099885d3d 50 #endif
Just4pLeisure 1:ad71faa09868 51 if (!mcpSetBitRate(obj, bitRate)) { // set baudrate
Just4pLeisure 1:ad71faa09868 52 return 0;
Just4pLeisure 1:ad71faa09868 53 }
Just4pLeisure 2:fd026fcfde94 54 // return mcpSetMode(obj, MODE_NORMAL) ? 1 : 0; // set Normal mode and return
Just4pLeisure 2:fd026fcfde94 55 return mcpSetMode(obj, mode) ? 1 : 0; // set Normal mode and return
Just4pLeisure 0:f5d099885d3d 56 }
Just4pLeisure 0:f5d099885d3d 57
Just4pLeisure 0:f5d099885d3d 58 /** set MCP2515 operation mode
Just4pLeisure 0:f5d099885d3d 59 *
Just4pLeisure 0:f5d099885d3d 60 * Configuration, Normal, Sleep, Listen-only or Loopback
Just4pLeisure 0:f5d099885d3d 61 */
Just4pLeisure 2:fd026fcfde94 62 uint8_t mcpSetMode(mcp_can_t *obj, const uint8_t newmode)
Just4pLeisure 0:f5d099885d3d 63 {
Just4pLeisure 0:f5d099885d3d 64 mcpBitModify(obj, MCP_CANCTRL, MODE_MASK, newmode);
Just4pLeisure 0:f5d099885d3d 65 for (uint32_t i = 0; i<10; i++) {
Just4pLeisure 0:f5d099885d3d 66 if ((mcpRead(obj, MCP_CANSTAT) & MODE_MASK) == newmode) {
Just4pLeisure 0:f5d099885d3d 67 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 68 printf("Successfully entered mode: %02x time: %dms\r\n", newmode, i);
Just4pLeisure 0:f5d099885d3d 69 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 70 #endif
Just4pLeisure 0:f5d099885d3d 71 return 1;
Just4pLeisure 0:f5d099885d3d 72 }
Just4pLeisure 0:f5d099885d3d 73 wait_ms(1);
Just4pLeisure 0:f5d099885d3d 74 }
Just4pLeisure 0:f5d099885d3d 75 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 76 printf("Failed to enter mode: %02x\r\n", newmode);
Just4pLeisure 0:f5d099885d3d 77 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 78 #endif
Just4pLeisure 0:f5d099885d3d 79 return 0;
Just4pLeisure 0:f5d099885d3d 80 }
Just4pLeisure 0:f5d099885d3d 81
Just4pLeisure 0:f5d099885d3d 82 /** set the CAN bus bitrate
Just4pLeisure 0:f5d099885d3d 83 *
Just4pLeisure 0:f5d099885d3d 84 * Calculate suitable BTR register values.
Just4pLeisure 0:f5d099885d3d 85 * The Bit Rate Pre-scaler (BRP) can be in the range of 1-64.
Just4pLeisure 0:f5d099885d3d 86 * According to CANopen, Bit Time can be be between 25 and 8 Time Quanta (TQU).
Just4pLeisure 0:f5d099885d3d 87 * Bit Time = SyncSeg(1 TQU) + PropSeg(1-8 TQU) + PhaseSeg1(1-8 TQU) + PhaseSeg2(2-8 TQU).
Just4pLeisure 0:f5d099885d3d 88 * SyncSeg is always 1TQU, PhaseSeg2 must be at least 2TQU to be longer than the processing time.
Just4pLeisure 0:f5d099885d3d 89 * Opinions vary on when to take a sample but a point roughly 2/3 of Bit Time seems OK.
Just4pLeisure 0:f5d099885d3d 90 * Synchronisation Jump width can be 1-4 TQU, a value of 1 seems to be normal.
Just4pLeisure 0:f5d099885d3d 91 *
Just4pLeisure 0:f5d099885d3d 92 * 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 93 *
Just4pLeisure 0:f5d099885d3d 94 * This table has the sampling points as close to 2/3 (66.7%) as possible.
Just4pLeisure 0:f5d099885d3d 95 * The first value is PropSeg, 2nd PhaseSeg1.
Just4pLeisure 0:f5d099885d3d 96 * PhaseSeg2 will be the same as PhaseSeg1 when btlmode bit is initialised to 0.
Just4pLeisure 0:f5d099885d3d 97 */
Just4pLeisure 0:f5d099885d3d 98 static const uint8_t timing_pts[18][2] = {
Just4pLeisure 0:f5d099885d3d 99 {0x0, 0x2}, // 8, 62.5%
Just4pLeisure 0:f5d099885d3d 100 {0x1, 0x2}, // 9, 66.7%
Just4pLeisure 0:f5d099885d3d 101 {0x2, 0x2}, // 10, 70.0%
Just4pLeisure 0:f5d099885d3d 102 {0x1, 0x3}, // 11, 63.6%
Just4pLeisure 0:f5d099885d3d 103 {0x2, 0x3}, // 12, 66.7%
Just4pLeisure 0:f5d099885d3d 104 {0x3, 0x3}, // 13, 69.2%
Just4pLeisure 0:f5d099885d3d 105 {0x2, 0x4}, // 14, 64.3%
Just4pLeisure 0:f5d099885d3d 106 {0x3, 0x4}, // 15, 66.7%
Just4pLeisure 0:f5d099885d3d 107 {0x4, 0x4}, // 16, 68.75%
Just4pLeisure 0:f5d099885d3d 108 {0x3, 0x5}, // 17, 64.7%
Just4pLeisure 0:f5d099885d3d 109 {0x4, 0x5}, // 18, 66.7%
Just4pLeisure 0:f5d099885d3d 110 {0x5, 0x5}, // 19, 63.2%
Just4pLeisure 0:f5d099885d3d 111 {0x4, 0x6}, // 20, 65.0%
Just4pLeisure 0:f5d099885d3d 112 {0x5, 0x6}, // 21, 66.7%
Just4pLeisure 0:f5d099885d3d 113 {0x6, 0x6}, // 22, 68.2%
Just4pLeisure 0:f5d099885d3d 114 {0x5, 0x7}, // 23, 65.2
Just4pLeisure 0:f5d099885d3d 115 {0x6, 0x7}, // 24, 66.7%
Just4pLeisure 0:f5d099885d3d 116 {0x7, 0x7}, // 25, 68.0%
Just4pLeisure 0:f5d099885d3d 117 };
Just4pLeisure 0:f5d099885d3d 118
Just4pLeisure 2:fd026fcfde94 119 uint8_t mcpSetBitRate(mcp_can_t *obj, const uint32_t bitRate)
Just4pLeisure 0:f5d099885d3d 120 {
Just4pLeisure 0:f5d099885d3d 121 union { // Access CANtiming as:
Just4pLeisure 0:f5d099885d3d 122 CANtiming x; // the organised struct
Just4pLeisure 0:f5d099885d3d 123 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 124 };
Just4pLeisure 0:f5d099885d3d 125 uint32_t bestBRP = 0;
Just4pLeisure 0:f5d099885d3d 126 uint32_t bestTQU = 0;
Just4pLeisure 0:f5d099885d3d 127 uint32_t bestCanRate = 0;
Just4pLeisure 0:f5d099885d3d 128 uint32_t minBRP = (MCP_CLOCK_FREQ / (2 * MCP_MAX_TIME_QUANTA * bitRate));
Just4pLeisure 0:f5d099885d3d 129 uint32_t maxBRP = (MCP_CLOCK_FREQ / (2 * MCP_MIN_TIME_QUANTA * bitRate));
Just4pLeisure 1:ad71faa09868 130
Just4pLeisure 1:ad71faa09868 131 #ifdef DEBUG
Just4pLeisure 1:ad71faa09868 132 printf("Setting configuration mode\r\n");
Just4pLeisure 1:ad71faa09868 133 #endif
Just4pLeisure 1:ad71faa09868 134 uint8_t initialMode = mcpRead(obj, MCP_CANCTRL) & MODE_MASK; // Store the current operation mode
Just4pLeisure 1:ad71faa09868 135 if(!mcpSetMode(obj, MODE_CONFIG)) { // Go into configuration mode
Just4pLeisure 1:ad71faa09868 136 return 0;
Just4pLeisure 1:ad71faa09868 137 }
Just4pLeisure 1:ad71faa09868 138
Just4pLeisure 0:f5d099885d3d 139 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise CANtiming (btlmode, sjw and sam all = 0)
Just4pLeisure 0:f5d099885d3d 140 if ((bitRate < CAN_MIN_RATE) || (bitRate > CAN_MAX_RATE)) {
Just4pLeisure 0:f5d099885d3d 141 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 142 printf("FAILED!! The requested Bit Rate is too high or too low: %d\r\n", bitRate);
Just4pLeisure 0:f5d099885d3d 143 #endif
Just4pLeisure 0:f5d099885d3d 144 return 0; // Cannot set the requested bit rate!
Just4pLeisure 0:f5d099885d3d 145 }
Just4pLeisure 0:f5d099885d3d 146 minBRP = (minBRP == 0) ? MCP_MIN_PRESCALER : minBRP;
Just4pLeisure 0:f5d099885d3d 147 maxBRP = (maxBRP > MCP_MAX_PRESCALER) ? MCP_MAX_PRESCALER : maxBRP;
Just4pLeisure 0:f5d099885d3d 148 for (uint32_t BRP = minBRP; BRP < (maxBRP + 1); BRP++) {
Just4pLeisure 0:f5d099885d3d 149 uint32_t timeQuanta = (MCP_CLOCK_FREQ / (2 * BRP * bitRate));
Just4pLeisure 0:f5d099885d3d 150 if ((timeQuanta >= MCP_MIN_TIME_QUANTA) && (timeQuanta <= MCP_MAX_TIME_QUANTA)) {
Just4pLeisure 0:f5d099885d3d 151 for (uint32_t TQU = timeQuanta; TQU <= MCP_MAX_TIME_QUANTA; TQU++) {
Just4pLeisure 0:f5d099885d3d 152 uint32_t thisCanRate = MCP_CLOCK_FREQ / (2 * BRP * TQU);
Just4pLeisure 0:f5d099885d3d 153 if ( abs((int)bitRate - (int)thisCanRate) < abs((int)bitRate - (int)bestCanRate)) {
Just4pLeisure 0:f5d099885d3d 154 bestCanRate = thisCanRate;
Just4pLeisure 0:f5d099885d3d 155 bestBRP= BRP;
Just4pLeisure 0:f5d099885d3d 156 bestTQU= TQU;
Just4pLeisure 0:f5d099885d3d 157 }
Just4pLeisure 0:f5d099885d3d 158 }
Just4pLeisure 0:f5d099885d3d 159 }
Just4pLeisure 0:f5d099885d3d 160 }
Just4pLeisure 0:f5d099885d3d 161 x.brp = (bestBRP - 1);
Just4pLeisure 0:f5d099885d3d 162 x.prseg = (timing_pts[bestTQU - 8][0]);
Just4pLeisure 0:f5d099885d3d 163 x.phseg1 = (timing_pts[bestTQU - 8][1]);
Just4pLeisure 0:f5d099885d3d 164 mcpWriteMultiple(obj, MCP_CNF3, y, sizeof(x) ); // Copy CANtiming to the MCP2515 (as an array)
Just4pLeisure 0:f5d099885d3d 165 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 166 printf("minBRP %d maxBRP %d\r\n", minBRP, maxBRP);
Just4pLeisure 0:f5d099885d3d 167 printf("Bitrate: %d\tactualBitRate: %d\t Error: %1.2f percent.\r\n", bitRate, bestCanRate, (100-(100*(float)bitRate/(float)bestCanRate)));
Just4pLeisure 0:f5d099885d3d 168 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 169 printf("Syncseg: 1\tPropSeg: %d\tPhaseSeg1: %d\tPhaseSeg2: %d\r\n", (x.prseg+1), (x.phseg1+1), (x.phseg1+1));
Just4pLeisure 0:f5d099885d3d 170 printf("Setting normal mode\r\n");
Just4pLeisure 0:f5d099885d3d 171 #endif
Just4pLeisure 1:ad71faa09868 172 return (mcpSetMode(obj, initialMode)) ? 1 : 0; // desired bit rate set enter normal mode and return
Just4pLeisure 0:f5d099885d3d 173 }
Just4pLeisure 0:f5d099885d3d 174
Just4pLeisure 0:f5d099885d3d 175 /** write a CAN id to a mask, filter or transmit buffer
Just4pLeisure 0:f5d099885d3d 176 */
Just4pLeisure 2:fd026fcfde94 177 void mcpWriteId(mcp_can_t *obj, const uint8_t mcp_addr, const uint8_t ext, const uint32_t id )
Just4pLeisure 0:f5d099885d3d 178 {
Just4pLeisure 0:f5d099885d3d 179 union { // Access CANid as:
Just4pLeisure 0:f5d099885d3d 180 CANid x; // the organised struct
Just4pLeisure 0:f5d099885d3d 181 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 182 };
Just4pLeisure 0:f5d099885d3d 183
Just4pLeisure 0:f5d099885d3d 184 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise CANid structure
Just4pLeisure 0:f5d099885d3d 185 x.ide = ext; // Extended Identifier Flag
Just4pLeisure 0:f5d099885d3d 186 if (x.ide == CANExtended) {
Just4pLeisure 0:f5d099885d3d 187 x.sid10_3 = (uint8_t) (id >> 21); // SID10..3
Just4pLeisure 0:f5d099885d3d 188 x.sid2_0 = (uint8_t) (id >> 18) & 0x07; // SID2..0
Just4pLeisure 0:f5d099885d3d 189 x.eid17_16 = (uint8_t) (id >> 16) & 0x03; // EID17..16
Just4pLeisure 0:f5d099885d3d 190 x.eid15_8 = (uint8_t) (id >> 8); // EID15..8
Just4pLeisure 0:f5d099885d3d 191 x.eid7_0 = (uint8_t) id; // EID7..0
Just4pLeisure 0:f5d099885d3d 192 } else {
Just4pLeisure 0:f5d099885d3d 193 x.sid10_3 = (uint8_t) (id >> 3); // SID10..3
Just4pLeisure 0:f5d099885d3d 194 x.sid2_0 = (uint8_t) (id & 0x07); // SID2..0
Just4pLeisure 0:f5d099885d3d 195 }
Just4pLeisure 0:f5d099885d3d 196 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 197 printf("sizeof CanIdStruct: %d bytes\r\n", sizeof(x));
Just4pLeisure 0:f5d099885d3d 198 printf("sid10_3: %x\r\n", x.sid10_3);
Just4pLeisure 0:f5d099885d3d 199 printf("eid17_16: %x\r\n", x.eid17_16);
Just4pLeisure 0:f5d099885d3d 200 printf("ide: %x\r\n", x.ide);
Just4pLeisure 0:f5d099885d3d 201 printf("srtr: %x\r\n", x.srtr);
Just4pLeisure 0:f5d099885d3d 202 printf("sid2_0: %x\r\n", x.sid2_0);
Just4pLeisure 0:f5d099885d3d 203 printf("eid15_8: %x\r\n", x.eid15_8);
Just4pLeisure 0:f5d099885d3d 204 printf("eid7_0: %x\r\n", x.eid7_0);
Just4pLeisure 0:f5d099885d3d 205 #endif
Just4pLeisure 0:f5d099885d3d 206 mcpWriteMultiple(obj, mcp_addr, y, sizeof(x) ); // Copy CANid to the MCP2515 (as an array)
Just4pLeisure 0:f5d099885d3d 207 }
Just4pLeisure 0:f5d099885d3d 208
Just4pLeisure 0:f5d099885d3d 209 /** write a CAN message to the MCP2515
Just4pLeisure 0:f5d099885d3d 210 */
Just4pLeisure 2:fd026fcfde94 211 uint8_t mcpCanWrite(mcp_can_t *obj, CAN_Message msg)
Just4pLeisure 0:f5d099885d3d 212 {
Just4pLeisure 0:f5d099885d3d 213 union { // Access CANMsg as:
Just4pLeisure 0:f5d099885d3d 214 CANMsg x; // the organised struct
Just4pLeisure 0:f5d099885d3d 215 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 216 };
Just4pLeisure 0:f5d099885d3d 217 uint8_t bufferCommand[] = {MCP_WRITE_TX0, MCP_WRITE_TX1, MCP_WRITE_TX2};
Just4pLeisure 0:f5d099885d3d 218 uint8_t rtsCommand[] = {MCP_RTS_TX0, MCP_RTS_TX1, MCP_RTS_TX2};
Just4pLeisure 0:f5d099885d3d 219 uint8_t status = mcpStatus(obj);
Just4pLeisure 0:f5d099885d3d 220 uint32_t num = 0;
Just4pLeisure 0:f5d099885d3d 221 // Check if there is a free message buffer
Just4pLeisure 0:f5d099885d3d 222 if (!(status & MCP_STAT_TX0REQ)) { // TX Message Buffer 0 free?
Just4pLeisure 0:f5d099885d3d 223 num = 0;
Just4pLeisure 0:f5d099885d3d 224 } else if (!(status & MCP_STAT_TX1REQ)) { // TX Message Buffer 1 free?
Just4pLeisure 0:f5d099885d3d 225 num = 1;
Just4pLeisure 0:f5d099885d3d 226 } else if (!(status & MCP_STAT_TX2REQ)) { // TX Message Buffer 2 free?
Just4pLeisure 0:f5d099885d3d 227 num = 2;
Just4pLeisure 0:f5d099885d3d 228 } else {
Just4pLeisure 0:f5d099885d3d 229 return 0; // No free transmit buffers in the MCP2515 CAN controller chip
Just4pLeisure 0:f5d099885d3d 230 }
Just4pLeisure 0:f5d099885d3d 231 // populate CANMsg structure
Just4pLeisure 0:f5d099885d3d 232 for (uint32_t i = 0; i < sizeof(x); i++) y[i] = NULL; // Initialise CANMsg structure
Just4pLeisure 0:f5d099885d3d 233 x.id.ide = msg.format; // Extended Identifier Flag
Just4pLeisure 0:f5d099885d3d 234 if (x.id.ide == CANExtended) {
Just4pLeisure 0:f5d099885d3d 235 x.id.sid10_3 = (uint8_t) (msg.id >> 21); // SID10..3
Just4pLeisure 0:f5d099885d3d 236 x.id.sid2_0 = (uint8_t) (msg.id >> 18) & 0x07; // SID2..0
Just4pLeisure 0:f5d099885d3d 237 x.id.eid17_16 = (uint8_t) (msg.id >> 16) & 0x03; // EID17..16
Just4pLeisure 0:f5d099885d3d 238 x.id.eid15_8 = (uint8_t) (msg.id >> 8); // EID15..8
Just4pLeisure 0:f5d099885d3d 239 x.id.eid7_0 = (uint8_t) msg.id; // EID7..0
Just4pLeisure 0:f5d099885d3d 240 } else {
Just4pLeisure 0:f5d099885d3d 241 x.id.sid10_3 = (uint8_t) (msg.id >> 3); // SID10..3
Just4pLeisure 0:f5d099885d3d 242 x.id.sid2_0 = (uint8_t) (msg.id & 0x07); // SID2..0
Just4pLeisure 0:f5d099885d3d 243 }
Just4pLeisure 0:f5d099885d3d 244 x.dlc = msg.len & 0x0f; // Number of bytes in can message
Just4pLeisure 0:f5d099885d3d 245 x.ertr = msg.type; // Data or remote message
Just4pLeisure 0:f5d099885d3d 246 memcpy(x.data,msg.data,x.dlc); // Get the Data bytes
Just4pLeisure 0:f5d099885d3d 247 // write CANmsg to the specified TX buffer 'num'
Just4pLeisure 0:f5d099885d3d 248 mcpWriteBuffer(obj, bufferCommand[num], y, sizeof(x)); // Write the message ,CANMsg, to the MCP2515's Tx buffer 'num' (as an array)
Just4pLeisure 0:f5d099885d3d 249 mcpBufferRTS(obj, rtsCommand[num]);
Just4pLeisure 0:f5d099885d3d 250 return 1; // Indicate that message has been transmitted
Just4pLeisure 0:f5d099885d3d 251 }
Just4pLeisure 0:f5d099885d3d 252
Just4pLeisure 0:f5d099885d3d 253 /** read a CAN message from the MCP2515
Just4pLeisure 0:f5d099885d3d 254 */
Just4pLeisure 2:fd026fcfde94 255 uint8_t mcpCanRead(mcp_can_t *obj, CAN_Message *msg)
Just4pLeisure 0:f5d099885d3d 256 {
Just4pLeisure 0:f5d099885d3d 257 union { // Access CANMsg as:
Just4pLeisure 0:f5d099885d3d 258 CANMsg x; // the organised struct
Just4pLeisure 0:f5d099885d3d 259 uint8_t y[]; // or contiguous memory array
Just4pLeisure 0:f5d099885d3d 260 };
Just4pLeisure 0:f5d099885d3d 261 uint8_t bufferCommand[] = {MCP_READ_RX0, MCP_READ_RX1};
Just4pLeisure 0:f5d099885d3d 262 uint8_t status = mcpReceiveStatus(obj);
Just4pLeisure 0:f5d099885d3d 263 bool num = 0;
Just4pLeisure 0:f5d099885d3d 264 // Check if there is a message the buffers
Just4pLeisure 0:f5d099885d3d 265 if (status & MCP_RXSTAT_RXB0) { // Msg in Buffer 0?
Just4pLeisure 0:f5d099885d3d 266 num = 0;
Just4pLeisure 0:f5d099885d3d 267 } else if (status & MCP_RXSTAT_RXB1) { // Msg in Buffer 1?
Just4pLeisure 0:f5d099885d3d 268 num = 1;
Just4pLeisure 0:f5d099885d3d 269 } else {
Just4pLeisure 0:f5d099885d3d 270 return 0; // No messages waiting
Just4pLeisure 0:f5d099885d3d 271 }
Just4pLeisure 0:f5d099885d3d 272 mcpReadBuffer(obj, bufferCommand[0], y, sizeof(x)); // Read the message into CANMsg (as an array)
Just4pLeisure 0:f5d099885d3d 273 mcpBitModify(obj, MCP_CANINTF, (!num ? MCP_RX0IF : MCP_RX1IF), 0); // Free the message buffer
Just4pLeisure 0:f5d099885d3d 274 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 275 printf("sizeof CanMsgStruct: %d bytes\r\n", sizeof(x));
Just4pLeisure 0:f5d099885d3d 276 printf("sizeof CanMsgArray: %d bytes\r\n", sizeof(y));
Just4pLeisure 0:f5d099885d3d 277 printf("sid10_3: %x\r\n", x.id.sid10_3);
Just4pLeisure 0:f5d099885d3d 278 printf("eid17_16: %x\r\n", x.id.eid17_16);
Just4pLeisure 0:f5d099885d3d 279 printf("ide: %x\r\n", x.id.ide);
Just4pLeisure 0:f5d099885d3d 280 printf("srtr: %x\r\n", x.id.srtr);
Just4pLeisure 0:f5d099885d3d 281 printf("sid2_0: %x\r\n", x.id.sid2_0);
Just4pLeisure 0:f5d099885d3d 282 printf("eid15_8: %x\r\n", x.id.eid15_8);
Just4pLeisure 0:f5d099885d3d 283 printf("eid7_0: %x\r\n", x.id.eid7_0);
Just4pLeisure 0:f5d099885d3d 284 printf("dlc: %x\r\n", x.dlc);
Just4pLeisure 0:f5d099885d3d 285 printf("ertr: %x\r\n", x.ertr);
Just4pLeisure 0:f5d099885d3d 286 printf("data: ");
Just4pLeisure 0:f5d099885d3d 287 for (char i=0; i<8; i++)
Just4pLeisure 0:f5d099885d3d 288 printf("%02x,", x.data[i]);
Just4pLeisure 0:f5d099885d3d 289 printf("\r\n");
Just4pLeisure 0:f5d099885d3d 290 #endif
Just4pLeisure 0:f5d099885d3d 291 msg->format = (status & MCP_RXSTAT_IDE) ? CANExtended : CANStandard;// Extended CAN id Flag
Just4pLeisure 0:f5d099885d3d 292 if (msg->format == CANExtended) { // Assemble the Extended CAN id
Just4pLeisure 0:f5d099885d3d 293 msg->id = (x.id.sid10_3 << 21) |
Just4pLeisure 0:f5d099885d3d 294 (x.id.sid2_0 << 18) |
Just4pLeisure 0:f5d099885d3d 295 (x.id.eid17_16 << 16) |
Just4pLeisure 0:f5d099885d3d 296 (x.id.eid15_8 << 8) |
Just4pLeisure 0:f5d099885d3d 297 (x.id.eid7_0);
Just4pLeisure 0:f5d099885d3d 298 } else { // Assemble the Standard CAN id
Just4pLeisure 0:f5d099885d3d 299 msg->id = (x.id.sid10_3 << 3) |
Just4pLeisure 0:f5d099885d3d 300 (x.id.sid2_0);
Just4pLeisure 0:f5d099885d3d 301 }
Just4pLeisure 0:f5d099885d3d 302 msg->len = x.dlc; // Number of bytes in CAN message
Just4pLeisure 0:f5d099885d3d 303 msg->type = (status & MCP_RXSTAT_RTR) ? CANRemote : CANData; // Determine if a Remote or Data message type
Just4pLeisure 0:f5d099885d3d 304 memcpy(msg->data,x.data,x.dlc); // Get the Data bytes
Just4pLeisure 0:f5d099885d3d 305 return 1; // Indicate that message has been retrieved
Just4pLeisure 0:f5d099885d3d 306 }
Just4pLeisure 0:f5d099885d3d 307
Just4pLeisure 0:f5d099885d3d 308 /** initialise an Acceptance Mask
Just4pLeisure 0:f5d099885d3d 309 */
Just4pLeisure 2:fd026fcfde94 310 uint8_t mcpInitMask(mcp_can_t *obj, uint8_t num, uint32_t ulData, bool ext)
Just4pLeisure 0:f5d099885d3d 311 {
Just4pLeisure 0:f5d099885d3d 312 uint8_t mask[2] = { MCP_RXM0SIDH, MCP_RXM1SIDH };
Just4pLeisure 0:f5d099885d3d 313
Just4pLeisure 0:f5d099885d3d 314 if (num > 1) {
Just4pLeisure 0:f5d099885d3d 315 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 316 printf("Trying to set an invalid Mask number: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 317 #endif
Just4pLeisure 0:f5d099885d3d 318 return 0;
Just4pLeisure 0:f5d099885d3d 319 }
Just4pLeisure 0:f5d099885d3d 320 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 321 printf("Begin to set Mask!!\r\n");
Just4pLeisure 0:f5d099885d3d 322 #endif
Just4pLeisure 1:ad71faa09868 323 uint8_t initialMode = mcpRead(obj, MCP_CANCTRL) & MODE_MASK; // Store the current operation mode
Just4pLeisure 0:f5d099885d3d 324 if(!mcpSetMode(obj, MODE_CONFIG)) {
Just4pLeisure 0:f5d099885d3d 325 return 0;
Just4pLeisure 0:f5d099885d3d 326 }
Just4pLeisure 0:f5d099885d3d 327 mcpWriteId(obj, mask[num], ext, ulData);
Just4pLeisure 1:ad71faa09868 328 if(!mcpSetMode(obj, initialMode)) {
Just4pLeisure 0:f5d099885d3d 329 return 0;
Just4pLeisure 0:f5d099885d3d 330 }
Just4pLeisure 0:f5d099885d3d 331 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 332 printf("Successfully set Mask number: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 333 #endif
Just4pLeisure 0:f5d099885d3d 334 return 1;
Just4pLeisure 0:f5d099885d3d 335 }
Just4pLeisure 0:f5d099885d3d 336
Just4pLeisure 0:f5d099885d3d 337 /** initialise an Acceptance Filter
Just4pLeisure 0:f5d099885d3d 338 */
Just4pLeisure 2:fd026fcfde94 339 uint8_t mcpInitFilter(mcp_can_t *obj, uint8_t num, uint32_t ulData, bool ext)
Just4pLeisure 0:f5d099885d3d 340 {
Just4pLeisure 0:f5d099885d3d 341 uint8_t filter[6] = { MCP_RXF0SIDH, MCP_RXF1SIDH, MCP_RXF2SIDH, MCP_RXF3SIDH, MCP_RXF4SIDH, MCP_RXF5SIDH };
Just4pLeisure 0:f5d099885d3d 342
Just4pLeisure 0:f5d099885d3d 343 if (num > 5) {
Just4pLeisure 0:f5d099885d3d 344 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 345 printf("Trying to set an invalid Filter number: %d\r\n", num);
Just4pLeisure 0:f5d099885d3d 346 #endif
Just4pLeisure 0:f5d099885d3d 347 return 0;
Just4pLeisure 0:f5d099885d3d 348 }
Just4pLeisure 0:f5d099885d3d 349 #ifdef DEBUG
Just4pLeisure 0:f5d099885d3d 350 printf("Begin to set Filter!!\r\n");
Just4pLeisure 0:f5d099885d3d 351 #endif
Just4pLeisure 1:ad71faa09868 352 uint8_t initialMode = mcpRead(obj, MCP_CANCTRL) & MODE_MASK; // Store the current operation mode
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 1:ad71faa09868 357 if(!mcpSetMode(obj, initialMode)) {
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 2:fd026fcfde94 366 /* Report on the specified errors and warnings
Just4pLeisure 2:fd026fcfde94 367 */
Just4pLeisure 2:fd026fcfde94 368 uint8_t mcpErrorType(mcp_can_t *obj, const CANFlags type)
Just4pLeisure 2:fd026fcfde94 369 {
Just4pLeisure 2:fd026fcfde94 370 uint8_t which[] = { MCP_EFLG_ALLMASK,
Just4pLeisure 2:fd026fcfde94 371 MCP_EFLG_ERRORMASK,
Just4pLeisure 2:fd026fcfde94 372 MCP_EFLG_WARNMASK,
Just4pLeisure 2:fd026fcfde94 373 MCP_EFLG_RX1OVR,
Just4pLeisure 2:fd026fcfde94 374 MCP_EFLG_RX0OVR,
Just4pLeisure 2:fd026fcfde94 375 MCP_EFLG_TXBO,
Just4pLeisure 2:fd026fcfde94 376 MCP_EFLG_TXEP,
Just4pLeisure 2:fd026fcfde94 377 MCP_EFLG_RXEP,
Just4pLeisure 2:fd026fcfde94 378 MCP_EFLG_TXWAR,
Just4pLeisure 2:fd026fcfde94 379 MCP_EFLG_RXWAR,
Just4pLeisure 2:fd026fcfde94 380 MCP_EFLG_EWARN
Just4pLeisure 2:fd026fcfde94 381 };
Just4pLeisure 2:fd026fcfde94 382
Just4pLeisure 2:fd026fcfde94 383 return (mcpRead(obj, MCP_EFLG) & which[type]) ? 1 : 0;
Just4pLeisure 2:fd026fcfde94 384 }
Just4pLeisure 2:fd026fcfde94 385
Just4pLeisure 2:fd026fcfde94 386 /* Return contents of the error and warning flags register
Just4pLeisure 2:fd026fcfde94 387 */
Just4pLeisure 2:fd026fcfde94 388 uint8_t mcpErrorFlags(mcp_can_t *obj)
Just4pLeisure 2:fd026fcfde94 389 {
Just4pLeisure 2:fd026fcfde94 390 return (mcpRead(obj, MCP_EFLG));
Just4pLeisure 2:fd026fcfde94 391 }
Just4pLeisure 2:fd026fcfde94 392
Just4pLeisure 0:f5d099885d3d 393 /* Number of message reception errors
Just4pLeisure 0:f5d099885d3d 394 */
Just4pLeisure 2:fd026fcfde94 395 uint8_t mcpReceptionErrorCount(mcp_can_t *obj)
Just4pLeisure 0:f5d099885d3d 396 {
Just4pLeisure 0:f5d099885d3d 397 return (mcpRead(obj, MCP_REC));
Just4pLeisure 0:f5d099885d3d 398 }
Just4pLeisure 0:f5d099885d3d 399
Just4pLeisure 0:f5d099885d3d 400 /* Number of message transmission errors
Just4pLeisure 0:f5d099885d3d 401 */
Just4pLeisure 2:fd026fcfde94 402 uint8_t mcpTransmissionErrorCount(mcp_can_t *obj)
Just4pLeisure 0:f5d099885d3d 403 {
Just4pLeisure 0:f5d099885d3d 404 return (mcpRead(obj, MCP_TEC));
Just4pLeisure 0:f5d099885d3d 405 }
Just4pLeisure 0:f5d099885d3d 406
Just4pLeisure 0:f5d099885d3d 407 /* Select between monitor (silent = 1) and normal (silent = 0) modes
Just4pLeisure 0:f5d099885d3d 408 */
Just4pLeisure 2:fd026fcfde94 409 void mcpMonitor(mcp_can_t *obj, const bool silent)
Just4pLeisure 0:f5d099885d3d 410 {
Just4pLeisure 0:f5d099885d3d 411 silent ? mcpSetMode(obj, MODE_LISTENONLY) : mcpSetMode(obj, MODE_NORMAL);
Just4pLeisure 0:f5d099885d3d 412 }
Just4pLeisure 0:f5d099885d3d 413
Just4pLeisure 0:f5d099885d3d 414 /* Change CAN operation to the specified mode
Just4pLeisure 0:f5d099885d3d 415 */
Just4pLeisure 2:fd026fcfde94 416 uint8_t mcpMode(mcp_can_t *obj, const CANMode mode)
Just4pLeisure 0:f5d099885d3d 417 {
Just4pLeisure 2:fd026fcfde94 418 uint8_t which[] = { MODE_NORMAL,
Just4pLeisure 2:fd026fcfde94 419 MODE_SLEEP,
Just4pLeisure 2:fd026fcfde94 420 MODE_LOOPBACK,
Just4pLeisure 2:fd026fcfde94 421 MODE_LISTENONLY,
Just4pLeisure 2:fd026fcfde94 422 MODE_CONFIG,
Just4pLeisure 2:fd026fcfde94 423 MODE_CONFIG
Just4pLeisure 2:fd026fcfde94 424 };
Just4pLeisure 0:f5d099885d3d 425
Just4pLeisure 2:fd026fcfde94 426 if (mode == _M_RESET) {
Just4pLeisure 0:f5d099885d3d 427 mcpReset(obj);
Just4pLeisure 0:f5d099885d3d 428 }
Just4pLeisure 0:f5d099885d3d 429 if (mcpSetMode(obj, which[mode])) {
Just4pLeisure 0:f5d099885d3d 430 return 1;
Just4pLeisure 0:f5d099885d3d 431 }
Just4pLeisure 0:f5d099885d3d 432 return 0;
Just4pLeisure 0:f5d099885d3d 433 }
Just4pLeisure 2:fd026fcfde94 434
Just4pLeisure 2:fd026fcfde94 435 /* Configure interrupt sources
Just4pLeisure 2:fd026fcfde94 436 */
Just4pLeisure 2:fd026fcfde94 437 void mcpSetInterrupts(mcp_can_t *obj, const CANIrqs irqSet)
Just4pLeisure 2:fd026fcfde94 438 {
Just4pLeisure 2:fd026fcfde94 439 uint8_t which[] = { MCP_NO_INTS,
Just4pLeisure 2:fd026fcfde94 440 MCP_ALL_INTS,
Just4pLeisure 2:fd026fcfde94 441 MCP_RX_INTS,
Just4pLeisure 2:fd026fcfde94 442 MCP_TX_INTS,
Just4pLeisure 2:fd026fcfde94 443 MCP_RX0IF,
Just4pLeisure 2:fd026fcfde94 444 MCP_RX1IF,
Just4pLeisure 2:fd026fcfde94 445 MCP_TX0IF,
Just4pLeisure 2:fd026fcfde94 446 MCP_TX1IF,
Just4pLeisure 2:fd026fcfde94 447 MCP_TX2IF,
Just4pLeisure 2:fd026fcfde94 448 MCP_ERRIF,
Just4pLeisure 2:fd026fcfde94 449 MCP_WAKIF,
Just4pLeisure 2:fd026fcfde94 450 MCP_MERRF
Just4pLeisure 2:fd026fcfde94 451 };
Just4pLeisure 2:fd026fcfde94 452
Just4pLeisure 2:fd026fcfde94 453 mcpWrite(obj, MCP_CANINTE, which[irqSet]);
Just4pLeisure 2:fd026fcfde94 454 }
Just4pLeisure 2:fd026fcfde94 455
Just4pLeisure 2:fd026fcfde94 456 /* Report on the specified interrupt causes
Just4pLeisure 2:fd026fcfde94 457 */
Just4pLeisure 2:fd026fcfde94 458 uint8_t mcpInterruptType(mcp_can_t *obj, const CANIrqs irqFlag)
Just4pLeisure 2:fd026fcfde94 459 {
Just4pLeisure 2:fd026fcfde94 460 uint8_t which[] = { MCP_NO_INTS,
Just4pLeisure 2:fd026fcfde94 461 MCP_ALL_INTS,
Just4pLeisure 2:fd026fcfde94 462 MCP_RX_INTS,
Just4pLeisure 2:fd026fcfde94 463 MCP_TX_INTS,
Just4pLeisure 2:fd026fcfde94 464 MCP_RX0IF,
Just4pLeisure 2:fd026fcfde94 465 MCP_RX1IF,
Just4pLeisure 2:fd026fcfde94 466 MCP_TX0IF,
Just4pLeisure 2:fd026fcfde94 467 MCP_TX1IF,
Just4pLeisure 2:fd026fcfde94 468 MCP_TX2IF,
Just4pLeisure 2:fd026fcfde94 469 MCP_ERRIF,
Just4pLeisure 2:fd026fcfde94 470 MCP_WAKIF,
Just4pLeisure 2:fd026fcfde94 471 MCP_MERRF
Just4pLeisure 2:fd026fcfde94 472 };
Just4pLeisure 2:fd026fcfde94 473
Just4pLeisure 2:fd026fcfde94 474 return (mcpRead(obj, MCP_EFLG) & which[irqFlag]) ? 1 : 0;
Just4pLeisure 2:fd026fcfde94 475 }
Just4pLeisure 2:fd026fcfde94 476
Just4pLeisure 2:fd026fcfde94 477 /* Return contents of the interrupt flags register
Just4pLeisure 2:fd026fcfde94 478 */
Just4pLeisure 2:fd026fcfde94 479 uint8_t mcpInterruptFlags(mcp_can_t *obj)
Just4pLeisure 2:fd026fcfde94 480 {
Just4pLeisure 2:fd026fcfde94 481 return (mcpRead(obj, MCP_EFLG));
Just4pLeisure 2:fd026fcfde94 482 }