single_wire_UART.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00034 #include <ioavr.h>              //Device specific register/Bit definitions.
00035 #include <inavr.h>              //The __enable_interrupt() intrinsic.
00036 #include "stdint.h"             //Integer types.
00037 #include "single_wire_UART.h"   //UART settings and device spesific.
00038 
00039 /* Counter values */
00040 #define UART_STATE_IDLE       0
00041 #define RECEIVE_FIRST_DATA    3
00042 #define RECEIVE_LAST_DATA     17
00043 #define RECEIVE_STOP_1        19
00044 #define RECEIVE_FINISH        23
00045 #define TRANSMIT_FIRST_DATA   2
00046 #define TRANSMIT_LAST_DATA    16
00047 #define TRANSMIT_STOP_1       18
00048 #define TRANSMIT_STOP_2       20
00049 #define TRANSMIT_FINISH       22
00050 
00051 /* Prototypes */
00052 void SW_UART_Complete_Transfer(void);
00053 void SW_UART_Initiate_Transmission(void);
00054 
00055 volatile uint8_t SW_UART_status;          
00056 static volatile uint8_t UART_counter;     
00057 
00058 /* Communication parameters. */
00059 static volatile uint8_t   UART_Tx_data;     
00060 static volatile uint8_t   UART_Rx_data;     
00061 static volatile uint8_t   UART_Tx_buffer;   
00062 static volatile uint8_t   UART_Rx_buffer;   
00063 
00064 
00077 void SW_UART_Enable(void)
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 }
00091 
00092 
00098 /*
00099 void SW_UART_Disable()
00100 {
00101   SW_UART_status = 0x00;
00102   DISABLE_UART_TIMER_INTERRUPT();
00103   DISABLE_UART_EXTERNAL_INTERRUPT();
00104   STOP_UART_TIMER();
00105 }
00106 */
00107 
00108 
00121 void SW_UART_Transmit(uint8_t data)
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 }
00143 
00144 
00156 uint8_t SW_UART_Receive(void)
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 }
00163 
00164 
00173 #pragma vector=SW_UART_EXTERNAL_INTERRUPT_VECTOR
00174 __interrupt void External_SW_UART_ISR(void)
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 }
00190 
00191 
00203 #pragma vector=SW_UART_TIMER_COMPARE_INTERRUPT_VECTOR
00204 __interrupt void Timer_SW_UART_ISR(void)
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 }

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