Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:7b81b19d9b10, committed 2012-07-15
- Comitter:
- WiredHome
- Date:
- Sun Jul 15 15:15:19 2012 +0000
- Child:
- 1:f0b4e47d948d
- Commit message:
- [mbed] converted /A_CANAdapter/CANUtilities/CANPort
Changed in this revision
| CANPort.cpp | Show annotated file Show diff for this revision Revisions of this file |
| CANPort.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CANPort.cpp Sun Jul 15 15:15:19 2012 +0000
@@ -0,0 +1,243 @@
+/// @file CANPort.cpp is where all the port level functionality resides
+///
+/// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved.
+/// Individuals may use this application for evaluation or non-commercial
+/// purposes. Within this restriction, changes may be made to this application
+/// as long as this copyright notice is retained. The user shall make
+/// clear that their work is a derived work, and not the original.
+/// Users of this application and sources accept this application "as is" and
+/// shall hold harmless Smartware Computing, for any undesired results while
+/// using this application - whether real or imagined.
+///
+/// @author David Smart, Smartware Computing
+///
+/// 20110718
+/// Fixed a bug in the Receive handler - it was not propagating the message
+/// out.
+/// 20110605
+/// Revised the SlopeControl so that it actually works for any change in value
+/// where it was previously able to go low or high, but once as an input it
+/// then would not go back to an output.
+///
+#include "mbed.h"
+#include "CANPort.h"
+#include "Utilities.h"
+
+#define FLASH_PERIOD (float)0.04
+#define FLASH_TX_LEVEL 0.10
+#define FLASH_RX_LEVEL 1.00
+
+
+CANPort::CANPort(CANCHANNEL_T chNum, PinName rd, PinName td, PinName _activityPin, PinName _slopePin, CANSlopeControl_T slope) {
+ channel = chNum;
+ can = new CAN(rd, td);
+ if (_activityPin != NC) {
+ activityPin = new PwmOut(_activityPin);
+ activityPin->pulsewidth_us(100);
+ }
+ else
+ activityPin = NULL;
+ if (_slopePin != NC) {
+ slopePin = new DigitalInOut(_slopePin);
+ SetSlopeControl(slope);
+ } else
+ slopePin = NULL;
+ slopePinName = _slopePin;
+ txCounter = 0;
+ rxCounter = 0;
+}
+
+
+CANPort::~CANPort() {
+ if (slopePin)
+ delete slopePin;
+ if (activityPin)
+ delete activityPin;
+ if (can)
+ delete can;
+ slopePin = NULL;
+ activityPin = NULL;
+ can = NULL;
+}
+
+
+bool CANPort::TransmitMsg(CANmsg msg) {
+ bool success = false;
+
+ if (msg.dir == xmt) { // we have to have indicated our intent to transmit
+ msg.ch = channel;
+ if (can->write(CANMessage(msg.id, (char *)&msg.data, msg.len, CANData, msg.format))) {
+ txCounter++;
+ Flash(msg.dir);
+ success = true;
+ }
+ }
+ return success;
+}
+
+
+bool CANPort::ReceiveMsg(CANmsg &msg) {
+ bool success = false;
+ CANMessage _msg;
+
+ if (can->read(_msg)) {
+ /// @TODO This looks like a very inefficient method, but it works.
+ CANmsg Xmsg(channel, rcv, _msg);
+ msg = Xmsg;
+ rxCounter++;
+ Flash(msg.dir);
+ success = true;
+ }
+ return success;
+}
+
+
+void CANPort::Attach( void (*fptr)(void)) {
+ can->attach(fptr);
+}
+
+
+void CANPort::Extinguish(void) {
+ if (activityPin) {
+ *activityPin = 0.0;
+ }
+}
+
+
+void CANPort::Flash(CANDIR_T tx) {
+ if (activityPin) {
+ *activityPin = (tx == xmt) ? FLASH_TX_LEVEL : FLASH_RX_LEVEL; // dim for transmit, bright for receive
+ activityTimeout.attach(this, &CANPort::Extinguish, FLASH_PERIOD);
+ }
+}
+
+
+bool CANPort::SetAutoReset(bool enable) {
+ autoReset = enable;
+ return true;
+}
+
+
+bool CANPort::SetBusMode(CANBusMode_T mode) {
+ switch (mode) {
+ case MONITOR:
+ can->monitor(true);
+ busMode = mode;
+ break;
+ case ACTIVE:
+ can->monitor(false);
+ busMode = mode;
+ break;
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+CANBusMode_T CANPort::GetBusMode() {
+ return busMode;
+}
+
+
+bool CANPort::SetSlopeControl(CANSlopeControl_T slope) {
+ if (slopePin) {
+ slopeMode = slope;
+ switch (slope) {
+ case HIGHSPEED:
+ slopePin->output();
+ slopePin->write(0);
+ break;
+ case NORMALSPEED:
+ slopePin->input();
+ slopePin->mode(PullNone);
+ break;
+ case STANDBY:
+ slopePin->output();
+ slopePin->write(1);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ } else
+ return false;
+}
+
+
+CANSlopeControl_T CANPort::GetSlopeControl() {
+ return slopeMode;
+}
+
+
+bool CANPort::SetBitRate(int rate) {
+ if (can->frequency(rate)) {
+ bitRate = rate;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+int CANPort::GetBitRate() {
+ return bitRate;
+}
+
+
+int CANPort::GetTxCounter() {
+ return txCounter;
+}
+
+
+int CANPort::GetRxCounter() {
+ return rxCounter;
+}
+
+
+int CANPort::GetTxErrorCounter() {
+ return can->tderror();
+}
+
+
+int CANPort::GetRxErrorCounter() {
+ return can->rderror();
+}
+
+
+bool CANPort::ResetChip() {
+ can->reset();
+ return true;
+}
+
+
+void CANPort::PrintInfo(Serial * stream) {
+ if (stream) {
+ stream->printf("\r\n");
+ stream->printf(" Register: CAN1 CAN2 Register: CAN1 CAN2\r\n");
+ stream->printf(" MOD: %08X %08X ", LPC_CAN1->MOD, LPC_CAN2->MOD);
+ stream->printf(" GSR: %08X %08X\r\n", LPC_CAN1->GSR, LPC_CAN2->GSR);
+ stream->printf(" ICR: %08X %08X ", LPC_CAN1->ICR, LPC_CAN2->ICR);
+ stream->printf(" IER: %08X %08X\r\n", LPC_CAN1->IER, LPC_CAN2->IER);
+ stream->printf(" BTR: %08X %08X ", LPC_CAN1->BTR, LPC_CAN2->BTR);
+ stream->printf(" EWL: %08X %08X\r\n", LPC_CAN1->EWL, LPC_CAN2->EWL);
+ stream->printf(" SR: %08X %08X ", LPC_CAN1->SR, LPC_CAN2->SR );
+ stream->printf(" RFS: %08X %08X\r\n", LPC_CAN1->RFS, LPC_CAN2->RFS);
+ stream->printf(" RID: %08X %08X ", LPC_CAN1->RID, LPC_CAN2->RID);
+ stream->printf(" RDA: %08X %08X\r\n", LPC_CAN1->RDA, LPC_CAN2->RDA);
+ stream->printf(" RDB: %08X %08X ", LPC_CAN1->RDB, LPC_CAN2->RDB);
+ stream->printf(" TFI1: %08X %08X\r\n", LPC_CAN1->TFI1, LPC_CAN2->TFI1);
+ stream->printf(" TID1: %08X %08X ", LPC_CAN1->TID1, LPC_CAN2->TID1);
+ stream->printf(" TDA1: %08X %08X\r\n", LPC_CAN1->TDA1, LPC_CAN2->TDA1);
+ stream->printf(" TDB1: %08X %08X ", LPC_CAN1->TDB1, LPC_CAN2->TDB1);
+ stream->printf(" TFI2: %08X %08X\r\n", LPC_CAN1->TFI2, LPC_CAN2->TFI2);
+ stream->printf(" TID2: %08X %08X ", LPC_CAN1->TID2, LPC_CAN2->TID2);
+ stream->printf(" TDA2: %08X %08X\r\n", LPC_CAN1->TDA2, LPC_CAN2->TDA2);
+ stream->printf(" TDB2: %08X %08X ", LPC_CAN1->TDB2, LPC_CAN2->TDB2);
+ stream->printf(" TFI3: %08X %08X\r\n", LPC_CAN1->TFI3, LPC_CAN2->TFI3);
+ stream->printf(" TID3: %08X %08X ", LPC_CAN1->TID3, LPC_CAN2->TID3);
+ stream->printf(" TDA3: %08X %08X\r\n", LPC_CAN1->TDA3, LPC_CAN2->TDA3);
+ stream->printf(" TDB3: %08X %08X ", LPC_CAN1->TDB3, LPC_CAN2->TDB3);
+ stream->printf("\r\n");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CANPort.h Sun Jul 15 15:15:19 2012 +0000
@@ -0,0 +1,285 @@
+/// @file CANPort.h is where all the port level functionality is defined
+///
+/// This module creates the physical interface, services the hardware, and provides
+/// additional functionality on top of that (e.g. timestamp messages).
+///
+/// @todo Instead of providing a callback directly to the user code, all
+/// callbacks should be handled in this class, and then the user
+/// callback could be activated. In this way, the rxCounter, timestamps,
+/// and other features are preserved.
+///
+/// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved.
+/// Individuals may use this application for evaluation or non-commercial
+/// purposes. Within this restriction, changes may be made to this application
+/// as long as this copyright notice is retained. The user shall make
+/// clear that their work is a derived work, and not the original.
+/// Users of this application and sources accept this application "as is" and
+/// shall hold harmless Smartware Computing, for any undesired results while
+/// using this application - whether real or imagined.
+///
+/// @author David Smart, Smartware Computing
+///
+/// History
+/// v1.01 20110608
+/// \li initial version numbered to match other CAN components
+///
+#ifndef CANPORT_H
+#define CANPORT_H
+#include "mbed.h"
+#include "CANMessage.h"
+#include "Utilities.h" // mbed <-> Visual Studio
+
+
+typedef enum {
+ HIGHSPEED,
+ NORMALSPEED,
+ STANDBY
+} CANSlopeControl_T;
+
+typedef enum {
+ MONITOR,
+ ACTIVE
+} CANBusMode_T;
+
+/// This is the CANPort, which is the physical interface to CAN
+///
+/// This derived class has a number of additional capabilities:
+/// \li activity indicator to show receive and transmit activity per port
+/// \li slope control pin to permit controlling performance and power modes
+/// \li counters, to keep track of received and transmitted messages
+/// \li and more...
+///
+class CANPort {
+public:
+
+ /// The advanced form of the constructure to create a CANPort, name
+ /// an activity indicator, and name a slope control pin
+ ///
+ /// This version lets you specify the receive and transmit pins
+ /// for a CANPort, indicate a pin which is used to indicate
+ /// CAN activity, both receive and transmit, and identify a slope
+ /// control pin.
+ ///
+ /// @param chNum is the user assigned channel number given to this port
+ /// @param rd is the receive pin
+ /// @param td is the transmit pin
+ /// @param activityPin is the PWM pin used to indicate CAN traffic
+ /// @param slopePin is the DigitalInOut pin used to control slope
+ /// @param slope is the initial slope setting
+ ///
+ CANPort(CANCHANNEL_T chNum, PinName rd, PinName td, PinName activityPin = NC, PinName slopePin = NC, CANSlopeControl_T slope = NORMALSPEED);
+
+ /// Destroys the CANPort
+ virtual ~CANPort();
+
+ /// Transmit a message to the bus
+ ///
+ /// This method transmits a message to the bus.
+ ///
+ /// @param msg is a CANmsg
+ /// @returns true if the message was successfully written to CAN
+ ///
+ bool TransmitMsg(CANmsg msg);
+
+ /// Read a message from the bus into a buffer
+ ///
+ /// This method will extract a message from the bus and put it
+ /// in the message space provided
+ ///
+ /// @param msg is a reference to a CANmsg into which the msg is placed
+ /// @returns true if a message was received and processed
+ ///
+ bool ReceiveMsg(CANmsg &msg);
+
+ /// This flashes the activity indicator associated with this CANPort
+ ///
+ /// If the activity indicator is configured.
+ ///
+ /// @param tx indiciates if the flash is to be a sign of xmt or rcv
+ /// it will flash dimly for a transmit and bright for a receive
+ ///
+ void Flash(CANDIR_T tx);
+
+ /// This extinguishes the activity indicator associated with this CANPort
+ ///
+ /// If the activity indicator is configured.
+ ///
+ void Extinguish(void);
+
+ /// Attach a callback whenever a CAN receive interrupt is generated
+ ///
+ /// This attaches a simple callback to the CAN ISR
+ ///
+ /// @param fptr pointer to the function to be called
+ ///
+ void Attach( void (*fptr)(void) );
+
+ /// Attach a callback whenever a CAN receive interrupt is generated
+ ///
+ /// This attaches a callback to the CAN ISR
+ ///
+ /// @param tptr pointer to the object to call the member function on
+ /// @param mptr pointer to the member function to be called
+ ///
+ template <typename T> void Attach(T * tptr, void (T::*mptr)(void)) {
+ can->attach(tptr, mptr);
+ }
+
+ /// This provides control of the AutoReset feature
+ ///
+ /// AutoReset is a feature that permits automatically resetting the
+ /// CAN chip when it is trapped in an error state (e.g. bus off).
+ /// The default is disabled.
+ ///
+ /// @param enable is used to enable or disable the auto reset feature
+ /// @returns true if the command was accepted
+ ///
+ bool SetAutoReset(bool enable);
+
+ /// This returns the current state of the AutoReset feature
+ ///
+ /// Returns a value indicating the current state
+ ///
+ /// @returns true if AutoReset is enabled
+ /// @returns false if AutoReset is disabled
+ ///
+ bool GetAutoReset() { return autoReset; }
+
+ /// This provides control to set the bus mode as active or listener only
+ ///
+ /// The CAN adapter can be placed into a monitor(LISTENER) mode (sometimes
+ /// called promiscuous mode) or into an active mode, in which case it
+ /// will send hardware acknowledge.
+ ///
+ /// @param mode is either MONITOR or ACTIVE
+ /// @returns true if the command was accepted
+ ///
+ bool SetBusMode(CANBusMode_T mode);
+
+ /// This returns the current state of the bus mode
+ ///
+ /// @returns MONITOR if the chip is in the monitor (listen / promiscuous) mode
+ /// @returns ACTIVE if the chip is in the active mode
+ ///
+ CANBusMode_T GetBusMode();
+
+ /// This provides control to set the transceiver slope control mode
+ ///
+ /// Many CAN transceivers can be operated in one of several modes -
+ /// \li HIGHSPEED - which supports the highest frequency of communication, but
+ /// does tend to generate more EMI unless the cable is properly shielded
+ /// \li NORMALSPEED - which wave-shapes the rising and falling edge, and
+ /// significantly reduces the EMI concerns, but may trade off the
+ /// highest performance.
+ /// \li STANDBY - which puts the chip into the lowest power state, and prevents
+ /// transmission of a message. It can typically still receive messages,
+ /// but this mode may also be useful for other purposes (wake on CAN,
+ /// autobaud w/o disrupting bus traffic, etc.)
+ ///
+ /// @param slope sets the slope control to one of the states HIGHSPEED,
+ /// NORMALSPEED, or STANDBY
+ /// @returns true if the command succeeded
+ /// @returns false if the command failed, which may be due to not having
+ /// defined a slope control pin.
+ ///
+ bool SetSlopeControl(CANSlopeControl_T slope);
+
+ /// This returns the current state of the slope control
+ ///
+ /// The state is controlled by the SetSlopeControl command.
+ ///
+ /// @returns the current state; one of HIGHSPEED, NORMALSPEED, or STANDBY
+ ///
+ CANSlopeControl_T GetSlopeControl();
+
+ /// This sets the bitrate for the CAN channel
+ ///
+ /// This sets the bitrate for the CAN channel. The rate is in bits per
+ /// second. The actual bitrate and the sample point is automagically
+ /// determined from the internal algorithms provided by the mbed library.
+ ///
+ /// This API appears redundant to the frequency api, however this one
+ /// will retain the rate setting and then permits the query of the bitrate.
+ ///
+ /// @param rate is the desired bitrate in bits per second.
+ /// @returns true if teh command succeeded
+ ///
+ bool SetBitRate(int rate);
+
+ /// This returns the current desired bitrate for the CAN channel
+ ///
+ /// This returns the previously set bitrate. Note that the actual bitrate
+ /// may be different, due to the internal calculations of the mbed library.
+ ///
+ /// @returns the bitrate in bits per second
+ ///
+ int GetBitRate();
+
+ /// This returns the number of messages that were sent by this CAN channel
+ ///
+ /// The counter is never reset.
+ ///
+ /// @returns the number of messages sent by this CAN channel
+ ///
+ int GetTxCounter();
+
+ /// This returns the number of messages that were received by this CAN channel
+ ///
+ /// The counter is never reset.
+ ///
+ /// @returns the number of messages received by this CAN channel
+ ///
+ int GetRxCounter();
+
+ /// This returns the number of transmit errors
+ ///
+ /// As counted by the hardware
+ ///
+ /// @returns the number of transmit errors
+ int GetTxErrorCounter();
+
+ /// This returns the number of receive errors
+ ///
+ /// As counted by the hardware
+ ///
+ /// @returns the number of receive errors
+ int GetRxErrorCounter();
+
+ /// This resets the CAN interface
+ ///
+ /// Unconditionally.
+ ///
+ /// @returns true if success
+ ///
+ bool ResetChip();
+
+ /// This writes various CAN info to the selected serial channel
+ ///
+ /// When supplied with a Serial port channel, this will output
+ /// some possibly interesting information about the CAN configuration.
+ /// It does not output details for only the active objects channel,
+ /// rather it outputs information about the CAN subsystem.
+ ///
+ /// @param stream is the handle of a serial channel
+ /// @returns nothing
+ ///
+ void PrintInfo(Serial * stream);
+
+private:
+ CANCHANNEL_T channel; // user assigned port number of this port
+ CAN * can; // bind to a specific CAN
+ CANBusMode_T busMode; // monitor or active mode
+ int bitRate; // bit rate for this bus
+ PwmOut * activityPin; // LED to indicate activity
+ Timeout activityTimeout; // used to extinguish the LED
+
+ DigitalInOut * slopePin; // pin used to control the transceiver slope modes
+ PinName slopePinName;
+ CANSlopeControl_T slopeMode;// current mode
+
+ bool autoReset; // true when auto reset on error is enabled
+ uint32_t txCounter;
+ uint32_t rxCounter;
+};
+
+#endif // CANPORT_H