from https://developer.mbed.org/cookbook/Serial-Interrupts

Dependencies:   mbed

Fork of Serial_interrupts by jim hamblen

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?

UserRevisionLine numberNew 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 }