CANMessage is the primitive CAN message object. It supports creation, parsing, formatting of messages. Can be easily integrated with CANPort and CANQueue libraries.
CANMessage.cpp
00001 /// @file CANMessage.h 00002 /// This is the basic CAN message, and supports construction of, formatting and decoding. 00003 /// 00004 /// @version 1.0 00005 /// 00006 /// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved. 00007 /// Individuals may use this application for evaluation or non-commercial 00008 /// purposes. Within this restriction, changes may be made to this application 00009 /// as long as this copyright notice is retained. The user shall make 00010 /// clear that their work is a derived work, and not the original. 00011 /// Users of this application and sources accept this application "as is" and 00012 /// shall hold harmless Smartware Computing, for any undesired results while 00013 /// using this application - whether real or imagined. 00014 /// 00015 /// @author David Smart, Smartware Computing 00016 /// 00017 /// @note 00018 /// Version History 00019 /// 20110724 00020 /// \li Extending timestamp to 64 bits 00021 /// 00022 #include <mbed.h> 00023 00024 #include "CANMessage.h" 00025 #include "Utilities.h" // missing functions... 00026 00027 static Timer timer; 00028 static bool timer_on; 00029 00030 static char mytolower(char a) { 00031 if (a >= 'A' && a <= 'Z') 00032 return (a - 'A' + 'a'); 00033 else 00034 return a; 00035 } 00036 00037 static int mystrnicmp(const char *l, const char *r, size_t n) { 00038 int result = 0; 00039 00040 if (n != 0) { 00041 do { 00042 result = mytolower(*l++) - mytolower(*r++); 00043 } while ((result == 0) && (*l != '\0') && (--n > 0)); 00044 } 00045 if (result < -1) 00046 result = -1; 00047 else if (result > 1) 00048 result = 1; 00049 return result; 00050 } 00051 00052 CANmsg::CANmsg() { 00053 if (!timer_on) { 00054 timer.start(); 00055 timer_on = true; 00056 } 00057 timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us(); 00058 } 00059 00060 CANmsg::CANmsg(CANCHANNEL_T _ch, CANDIR_T _dir, CANMessage _msg) { 00061 if (!timer_on) { 00062 timer.start(); 00063 timer_on = true; 00064 } 00065 timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us(); 00066 ch = _ch; 00067 dir = _dir; 00068 id = _msg.id; 00069 len = _msg.len; 00070 for (int i=0; i<len; i++) 00071 data[i] = _msg.data[i]; 00072 format = _msg.format; 00073 type = _msg.type; 00074 } 00075 00076 // 0 1 2 3 4 5---------------------| 6 7 8 00077 // t xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0 0 1234.567890 00078 // If the first letter is not 't'ransmit or 'r'eceive, transmit is 00079 // assumed 00080 // xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0 0 1234.567890 00081 CANmsg::CANmsg(char *p) { 00082 if (!timer_on) { 00083 timer.start(); 00084 timer_on = true; 00085 } 00086 ParseCANMessage(p); 00087 } 00088 00089 CANmsg::~CANmsg() { 00090 } 00091 00092 bool CANmsg::ParseCANMessage(char *p) { 00093 //int state = 0; 00094 //printf("\r\nParseCANMessage(%s)\r\n",p); 00095 char *token; 00096 char *search = " ,\t"; // any of these is a separator 00097 token = strtok(p, search); // might now point to 't'|'r', or 'xtd'|'nrm' 00098 if (*token == 'r') 00099 dir = rcv; 00100 else 00101 dir = xmt; 00102 if (*token == 't' || *token == 'r') // transmit or receive 00103 token = strtok(NULL, search); // advance past 't'|'r' 00104 if (mystrnicmp(token,"xtd",3) == 0) 00105 format = CANExtended; 00106 else if (mystrnicmp(token, "nrm", 3) == 0) 00107 format = CANStandard; 00108 token = strtok(NULL, search); 00109 ch = (CANCHANNEL_T)(atoi(token) - 1); 00110 token = strtok(NULL, search); 00111 id = hextoul(token); 00112 token = strtok(NULL, search); 00113 len = hextoul(token); 00114 for (int i=0; i<len; i++) { 00115 token = strtok(NULL, search); 00116 data[i] = (char)hextoul(token); 00117 } 00118 token = strtok(NULL, search); 00119 // fixedZero = atoi(token) 00120 token = strtok(NULL, search); 00121 // lostMessages = atoi(token); 00122 token = strtok(NULL, search); 00123 timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us(); // set it to "now" 00124 if (token) 00125 timestamp = (uint32_t)(1000000 * atof(token)); 00126 return true; 00127 } 00128 00129 void CANmsg::SetTimestamp() { 00130 timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us(); 00131 } 00132 00133 // 12345678901234567890123456789012345678901234567890123456789012345 00134 // r xtd 01 1CF00400 08 11 22 33 44 55 66 77 88 0 0 12.123456 00135 void CANmsg::FormatCANMessage(char *buffer, int buflen) { 00136 if (buflen >= 68) { // 63+\r+\n+\0+2spare 00137 if (format >= 128) { 00138 sprintf(buffer, "%c %s %02d %8s %02X ", 00139 (dir == xmt ) ? 't' : 'r', 00140 "ERR", 00141 ch + 1, 00142 (format == 128) ? "active" : "passive", 00143 8); 00144 for (int d=0; d<8; d++) { 00145 sprintf(buffer + strlen(buffer), "%02X ", 0); 00146 } 00147 } else { 00148 sprintf(buffer, "%c %s %02d %08X %02X ", 00149 (dir == xmt ) ? 't' : 'r', 00150 (format == CANExtended) ? "xtd" : "nrm", 00151 ch + 1, 00152 id, 00153 len); 00154 for (int d=0; d<8; d++) { 00155 if (d < len) 00156 sprintf(buffer + strlen(buffer), "%02X ", data[d]); 00157 else 00158 strcat(buffer, " "); 00159 } 00160 } 00161 uint32_t uSec = timestamp % 1000000; // integer math is faster than float 00162 uint32_t Sec = timestamp / 1000000; 00163 sprintf(buffer + strlen(buffer), "0 0 %6u.%06u", Sec, uSec); 00164 } else { 00165 strcpy(buffer,"ERROR, buf too small"); 00166 } 00167 }
Generated on Sat Jul 16 2022 14:23:32 by 1.7.2