Dr. Pucher
/
Serial_interrupts
Test
main.cpp@0:023c5cda6102, 2010-11-16 (annotated)
- Committer:
- 4180_1
- Date:
- Tue Nov 16 15:00:30 2010 +0000
- Revision:
- 0:023c5cda6102
- Child:
- 2:f026b40fadb1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
4180_1 | 0:023c5cda6102 | 1 | |
4180_1 | 0:023c5cda6102 | 2 | #include "mbed.h" |
4180_1 | 0:023c5cda6102 | 3 | // Serial TX & RX interrupt loopback test using formatted IO - sprintf and sscanf |
4180_1 | 0:023c5cda6102 | 4 | // Connect TX to RX (p9 to p10) |
4180_1 | 0:023c5cda6102 | 5 | // or can also use USB and type back in the number printed out in a terminal window |
4180_1 | 0:023c5cda6102 | 6 | // Sends out ASCII numbers in a loop and reads them back |
4180_1 | 0:023c5cda6102 | 7 | // If not the same number LED4 goes on |
4180_1 | 0:023c5cda6102 | 8 | // LED1 and LED2 indicate RX and TX interrupt routine activity |
4180_1 | 0:023c5cda6102 | 9 | // LED3 changing indicate main loop running |
4180_1 | 0:023c5cda6102 | 10 | |
4180_1 | 0:023c5cda6102 | 11 | |
4180_1 | 0:023c5cda6102 | 12 | Serial device(p9, p10); // tx, rx |
4180_1 | 0:023c5cda6102 | 13 | // Can also use USB and type back in the number printed out in a terminal window |
4180_1 | 0:023c5cda6102 | 14 | // Serial monitor_device(USBTX, USBRX); |
4180_1 | 0:023c5cda6102 | 15 | DigitalOut led1(LED1); |
4180_1 | 0:023c5cda6102 | 16 | DigitalOut led2(LED2); |
4180_1 | 0:023c5cda6102 | 17 | DigitalOut led3(LED3); |
4180_1 | 0:023c5cda6102 | 18 | DigitalOut led4(LED4); |
4180_1 | 0:023c5cda6102 | 19 | |
4180_1 | 0:023c5cda6102 | 20 | |
4180_1 | 0:023c5cda6102 | 21 | void Tx_interrupt(); |
4180_1 | 0:023c5cda6102 | 22 | void Rx_interrupt(); |
4180_1 | 0:023c5cda6102 | 23 | void send_line(); |
4180_1 | 0:023c5cda6102 | 24 | void read_line(); |
4180_1 | 0:023c5cda6102 | 25 | |
4180_1 | 0:023c5cda6102 | 26 | |
4180_1 | 0:023c5cda6102 | 27 | // Circular buffers for serial TX and RX data - used by interrupt routines |
4180_1 | 0:023c5cda6102 | 28 | const int buffer_size = 255; |
4180_1 | 0:023c5cda6102 | 29 | // might need to increase buffer size for high baud rates |
4180_1 | 0:023c5cda6102 | 30 | char tx_buffer[buffer_size]; |
4180_1 | 0:023c5cda6102 | 31 | char rx_buffer[buffer_size]; |
4180_1 | 0:023c5cda6102 | 32 | // Circular buffer pointers |
4180_1 | 0:023c5cda6102 | 33 | // volatile makes read-modify-write atomic |
4180_1 | 0:023c5cda6102 | 34 | volatile int tx_in=0; |
4180_1 | 0:023c5cda6102 | 35 | volatile int tx_out=0; |
4180_1 | 0:023c5cda6102 | 36 | volatile int rx_in=0; |
4180_1 | 0:023c5cda6102 | 37 | volatile int rx_out=0; |
4180_1 | 0:023c5cda6102 | 38 | // Line buffers for sprintf and sscanf |
4180_1 | 0:023c5cda6102 | 39 | char tx_line[80]; |
4180_1 | 0:023c5cda6102 | 40 | char rx_line[80]; |
4180_1 | 0:023c5cda6102 | 41 | |
4180_1 | 0:023c5cda6102 | 42 | // main test program |
4180_1 | 0:023c5cda6102 | 43 | int main() { |
4180_1 | 0:023c5cda6102 | 44 | int i=0; |
4180_1 | 0:023c5cda6102 | 45 | int rx_i=0; |
4180_1 | 0:023c5cda6102 | 46 | device.baud(9600); |
4180_1 | 0:023c5cda6102 | 47 | |
4180_1 | 0:023c5cda6102 | 48 | // Setup a serial interrupt function to receive data |
4180_1 | 0:023c5cda6102 | 49 | device.attach(&Rx_interrupt, Serial::RxIrq); |
4180_1 | 0:023c5cda6102 | 50 | // Setup a serial interrupt function to transmit data |
4180_1 | 0:023c5cda6102 | 51 | device.attach(&Tx_interrupt, Serial::TxIrq); |
4180_1 | 0:023c5cda6102 | 52 | |
4180_1 | 0:023c5cda6102 | 53 | // Formatted IO test using send and receive serial interrupts |
4180_1 | 0:023c5cda6102 | 54 | // with sprintf and sscanf |
4180_1 | 0:023c5cda6102 | 55 | while (1) { |
4180_1 | 0:023c5cda6102 | 56 | // Loop to generate different test values - send value in hex, decimal, and octal and then read back |
4180_1 | 0:023c5cda6102 | 57 | for (i=0; i<0xFFFF; i++) { |
4180_1 | 0:023c5cda6102 | 58 | led3=1; |
4180_1 | 0:023c5cda6102 | 59 | // Print ASCII number to tx line buffer in hex |
4180_1 | 0:023c5cda6102 | 60 | sprintf(tx_line,"%x\r\n",i); |
4180_1 | 0:023c5cda6102 | 61 | // Copy tx line buffer to large tx buffer for tx interrupt routine |
4180_1 | 0:023c5cda6102 | 62 | send_line(); |
4180_1 | 0:023c5cda6102 | 63 | // Print ASCII number to tx line buffer in decimal |
4180_1 | 0:023c5cda6102 | 64 | sprintf(tx_line,"%d\r\n",i); |
4180_1 | 0:023c5cda6102 | 65 | // Copy tx line buffer to large tx buffer for tx interrupt routine |
4180_1 | 0:023c5cda6102 | 66 | send_line(); |
4180_1 | 0:023c5cda6102 | 67 | // Print ASCII number to tx line buffer in octal |
4180_1 | 0:023c5cda6102 | 68 | sprintf(tx_line,"%o\r\n",i); |
4180_1 | 0:023c5cda6102 | 69 | // Copy tx line buffer to large tx buffer for tx interrupt routine |
4180_1 | 0:023c5cda6102 | 70 | send_line(); |
4180_1 | 0:023c5cda6102 | 71 | led3=0; |
4180_1 | 0:023c5cda6102 | 72 | // Read a line from the large rx buffer from rx interrupt routine |
4180_1 | 0:023c5cda6102 | 73 | read_line(); |
4180_1 | 0:023c5cda6102 | 74 | // Read ASCII number from rx line buffer |
4180_1 | 0:023c5cda6102 | 75 | sscanf(rx_line,"%x",&rx_i); |
4180_1 | 0:023c5cda6102 | 76 | // Check that numbers are the same |
4180_1 | 0:023c5cda6102 | 77 | if (i != rx_i) led4=1; |
4180_1 | 0:023c5cda6102 | 78 | // Read a line from the large rx buffer from rx interrupt routine |
4180_1 | 0:023c5cda6102 | 79 | read_line(); |
4180_1 | 0:023c5cda6102 | 80 | // Read ASCII number from rx line buffer |
4180_1 | 0:023c5cda6102 | 81 | sscanf(rx_line,"%d",&rx_i); |
4180_1 | 0:023c5cda6102 | 82 | // Check that numbers are the same |
4180_1 | 0:023c5cda6102 | 83 | if (i != rx_i) led4=1; |
4180_1 | 0:023c5cda6102 | 84 | // Read a line from the large rx buffer from rx interrupt routine |
4180_1 | 0:023c5cda6102 | 85 | read_line(); |
4180_1 | 0:023c5cda6102 | 86 | // Read ASCII number from rx line buffer |
4180_1 | 0:023c5cda6102 | 87 | sscanf(rx_line,"%o",&rx_i); |
4180_1 | 0:023c5cda6102 | 88 | // Check that numbers are the same |
4180_1 | 0:023c5cda6102 | 89 | if (i != rx_i) led4=1; |
4180_1 | 0:023c5cda6102 | 90 | } |
4180_1 | 0:023c5cda6102 | 91 | } |
4180_1 | 0:023c5cda6102 | 92 | } |
4180_1 | 0:023c5cda6102 | 93 | |
4180_1 | 0:023c5cda6102 | 94 | // Copy tx line buffer to large tx buffer for tx interrupt routine |
4180_1 | 0:023c5cda6102 | 95 | void send_line() { |
4180_1 | 0:023c5cda6102 | 96 | int i; |
4180_1 | 0:023c5cda6102 | 97 | char temp_char; |
4180_1 | 0:023c5cda6102 | 98 | bool empty; |
4180_1 | 0:023c5cda6102 | 99 | i = 0; |
4180_1 | 0:023c5cda6102 | 100 | // Start Critical Section - don't interrupt while changing global buffer variables |
4180_1 | 0:023c5cda6102 | 101 | NVIC_DisableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 102 | empty = (tx_in == tx_out); |
4180_1 | 0:023c5cda6102 | 103 | while ((i==0) || (tx_line[i-1] != '\n')) { |
4180_1 | 0:023c5cda6102 | 104 | // Wait if buffer full |
4180_1 | 0:023c5cda6102 | 105 | if (((tx_in + 1) % buffer_size) == tx_out) { |
4180_1 | 0:023c5cda6102 | 106 | // End Critical Section - need to let interrupt routine empty buffer by sending |
4180_1 | 0:023c5cda6102 | 107 | NVIC_EnableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 108 | while (((tx_in + 1) % buffer_size) == tx_out) { |
4180_1 | 0:023c5cda6102 | 109 | } |
4180_1 | 0:023c5cda6102 | 110 | // Start Critical Section - don't interrupt while changing global buffer variables |
4180_1 | 0:023c5cda6102 | 111 | NVIC_DisableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 112 | } |
4180_1 | 0:023c5cda6102 | 113 | tx_buffer[tx_in] = tx_line[i]; |
4180_1 | 0:023c5cda6102 | 114 | i++; |
4180_1 | 0:023c5cda6102 | 115 | tx_in = (tx_in + 1) % buffer_size; |
4180_1 | 0:023c5cda6102 | 116 | } |
4180_1 | 0:023c5cda6102 | 117 | if (device.writeable() && (empty)) { |
4180_1 | 0:023c5cda6102 | 118 | temp_char = tx_buffer[tx_out]; |
4180_1 | 0:023c5cda6102 | 119 | tx_out = (tx_out + 1) % buffer_size; |
4180_1 | 0:023c5cda6102 | 120 | // Send first character to start tx interrupts, if stopped |
4180_1 | 0:023c5cda6102 | 121 | device.putc(temp_char); |
4180_1 | 0:023c5cda6102 | 122 | } |
4180_1 | 0:023c5cda6102 | 123 | // End Critical Section |
4180_1 | 0:023c5cda6102 | 124 | NVIC_EnableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 125 | return; |
4180_1 | 0:023c5cda6102 | 126 | } |
4180_1 | 0:023c5cda6102 | 127 | |
4180_1 | 0:023c5cda6102 | 128 | // Read a line from the large rx buffer from rx interrupt routine |
4180_1 | 0:023c5cda6102 | 129 | void read_line() { |
4180_1 | 0:023c5cda6102 | 130 | int i; |
4180_1 | 0:023c5cda6102 | 131 | i = 0; |
4180_1 | 0:023c5cda6102 | 132 | // Start Critical Section - don't interrupt while changing global buffer variables |
4180_1 | 0:023c5cda6102 | 133 | NVIC_DisableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 134 | // Loop reading rx buffer characters until end of line character |
4180_1 | 0:023c5cda6102 | 135 | while ((i==0) || (rx_line[i-1] != '\r')) { |
4180_1 | 0:023c5cda6102 | 136 | // Wait if buffer empty |
4180_1 | 0:023c5cda6102 | 137 | if (rx_in == rx_out) { |
4180_1 | 0:023c5cda6102 | 138 | // End Critical Section - need to allow rx interrupt to get new characters for buffer |
4180_1 | 0:023c5cda6102 | 139 | NVIC_EnableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 140 | while (rx_in == rx_out) { |
4180_1 | 0:023c5cda6102 | 141 | } |
4180_1 | 0:023c5cda6102 | 142 | // Start Critical Section - don't interrupt while changing global buffer variables |
4180_1 | 0:023c5cda6102 | 143 | NVIC_DisableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 144 | } |
4180_1 | 0:023c5cda6102 | 145 | rx_line[i] = rx_buffer[rx_out]; |
4180_1 | 0:023c5cda6102 | 146 | i++; |
4180_1 | 0:023c5cda6102 | 147 | rx_out = (rx_out + 1) % buffer_size; |
4180_1 | 0:023c5cda6102 | 148 | } |
4180_1 | 0:023c5cda6102 | 149 | rx_line[i-1] = 0; |
4180_1 | 0:023c5cda6102 | 150 | // End Critical Section |
4180_1 | 0:023c5cda6102 | 151 | NVIC_EnableIRQ(UART1_IRQn); |
4180_1 | 0:023c5cda6102 | 152 | return; |
4180_1 | 0:023c5cda6102 | 153 | } |
4180_1 | 0:023c5cda6102 | 154 | |
4180_1 | 0:023c5cda6102 | 155 | // Interupt Routine to read in data from serial port |
4180_1 | 0:023c5cda6102 | 156 | void Rx_interrupt() { |
4180_1 | 0:023c5cda6102 | 157 | led1=1; |
4180_1 | 0:023c5cda6102 | 158 | // Loop just in case more than one character is in UART's receive FIFO buffer |
4180_1 | 0:023c5cda6102 | 159 | // Stop if buffer full |
4180_1 | 0:023c5cda6102 | 160 | while ((device.readable()) || (((rx_in + 1) % buffer_size) == rx_out)) { |
4180_1 | 0:023c5cda6102 | 161 | rx_buffer[rx_in] = device.getc(); |
4180_1 | 0:023c5cda6102 | 162 | // Uncomment to Echo to USB serial to watch data flow |
4180_1 | 0:023c5cda6102 | 163 | // monitor_device.putc(rx_buffer[rx_in]); |
4180_1 | 0:023c5cda6102 | 164 | rx_in = (rx_in + 1) % buffer_size; |
4180_1 | 0:023c5cda6102 | 165 | } |
4180_1 | 0:023c5cda6102 | 166 | led1=0; |
4180_1 | 0:023c5cda6102 | 167 | return; |
4180_1 | 0:023c5cda6102 | 168 | } |
4180_1 | 0:023c5cda6102 | 169 | |
4180_1 | 0:023c5cda6102 | 170 | // Interupt Routine to write out data to serial port |
4180_1 | 0:023c5cda6102 | 171 | void Tx_interrupt() { |
4180_1 | 0:023c5cda6102 | 172 | led2=1; |
4180_1 | 0:023c5cda6102 | 173 | // Loop to fill more than one character in UART's transmit FIFO buffer |
4180_1 | 0:023c5cda6102 | 174 | // Stop if buffer empty |
4180_1 | 0:023c5cda6102 | 175 | while ((device.writeable()) && (tx_in != tx_out)) { |
4180_1 | 0:023c5cda6102 | 176 | device.putc(tx_buffer[tx_out]); |
4180_1 | 0:023c5cda6102 | 177 | tx_out = (tx_out + 1) % buffer_size; |
4180_1 | 0:023c5cda6102 | 178 | } |
4180_1 | 0:023c5cda6102 | 179 | led2=0; |
4180_1 | 0:023c5cda6102 | 180 | return; |
4180_1 | 0:023c5cda6102 | 181 | } |