
vehicle CAN message log to SD file system using ring buffer memory
Dependencies: SDFileSystem mbed
main.cpp
00001 // CAN message log to SD card using can2.attach with ring buffer 00002 // 2013/Jan/25 using official SDFileSyatem library 00003 00004 #include "mbed.h" 00005 #include "SDFileSystem.h" 00006 00007 CAN can2(p30, p29); 00008 CANMessage can_MsgRx; 00009 Timer timer; 00010 00011 // LED to know the status 00012 DigitalOut User_Led1(LED1); 00013 DigitalOut User_Led2(LED2); 00014 DigitalOut User_Led3(LED3); 00015 DigitalOut User_Led4(LED4); 00016 #define LED_ON 1 00017 #define LED_OFF 0 00018 00019 // status monitor 00020 Serial pc(USBTX, USBRX); 00021 00022 SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs, name 00023 FILE *fp; 00024 int file_open = 0; 00025 00026 // button switch for closing file 00027 DigitalIn button1(p16); 00028 DigitalIn button2(p17); 00029 DigitalIn button3(p18); 00030 DigitalIn button4(p19); 00031 int SW0 = 0x0f, SW1 = 0x0f, SW2 = 0x0f, BUTTON = 0; 00032 Ticker sw_check; 00033 00034 // function prototypes 00035 void can_check(void); 00036 void check_sw(); 00037 00038 // CAN message ring buffer 00039 #define BUFFER_SIZE 512 // buffer size must be power of 2 00040 #define BUFFER_MASK ( BUFFER_SIZE - 1 ) 00041 unsigned int second[BUFFER_SIZE]; 00042 unsigned short can_id[BUFFER_SIZE]; 00043 unsigned char msg_length[BUFFER_SIZE]; 00044 unsigned char data[8][BUFFER_SIZE]; 00045 volatile unsigned int head = 0; 00046 volatile unsigned int tail = 0; 00047 00048 int main() 00049 { 00050 button1.mode(PullUp); 00051 button2.mode(PullUp); 00052 button3.mode(PullUp); 00053 button4.mode(PullUp); 00054 sw_check.attach_us(&check_sw, 5000); // button switch status check every 5 msec 00055 00056 can2.frequency(500000); 00057 pc.baud(9600); 00058 pc.printf("CAN log to SD card using ring buffer, 9600 bps\r\n"); 00059 00060 User_Led1 = LED_OFF; 00061 User_Led2 = LED_OFF; 00062 User_Led3 = LED_OFF; 00063 User_Led4 = LED_OFF; 00064 00065 char file_name[20]; 00066 00067 time_t t; 00068 t = time( NULL ) + 32400; // UTC + 9 hours for JST 00069 strftime( file_name, 20, "/sd/%y%m%d%H%M.log", localtime( &t ) ); 00070 pc.printf( "log file is %s\r\n", file_name ); 00071 00072 fp = fopen(file_name, "w"); 00073 if ( fp == NULL ) { 00074 pc.printf("Unable to create the file '%s'\r\n", file_name); 00075 pc.printf("Please try again\r\n"); 00076 00077 User_Led1 = LED_OFF; // file open fail 00078 file_open = 0; 00079 } else { 00080 User_Led1 = LED_ON; // file open 00081 file_open = 1; 00082 } 00083 00084 timer.stop(); 00085 timer.reset(); 00086 timer.start(); 00087 can2.attach(&can_check); 00088 00089 int tmptail; 00090 while(1) { 00091 if ( head != tail ) { 00092 tmptail = (tail + 1) & BUFFER_MASK; 00093 fprintf(fp, "%03X,%03X,", head&0xfff, tmptail&0xfff); 00094 fprintf(fp, "%08X,", second[tmptail]); 00095 fprintf(fp, "t%03X%d", can_id[tmptail], msg_length[tmptail]); 00096 00097 for (int i=0; i<msg_length[tmptail]; i++) { 00098 fprintf(fp, "%02X", data[i][tmptail]); 00099 } // for 00100 fprintf(fp, "\r\n"); 00101 00102 tail = tmptail; // update tail after data sent 00103 if ( tail == 0 ) { 00104 User_Led3 = !User_Led3; // toggle led3 showing new cycle of ring buffer 00105 t = time( NULL ) + 32400; // UTC + 9 hours for JST 00106 strftime( file_name, 20, "%T", localtime( &t ) ); 00107 pc.printf("new cycle of ring buffer at %s\r\n", file_name); 00108 } 00109 } // if head != tail 00110 00111 if ( BUTTON&0x01 ) { // button1 pressed 00112 BUTTON &= 0xfe; // clear button status 00113 can2.attach(0); // detach CAN interrupt 00114 file_open = 0; 00115 //Close the file 00116 fclose(fp); 00117 pc.printf("file closed\r\n"); 00118 User_Led1 = LED_OFF; 00119 } // if button 00120 } // while 00121 } // main 00122 00123 // read CAN2 message using intterupt and ring buffer 00124 void can_check(void) { 00125 int temp_head; 00126 if ( file_open == 1 ) { 00127 while ( can2.read(can_MsgRx) ) { 00128 temp_head = (head + 1) & BUFFER_MASK; 00129 if ( temp_head == tail ) { // buffer overflow error 00130 fclose(fp); 00131 fprintf(stderr, "buffer overflow\r\n"); 00132 fprintf(stderr, "head = %d\r\n", head); 00133 fprintf(stderr, "tail = %d\r\n", tail); 00134 User_Led4 = 1; // buffer overflow error 00135 exit(1); 00136 } // if 00137 00138 second[temp_head] = timer.read_us(); 00139 can_id[temp_head] = can_MsgRx.id & 0xFFF; 00140 msg_length[temp_head] = can_MsgRx.len; 00141 for (int i=0; i<can_MsgRx.len; i++) { 00142 data[i][temp_head] = can_MsgRx.data[i]; 00143 } // for 00144 head = temp_head; // update head after data stored 00145 User_Led2 = !User_Led2; // toggle led2 showing CAN message reading 00146 } // while 00147 } // if open 00148 } // can_check 00149 00150 // read switch status, called every 5 msec 00151 void check_sw() { 00152 SW2 = SW1; // shift previous status 00153 SW1 = SW0; // shift previous status 00154 // get new status 00155 SW0 = button1.read()+(button2.read()<<1)+(button3.read()<<2)+(button4.read()<<3); 00156 // following sequence detects switch press edge 00157 // HIGH(SW2) -> LOW(SW1) -> LOW(SW0) 00158 BUTTON |= ((~(SW0|SW1))&SW2); // update button status 00159 } // check_sw
Generated on Fri Jul 15 2022 02:48:09 by
