
vehicle CAN message log to SD file system using ring buffer memory
Dependencies: SDFileSystem mbed
main.cpp
- Committer:
- ym1784
- Date:
- 2013-01-25
- Revision:
- 0:de9553dd79ec
- Child:
- 1:4a538cae9042
File content as of revision 0:de9553dd79ec:
// 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