Beispiel #1
0
__interrupt void USI_TXRX (void)
{
  if (USICTL1 & USISTTIFG)                  // Start entry?
  {
    P1OUT |= 0x01;                          // LED on: sequence start
    I2C_State = 2;                          // Enter 1st state on start
  }

  switch(__even_in_range(I2C_State,14))
    {
      case 0:                               // Idle, should not get here
              break;

      case 2: // RX Address
              USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX address
              USICTL1 &= ~USISTTIFG;        // Clear start flag
              I2C_State = 4;                // Go to next state: check address
              break;

      case 4: // Process Address and send (N)Ack
              if (USISRL & 0x01){            // If master read...
                SLV_Addr = 0x91;             // Save R/W bit
                transmit = 1;}
              else{transmit = 0;
                  SLV_Addr = 0x90;}
              USICTL0 |= USIOE;             // SDA = output
              if (USISRL == SLV_Addr)       // Address match?
              {
                USISRL = 0x00;              // Send Ack
                P1OUT &= ~0x01;             // LED off
                if (transmit == 0){ 
                  I2C_State = 6;}           // Go to next state: RX data
                if (transmit == 1){  
                  I2C_State = 10;}          // Else go to next state: TX data
              }
              else
              {
                USISRL = 0xFF;              // Send NAck
                P1OUT |= 0x01;              // LED on: error
                I2C_State = 8;              // next state: prep for next Start
              }
              USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
              break;

    case 6: // Receive data byte
              Data_RX();
              break;  

      case 8:// Check Data & TX (N)Ack
              USICTL0 |= USIOE;             // SDA = output
              if (Bytecount <= (Number_of_Bytes-2))          
                                            // If not last byte
              {
                USISRL = 0x00;              // Send Ack
                I2C_State = 6;              // Rcv another byte
                Bytecount++;
                USICNT |= 0x01;             // Bit counter = 1, send (N)Ack bit
              }
              else                          // Last Byte
              {
                USISRL = 0xFF;              // Send NAck
              USICTL0 &= ~USIOE;            // SDA = input
              SLV_Addr = 0x90;              // Reset slave address
              I2C_State = 0;                // Reset state machine
              Bytecount =0;                 // Reset counter for next TX/RX
              }
              
              
              break;

     case 10: // Send Data byte
              TX_Data();
              break;

      case 12:// Receive Data (N)Ack
              USICTL0 &= ~USIOE;            // SDA = input
              USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack
              I2C_State = 14;               // Go to next state: check (N)Ack
              break;

      case 14:// Process Data Ack/NAck
           if (USISRL & 0x01)               // If Nack received...
              {
              USICTL0 &= ~USIOE;            // SDA = input
              SLV_Addr = 0x90;              // Reset slave address
              I2C_State = 0;                // Reset state machine
               Bytecount = 0;
             // LPM0_EXIT;                  // Exit active for next transfer
              }
              else                          // Ack received
              {
                P1OUT &= ~0x01;             // LED off
                TX_Data();                  // TX next byte
               }
	       break;
    
      }
  USICTL1 &= ~USIIFG;                       // Clear pending flags
}
Beispiel #2
0
__interrupt void USI_TXRX (void){


	switch(I2C_State){
		case 0: // Generate Start Condition & send address to slave
			Bytecount = 0;
			USISRL = 0x00;                // Generate Start Condition...
			USICTL0 |= USIGE+USIOE;
			USICTL0 &= ~USIGE;
			USISRL = slave_i2c_address;		// Send slave address + write first!
			USICNT = 8;
			// USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address
			I2C_State = 2;              	  // next state: rcv address (N)Ack
			break;

		case 2: // Receive Address Ack/Nack bit
			USICTL0 &= ~USIOE;            // SDA = input
			USICNT |= 0x01;               // Bit counter=1, receive (N)Ack bit
			I2C_State = 4;                // Go to next state: check (N)Ack
			break;

		case 4: // Process Address Ack/Nack & handle data TX

			if (USISRL & 0x01)            // If Nack received...
			{ // Send stop...
				USICTL0 |= USIOE;             // SDA = output
				USISRL = 0x00;
				USICNT |=  0x01;            // Bit counter=1, SCL high, SDA low
				I2C_State = 14;             // Go to next state: generate Stop
			}
			else
			{ // Ack received, TX adress to slave...
				if (slave_address_sent == 1){
					// Now, the slave will start sending data.
					// This should really only happen if
					// transmit == 0..
					Data_RX();
				} else{
					// Send the slave address across.
					USICTL0 |= USIOE;             // SDA = output
					USISRL = curr_reg_address;            // Load data byte
					USICNT |=  0x08;              // Bit counter = 8, start TX
					Bytecount++;
					I2C_State = 10;               // next state: receive data (N)Ac
				}


			}
			break;

		case 5: // Generate repeated start condition

			USISRL = 0x00;                // While clock is high, force SDA low.
			USICTL0 |= USIGE+USIOE;
			USICTL0 &= ~USIGE;

			USICTL0 |= USIOE;	// make sure that the output is enabled.

			// Now send slave address.
			USISRL = slave_i2c_address + 1;		// Send slave address + read.
			USICNT =  8; // Bit counter = 8, TX Address

			slave_address_sent = 1; // Set flag, so that data is sent in state 4.
			I2C_State = 2;              	  // next state: rcv address (N)Ack

			break;

		case 6: // Send Data Ack/Nack bit
			USICTL0 |= USIOE;             // SDA = output
			curr_output = USISRL;		// grab output


			if (Bytecount <= number_of_bytes-2)
			{                             // If this is not the last byte
				USISRL = 0x00;              // Send Ack
				I2C_State = 4;              // Go to next state: data/rcv again
				Bytecount++;
			}

			else //last byte: send NACK
			{
				USISRL = 0xFF;              // Send NAck
				I2C_State = 8;              // stop condition
			}

			USICNT |= 0x01;               // Bit counter = 1, send (N)Ack bit
			break;

		case 8: // Prep Stop Condition
			USICTL0 |= USIOE;             // SDA = output
			USISRL = 0x00;
			USICNT |=  0x01;              // Bit counter= 1, SCL high, SDA low
			I2C_State = 14;               // Go to next state: generate Stop
			break;

		case 10: // Receive Data Ack/Nack bit
			USICTL0 &= ~USIOE;            // SDA = input
			USICNT |= 0x01;               // Bit counter = 1, receive (N)Ack bit
			I2C_State = 12;               // Go to next state: check (N)Ack
			break;

		case 12: // Process Data Ack/Nack & send Stop
			USICTL0 |= USIOE;

			if (Transmit == 1){
				if (Bytecount == number_of_bytes){// If last byte
					USISRL = 0x00;
					I2C_State = 14;               // Go to next state: generate Stop
					USICNT |=  0x01;             // set count=1 to trigger next state
					Bytecount++;
				}else{
					Data_TX();                  // TX byte
				}
			} else {
				// prepare a repeated start transmission.

				USICTL0 |= USIOE;
				USISRL = 0xFF;
				USICNT = 1;

				I2C_State = 5;
			}

			break;

		case 14:// Generate Stop Condition
			USISRL = 0x0FF;               // USISRL = 1 to release SDA
			USICTL0 |= USIGE;             // Transparent latch enabled
			USICTL0 &= ~(USIGE+USIOE);    // Latch/SDA output disabled
			I2C_State = 0;                // Reset state machine for next xmt
			slave_address_sent = 0;		// Reset flag
			LPM0_EXIT;                    // Exit active for next transfer
			break;
		}

  USICTL1 &= ~USIIFG;                       // Clear pending flag
}