CANPort provides a higher level interface to a CAN communication channel, and provides timestamping, servicing additional hardware interfaces (optional activity LED, CAN transceiver slope control)
CANPort.cpp@1:f0b4e47d948d, 2019-08-28 (annotated)
- Committer:
- WiredHome
- Date:
- Wed Aug 28 22:02:49 2019 +0000
- Revision:
- 1:f0b4e47d948d
- Parent:
- 0:7b81b19d9b10
- Child:
- 3:4c780c641125
Minor updates based on mbed version.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:7b81b19d9b10 | 1 | /// @file CANPort.cpp is where all the port level functionality resides |
WiredHome | 0:7b81b19d9b10 | 2 | /// |
WiredHome | 0:7b81b19d9b10 | 3 | /// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved. |
WiredHome | 0:7b81b19d9b10 | 4 | /// Individuals may use this application for evaluation or non-commercial |
WiredHome | 0:7b81b19d9b10 | 5 | /// purposes. Within this restriction, changes may be made to this application |
WiredHome | 0:7b81b19d9b10 | 6 | /// as long as this copyright notice is retained. The user shall make |
WiredHome | 0:7b81b19d9b10 | 7 | /// clear that their work is a derived work, and not the original. |
WiredHome | 0:7b81b19d9b10 | 8 | /// Users of this application and sources accept this application "as is" and |
WiredHome | 0:7b81b19d9b10 | 9 | /// shall hold harmless Smartware Computing, for any undesired results while |
WiredHome | 0:7b81b19d9b10 | 10 | /// using this application - whether real or imagined. |
WiredHome | 0:7b81b19d9b10 | 11 | /// |
WiredHome | 0:7b81b19d9b10 | 12 | /// @author David Smart, Smartware Computing |
WiredHome | 0:7b81b19d9b10 | 13 | /// |
WiredHome | 0:7b81b19d9b10 | 14 | /// 20110718 |
WiredHome | 0:7b81b19d9b10 | 15 | /// Fixed a bug in the Receive handler - it was not propagating the message |
WiredHome | 0:7b81b19d9b10 | 16 | /// out. |
WiredHome | 0:7b81b19d9b10 | 17 | /// 20110605 |
WiredHome | 0:7b81b19d9b10 | 18 | /// Revised the SlopeControl so that it actually works for any change in value |
WiredHome | 0:7b81b19d9b10 | 19 | /// where it was previously able to go low or high, but once as an input it |
WiredHome | 0:7b81b19d9b10 | 20 | /// then would not go back to an output. |
WiredHome | 0:7b81b19d9b10 | 21 | /// |
WiredHome | 0:7b81b19d9b10 | 22 | #include "mbed.h" |
WiredHome | 0:7b81b19d9b10 | 23 | #include "CANPort.h" |
WiredHome | 0:7b81b19d9b10 | 24 | #include "Utilities.h" |
WiredHome | 0:7b81b19d9b10 | 25 | |
WiredHome | 0:7b81b19d9b10 | 26 | #define FLASH_PERIOD (float)0.04 |
WiredHome | 0:7b81b19d9b10 | 27 | #define FLASH_TX_LEVEL 0.10 |
WiredHome | 0:7b81b19d9b10 | 28 | #define FLASH_RX_LEVEL 1.00 |
WiredHome | 0:7b81b19d9b10 | 29 | |
WiredHome | 0:7b81b19d9b10 | 30 | |
WiredHome | 0:7b81b19d9b10 | 31 | CANPort::CANPort(CANCHANNEL_T chNum, PinName rd, PinName td, PinName _activityPin, PinName _slopePin, CANSlopeControl_T slope) { |
WiredHome | 0:7b81b19d9b10 | 32 | channel = chNum; |
WiredHome | 0:7b81b19d9b10 | 33 | can = new CAN(rd, td); |
WiredHome | 0:7b81b19d9b10 | 34 | if (_activityPin != NC) { |
WiredHome | 0:7b81b19d9b10 | 35 | activityPin = new PwmOut(_activityPin); |
WiredHome | 0:7b81b19d9b10 | 36 | activityPin->pulsewidth_us(100); |
WiredHome | 0:7b81b19d9b10 | 37 | } |
WiredHome | 0:7b81b19d9b10 | 38 | else |
WiredHome | 0:7b81b19d9b10 | 39 | activityPin = NULL; |
WiredHome | 0:7b81b19d9b10 | 40 | if (_slopePin != NC) { |
WiredHome | 0:7b81b19d9b10 | 41 | slopePin = new DigitalInOut(_slopePin); |
WiredHome | 0:7b81b19d9b10 | 42 | SetSlopeControl(slope); |
WiredHome | 0:7b81b19d9b10 | 43 | } else |
WiredHome | 0:7b81b19d9b10 | 44 | slopePin = NULL; |
WiredHome | 0:7b81b19d9b10 | 45 | slopePinName = _slopePin; |
WiredHome | 0:7b81b19d9b10 | 46 | txCounter = 0; |
WiredHome | 0:7b81b19d9b10 | 47 | rxCounter = 0; |
WiredHome | 0:7b81b19d9b10 | 48 | } |
WiredHome | 0:7b81b19d9b10 | 49 | |
WiredHome | 0:7b81b19d9b10 | 50 | |
WiredHome | 0:7b81b19d9b10 | 51 | CANPort::~CANPort() { |
WiredHome | 0:7b81b19d9b10 | 52 | if (slopePin) |
WiredHome | 0:7b81b19d9b10 | 53 | delete slopePin; |
WiredHome | 0:7b81b19d9b10 | 54 | if (activityPin) |
WiredHome | 0:7b81b19d9b10 | 55 | delete activityPin; |
WiredHome | 0:7b81b19d9b10 | 56 | if (can) |
WiredHome | 0:7b81b19d9b10 | 57 | delete can; |
WiredHome | 0:7b81b19d9b10 | 58 | slopePin = NULL; |
WiredHome | 0:7b81b19d9b10 | 59 | activityPin = NULL; |
WiredHome | 0:7b81b19d9b10 | 60 | can = NULL; |
WiredHome | 0:7b81b19d9b10 | 61 | } |
WiredHome | 0:7b81b19d9b10 | 62 | |
WiredHome | 0:7b81b19d9b10 | 63 | |
WiredHome | 0:7b81b19d9b10 | 64 | bool CANPort::TransmitMsg(CANmsg msg) { |
WiredHome | 0:7b81b19d9b10 | 65 | bool success = false; |
WiredHome | 0:7b81b19d9b10 | 66 | |
WiredHome | 0:7b81b19d9b10 | 67 | if (msg.dir == xmt) { // we have to have indicated our intent to transmit |
WiredHome | 0:7b81b19d9b10 | 68 | msg.ch = channel; |
WiredHome | 0:7b81b19d9b10 | 69 | if (can->write(CANMessage(msg.id, (char *)&msg.data, msg.len, CANData, msg.format))) { |
WiredHome | 0:7b81b19d9b10 | 70 | txCounter++; |
WiredHome | 0:7b81b19d9b10 | 71 | Flash(msg.dir); |
WiredHome | 0:7b81b19d9b10 | 72 | success = true; |
WiredHome | 0:7b81b19d9b10 | 73 | } |
WiredHome | 0:7b81b19d9b10 | 74 | } |
WiredHome | 0:7b81b19d9b10 | 75 | return success; |
WiredHome | 0:7b81b19d9b10 | 76 | } |
WiredHome | 0:7b81b19d9b10 | 77 | |
WiredHome | 0:7b81b19d9b10 | 78 | |
WiredHome | 0:7b81b19d9b10 | 79 | bool CANPort::ReceiveMsg(CANmsg &msg) { |
WiredHome | 0:7b81b19d9b10 | 80 | bool success = false; |
WiredHome | 0:7b81b19d9b10 | 81 | CANMessage _msg; |
WiredHome | 0:7b81b19d9b10 | 82 | |
WiredHome | 0:7b81b19d9b10 | 83 | if (can->read(_msg)) { |
WiredHome | 0:7b81b19d9b10 | 84 | /// @TODO This looks like a very inefficient method, but it works. |
WiredHome | 0:7b81b19d9b10 | 85 | CANmsg Xmsg(channel, rcv, _msg); |
WiredHome | 0:7b81b19d9b10 | 86 | msg = Xmsg; |
WiredHome | 0:7b81b19d9b10 | 87 | rxCounter++; |
WiredHome | 0:7b81b19d9b10 | 88 | Flash(msg.dir); |
WiredHome | 0:7b81b19d9b10 | 89 | success = true; |
WiredHome | 0:7b81b19d9b10 | 90 | } |
WiredHome | 0:7b81b19d9b10 | 91 | return success; |
WiredHome | 0:7b81b19d9b10 | 92 | } |
WiredHome | 0:7b81b19d9b10 | 93 | |
WiredHome | 0:7b81b19d9b10 | 94 | |
WiredHome | 0:7b81b19d9b10 | 95 | void CANPort::Attach( void (*fptr)(void)) { |
WiredHome | 0:7b81b19d9b10 | 96 | can->attach(fptr); |
WiredHome | 0:7b81b19d9b10 | 97 | } |
WiredHome | 0:7b81b19d9b10 | 98 | |
WiredHome | 0:7b81b19d9b10 | 99 | |
WiredHome | 0:7b81b19d9b10 | 100 | void CANPort::Extinguish(void) { |
WiredHome | 0:7b81b19d9b10 | 101 | if (activityPin) { |
WiredHome | 0:7b81b19d9b10 | 102 | *activityPin = 0.0; |
WiredHome | 0:7b81b19d9b10 | 103 | } |
WiredHome | 0:7b81b19d9b10 | 104 | } |
WiredHome | 0:7b81b19d9b10 | 105 | |
WiredHome | 0:7b81b19d9b10 | 106 | |
WiredHome | 0:7b81b19d9b10 | 107 | void CANPort::Flash(CANDIR_T tx) { |
WiredHome | 0:7b81b19d9b10 | 108 | if (activityPin) { |
WiredHome | 0:7b81b19d9b10 | 109 | *activityPin = (tx == xmt) ? FLASH_TX_LEVEL : FLASH_RX_LEVEL; // dim for transmit, bright for receive |
WiredHome | 1:f0b4e47d948d | 110 | #if (MBED_MAJOR_VERSION >= 5) || (MBED_LIBRARY_VERSION > 127) |
WiredHome | 1:f0b4e47d948d | 111 | activityTimeout.attach(callback(this, &CANPort::Extinguish), FLASH_PERIOD); |
WiredHome | 1:f0b4e47d948d | 112 | #else |
WiredHome | 0:7b81b19d9b10 | 113 | activityTimeout.attach(this, &CANPort::Extinguish, FLASH_PERIOD); |
WiredHome | 1:f0b4e47d948d | 114 | #endif |
WiredHome | 0:7b81b19d9b10 | 115 | } |
WiredHome | 0:7b81b19d9b10 | 116 | } |
WiredHome | 0:7b81b19d9b10 | 117 | |
WiredHome | 0:7b81b19d9b10 | 118 | |
WiredHome | 0:7b81b19d9b10 | 119 | bool CANPort::SetAutoReset(bool enable) { |
WiredHome | 0:7b81b19d9b10 | 120 | autoReset = enable; |
WiredHome | 0:7b81b19d9b10 | 121 | return true; |
WiredHome | 0:7b81b19d9b10 | 122 | } |
WiredHome | 0:7b81b19d9b10 | 123 | |
WiredHome | 0:7b81b19d9b10 | 124 | |
WiredHome | 0:7b81b19d9b10 | 125 | bool CANPort::SetBusMode(CANBusMode_T mode) { |
WiredHome | 0:7b81b19d9b10 | 126 | switch (mode) { |
WiredHome | 0:7b81b19d9b10 | 127 | case MONITOR: |
WiredHome | 0:7b81b19d9b10 | 128 | can->monitor(true); |
WiredHome | 0:7b81b19d9b10 | 129 | busMode = mode; |
WiredHome | 0:7b81b19d9b10 | 130 | break; |
WiredHome | 0:7b81b19d9b10 | 131 | case ACTIVE: |
WiredHome | 0:7b81b19d9b10 | 132 | can->monitor(false); |
WiredHome | 0:7b81b19d9b10 | 133 | busMode = mode; |
WiredHome | 0:7b81b19d9b10 | 134 | break; |
WiredHome | 0:7b81b19d9b10 | 135 | default: |
WiredHome | 0:7b81b19d9b10 | 136 | return false; |
WiredHome | 0:7b81b19d9b10 | 137 | } |
WiredHome | 0:7b81b19d9b10 | 138 | return true; |
WiredHome | 0:7b81b19d9b10 | 139 | } |
WiredHome | 0:7b81b19d9b10 | 140 | |
WiredHome | 0:7b81b19d9b10 | 141 | |
WiredHome | 0:7b81b19d9b10 | 142 | CANBusMode_T CANPort::GetBusMode() { |
WiredHome | 0:7b81b19d9b10 | 143 | return busMode; |
WiredHome | 0:7b81b19d9b10 | 144 | } |
WiredHome | 0:7b81b19d9b10 | 145 | |
WiredHome | 0:7b81b19d9b10 | 146 | |
WiredHome | 0:7b81b19d9b10 | 147 | bool CANPort::SetSlopeControl(CANSlopeControl_T slope) { |
WiredHome | 0:7b81b19d9b10 | 148 | if (slopePin) { |
WiredHome | 0:7b81b19d9b10 | 149 | slopeMode = slope; |
WiredHome | 0:7b81b19d9b10 | 150 | switch (slope) { |
WiredHome | 0:7b81b19d9b10 | 151 | case HIGHSPEED: |
WiredHome | 0:7b81b19d9b10 | 152 | slopePin->output(); |
WiredHome | 0:7b81b19d9b10 | 153 | slopePin->write(0); |
WiredHome | 0:7b81b19d9b10 | 154 | break; |
WiredHome | 0:7b81b19d9b10 | 155 | case NORMALSPEED: |
WiredHome | 0:7b81b19d9b10 | 156 | slopePin->input(); |
WiredHome | 0:7b81b19d9b10 | 157 | slopePin->mode(PullNone); |
WiredHome | 0:7b81b19d9b10 | 158 | break; |
WiredHome | 0:7b81b19d9b10 | 159 | case STANDBY: |
WiredHome | 0:7b81b19d9b10 | 160 | slopePin->output(); |
WiredHome | 0:7b81b19d9b10 | 161 | slopePin->write(1); |
WiredHome | 0:7b81b19d9b10 | 162 | break; |
WiredHome | 0:7b81b19d9b10 | 163 | default: |
WiredHome | 0:7b81b19d9b10 | 164 | return false; |
WiredHome | 0:7b81b19d9b10 | 165 | } |
WiredHome | 0:7b81b19d9b10 | 166 | return true; |
WiredHome | 0:7b81b19d9b10 | 167 | } else |
WiredHome | 0:7b81b19d9b10 | 168 | return false; |
WiredHome | 0:7b81b19d9b10 | 169 | } |
WiredHome | 0:7b81b19d9b10 | 170 | |
WiredHome | 0:7b81b19d9b10 | 171 | |
WiredHome | 0:7b81b19d9b10 | 172 | CANSlopeControl_T CANPort::GetSlopeControl() { |
WiredHome | 0:7b81b19d9b10 | 173 | return slopeMode; |
WiredHome | 0:7b81b19d9b10 | 174 | } |
WiredHome | 0:7b81b19d9b10 | 175 | |
WiredHome | 0:7b81b19d9b10 | 176 | |
WiredHome | 0:7b81b19d9b10 | 177 | bool CANPort::SetBitRate(int rate) { |
WiredHome | 0:7b81b19d9b10 | 178 | if (can->frequency(rate)) { |
WiredHome | 0:7b81b19d9b10 | 179 | bitRate = rate; |
WiredHome | 0:7b81b19d9b10 | 180 | return true; |
WiredHome | 0:7b81b19d9b10 | 181 | } else { |
WiredHome | 0:7b81b19d9b10 | 182 | return false; |
WiredHome | 0:7b81b19d9b10 | 183 | } |
WiredHome | 0:7b81b19d9b10 | 184 | } |
WiredHome | 0:7b81b19d9b10 | 185 | |
WiredHome | 0:7b81b19d9b10 | 186 | |
WiredHome | 0:7b81b19d9b10 | 187 | int CANPort::GetBitRate() { |
WiredHome | 0:7b81b19d9b10 | 188 | return bitRate; |
WiredHome | 0:7b81b19d9b10 | 189 | } |
WiredHome | 0:7b81b19d9b10 | 190 | |
WiredHome | 0:7b81b19d9b10 | 191 | |
WiredHome | 0:7b81b19d9b10 | 192 | int CANPort::GetTxCounter() { |
WiredHome | 0:7b81b19d9b10 | 193 | return txCounter; |
WiredHome | 0:7b81b19d9b10 | 194 | } |
WiredHome | 0:7b81b19d9b10 | 195 | |
WiredHome | 0:7b81b19d9b10 | 196 | |
WiredHome | 0:7b81b19d9b10 | 197 | int CANPort::GetRxCounter() { |
WiredHome | 0:7b81b19d9b10 | 198 | return rxCounter; |
WiredHome | 0:7b81b19d9b10 | 199 | } |
WiredHome | 0:7b81b19d9b10 | 200 | |
WiredHome | 0:7b81b19d9b10 | 201 | |
WiredHome | 0:7b81b19d9b10 | 202 | int CANPort::GetTxErrorCounter() { |
WiredHome | 0:7b81b19d9b10 | 203 | return can->tderror(); |
WiredHome | 0:7b81b19d9b10 | 204 | } |
WiredHome | 0:7b81b19d9b10 | 205 | |
WiredHome | 0:7b81b19d9b10 | 206 | |
WiredHome | 0:7b81b19d9b10 | 207 | int CANPort::GetRxErrorCounter() { |
WiredHome | 0:7b81b19d9b10 | 208 | return can->rderror(); |
WiredHome | 0:7b81b19d9b10 | 209 | } |
WiredHome | 0:7b81b19d9b10 | 210 | |
WiredHome | 0:7b81b19d9b10 | 211 | |
WiredHome | 0:7b81b19d9b10 | 212 | bool CANPort::ResetChip() { |
WiredHome | 0:7b81b19d9b10 | 213 | can->reset(); |
WiredHome | 0:7b81b19d9b10 | 214 | return true; |
WiredHome | 0:7b81b19d9b10 | 215 | } |
WiredHome | 0:7b81b19d9b10 | 216 | |
WiredHome | 0:7b81b19d9b10 | 217 | |
WiredHome | 0:7b81b19d9b10 | 218 | void CANPort::PrintInfo(Serial * stream) { |
WiredHome | 0:7b81b19d9b10 | 219 | if (stream) { |
WiredHome | 0:7b81b19d9b10 | 220 | stream->printf("\r\n"); |
WiredHome | 0:7b81b19d9b10 | 221 | stream->printf(" Register: CAN1 CAN2 Register: CAN1 CAN2\r\n"); |
WiredHome | 0:7b81b19d9b10 | 222 | stream->printf(" MOD: %08X %08X ", LPC_CAN1->MOD, LPC_CAN2->MOD); |
WiredHome | 0:7b81b19d9b10 | 223 | stream->printf(" GSR: %08X %08X\r\n", LPC_CAN1->GSR, LPC_CAN2->GSR); |
WiredHome | 0:7b81b19d9b10 | 224 | stream->printf(" ICR: %08X %08X ", LPC_CAN1->ICR, LPC_CAN2->ICR); |
WiredHome | 0:7b81b19d9b10 | 225 | stream->printf(" IER: %08X %08X\r\n", LPC_CAN1->IER, LPC_CAN2->IER); |
WiredHome | 0:7b81b19d9b10 | 226 | stream->printf(" BTR: %08X %08X ", LPC_CAN1->BTR, LPC_CAN2->BTR); |
WiredHome | 0:7b81b19d9b10 | 227 | stream->printf(" EWL: %08X %08X\r\n", LPC_CAN1->EWL, LPC_CAN2->EWL); |
WiredHome | 0:7b81b19d9b10 | 228 | stream->printf(" SR: %08X %08X ", LPC_CAN1->SR, LPC_CAN2->SR ); |
WiredHome | 0:7b81b19d9b10 | 229 | stream->printf(" RFS: %08X %08X\r\n", LPC_CAN1->RFS, LPC_CAN2->RFS); |
WiredHome | 0:7b81b19d9b10 | 230 | stream->printf(" RID: %08X %08X ", LPC_CAN1->RID, LPC_CAN2->RID); |
WiredHome | 0:7b81b19d9b10 | 231 | stream->printf(" RDA: %08X %08X\r\n", LPC_CAN1->RDA, LPC_CAN2->RDA); |
WiredHome | 0:7b81b19d9b10 | 232 | stream->printf(" RDB: %08X %08X ", LPC_CAN1->RDB, LPC_CAN2->RDB); |
WiredHome | 0:7b81b19d9b10 | 233 | stream->printf(" TFI1: %08X %08X\r\n", LPC_CAN1->TFI1, LPC_CAN2->TFI1); |
WiredHome | 0:7b81b19d9b10 | 234 | stream->printf(" TID1: %08X %08X ", LPC_CAN1->TID1, LPC_CAN2->TID1); |
WiredHome | 0:7b81b19d9b10 | 235 | stream->printf(" TDA1: %08X %08X\r\n", LPC_CAN1->TDA1, LPC_CAN2->TDA1); |
WiredHome | 0:7b81b19d9b10 | 236 | stream->printf(" TDB1: %08X %08X ", LPC_CAN1->TDB1, LPC_CAN2->TDB1); |
WiredHome | 0:7b81b19d9b10 | 237 | stream->printf(" TFI2: %08X %08X\r\n", LPC_CAN1->TFI2, LPC_CAN2->TFI2); |
WiredHome | 0:7b81b19d9b10 | 238 | stream->printf(" TID2: %08X %08X ", LPC_CAN1->TID2, LPC_CAN2->TID2); |
WiredHome | 0:7b81b19d9b10 | 239 | stream->printf(" TDA2: %08X %08X\r\n", LPC_CAN1->TDA2, LPC_CAN2->TDA2); |
WiredHome | 0:7b81b19d9b10 | 240 | stream->printf(" TDB2: %08X %08X ", LPC_CAN1->TDB2, LPC_CAN2->TDB2); |
WiredHome | 0:7b81b19d9b10 | 241 | stream->printf(" TFI3: %08X %08X\r\n", LPC_CAN1->TFI3, LPC_CAN2->TFI3); |
WiredHome | 0:7b81b19d9b10 | 242 | stream->printf(" TID3: %08X %08X ", LPC_CAN1->TID3, LPC_CAN2->TID3); |
WiredHome | 0:7b81b19d9b10 | 243 | stream->printf(" TDA3: %08X %08X\r\n", LPC_CAN1->TDA3, LPC_CAN2->TDA3); |
WiredHome | 0:7b81b19d9b10 | 244 | stream->printf(" TDB3: %08X %08X ", LPC_CAN1->TDB3, LPC_CAN2->TDB3); |
WiredHome | 0:7b81b19d9b10 | 245 | stream->printf("\r\n"); |
WiredHome | 0:7b81b19d9b10 | 246 | } |
WiredHome | 0:7b81b19d9b10 | 247 | } |