Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

USI_TWI_Master.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00032 #include <inavr.h>
00033 #include <iotiny24.h>   // standard IAR header file with 4.11A and later
00034 #include "USI_TWI_Master.h"
00035 
00036 unsigned char USI_TWI_Master_Transfer( unsigned char );
00037 unsigned char USI_TWI_Master_Stop( void );
00038 
00039 union  USI_TWI_state
00040 {
00041   unsigned char errorState;         // Can reuse the TWI_state for error states due to that it will not be need if there exists an error.
00042   struct
00043   {
00044     unsigned char addressMode         : 1;
00045     unsigned char masterWriteDataMode : 1;
00046     unsigned char unused              : 6;
00047   };
00048 }   USI_TWI_state;
00049 
00050 #pragma vector = USI_START_vect
00051 __interrupt void USI_START_ISR(void)
00052 {
00053   USISR |= (1<<USISIF);             // ignore start condition
00054 }
00055 
00056 /*---------------------------------------------------------------
00057  USI TWI single master initialization function
00058 ---------------------------------------------------------------*/
00059 void USI_TWI_Master_Initialise( void )
00060 {
00061   PORT_USI |= (1<<PIN_USI_SDA);           // Enable pullup on SDA, to set high as released state.
00062   PORT_USI |= (1<<PIN_USI_SCL);           // Enable pullup on SCL, to set high as released state.
00063 
00064   DDR_USI  |= (1<<PIN_USI_SCL);           // Enable SCL as output.
00065   DDR_USI  |= (1<<PIN_USI_SDA);           // Enable SDA as output.
00066 
00067   USIDR    =  0xFF;                       // Preload dataregister with "released level" data.
00068 /*
00069   USICR    =  (1<<USISIE)|(0<<USIOIE)|                            // ENABLE Interrupts.
00070 */
00071   USICR    =  (0<<USISIE)|(0<<USIOIE)|                            // Disable Interrupts.
00072               (1<<USIWM1)|(0<<USIWM0)|                            // Set USI in Two-wire mode.
00073               (1<<USICS1)|(0<<USICS0)|(1<<USICLK)|                // Software stobe as counter clock source
00074               (0<<USITC);
00075   USISR   =   (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Clear flags,
00076               (0x0<<USICNT0);                                     // and reset counter.
00077 }
00078 
00079 /*---------------------------------------------------------------
00080 Use this function to get hold of the error message from the last transmission
00081 ---------------------------------------------------------------*/
00082 unsigned char USI_TWI_Get_State_Info( void )
00083 {
00084   return ( USI_TWI_state.errorState );                            // Return error state.
00085 }
00086 
00087 /*---------------------------------------------------------------
00088  USI Transmit and receive function. LSB of first byte in data
00089  indicates if a read or write cycles is performed. If set a read
00090  operation is performed.
00091 
00092  Function generates (Repeated) Start Condition, sends address and
00093  R/W, Reads/Writes Data, and verifies/sends ACK.
00094 
00095  Success or error code is returned. Error codes are defined in
00096  USI_TWI_Master.h
00097 ---------------------------------------------------------------*/
00098 
00099 //__x unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *msg, unsigned char msgSize)
00100 unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *msg, unsigned char msgSize)
00101 {
00102   unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
00103                                  (0x0<<USICNT0);                                     // set USI to shift 8 bits i.e. count 16 clock edges.
00104   unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
00105                                  (0xE<<USICNT0);                                     // set USI to shift 1 bit i.e. count 2 clock edges.
00106 
00107   USI_TWI_state.errorState = 0;
00108   USI_TWI_state.addressMode = TRUE;
00109 
00110 #ifdef PARAM_VERIFICATION
00111   if(msg > (unsigned char*)RAMEND)                 // Test if address is outside SRAM space
00112   {
00113     USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND;
00114     return (FALSE);
00115   }
00116   if(msgSize <= 1)                                 // Test if the transmission buffer is empty
00117   {
00118     USI_TWI_state.errorState = USI_TWI_NO_DATA;
00119     return (FALSE);
00120   }
00121 #endif
00122 
00123 #ifdef NOISE_TESTING                                // Test if any unexpected conditions have arrived prior to this execution.
00124   if( USISR & (1<<USISIF) )
00125   {
00126     USI_TWI_state.errorState = USI_TWI_UE_START_CON;
00127     return (FALSE);
00128   }
00129   if( USISR & (1<<USIPF) )
00130   {
00131     USI_TWI_state.errorState = USI_TWI_UE_STOP_CON;
00132     return (FALSE);
00133   }
00134   if( USISR & (1<<USIDC) )
00135   {
00136     USI_TWI_state.errorState = USI_TWI_UE_DATA_COL;
00137     return (FALSE);
00138   }
00139 #endif
00140 
00141   if ( !(*msg & (1<<TWI_READ_BIT)) )                // The LSB in the address byte determines if is a masterRead or masterWrite operation.
00142   {
00143     USI_TWI_state.masterWriteDataMode = TRUE;
00144   }
00145 
00146 /* Release SCL to ensure that (repeated) Start can be performed */
00147   PORT_USI |= (1<<PIN_USI_SCL);                     // Release SCL.
00148   while( !(PORT_USI & (1<<PIN_USI_SCL)) );          // Verify that SCL becomes high.
00149 #ifdef TWI_FAST_MODE
00150   __delay_cycles( T4_TWI );                         // Delay for T4TWI if TWI_FAST_MODE
00151 #else
00152   __delay_cycles( T2_TWI );                         // Delay for T2TWI if TWI_STANDARD_MODE
00153 #endif
00154 
00155 /* Generate Start Condition */
00156   PORT_USI &= ~(1<<PIN_USI_SDA);                    // Force SDA LOW.
00157   __delay_cycles( T4_TWI );
00158   PORT_USI &= ~(1<<PIN_USI_SCL);                    // Pull SCL LOW.
00159   PORT_USI |= (1<<PIN_USI_SDA);                     // Release SDA.
00160 
00161 #ifdef SIGNAL_VERIFY
00162   if( !(USISR & (1<<USISIF)) )
00163   {
00164     USI_TWI_state.errorState = USI_TWI_MISSING_START_CON;
00165     return (FALSE);
00166   }
00167 #endif
00168 
00169 /*Write address and Read/Write data */
00170   do
00171   {
00172     /* If masterWrite cycle (or inital address tranmission)*/
00173     if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode)
00174     {
00175       /* Write a byte */
00176       PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
00177       USIDR     = *(msg++);                        // Setup data.
00178       USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
00179 
00180       /* Clock and verify (N)ACK from slave */
00181       DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
00182       if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
00183       {
00184         if ( USI_TWI_state.addressMode )
00185           USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
00186         else
00187           USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
00188         return (FALSE);
00189       }
00190       USI_TWI_state.addressMode = FALSE;            // Only perform address transmission once.
00191     }
00192     /* Else masterRead cycle*/
00193     else
00194     {
00195       /* Read a data byte */
00196       DDR_USI   &= ~(1<<PIN_USI_SDA);               // Enable SDA as input.
00197       *(msg++)  = USI_TWI_Master_Transfer( tempUSISR_8bit );
00198 
00199       /* Prepare to generate ACK (or NACK in case of End Of Transmission) */
00200       if( msgSize == 1)                            // If transmission of last byte was performed.
00201       {
00202         USIDR = 0xFF;                              // Load NACK to confirm End Of Transmission.
00203       }
00204       else
00205       {
00206         USIDR = 0x00;                              // Load ACK. Set data register bit 7 (output for SDA) low.
00207       }
00208       USI_TWI_Master_Transfer( tempUSISR_1bit );   // Generate ACK/NACK.
00209     }
00210   }while( --msgSize) ;                             // Until all data sent/received.
00211 
00212   USI_TWI_Master_Stop();                           // Send a STOP condition on the TWI bus.
00213 
00214 /* Transmission successfully completed*/
00215   return (TRUE);
00216 }
00217 
00218 unsigned char USI_TWI_LCD_Test(void)
00219 {
00220   unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
00221                                  (0x0<<USICNT0);                                     // set USI to shift 8 bits i.e. count 16 clock edges.
00222   unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|      // Prepare register value to: Clear flags, and
00223                                  (0xE<<USICNT0);                                     // set USI to shift 1 bit i.e. count 2 clock edges.
00224 
00225   USI_TWI_state.errorState = 0;
00226   USI_TWI_state.addressMode = TRUE;
00227 
00228 /* Release SCL to ensure that (repeated) Start can be performed */
00229   PORT_USI |= (1<<PIN_USI_SCL);                     // Release SCL.
00230   while( !(PORT_USI & (1<<PIN_USI_SCL)) );          // Verify that SCL becomes high.
00231 #ifdef TWI_FAST_MODE
00232   __delay_cycles( T4_TWI );                         // Delay for T4TWI if TWI_FAST_MODE
00233 #else
00234   __delay_cycles( T2_TWI );                         // Delay for T2TWI if TWI_STANDARD_MODE
00235 #endif
00236 
00237 /* Generate Start Condition */
00238   PORT_USI &= ~(1<<PIN_USI_SDA);                    // Force SDA LOW.
00239   __delay_cycles( T4_TWI );
00240   PORT_USI &= ~(1<<PIN_USI_SCL);                    // Pull SCL LOW.
00241   PORT_USI |= (1<<PIN_USI_SDA);                     // Release SDA.
00242 
00243   // Inital address tranmission
00244   PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW
00245   USIDR     = 0x76 | (FALSE<<TWI_READ_BIT);     // Setup address + R/W bit
00246   USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
00247 
00248   // Clock and verify (N)ACK from slave
00249   DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
00250   if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
00251   {
00252     USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS;
00253     return (FALSE);
00254   }
00255 
00256   // Write control byte
00257   PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
00258   USIDR     = 0x80;                             // Setup data.
00259   USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
00260 
00261   // Clock and verify (N)ACK from slave
00262   DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
00263   if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
00264   {
00265     USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
00266     return (FALSE);
00267   }
00268 
00269   // Write data byte
00270   PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
00271   USIDR     = 0x0E;                             // displ & curs on
00272   USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
00273 
00274   // Clock and verify (N)ACK from slave
00275   DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
00276   if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
00277   {
00278     USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
00279     return (FALSE);
00280   }
00281 
00282   // Write control byte
00283   PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
00284   USIDR     = 0x00;                             // Last control byte
00285   USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
00286 
00287   // Clock and verify (N)ACK from slave
00288   DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
00289   if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
00290   {
00291     USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
00292     return (FALSE);
00293   }
00294 
00295   // Write data byte
00296   PORT_USI &= ~(1<<PIN_USI_SCL);                // Pull SCL LOW.
00297   USIDR     = 0x06;                             // addr incr & curs shift
00298   USI_TWI_Master_Transfer( tempUSISR_8bit );    // Send 8 bits on bus.
00299 
00300   // Clock and verify (N)ACK from slave
00301   DDR_USI  &= ~(1<<PIN_USI_SDA);                // Enable SDA as input.
00302   if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) )
00303   {
00304     USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA;
00305     return (FALSE);
00306   }
00307 
00308   USI_TWI_Master_Stop();                           // Send a STOP condition on the TWI bus.
00309 
00310 /* Transmission successfully completed*/
00311   return (TRUE);
00312 }
00313 
00314 
00315 /*---------------------------------------------------------------
00316  Core function for shifting data in and out from the USI.
00317  Data to be sent has to be placed into the USIDR prior to calling
00318  this function. Data read, will be return'ed from the function.
00319 ---------------------------------------------------------------*/
00320 unsigned char USI_TWI_Master_Transfer( unsigned char temp )
00321 {
00322   USISR = temp;                                     // Set USISR according to temp.
00323                                                     // Prepare clocking.
00324   temp  =  (0<<USISIE)|(0<<USIOIE)|                 // Interrupts disabled
00325            (1<<USIWM1)|(0<<USIWM0)|                 // Set USI in Two-wire mode.
00326            (1<<USICS1)|(0<<USICS0)|(1<<USICLK)|     // Software clock strobe as source.
00327            (1<<USITC);                              // Toggle Clock Port.
00328 
00329   do
00330   {
00331     __delay_cycles( T2_TWI );
00332     USICR = temp;                          // Generate positve SCL edge.
00333 
00334     while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high.
00335 
00336     __delay_cycles( T4_TWI );
00337     USICR = temp;                          // Generate negative SCL edge.
00338   }while( !(USISR & (1<<USIOIF)) );        // Check for transfer complete.
00339 
00340   __delay_cycles( T2_TWI );
00341   temp  = USIDR;                           // Read out data.
00342   USIDR = 0xFF;                            // Release SDA.
00343   DDR_USI |= (1<<PIN_USI_SDA);             // Enable SDA as output.
00344 
00345   return temp;                             // Return the data from the USIDR
00346 }
00347 
00348 /*---------------------------------------------------------------
00349  Function for generating a TWI Stop Condition. Used to release
00350  the TWI bus.
00351 ---------------------------------------------------------------*/
00352 unsigned char USI_TWI_Master_Stop( void )
00353 {
00354   PORT_USI &= ~(1<<PIN_USI_SDA);           // Pull SDA low.
00355   PORT_USI |= (1<<PIN_USI_SCL);            // Release SCL.
00356   while( !(PIN_USI & (1<<PIN_USI_SCL)) );  // Wait for SCL to go high.
00357   __delay_cycles( T4_TWI );
00358   PORT_USI |= (1<<PIN_USI_SDA);            // Release SDA.
00359   __delay_cycles( T2_TWI );
00360 
00361 #ifdef SIGNAL_VERIFY
00362   if( !(USISR & (1<<USIPF)) )
00363   {
00364     USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON;
00365     return (FALSE);
00366   }
00367 #endif
00368 
00369   return (TRUE);
00370 }

Generated on Mon Oct 10 15:25:09 2005 for AVR245: Code Lock with 4x4 Keypad and I2C(TM) LCD by  doxygen 1.4.4