
soft serial ok with GPS
Dependencies: mbed
main.cpp@0:a563059f0473, 2020-05-10 (annotated)
- Committer:
- eric11fr
- Date:
- Sun May 10 21:31:58 2020 +0000
- Revision:
- 0:a563059f0473
serial_uart_ok with GPS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
eric11fr | 0:a563059f0473 | 1 | #include "mbed.h" |
eric11fr | 0:a563059f0473 | 2 | |
eric11fr | 0:a563059f0473 | 3 | // UART.C |
eric11fr | 0:a563059f0473 | 4 | // |
eric11fr | 0:a563059f0473 | 5 | // Generic software uart written in C, requiring a timer set to 3 times |
eric11fr | 0:a563059f0473 | 6 | // the baud rate, and two software read/write pins for the receive and |
eric11fr | 0:a563059f0473 | 7 | // transmit functions. |
eric11fr | 0:a563059f0473 | 8 | // |
eric11fr | 0:a563059f0473 | 9 | // * Received characters are buffered |
eric11fr | 0:a563059f0473 | 10 | // * putchar(), getchar(), kbhit() and flush_input_buffer() are available |
eric11fr | 0:a563059f0473 | 11 | // * There is a facility for background processing while waiting for input |
eric11fr | 0:a563059f0473 | 12 | // |
eric11fr | 0:a563059f0473 | 13 | // Colin Gittins, Software Engineer, Halliburton Energy Services |
eric11fr | 0:a563059f0473 | 14 | // |
eric11fr | 0:a563059f0473 | 15 | // The baud rate can be configured by changing the BAUD_RATE macro as |
eric11fr | 0:a563059f0473 | 16 | // follows: |
eric11fr | 0:a563059f0473 | 17 | // |
eric11fr | 0:a563059f0473 | 18 | // #define BAUD_RATE 19200.0 |
eric11fr | 0:a563059f0473 | 19 | // |
eric11fr | 0:a563059f0473 | 20 | // The function init_uart() must be called before any comms can take place |
eric11fr | 0:a563059f0473 | 21 | // |
eric11fr | 0:a563059f0473 | 22 | // Interface routines required: |
eric11fr | 0:a563059f0473 | 23 | // 1. get_rx_pin_status() |
eric11fr | 0:a563059f0473 | 24 | // Returns 0 or 1 dependent on whether the receive pin is high or low. |
eric11fr | 0:a563059f0473 | 25 | // 2. set_tx_pin_high() |
eric11fr | 0:a563059f0473 | 26 | // Sets the transmit pin to the high state. |
eric11fr | 0:a563059f0473 | 27 | // 3. set_tx_pin_low() |
eric11fr | 0:a563059f0473 | 28 | // Sets the transmit pin to the low state. |
eric11fr | 0:a563059f0473 | 29 | // 4. idle() |
eric11fr | 0:a563059f0473 | 30 | // Background functions to execute while waiting for input. |
eric11fr | 0:a563059f0473 | 31 | // 5. timer_set( BAUD_RATE ) |
eric11fr | 0:a563059f0473 | 32 | // Sets the timer to 3 times the baud rate. |
eric11fr | 0:a563059f0473 | 33 | // 6. set_timer_interrupt( timer_isr ) |
eric11fr | 0:a563059f0473 | 34 | // Enables the timer interrupt. |
eric11fr | 0:a563059f0473 | 35 | // |
eric11fr | 0:a563059f0473 | 36 | // Functions provided: |
eric11fr | 0:a563059f0473 | 37 | // 1. void flush_input_buffer( void ) |
eric11fr | 0:a563059f0473 | 38 | // Clears the contents of the input buffer. |
eric11fr | 0:a563059f0473 | 39 | // 2. char kbhit( void ) |
eric11fr | 0:a563059f0473 | 40 | // Tests whether an input character has been received. |
eric11fr | 0:a563059f0473 | 41 | // 3. char getchar( void ) |
eric11fr | 0:a563059f0473 | 42 | // Reads a character from the input buffer, waiting if necessary. |
eric11fr | 0:a563059f0473 | 43 | // 4. void turn_rx_on( void ) |
eric11fr | 0:a563059f0473 | 44 | // Turns on the receive function. |
eric11fr | 0:a563059f0473 | 45 | // 5. void turn_rx_off( void ) |
eric11fr | 0:a563059f0473 | 46 | // Turns off the receive function. |
eric11fr | 0:a563059f0473 | 47 | // 6. void putchar( char ) |
eric11fr | 0:a563059f0473 | 48 | // Writes a character to the serial port. |
eric11fr | 0:a563059f0473 | 49 | |
eric11fr | 0:a563059f0473 | 50 | #include <stdio.h> |
eric11fr | 0:a563059f0473 | 51 | |
eric11fr | 0:a563059f0473 | 52 | #define BAUD_RATE 9600 |
eric11fr | 0:a563059f0473 | 53 | #define IN_BUF_SIZE 256 |
eric11fr | 0:a563059f0473 | 54 | |
eric11fr | 0:a563059f0473 | 55 | #define TRUE 1 |
eric11fr | 0:a563059f0473 | 56 | #define FALSE 0 |
eric11fr | 0:a563059f0473 | 57 | |
eric11fr | 0:a563059f0473 | 58 | static unsigned char inbuf[IN_BUF_SIZE]; |
eric11fr | 0:a563059f0473 | 59 | static unsigned char qin = 0; |
eric11fr | 0:a563059f0473 | 60 | static unsigned char qout = 0; |
eric11fr | 0:a563059f0473 | 61 | |
eric11fr | 0:a563059f0473 | 62 | static char flag_rx_waiting_for_stop_bit; |
eric11fr | 0:a563059f0473 | 63 | static char flag_rx_off; |
eric11fr | 0:a563059f0473 | 64 | static char rx_mask; |
eric11fr | 0:a563059f0473 | 65 | static char flag_rx_ready; |
eric11fr | 0:a563059f0473 | 66 | static char flag_tx_ready; |
eric11fr | 0:a563059f0473 | 67 | static char timer_rx_ctr; |
eric11fr | 0:a563059f0473 | 68 | static char timer_tx_ctr; |
eric11fr | 0:a563059f0473 | 69 | static char bits_left_in_rx; |
eric11fr | 0:a563059f0473 | 70 | static char bits_left_in_tx; |
eric11fr | 0:a563059f0473 | 71 | static char rx_num_of_bits; |
eric11fr | 0:a563059f0473 | 72 | static char tx_num_of_bits; |
eric11fr | 0:a563059f0473 | 73 | static int internal_rx_buffer; |
eric11fr | 0:a563059f0473 | 74 | static int internal_tx_buffer; |
eric11fr | 0:a563059f0473 | 75 | static int user_tx_buffer; |
eric11fr | 0:a563059f0473 | 76 | |
eric11fr | 0:a563059f0473 | 77 | DigitalOut TX(D4); |
eric11fr | 0:a563059f0473 | 78 | DigitalIn RX(D3); |
eric11fr | 0:a563059f0473 | 79 | Ticker ticker; |
eric11fr | 0:a563059f0473 | 80 | |
eric11fr | 0:a563059f0473 | 81 | Serial pc(USBTX, USBRX); |
eric11fr | 0:a563059f0473 | 82 | |
eric11fr | 0:a563059f0473 | 83 | |
eric11fr | 0:a563059f0473 | 84 | //Background functions to execute while waiting for input. |
eric11fr | 0:a563059f0473 | 85 | void idle(){ |
eric11fr | 0:a563059f0473 | 86 | wait_us(0.2); |
eric11fr | 0:a563059f0473 | 87 | } |
eric11fr | 0:a563059f0473 | 88 | |
eric11fr | 0:a563059f0473 | 89 | //Sets the transmit pin to the high state. |
eric11fr | 0:a563059f0473 | 90 | void set_tx_pin_high() { |
eric11fr | 0:a563059f0473 | 91 | TX = 1; |
eric11fr | 0:a563059f0473 | 92 | } |
eric11fr | 0:a563059f0473 | 93 | |
eric11fr | 0:a563059f0473 | 94 | //Sets the transmit pin to the low state. |
eric11fr | 0:a563059f0473 | 95 | void set_tx_pin_low() { |
eric11fr | 0:a563059f0473 | 96 | TX = 0; |
eric11fr | 0:a563059f0473 | 97 | } |
eric11fr | 0:a563059f0473 | 98 | |
eric11fr | 0:a563059f0473 | 99 | //Returns 0 or 1 dependent on whether the receive pin is high or low |
eric11fr | 0:a563059f0473 | 100 | int get_rx_pin_status() { |
eric11fr | 0:a563059f0473 | 101 | return RX.read(); |
eric11fr | 0:a563059f0473 | 102 | } |
eric11fr | 0:a563059f0473 | 103 | |
eric11fr | 0:a563059f0473 | 104 | void timer_isr(void) |
eric11fr | 0:a563059f0473 | 105 | { |
eric11fr | 0:a563059f0473 | 106 | char mask, start_bit, flag_in; |
eric11fr | 0:a563059f0473 | 107 | |
eric11fr | 0:a563059f0473 | 108 | |
eric11fr | 0:a563059f0473 | 109 | // Transmitter Section |
eric11fr | 0:a563059f0473 | 110 | if ( flag_tx_ready ) |
eric11fr | 0:a563059f0473 | 111 | { |
eric11fr | 0:a563059f0473 | 112 | |
eric11fr | 0:a563059f0473 | 113 | if ( --timer_tx_ctr<=0 ) |
eric11fr | 0:a563059f0473 | 114 | { |
eric11fr | 0:a563059f0473 | 115 | mask = internal_tx_buffer&1; |
eric11fr | 0:a563059f0473 | 116 | internal_tx_buffer >>= 1; |
eric11fr | 0:a563059f0473 | 117 | if ( mask ) |
eric11fr | 0:a563059f0473 | 118 | { |
eric11fr | 0:a563059f0473 | 119 | set_tx_pin_high(); |
eric11fr | 0:a563059f0473 | 120 | } |
eric11fr | 0:a563059f0473 | 121 | else |
eric11fr | 0:a563059f0473 | 122 | { |
eric11fr | 0:a563059f0473 | 123 | set_tx_pin_low(); |
eric11fr | 0:a563059f0473 | 124 | } |
eric11fr | 0:a563059f0473 | 125 | timer_tx_ctr = 3; |
eric11fr | 0:a563059f0473 | 126 | if ( --bits_left_in_tx<=0 ) |
eric11fr | 0:a563059f0473 | 127 | { |
eric11fr | 0:a563059f0473 | 128 | flag_tx_ready = FALSE; |
eric11fr | 0:a563059f0473 | 129 | } |
eric11fr | 0:a563059f0473 | 130 | } |
eric11fr | 0:a563059f0473 | 131 | } |
eric11fr | 0:a563059f0473 | 132 | // Receiver Section |
eric11fr | 0:a563059f0473 | 133 | if ( flag_rx_off==FALSE ) |
eric11fr | 0:a563059f0473 | 134 | { |
eric11fr | 0:a563059f0473 | 135 | if ( flag_rx_waiting_for_stop_bit ) |
eric11fr | 0:a563059f0473 | 136 | { |
eric11fr | 0:a563059f0473 | 137 | if ( --timer_rx_ctr<=0 ) |
eric11fr | 0:a563059f0473 | 138 | { |
eric11fr | 0:a563059f0473 | 139 | flag_rx_waiting_for_stop_bit = FALSE; |
eric11fr | 0:a563059f0473 | 140 | flag_rx_ready = FALSE; |
eric11fr | 0:a563059f0473 | 141 | internal_rx_buffer &= 0xFF; |
eric11fr | 0:a563059f0473 | 142 | if ( internal_rx_buffer!=0xC2 ) |
eric11fr | 0:a563059f0473 | 143 | { |
eric11fr | 0:a563059f0473 | 144 | inbuf[qin] = internal_rx_buffer; |
eric11fr | 0:a563059f0473 | 145 | if ( ++qin>=IN_BUF_SIZE ) |
eric11fr | 0:a563059f0473 | 146 | { |
eric11fr | 0:a563059f0473 | 147 | qin = 0; |
eric11fr | 0:a563059f0473 | 148 | } |
eric11fr | 0:a563059f0473 | 149 | } |
eric11fr | 0:a563059f0473 | 150 | } |
eric11fr | 0:a563059f0473 | 151 | } |
eric11fr | 0:a563059f0473 | 152 | else // rx_test_busy |
eric11fr | 0:a563059f0473 | 153 | { |
eric11fr | 0:a563059f0473 | 154 | if ( flag_rx_ready==FALSE ) |
eric11fr | 0:a563059f0473 | 155 | { |
eric11fr | 0:a563059f0473 | 156 | start_bit = get_rx_pin_status(); |
eric11fr | 0:a563059f0473 | 157 | // Test for Start Bit |
eric11fr | 0:a563059f0473 | 158 | if ( start_bit==0 ) |
eric11fr | 0:a563059f0473 | 159 | { |
eric11fr | 0:a563059f0473 | 160 | flag_rx_ready = TRUE; |
eric11fr | 0:a563059f0473 | 161 | internal_rx_buffer = 0; |
eric11fr | 0:a563059f0473 | 162 | timer_rx_ctr = 4; |
eric11fr | 0:a563059f0473 | 163 | bits_left_in_rx = rx_num_of_bits; |
eric11fr | 0:a563059f0473 | 164 | rx_mask = 1; |
eric11fr | 0:a563059f0473 | 165 | } |
eric11fr | 0:a563059f0473 | 166 | } |
eric11fr | 0:a563059f0473 | 167 | else // rx_busy |
eric11fr | 0:a563059f0473 | 168 | { |
eric11fr | 0:a563059f0473 | 169 | if ( --timer_rx_ctr<=0 ) |
eric11fr | 0:a563059f0473 | 170 | { // rcv |
eric11fr | 0:a563059f0473 | 171 | timer_rx_ctr = 3; |
eric11fr | 0:a563059f0473 | 172 | flag_in = get_rx_pin_status(); |
eric11fr | 0:a563059f0473 | 173 | if ( flag_in ) |
eric11fr | 0:a563059f0473 | 174 | { |
eric11fr | 0:a563059f0473 | 175 | internal_rx_buffer |= rx_mask; |
eric11fr | 0:a563059f0473 | 176 | } |
eric11fr | 0:a563059f0473 | 177 | rx_mask <<= 1; |
eric11fr | 0:a563059f0473 | 178 | if ( --bits_left_in_rx<=0 ) |
eric11fr | 0:a563059f0473 | 179 | { |
eric11fr | 0:a563059f0473 | 180 | flag_rx_waiting_for_stop_bit = TRUE; |
eric11fr | 0:a563059f0473 | 181 | } |
eric11fr | 0:a563059f0473 | 182 | } |
eric11fr | 0:a563059f0473 | 183 | } |
eric11fr | 0:a563059f0473 | 184 | } |
eric11fr | 0:a563059f0473 | 185 | } |
eric11fr | 0:a563059f0473 | 186 | } |
eric11fr | 0:a563059f0473 | 187 | |
eric11fr | 0:a563059f0473 | 188 | void init_uart( void ) |
eric11fr | 0:a563059f0473 | 189 | { |
eric11fr | 0:a563059f0473 | 190 | flag_tx_ready = FALSE; |
eric11fr | 0:a563059f0473 | 191 | flag_rx_ready = FALSE; |
eric11fr | 0:a563059f0473 | 192 | flag_rx_waiting_for_stop_bit = FALSE; |
eric11fr | 0:a563059f0473 | 193 | flag_rx_off = FALSE; |
eric11fr | 0:a563059f0473 | 194 | rx_num_of_bits = 8;//10 |
eric11fr | 0:a563059f0473 | 195 | tx_num_of_bits = 8;//10 |
eric11fr | 0:a563059f0473 | 196 | |
eric11fr | 0:a563059f0473 | 197 | set_tx_pin_low(); |
eric11fr | 0:a563059f0473 | 198 | ticker.attach_us(&timer_isr, 1000000.0 / (BAUD_RATE * 3.0)); |
eric11fr | 0:a563059f0473 | 199 | |
eric11fr | 0:a563059f0473 | 200 | } |
eric11fr | 0:a563059f0473 | 201 | |
eric11fr | 0:a563059f0473 | 202 | char _getchar( void ) |
eric11fr | 0:a563059f0473 | 203 | { |
eric11fr | 0:a563059f0473 | 204 | char ch; |
eric11fr | 0:a563059f0473 | 205 | |
eric11fr | 0:a563059f0473 | 206 | do |
eric11fr | 0:a563059f0473 | 207 | { |
eric11fr | 0:a563059f0473 | 208 | while ( qout==qin ) |
eric11fr | 0:a563059f0473 | 209 | { |
eric11fr | 0:a563059f0473 | 210 | idle(); |
eric11fr | 0:a563059f0473 | 211 | } |
eric11fr | 0:a563059f0473 | 212 | ch = inbuf[qout] & 0xFF; |
eric11fr | 0:a563059f0473 | 213 | if ( ++qout>=IN_BUF_SIZE ) |
eric11fr | 0:a563059f0473 | 214 | { |
eric11fr | 0:a563059f0473 | 215 | qout = 0; |
eric11fr | 0:a563059f0473 | 216 | } |
eric11fr | 0:a563059f0473 | 217 | } |
eric11fr | 0:a563059f0473 | 218 | while ( ch==0x0A || ch==0xC2 ); |
eric11fr | 0:a563059f0473 | 219 | return( ch ); |
eric11fr | 0:a563059f0473 | 220 | } |
eric11fr | 0:a563059f0473 | 221 | |
eric11fr | 0:a563059f0473 | 222 | void _putchar( int ch ) |
eric11fr | 0:a563059f0473 | 223 | { |
eric11fr | 0:a563059f0473 | 224 | while ( flag_tx_ready ); |
eric11fr | 0:a563059f0473 | 225 | user_tx_buffer = ch; |
eric11fr | 0:a563059f0473 | 226 | |
eric11fr | 0:a563059f0473 | 227 | // invoke_UART_transmit |
eric11fr | 0:a563059f0473 | 228 | timer_tx_ctr = 3; |
eric11fr | 0:a563059f0473 | 229 | bits_left_in_tx = tx_num_of_bits; |
eric11fr | 0:a563059f0473 | 230 | internal_tx_buffer = (user_tx_buffer<<1) | 0x200;; |
eric11fr | 0:a563059f0473 | 231 | flag_tx_ready = TRUE; |
eric11fr | 0:a563059f0473 | 232 | } |
eric11fr | 0:a563059f0473 | 233 | |
eric11fr | 0:a563059f0473 | 234 | void flush_input_buffer( void ) |
eric11fr | 0:a563059f0473 | 235 | { |
eric11fr | 0:a563059f0473 | 236 | qin = 0; |
eric11fr | 0:a563059f0473 | 237 | qout = 0; |
eric11fr | 0:a563059f0473 | 238 | } |
eric11fr | 0:a563059f0473 | 239 | |
eric11fr | 0:a563059f0473 | 240 | char kbhit( void ) |
eric11fr | 0:a563059f0473 | 241 | { |
eric11fr | 0:a563059f0473 | 242 | return( qin!=qout ); |
eric11fr | 0:a563059f0473 | 243 | } |
eric11fr | 0:a563059f0473 | 244 | |
eric11fr | 0:a563059f0473 | 245 | void turn_rx_on( void ) |
eric11fr | 0:a563059f0473 | 246 | { |
eric11fr | 0:a563059f0473 | 247 | flag_rx_off = FALSE; |
eric11fr | 0:a563059f0473 | 248 | } |
eric11fr | 0:a563059f0473 | 249 | |
eric11fr | 0:a563059f0473 | 250 | void turn_rx_off( void ) |
eric11fr | 0:a563059f0473 | 251 | { |
eric11fr | 0:a563059f0473 | 252 | flag_rx_off = TRUE; |
eric11fr | 0:a563059f0473 | 253 | } |
eric11fr | 0:a563059f0473 | 254 | |
eric11fr | 0:a563059f0473 | 255 | void printStr(char* str){ |
eric11fr | 0:a563059f0473 | 256 | int i = 0; |
eric11fr | 0:a563059f0473 | 257 | int len = strlen(str); |
eric11fr | 0:a563059f0473 | 258 | for(i = 0; i<len; i++){ |
eric11fr | 0:a563059f0473 | 259 | wait(0.01); |
eric11fr | 0:a563059f0473 | 260 | _putchar(str[i]); |
eric11fr | 0:a563059f0473 | 261 | } |
eric11fr | 0:a563059f0473 | 262 | } |
eric11fr | 0:a563059f0473 | 263 | |
eric11fr | 0:a563059f0473 | 264 | int main() { |
eric11fr | 0:a563059f0473 | 265 | |
eric11fr | 0:a563059f0473 | 266 | pc.baud(9600); |
eric11fr | 0:a563059f0473 | 267 | pc.printf("test"); |
eric11fr | 0:a563059f0473 | 268 | init_uart(); |
eric11fr | 0:a563059f0473 | 269 | |
eric11fr | 0:a563059f0473 | 270 | //printStr("d\n\r"); |
eric11fr | 0:a563059f0473 | 271 | wait(0.01); |
eric11fr | 0:a563059f0473 | 272 | //printStr("Voila!\n\r"); |
eric11fr | 0:a563059f0473 | 273 | //printStr("Voila!\n\r"); |
eric11fr | 0:a563059f0473 | 274 | while(1){ |
eric11fr | 0:a563059f0473 | 275 | // printStr("V"); |
eric11fr | 0:a563059f0473 | 276 | pc.putc( _getchar() ); |
eric11fr | 0:a563059f0473 | 277 | //wait(0.1); |
eric11fr | 0:a563059f0473 | 278 | } |
eric11fr | 0:a563059f0473 | 279 | } |