Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
Spencer Lee
03/11/11 05:05
Modified:
  03/11/11 05:36

Read: 866 times


 
#181544 - Smb Reading a two byte address
Hi I would like to perform a random read with a EEprom. A 16 bit address is written then a repeat start is issued this updates the pointer in the eeprom and allow the new memory location to be read.

The problem is the memory pointer is not being updated in the eprom, the data read back is the last position written to
the processor is the c8051f042.

For a random read my status register contains:
08 Start condition transmitted( control)
18 slave address ack recieve( low byte)
28 data byte (High address byte)
28 issue a repeat start
10 repeat start transmit
40 slave address transmitted wait for recive data
58 data byte recieved

I look at the data being sent, it'as all there. Which leads me to believe its a timing issue.

What di I miss

thanks




...insert code here[
///-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// SMBus Interrupt Service Routine (ISR)
//-----------------------------------------------------------------------------
//
// SMBus ISR state machine
// - Master only implementation - no slave states defined
// - All incoming data is written starting at the global pointer <pSMB_DATA_IN>
// - All outgoing data is read from the global pointer <pSMB_DATA_OUT>
//
void SMBUS_ISR (void) interrupt 7
{

   int xdata  itemp = 0xFFFF; 
   int xdata  ifoo;	
   
   static bit lo_hiByteFlag = 0;
   
   bit FAIL = 0;                       // Used by the ISR to flag failed
                                       // transfers

   static char  xdata ByteCnt;                      // Used by the ISR to count the
                                       // number of data bytes sent or
                                       // received

   static bit SEND_START = 0;          // Send a start
   static bit addrLowSendFlag = 0;     // Has the low byte Been sent?	 					   // = 1 sent hi Addr byte; =0  Low addr sent
   
   smb[smbcnt] = SMB0STA;
   smbcnt++;
      // Status code for the SMBus (SMB0STA register)
   switch (SMB0STA)
   {
      // Master Transmitter/Receiver: START condition transmitted.
      // Load SMB0DAT with slave device (EEPROM) address.
      case SMB_START_08:

         SMB0DAT = EPROM_DEVICE_ID;             // Load address of the slave.
         SMB0DAT &= 0xFE;              // Clear the LSB of the address for the
                                       // R/W bit
         SMB0DAT |= SMB_RW;            // Load R/W bit
       	 STA = 0;                      // Manually clear STA bit
         ByteCnt = 0;                  // reset data byte counter

         break;

      // Master Transmitter/Receiver: Repeated START condition transmitted.
      // For a READ: This state only occurs during an EEPROM read operation
      //  for the EEPROM's "random read", where a write operation with the
      //  data address must be done before the read operation.
      //
      // For a WRITE: N/A
      case SMB_RP_START_10:
	  	 lo_hiByteFlag = 0; 
         SMB0DAT = EPROM_DEVICE_ID;
		 SMB0DAT &= 0xFE;    			// Load address of the slave.
         SMB0DAT |= SMB_RW;            	// Load R/W bit
         STA = 0; 
		 STO = 0;                     	// Manually clear START bit.
         ByteCnt = 0;                        	// reset data byte counter
									   	
         break;

  	// Master Transmitter: Slave address + WRITE transmitted.  ACK received.
  	// For a READ or WRITE: the word (data) address in the EEPROM must now
  	// be sent after the slave address
  	// slave
	case SMB_MTADDACK_18:
 	     SMB0DAT = CHAR_ADDR_HIGH;
	     addrLowSendFlag = 1;
	 break;

///------------------------TRANSMIT ROUTINES -------------------------------------///

///-------------------------------------------------------------------------------///

 
	  
      // Master Transmitter: Slave address + WRITE transmitted.  NACK received.
      // If the EEPROM should be polled, restart the transfer.
      // Otherwise, reset the SMBus
      case SMB_MTADDNACK_20:
         if(SMB_ACKPOLL)
         {
            STA = 1;                   // Restart transfer
         }
         else
         {
            FAIL = 1;                  // Indicate failed transfer
         }                             // and handle at end of ISR

         break;



      // Master Transmitter: Data byte transmitted.  ACK received.
      // For a READ: the word address has been trasmitted, and a repeated
      //  start should be generated.
      //
	  case SMB_MTDB_ACK_28:

         // Has the Addr Hi byte been sent, if Yes, send the low address byte, Flag it
	if (addrLowSendFlag)
	{
	   SMB0DAT = CHAR_ADDR_LOW;
	   addrLowSendFlag = 0;
	}
	 else
	{
	     if (SMB_RANDOMREAD)
	     {
 		STA = 1;
		STO = 0;
		SMB_RW = READ;
		AA = 1;
		break;
	     } 
	     else  // Is this transfer a WRITE?
	     {
		if (SMB_RW == WRITE)            
		{
		   // Is there data to send?
		   if (ByteCnt < SMB_DATA_LEN)      
		   {
			SMB0DAT = SMB_SINGLEBYTE_OUT; 
			ByteCnt++;
	            }
		   else
		   {
		         STA = 0;
			AA = 0;
			STO = 1;                 // Set STO to terminte transfer
			SMB_BUSY = 0;            // Clear software busy flag
		   }
		}
		else {}                          // If this transfer is a READ, then take no action, as a

                                                                                        repeated            }                              // start will be generated for the read operation
	
	}
         break;

      // Master Transmitter: Data byte transmitted.  NACK received.
      // If the EEPROM should be polled, restart the transfer.
      // Otherwise, reset the SMBus
      case SMB_MTDB_NACK_30:
         if(SMB_ACKPOLL)
         {
            STA = 1;                   // Restart transfer
         }
         else
         {
            FAIL = 1;                  // Indicate failed transfer
         }                             // and handle at end of ISR

         break;

      // Master Transmitter: Arbitration lost.
      case SMB_MTARBLOST_38:

         FAIL = 1;                     // Indicate failed transfer
                                       // and handle at end of ISR

         break;

///------------------------ RECEIVE ROUTINE --------------------------------------///

///-------------------------------------------------------------------------------///




      // Master Receiver: Slave address + READ transmitted.  ACK received.
      // For a READ: check if this is a one-byte transfer. if so, set the
      //  NACK after the data byte is received to end the transfer. if not,
      //  set the ACK and receive the other data bytes.
      //
      // For a WRITE: N/A
      case SMB_MRADDACK_40:
         if (ByteCnt == SMB_DATA_LEN)
		 {
            AA = 0;                    // send NACK after byte is received
         }
         else
         {
            AA = 1;                    // More than one byte in this transfer,
                                       // send ACK after byte is received
         }
         break;

		

      // Master Receiver: Slave address + READ transmitted.  NACK received.
      // If the EEPROM should be polled, restart the transfer.
      // Otherwise, reset the SMBus
      case SMB_MRADDNACK_48:
         if(SMB_ACKPOLL)
         {
            STA = 1;                   // Restart transfer
         }
         else
         {
            FAIL = 1;                  // Indicate failed transfer
         }                             // and handle at end of ISR

         break;

      // Master Receiver: Data byte received.  ACK transmitted.
      // For a READ: receive each byte from the EEPROM.  if this is the last
      //  byte, send a NACK and set the STOP bit.
      //
      // For a WRITE: N/AGA
      case SMB_MRDBACK_50:
		 
	if (ByteCnt < SMB_DATA_LEN)
	{
            *pSMB_DATA_IN = SMB0DAT;   // Store received byte
        	    ByteCnt++;                       // Increment number of bytes received
			
	     if (ByteCnt == SMB_DATA_LEN)	
              {
                 SMB_BUSY = 0;              // Free SMBus interface
            	AA = 0;                    // Send NACK to indicate last byte of this transfer
           	 	STO = 1;                   // Send STOP to terminate transfer
              }	
	     else
	     {
		AA = 1;                     // Send ACK (may be cleared later  in the code)
          	STO = 0; 
              }
	}
       break;

     
      // Master Receiver: Data byte received.  NACK transmitted.
      // Read operation has completed.  Read data register and send STOP.
      case SMB_MRDBNACK_58:
       	  // Read_Array   
	  // ==1 reading Epprom Read Array 
		 
	
	 *pSMB_DATA_IN = SMB0DAT;   // Store received byte
           STO = 1;
	  SMB_BUSY = 0;
	  AA = 1;                       // Set AA for next transfer
	  
      break;
      // All other status codes invalid.  Reset communication.
      default:
         FAIL = 1;

         break;
   }

   if (FAIL)                           // If the transfer failed,
   {
      SMB0CN &= ~0x40;                 // Reset communication
      SMB0CN |= 0x40;
      STA = 0;
      STO = 0;
      AA = 0;

      SMB_BUSY = 0;                    // Free SMBus

      FAIL = 0;
   }

   SI = 0;                             // Clear interrupt flag
   }
]


List of 2 messages in thread
TopicAuthorDate
Smb Reading a two byte address      Spencer Lee      03/11/11 05:05      
   Duplicate thread      Andy Neil      03/11/11 07:14      

Back to Subject List