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