
vehicle CAN message log to SD file system using ring buffer memory
Dependencies: SDFileSystem mbed
Diff: main.cpp
- Revision:
- 0:de9553dd79ec
- Child:
- 1:4a538cae9042
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Jan 25 21:04:19 2013 +0000 @@ -0,0 +1,161 @@ +// CAN message log to SD card using can2.attach with ring buffer +// 2013/Jan/25 using official SDFileSyatem library + +#include "mbed.h" +#include "SDFileSystem.h" + +CAN can2(p30, p29); +CANMessage can_MsgRx; +Timer timer; + +// LED to know the status +DigitalOut User_Led1(LED1); +DigitalOut User_Led2(LED2); +DigitalOut User_Led3(LED3); +DigitalOut User_Led4(LED4); +#define LED_ON 1 +#define LED_OFF 0 + +// status monitor +Serial pc(USBTX, USBRX); + +SDFileSystem sd(p5, p6, p7, p8, "sd"); // mosi, miso, sclk, cs, name +FILE *fp; +int file_open = 0; + +// button switch for closing file +DigitalIn button1(p16); +DigitalIn button2(p17); +DigitalIn button3(p18); +DigitalIn button4(p19); +int SW0 = 0x0f, SW1 = 0x0f, SW2 = 0x0f, BUTTON = 0; +Ticker sw_check; + +// function prototypes +void can_check(void); +void check_sw(); + +// CAN message buffer +#define BUFFER_SIZE 512 // buffer size must be power of 2 +#define BUFFER_MASK ( BUFFER_SIZE - 1 ) +unsigned int second[BUFFER_SIZE]; +unsigned short can_id[BUFFER_SIZE]; +unsigned char msg_length[BUFFER_SIZE]; +unsigned char data[8][BUFFER_SIZE]; +volatile unsigned int head = 0; +volatile unsigned int tail = 0; + +int main() +{ + button1.mode(PullUp); + button2.mode(PullUp); + button3.mode(PullUp); + button4.mode(PullUp); + sw_check.attach_us(&check_sw, 5000); // status check every 5 msec + + can2.frequency(500000); + pc.baud(9600); + pc.printf("CAN log to SD card using ring buffer, 9600 bps\r\n"); + + User_Led1 = LED_OFF; + User_Led2 = LED_OFF; + User_Led3 = LED_OFF; + User_Led4 = LED_OFF; + + char file_name[20]; + + time_t t; + t = time( NULL ) + 32400; // UTC + 9 hours for JST + strftime( file_name, 20, "/sd/%y%m%d%H%M.log", localtime( &t ) ); + pc.printf( "log file is %s\r\n", file_name ); + + fp = fopen(file_name, "w"); + if ( fp == NULL ) { + pc.printf("Unable to create the file '%s'\r\n", file_name); + pc.printf("Please try again\r\n"); + + User_Led1 = LED_OFF; + file_open = 0; + } else { + User_Led1 = LED_ON; + file_open = 1; + } + + timer.stop(); + timer.reset(); + timer.start(); + can2.attach(&can_check); + + int tmptail; + while(1) { + if ( head != tail ) { + tmptail = (tail + 1) & BUFFER_MASK; + fprintf(fp, "%03X,%03X,", head&0xfff, tmptail&0xfff); + fprintf(fp, "%08X,", second[tmptail]); + fprintf(fp, "t%03X%d", can_id[tmptail], msg_length[tmptail]); + + for (int i=0; i<msg_length[tmptail]; i++) { + fprintf(fp, "%02X", data[i][tmptail]); + } // for + fprintf(fp, "\r\n"); + + tail = tmptail; // update tail after data sent + if ( tail == 0 ) { + // toggle led3 + User_Led3 = !User_Led3; + t = time( NULL ) + 32400; // UTC + 9 hours for JST + strftime( file_name, 20, "%T", localtime( &t ) ); + pc.printf("new cycle of ring buffer at %s\r\n", file_name); + } + } // if head != tail + + if ( BUTTON&0x01 ) { // button1 pressed + BUTTON &= 0xfe; // clear button status + can2.attach(0); // detach CAN interrupt + file_open = 0; + //Close the file + fclose(fp); + pc.printf("file closed\r\n"); + User_Led1 = LED_OFF; + } // if button + } // while +} // main + +// read CAN2 message using intterupt and ring buffer +void can_check(void) { + int temp_head; + if ( file_open == 1 ) { + while ( can2.read(can_MsgRx) ) { + temp_head = (head + 1) & BUFFER_MASK; + if ( temp_head == tail ) { // buffer overflow error + fclose(fp); + fprintf(stderr, "buffer overflow\r\n"); + fprintf(stderr, "head = %d\r\n", head); + fprintf(stderr, "tail = %d\r\n", tail); + User_Led4 = 1; + exit(1); + } // if + + second[temp_head] = timer.read_us(); + can_id[temp_head] = can_MsgRx.id & 0xFFF; + msg_length[temp_head] = can_MsgRx.len; + for (int i=0; i<can_MsgRx.len; i++) { + data[i][temp_head] = can_MsgRx.data[i]; + } // for + head = temp_head; // update head after data stored + // toggle led2 + User_Led2 = !User_Led2; + } // while + } // if open +} // can_check + +// read switch status, called every 5 msec +void check_sw() { + SW2 = SW1; // shift previous status + SW1 = SW0; // shift previous status +// get new status + SW0 = button1.read()+(button2.read()<<1)+(button3.read()<<2)+(button4.read()<<3); +// following sequence detects switch press edge +// HIGH(SW2) -> LOW(SW1) -> LOW(SW0) + BUTTON |= ((~(SW0|SW1))&SW2); // update button status +} // check_sw