关于ATMEGA32的TWI使用
前段时间使用ATMEGA32的TWI,总结如下:
unsigned char WriteRtc( unsigned char SlaAddr, unsigned char RegAddr, unsigned char *SlaData, unsigned char Length )
{
unsigned char i;
TWCR = ( 1TWINT ) | ( 1TWSTA ) | ( 1TWEN );
while( !( TWCR ( 1TWINT ) ) ); //wait for TWINT set , caused by start signal
TWDR = SlaAddr; //TWDR must be written when TWINT set
TWCR = ( 1TWINT ) | ( 1TWEN );
while( !( TWCR ( 1TWINT ) ) ); //wait for TWINT set , caused by transmit SlaAddr signal
TWDR = RegAddr; //write register address
TWCR = ( 1TWINT ) | ( 1TWEN ); //clear TWINT
while( !( TWCR ( 1TWINT ) ) ); //wait for TWINT set , caused by RegAddr signal
for( i = 0; i Length; i++ )
{
TWDR = *( SlaData+i );
TWCR = ( 1TWINT ) | ( 1TWEN );
while( !( TWCR ( 1TWINT ) ) );
}
TWCR = ( 1TWINT ) | ( 1TWEN ) | ( 1TWSTO ); // I2c stop
return(1);
}
//read RTC
unsigned char ReadRtc( unsigned char SlaAddr, unsigned char RegAddr, unsigned char *pRead, unsigned char Length )
{
unsigned char i;
TWCR = ( 1TWINT ) | ( 1TWSTA ) | ( 1TWEN ); //I2c start
while( !( TWCR ( 1TWINT ) ) ); //wait TWINT
TWDR = SlaAddr-1; //send slave address
TWCR = ( 1TWINT ) | ( 1TWEN );
while( !( TWCR ( 1TWINT ) ) );
TWDR = RegAddr; //send register of device
TWCR = ( 1TWINT ) | ( 1TWEN );
while( !( TWCR ( 1TWINT ) ) );
TWCR = ( 1TWINT ) | ( 1TWEN ) | ( 1TWSTO ); //I2c stop
DDRC = 0XFD; //set SDA as input
PORTC |= 0X02; //set pull-up resistor
TWCR = ( 1TWINT ) | ( 1TWSTA ) | ( 1TWEN ); //start I2c
while( !( TWCR ( 1TWINT ) ) ) ;
TWDR = SlaAddr;
TWCR = ( 1TWINT ) | ( 1TWEN ) ;
while( !( TWCR ( 1TWINT ) ) );
for( i = 0; i Length - 1; i++ )
{
TWCR = ( 1TWINT ) | ( 1TWEN ) | ( 1TWEA ); //send ack
while( !( TWCR ( 1TWINT ) ) );
*( pRead+i ) = TWDR;
}
TWCR = ( 1TWINT ) | ( 1TWEN ); //send nack
while( !( TWCR ( 1TWINT ) ) );
*( pRead+i ) = TWDR;
TWCR = ( 1TWINT ) | ( 1TWEN ) | ( 1TWSTO ); //I2c stop
DDRC |= 0X03;
return(1);
}
刚开始用的时候,老是读出错误的数据,最后用Beagle-GUI.抓取I2C,结果发现读I2C时,送出丛机地址和寄存器地址后就退出,原来是从机未发出ACK响应主机,因此关于ATMEGA32的TWI有几点要注意:
1. 首先,关于TWI写顺序是: I2cStart ----> WriteSlaAddr -----> WriteRegAddr ----> WriteData ----> I2cStop;
2. 其次, 关于TWI读N字节的顺序是:I2cStart ----> WriteSlaAddr ----> WriteRegAddr ----> I2cStop ----> I2cStart ---> WriteSlaAddr ----> sendAck----> receive data( (N-1) bytes ) ----->SendNACK ---->receive data ( the last byte) -----> I2cStop;
3. 最后提醒:读TWI的时候,读时的ACK是不一样的,前(N-1)个字节应该发出ACK信号响应,但是最后一个字节应该发送ACK信号。
以上的代码未加入容错机制,需要改善
- ATmega32外部中断嵌套(11-10)
- 基于OPenWrt开源系统的无线视频监控智能车设计(10-29)
- OTG技术在存储测试中的应用(09-07)
- 家用机器人设计方案汇总,包括清扫、保健、灭火等方面(05-11)
- 基于ATmega32的便携式车门压力测试仪设计(04-20)
- 一种基于双MCU的安全光幕设计方案(04-08)