Dr. Pucher
/
Serial_interrupts
Test
Diff: main.cpp
- Revision:
- 0:023c5cda6102
- Child:
- 2:f026b40fadb1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Nov 16 15:00:30 2010 +0000 @@ -0,0 +1,181 @@ + +#include "mbed.h" +// Serial TX & RX interrupt loopback test using formatted IO - sprintf and sscanf +// Connect TX to RX (p9 to p10) +// or can also use USB and type back in the number printed out in a terminal window +// Sends out ASCII numbers in a loop and reads them back +// If not the same number LED4 goes on +// LED1 and LED2 indicate RX and TX interrupt routine activity +// LED3 changing indicate main loop running + + +Serial device(p9, p10); // tx, rx +// Can also use USB and type back in the number printed out in a terminal window +// Serial monitor_device(USBTX, USBRX); +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); + + +void Tx_interrupt(); +void Rx_interrupt(); +void send_line(); +void read_line(); + + +// Circular buffers for serial TX and RX data - used by interrupt routines +const int buffer_size = 255; +// might need to increase buffer size for high baud rates +char tx_buffer[buffer_size]; +char rx_buffer[buffer_size]; +// Circular buffer pointers +// volatile makes read-modify-write atomic +volatile int tx_in=0; +volatile int tx_out=0; +volatile int rx_in=0; +volatile int rx_out=0; +// Line buffers for sprintf and sscanf +char tx_line[80]; +char rx_line[80]; + +// main test program +int main() { + int i=0; + int rx_i=0; + device.baud(9600); + +// Setup a serial interrupt function to receive data + device.attach(&Rx_interrupt, Serial::RxIrq); +// Setup a serial interrupt function to transmit data + device.attach(&Tx_interrupt, Serial::TxIrq); + +// Formatted IO test using send and receive serial interrupts +// with sprintf and sscanf + while (1) { +// Loop to generate different test values - send value in hex, decimal, and octal and then read back + for (i=0; i<0xFFFF; i++) { + led3=1; +// Print ASCII number to tx line buffer in hex + sprintf(tx_line,"%x\r\n",i); +// Copy tx line buffer to large tx buffer for tx interrupt routine + send_line(); +// Print ASCII number to tx line buffer in decimal + sprintf(tx_line,"%d\r\n",i); +// Copy tx line buffer to large tx buffer for tx interrupt routine + send_line(); +// Print ASCII number to tx line buffer in octal + sprintf(tx_line,"%o\r\n",i); +// Copy tx line buffer to large tx buffer for tx interrupt routine + send_line(); + led3=0; +// Read a line from the large rx buffer from rx interrupt routine + read_line(); +// Read ASCII number from rx line buffer + sscanf(rx_line,"%x",&rx_i); +// Check that numbers are the same + if (i != rx_i) led4=1; +// Read a line from the large rx buffer from rx interrupt routine + read_line(); +// Read ASCII number from rx line buffer + sscanf(rx_line,"%d",&rx_i); +// Check that numbers are the same + if (i != rx_i) led4=1; +// Read a line from the large rx buffer from rx interrupt routine + read_line(); +// Read ASCII number from rx line buffer + sscanf(rx_line,"%o",&rx_i); +// Check that numbers are the same + if (i != rx_i) led4=1; + } + } +} + +// Copy tx line buffer to large tx buffer for tx interrupt routine +void send_line() { + int i; + char temp_char; + bool empty; + i = 0; +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + empty = (tx_in == tx_out); + while ((i==0) || (tx_line[i-1] != '\n')) { +// Wait if buffer full + if (((tx_in + 1) % buffer_size) == tx_out) { +// End Critical Section - need to let interrupt routine empty buffer by sending + NVIC_EnableIRQ(UART1_IRQn); + while (((tx_in + 1) % buffer_size) == tx_out) { + } +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + } + tx_buffer[tx_in] = tx_line[i]; + i++; + tx_in = (tx_in + 1) % buffer_size; + } + if (device.writeable() && (empty)) { + temp_char = tx_buffer[tx_out]; + tx_out = (tx_out + 1) % buffer_size; +// Send first character to start tx interrupts, if stopped + device.putc(temp_char); + } +// End Critical Section + NVIC_EnableIRQ(UART1_IRQn); + return; +} + +// Read a line from the large rx buffer from rx interrupt routine +void read_line() { + int i; + i = 0; +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); +// Loop reading rx buffer characters until end of line character + while ((i==0) || (rx_line[i-1] != '\r')) { +// Wait if buffer empty + if (rx_in == rx_out) { +// End Critical Section - need to allow rx interrupt to get new characters for buffer + NVIC_EnableIRQ(UART1_IRQn); + while (rx_in == rx_out) { + } +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + } + rx_line[i] = rx_buffer[rx_out]; + i++; + rx_out = (rx_out + 1) % buffer_size; + } + rx_line[i-1] = 0; +// End Critical Section + NVIC_EnableIRQ(UART1_IRQn); + return; +} + +// Interupt Routine to read in data from serial port +void Rx_interrupt() { + led1=1; +// Loop just in case more than one character is in UART's receive FIFO buffer +// Stop if buffer full + while ((device.readable()) || (((rx_in + 1) % buffer_size) == rx_out)) { + rx_buffer[rx_in] = device.getc(); +// Uncomment to Echo to USB serial to watch data flow +// monitor_device.putc(rx_buffer[rx_in]); + rx_in = (rx_in + 1) % buffer_size; + } + led1=0; + return; +} + +// Interupt Routine to write out data to serial port +void Tx_interrupt() { + led2=1; +// Loop to fill more than one character in UART's transmit FIFO buffer +// Stop if buffer empty + while ((device.writeable()) && (tx_in != tx_out)) { + device.putc(tx_buffer[tx_out]); + tx_out = (tx_out + 1) % buffer_size; + } + led2=0; + return; +} \ No newline at end of file