|
我前几天发表了一个贴子,是关于ATMEGA的TWI编程的。
现在转贴一下21icc上mxh0506发表的贴子。我调试了一下,没有错误。
我就基本按照他的程序写的,贴出来与大家共享。
非常感谢mxh0506。支持阿莫。
// 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) = 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) = TWDR;
TwiStop();
return 1;
} |
|