|
一段小程序,没用仿真器,费了很大力气才除去所有BUG。 希望今后大家多交流,让我们这些做程序的人日子过得舒服些。 ////////////////////////////////////////////////////////////////////////// // AT24C64 support functions using ATMEGA's TWI // pin-WP is hard-wired to GND // fuctions work better outside interrupt routines // by MXH, 2003/07/30
#include "DStruct.h" #include <avr/twi.h>
// CONSTANTS DEFINITION FOR EEPROM #define EEADDR 0 #define EEWR 0 #define EERD 1 // TWINT *NOT* set after STOP condition is sent // check status? // TWSTO is cleared by hardware #define TwiStop() TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO) #define TwiStart() TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA) #define TWI_STATUS (TWSR & 0xF8)
BYTE byEEWait;
////////////////////////////////////////////////////////////////////////// // implementation
BOOL EEPStart(BYTE addr, BOOL bWrite) { byEEWait = 10; // 90~100ms poll_ack: TwiStart(); while (!(TWCR & (1<<TWINT))){ // wait if ( byEEWait == 0 ){ return FALSE; } } if ((TWI_STATUS != TW_START)&&(TWI_STATUS != TW_REP_START)) goto poll_ack; //byEEWait = 3; // 20~30ms // send SLA+R/W TWDR = addr | bWrite; TWCR = (1<<TWINT)|(1<<TWEN); while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ){ TwiStop(); return FALSE; } } if( EEWR == bWrite ){ // MT mode //if(TWI_STATUS != TW_MT_SLA_ACK) switch(TWI_STATUS){ case TW_MT_SLA_ACK: break; case TW_MT_SLA_NACK: goto poll_ack; default: TwiStop(); return FALSE; } }else{ // MR mode if(TWI_STATUS != TW_MR_SLA_ACK) return FALSE; } return TRUE; }
////////////////////////////////////////////////////////////////////// // BYTE EEPWrite( WORD uiAddress, WORD uiLen, void *pBuf ) //using 0 { unsigned int i,j,uiCnt; if( uiLen == 0 ) return 0; uiCnt = 0; // uiEnd = uiAddress + uiLen; i = uiAddress; do{ if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in return 0; } TWDR = (BYTE)((i>>8)&0x00ff); // MSB of address TWCR = (1<<TWINT)|(1<<TWEN); byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } if(TWI_STATUS != TW_MT_DATA_ACK){ return FALSE; } TWDR = (BYTE)(i&0x00ff); // LSB of address TWCR = (1<<TWINT)|(1<<TWEN); byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } if(TWI_STATUS != TW_MT_DATA_ACK) return FALSE; // write data for( j=0; j<32; j++ ){ TWDR = ((BYTE*)pBuf)[uiCnt]; TWCR = (1<<TWINT)|(1<<TWEN); byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } if(TWI_STATUS != TW_MT_DATA_ACK){ return FALSE; } i++; uiCnt++; if(( 0 == i%32 )||( uiCnt == uiLen )){ TwiStop(); break; } } }while( uiCnt < uiLen ); // while( !PollAck()); return 1; }
////////////////////////////////////////////////////////////////////// // BYTE EEPRead( WORD uiAddress, WORD uiLen, void *pBuf ) { UINT i; if ( uiLen == 0 ) return 0; if(!EEPStart(0xA0|EEADDR,EEWR)){ //PollAck() is built-in return 0; //↑ } // not RD but write device address to the chip TWDR = (BYTE)(( uiAddress >> 8) & 0x00ff ); //((BYTE*)(&uiAddress))[1]; // MSB of address TWCR = (1<<TWINT)|(1<<TWEN); byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } if (TWI_STATUS != TW_MT_DATA_ACK) return FALSE; TWDR = (BYTE)( uiAddress & 0x00ff ); //((BYTE*)(&uiAddress))[0]; // LSB of address TWCR = (1<<TWINT)|(1<<TWEN); byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } if (TWI_STATUS != TW_MT_DATA_ACK) return FALSE; if(!EEPStart(0xA0+EEADDR,EERD)){ //PollAck()){ return 0; //↑ }// ??? how to read? for ( i=0; i<uiLen-1; i++ ){ TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWEA); byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } if (TWI_STATUS != TW_MR_DATA_ACK) return FALSE; ((BYTE*)pBuf)[i] = TWDR; // EEInByte(); } TWCR = _BV(TWINT) | _BV(TWEN); // send NACK to indicate final byte byEEWait = 3; // 20~30ms while (!(TWCR & (1<<TWINT))){ if( byEEWait == 0 ) return FALSE; } //if (TWI_STATUS != TW_MR_DATA_ACK) // return FALSE; ((BYTE*)pBuf)[i] = TWDR; TwiStop(); return 1; }
|