The file contains the complete implementation for the single-wire software UART. See the header file for configuration of the UART. A timer compare interrupt and an external interrupt are used to generate interrupts needed by the driver. The SW_UART_Enable, SW_UART_Transmit and SW_UART_Receive functions and the SW_UART_status variable are used for communicating with the UART driver.
If available it is recommended to put the status byte in a general purpose i/o register. This will decrease code size and increase the speed for the UART driver.
Definition in file single_wire_UART.c.
#include <ioavr.h>
#include <inavr.h>
#include "stdint.h"
#include "single_wire_UART.h"
Include dependency graph for single_wire_UART.c:
Go to the source code of this file.
Defines | |
#define | RECEIVE_FINISH 23 |
#define | RECEIVE_FIRST_DATA 3 |
#define | RECEIVE_LAST_DATA 17 |
#define | RECEIVE_STOP_1 19 |
#define | TRANSMIT_FINISH 22 |
#define | TRANSMIT_FIRST_DATA 2 |
#define | TRANSMIT_LAST_DATA 16 |
#define | TRANSMIT_STOP_1 18 |
#define | TRANSMIT_STOP_2 20 |
#define | UART_STATE_IDLE 0 |
Functions | |
__interrupt void | External_SW_UART_ISR (void) |
External interrupt service routine. | |
void | SW_UART_Complete_Transfer (void) |
void | SW_UART_Enable (void) |
Enable the UART. | |
void | SW_UART_Initiate_Transmission (void) |
uint8_t | SW_UART_Receive (void) |
Receive one byte. | |
void | SW_UART_Transmit (uint8_t data) |
Transmit one byte. | |
__interrupt void | Timer_SW_UART_ISR (void) |
Timer compare interrupt service routine. | |
Variables | |
volatile uint8_t | SW_UART_status |
Byte holding status flags. | |
static volatile uint8_t | UART_counter |
Holds the counter used in the timer interrupt. | |
static volatile uint8_t | UART_Rx_buffer |
Reception buffer. | |
static volatile uint8_t | UART_Rx_data |
Byte holding data being received. | |
static volatile uint8_t | UART_Tx_buffer |
Transmission buffer. | |
static volatile uint8_t | UART_Tx_data |
Byte holding data being transmitted. |
#define RECEIVE_FINISH 23 |
#define RECEIVE_FIRST_DATA 3 |
#define RECEIVE_LAST_DATA 17 |
#define RECEIVE_STOP_1 19 |
#define TRANSMIT_FINISH 22 |
Definition at line 49 of file single_wire_UART.c.
#define TRANSMIT_FIRST_DATA 2 |
Definition at line 45 of file single_wire_UART.c.
Referenced by SW_UART_Transmit(), and Timer_SW_UART_ISR().
#define TRANSMIT_LAST_DATA 16 |
#define TRANSMIT_STOP_1 18 |
#define TRANSMIT_STOP_2 20 |
#define UART_STATE_IDLE 0 |
Definition at line 40 of file single_wire_UART.c.
Referenced by SW_UART_Enable(), SW_UART_Transmit(), and Timer_SW_UART_ISR().
__interrupt void External_SW_UART_ISR | ( | void | ) |
External interrupt service routine.
The falling edge in the beginning of the start bit will trigger this interrupt. Timer interrupt is enabled and counter is is set to RECEIVE_FIRST_DATA to signal that the next bit is the first data bit to be received.
Definition at line 174 of file single_wire_UART.c.
References CLEAR_UART_TIMER, CLEAR_UART_TIMER_INTERRUPT_FLAG, DISABLE_UART_EXTERNAL_INTERRUPT, ENABLE_UART_TIMER_INTERRUPT, READ_UART_PIN, RECEIVE_FIRST_DATA, SET_UART_TIMER_COMPARE_START_RECEIVE, START_UART_TIMER, STOP_UART_TIMER, UART_counter, and UART_Rx_data.
00175 { 00176 //Make sure bit is low. 00177 if(!READ_UART_PIN()) 00178 { 00179 UART_counter = RECEIVE_FIRST_DATA; //1. data bit is the next to be received 00180 UART_Rx_data = 0x00; 00181 STOP_UART_TIMER(); //Stop timer to make sure prescaler is reset. 00182 CLEAR_UART_TIMER(); 00183 SET_UART_TIMER_COMPARE_START_RECEIVE(); //Set timer compare value so the 1. data bit is sampled in the middle of the period. 00184 DISABLE_UART_EXTERNAL_INTERRUPT(); 00185 CLEAR_UART_TIMER_INTERRUPT_FLAG(); 00186 ENABLE_UART_TIMER_INTERRUPT(); 00187 START_UART_TIMER(); 00188 } 00189 }
void SW_UART_Complete_Transfer | ( | void | ) |
void SW_UART_Enable | ( | void | ) |
Enable the UART.
This function initialize the timer and buffers, and enables the external interrupt to sense for incoming data. It is important to run this function before calling any of the other UART functions. Received data will automatically be put in the RX buffer.
Definition at line 77 of file single_wire_UART.c.
References CLEAR_UART_EXTERNAL_INTERRUPT_FLAG, CLEAR_UART_TIMER_ON_COMPARE_MATCH, ENABLE_UART_EXTERNAL_INTERRUPT, INITIALIZE_UART_EXTERNAL_INTERRUPT, INITIALIZE_UART_PIN, SW_UART_status, UART_counter, and UART_STATE_IDLE.
Referenced by main().
00078 { 00079 //Tri-state communication pin. 00080 INITIALIZE_UART_PIN(); 00081 00082 SW_UART_status = 0x00; 00083 UART_counter = UART_STATE_IDLE; 00084 CLEAR_UART_TIMER_ON_COMPARE_MATCH(); 00085 00086 //Set up interrupts 00087 INITIALIZE_UART_EXTERNAL_INTERRUPT(); //Set up the external interrupt to wait for incoming start bit on correct pin. 00088 CLEAR_UART_EXTERNAL_INTERRUPT_FLAG(); //Clear flag in case it is already set for some reason. 00089 ENABLE_UART_EXTERNAL_INTERRUPT(); 00090 }
void SW_UART_Initiate_Transmission | ( | void | ) |
uint8_t SW_UART_Receive | ( | void | ) |
Receive one byte.
This function receives one byte of data by accessing the Rx buffer.
Definition at line 156 of file single_wire_UART.c.
References CLEAR_FLAG, SW_UART_RX_BUFFER_FULL, SW_UART_status, and UART_Rx_buffer.
Referenced by main().
00157 { 00158 uint8_t data; 00159 data = UART_Rx_buffer; 00160 CLEAR_FLAG( SW_UART_status, SW_UART_RX_BUFFER_FULL ); 00161 return data; 00162 }
void SW_UART_Transmit | ( | uint8_t | data | ) |
Transmit one byte.
This function sends one byte of data by putting it in the TX data and initialize a transmission if state is IDLE (UART_counter == 0)
data | Data to be sent. |
Definition at line 121 of file single_wire_UART.c.
References CLEAR_FLAG, CLEAR_UART_PIN, CLEAR_UART_TIMER, CLEAR_UART_TIMER_INTERRUPT_FLAG, DISABLE_UART_EXTERNAL_INTERRUPT, ENABLE_UART_TIMER_INTERRUPT, SET_FLAG, SET_UART_TIMER_COMPARE_START_TRANSMIT, START_UART_TIMER, SW_UART_status, SW_UART_TX_BUFFER_FULL, TRANSMIT_FIRST_DATA, UART_counter, UART_STATE_IDLE, UART_Tx_buffer, and UART_Tx_data.
Referenced by Print_String().
00122 { 00123 SET_FLAG( SW_UART_status, SW_UART_TX_BUFFER_FULL ); 00124 UART_Tx_buffer = data; 00125 00126 //Start transmission if no ongoing communication. 00127 if( UART_counter == UART_STATE_IDLE ) 00128 { 00129 //Copy byte from buffer and clear buffer full flag. 00130 UART_Tx_data = UART_Tx_buffer; 00131 CLEAR_FLAG( SW_UART_status, SW_UART_TX_BUFFER_FULL ); 00132 00133 DISABLE_UART_EXTERNAL_INTERRUPT(); 00134 CLEAR_UART_PIN(); //Write start bit. 00135 UART_counter = TRANSMIT_FIRST_DATA; //Update counter so the 1. data bit is the next bit to be transmitted. 00136 CLEAR_UART_TIMER(); //Clear timer. 00137 SET_UART_TIMER_COMPARE_START_TRANSMIT(); //Set timer compare value. 00138 CLEAR_UART_TIMER_INTERRUPT_FLAG(); //Make sure timer interrupt flag is not set. 00139 ENABLE_UART_TIMER_INTERRUPT(); 00140 START_UART_TIMER(); 00141 } 00142 }
__interrupt void Timer_SW_UART_ISR | ( | void | ) |
Timer compare interrupt service routine.
This interrupt is triggered when the compare register equals the timer. It increments the counter and handles the transmission and reception of each bit.
Definition at line 204 of file single_wire_UART.c.
References CLEAR_FLAG, CLEAR_UART_EXTERNAL_INTERRUPT_FLAG, CLEAR_UART_PIN, CLEAR_UART_TIMER, CLEAR_UART_TIMER_INTERRUPT_FLAG, DISABLE_UART_EXTERNAL_INTERRUPT, DISABLE_UART_TIMER_INTERRUPT, ENABLE_UART_EXTERNAL_INTERRUPT, READ_FLAG, READ_UART_PIN, RECEIVE_FINISH, RECEIVE_LAST_DATA, RECEIVE_STOP_1, SET_FLAG, SET_UART_PIN, SET_UART_TIMER_COMPARE_START_TRANSMIT, SET_UART_TIMER_COMPARE_WAIT_ONE, START_UART_TIMER, STOP_UART_TIMER, SW_UART_FRAME_ERROR, SW_UART_RX_BUFFER_FULL, SW_UART_RX_BUFFER_OVERFLOW, SW_UART_status, SW_UART_TX_BUFFER_FULL, TRANSMIT_FIRST_DATA, TRANSMIT_LAST_DATA, TRANSMIT_STOP_1, TRANSMIT_STOP_2, UART_counter, UART_Rx_buffer, UART_Rx_data, UART_STATE_IDLE, UART_Tx_buffer, and UART_Tx_data.
00205 { 00206 SET_UART_TIMER_COMPARE_WAIT_ONE(); //Set timer compare value to trigger the ISR once every bit period. 00207 00208 //Sample bit by checking the value on the UART pin: 00209 uint8_t bit_in = 0x00; 00210 if(READ_UART_PIN()) 00211 { 00212 bit_in = 0x01; 00213 } 00214 00216 //Receive if counter is odd. 00218 if(UART_counter & 0x01) 00219 { 00220 //If to receive data bit -> Copy received bit into Rx_data. 00221 if(UART_counter <= RECEIVE_LAST_DATA) 00222 { 00223 UART_Rx_data = ( UART_Rx_data >> 1 ); //Right shift RX_data so the new bit can be masked into the Rx_data byte. 00224 if(bit_in) 00225 { 00226 UART_Rx_data |= 0x80; //Set MSB of RX data if received bit == 1. 00227 } 00228 } 00229 00230 //If to receive stop bit -> Copy Rx data to Rx buffer. 00231 else if(UART_counter == RECEIVE_STOP_1) 00232 { 00233 //Set frame error flag if a low stop bit is received. 00234 if(!bit_in) 00235 { 00236 SET_FLAG( SW_UART_status, SW_UART_FRAME_ERROR ); 00237 //Disable timer and stop reception? 00238 } 00239 00240 //Set overflow error if RX_buffer is not received before new data is ready. 00241 if( READ_FLAG(SW_UART_status, SW_UART_RX_BUFFER_FULL)) 00242 { 00243 SET_FLAG(SW_UART_status, SW_UART_RX_BUFFER_OVERFLOW); 00244 } 00245 00246 UART_Rx_buffer = UART_Rx_data; 00247 SET_FLAG( SW_UART_status, SW_UART_RX_BUFFER_FULL ); 00248 CLEAR_UART_EXTERNAL_INTERRUPT_FLAG(); 00249 ENABLE_UART_EXTERNAL_INTERRUPT(); //Get ready to receive new byte. 00250 } 00251 00252 //If reception finished and no new incoming data has been detected. 00253 else if(UART_counter == RECEIVE_FINISH) 00254 { 00255 //Initiate transmission if there is data in TX_buffer. This is done in the 00256 //same way as in the UART_transmit routine. 00257 if( READ_FLAG(SW_UART_status, SW_UART_TX_BUFFER_FULL) ) 00258 { 00259 UART_Tx_data = UART_Tx_buffer; 00260 CLEAR_FLAG( SW_UART_status, SW_UART_TX_BUFFER_FULL ); 00261 DISABLE_UART_EXTERNAL_INTERRUPT(); 00262 CLEAR_UART_PIN(); //Write start bit. 00263 UART_counter = TRANSMIT_FIRST_DATA; //Update counter so the 1. data bit is the next bit to be transmitted. 00264 STOP_UART_TIMER(); //Stop timer to reset prescaler. 00265 CLEAR_UART_TIMER(); //Clear timer. 00266 SET_UART_TIMER_COMPARE_START_TRANSMIT(); //Set timer compare value 00267 CLEAR_UART_TIMER_INTERRUPT_FLAG(); //Make sure timer interrupt flag is not set. 00268 START_UART_TIMER(); 00269 return; //Exit ISR so the counter is not updated. 00270 } 00271 00272 //If no data is waiting to be transmitted in the Tx bufferSet to IDLE and disable interrupt if no TX data is waiting. 00273 else 00274 { 00275 STOP_UART_TIMER(); 00276 DISABLE_UART_TIMER_INTERRUPT(); 00277 UART_counter = UART_STATE_IDLE; 00278 return; //Exit ISR so the counter is not updated. 00279 } 00280 } 00281 } 00282 00284 //Transmit if counter is even. 00286 else 00287 { 00288 uint8_t bit_out = 0x00; 00289 00290 //Check if bit equals last bit sent. Set frame error flag if not. Also set UART_Tx_data to the next value. 00291 if(UART_counter != TRANSMIT_FIRST_DATA) 00292 { 00293 uint8_t last_bit_sent = 0x01; 00294 00295 if(UART_counter <= TRANSMIT_STOP_1) 00296 { 00297 last_bit_sent = UART_Tx_data & 0x01; 00298 UART_Tx_data = UART_Tx_data >> 1; //Right shift data bits. Does not have any effect for stop bits. 00299 } 00300 00301 //if a high bit was sent, but a low received, set frame error flag. 00302 if( last_bit_sent != bit_in ) 00303 { 00304 SET_FLAG(SW_UART_status, SW_UART_FRAME_ERROR); 00305 //Stop transmission ? 00306 } 00307 } 00308 00309 //If to transmit data bit, set bit_out according to UART_Tx_data. 00310 if(UART_counter <= TRANSMIT_LAST_DATA) 00311 { 00312 if( UART_Tx_data & 0x01 ) 00313 { 00314 bit_out = 0x01; 00315 } 00316 } 00317 00318 //If to transmit stop bit, set the bit to be transmitted high. 00319 else if(UART_counter == TRANSMIT_STOP_1) 00320 { 00321 bit_out = 0x01; 00322 } 00323 else if(UART_counter == TRANSMIT_STOP_2) 00324 { 00325 CLEAR_UART_EXTERNAL_INTERRUPT_FLAG(); 00326 ENABLE_UART_EXTERNAL_INTERRUPT(); 00327 bit_out = 0x01; 00328 } 00329 00330 //If transmission finished. Start a new transmission if data is present in the Tx buffer. Set the UART 00331 //idle if not. 00332 else 00333 { 00334 //Check if new data is ready to be sent. If not, set UART state to idle, disable the timer interrupt and 00335 //enable the external interrupt to make the UART wait for new incoming data. 00336 if(!READ_FLAG(SW_UART_status, SW_UART_TX_BUFFER_FULL)) 00337 { 00338 STOP_UART_TIMER(); 00339 DISABLE_UART_TIMER_INTERRUPT(); 00340 UART_counter = UART_STATE_IDLE; 00341 return; //Exit ISR so the counter is not updated. 00342 } 00343 00344 //Initiate transmission if there is data in TX_buffer. 00345 else 00346 { 00347 UART_Tx_data = UART_Tx_buffer; 00348 CLEAR_FLAG( SW_UART_status, SW_UART_TX_BUFFER_FULL ); 00349 UART_counter = TRANSMIT_FIRST_DATA - 2; //Need to substract 2 because counter is updated at the end of the ISR. 00350 DISABLE_UART_EXTERNAL_INTERRUPT(); 00351 //bit_out already set to 0x00. 00352 } 00353 } 00354 00355 //Transmit bit. 00356 if( bit_out ) 00357 { 00358 SET_UART_PIN(); 00359 } 00360 else 00361 { 00362 CLEAR_UART_PIN(); 00363 } 00364 } 00365 UART_counter = UART_counter + 2; //Update counter. 00366 }
volatile uint8_t SW_UART_status |
Byte holding status flags.
Definition at line 55 of file single_wire_UART.c.
Referenced by main(), Print_String(), SW_UART_Enable(), SW_UART_Receive(), SW_UART_Transmit(), and Timer_SW_UART_ISR().
volatile uint8_t UART_counter [static] |
Holds the counter used in the timer interrupt.
Definition at line 56 of file single_wire_UART.c.
Referenced by External_SW_UART_ISR(), SW_UART_Enable(), SW_UART_Transmit(), and Timer_SW_UART_ISR().
volatile uint8_t UART_Rx_buffer [static] |
Reception buffer.
Definition at line 62 of file single_wire_UART.c.
Referenced by SW_UART_Receive(), and Timer_SW_UART_ISR().
volatile uint8_t UART_Rx_data [static] |
Byte holding data being received.
Definition at line 60 of file single_wire_UART.c.
Referenced by External_SW_UART_ISR(), and Timer_SW_UART_ISR().
volatile uint8_t UART_Tx_buffer [static] |
Transmission buffer.
Definition at line 61 of file single_wire_UART.c.
Referenced by SW_UART_Transmit(), and Timer_SW_UART_ISR().
volatile uint8_t UART_Tx_data [static] |
Byte holding data being transmitted.
Definition at line 59 of file single_wire_UART.c.
Referenced by SW_UART_Transmit(), and Timer_SW_UART_ISR().