single_wire_UART.c File Reference


Detailed Description

This is the c file of the single-wire UART driver.

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.

Application note:
AVR274: Single-wire Software UART
Documentation
For comprehensive code documentation, supported compilers, compiler settings and supported devices see readme.html
Author:
Atmel Corporation: http://www.atmel.com
Support email: avr@atmel.com
Name
Revision
1513
RCSfile
single_wire_UART.c,v
Date
2007-03-29 13:17:03 +0200 (to, 29 mar 2007)

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 Documentation

#define RECEIVE_FINISH   23

Definition at line 44 of file single_wire_UART.c.

Referenced by Timer_SW_UART_ISR().

#define RECEIVE_FIRST_DATA   3

Definition at line 41 of file single_wire_UART.c.

Referenced by External_SW_UART_ISR().

#define RECEIVE_LAST_DATA   17

Definition at line 42 of file single_wire_UART.c.

Referenced by Timer_SW_UART_ISR().

#define RECEIVE_STOP_1   19

Definition at line 43 of file single_wire_UART.c.

Referenced by Timer_SW_UART_ISR().

#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

Definition at line 46 of file single_wire_UART.c.

Referenced by Timer_SW_UART_ISR().

#define TRANSMIT_STOP_1   18

Definition at line 47 of file single_wire_UART.c.

Referenced by Timer_SW_UART_ISR().

#define TRANSMIT_STOP_2   20

Definition at line 48 of file single_wire_UART.c.

Referenced by Timer_SW_UART_ISR().

#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().


Function Documentation

__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.

Note:
The UART can be stopped by disabling the timer and external interrupt.

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.

Note:
The SW_UART_RX_BUFFER_FULL flag must be one when this function is called.
Returns:
Data received.

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)

Note:
The SW_UART_TX_BUFFER_FULL flag must be 0 when this function is called, or data in transmit buffer will be lost.
Parameters:
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.

Note:
The WAIT_ONE define has to be less than the maximum time spent in this routine so an interrupt is not missed.

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 }


Variable Documentation

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().


Generated on Mon Apr 23 10:13:58 2007 for AVR274: Single-wire Software UART by  doxygen 1.5.1-p1