嘿嘿 时间是争取出来的 先就继续整理下AVR的TWI接口吧 TWI接口跟其它单片机的IIC接口功能及应用一样 TWI数据传输过程中的规则如下:
(1)TWI完成一次操作并等待反馈时,TWINT标志置位。直到TWINT清零,
时钟线SCL才会拉低
( 2 ) 当TWINT标志置位时,用户必须用与下一个TWI总线周期相关的值更新
TWI寄存器。例如TWDR寄存器必须载入下一个总线周期中要发送的值。
(3)当所有的TWI寄存器得到更新,而且其他挂起的应用程序也已经结束,
TWCR被写入数据。当写TWCR时,TWINT位应置位,对TWINT写1清除
此标志,TWI将开始执行由TWCR设定的操作
好了代码实现如下:这是 0x80开始写入0到9,然后再从AT24C02中读入,把读取的数据发往串口。
#include < iom16v.h >
#include < macros.h >
#include " I2C.H " //调用库函数 这个库函数写在下面呢
#define uchar unsinged char
//主函数
void main ( void )
{
uchar i ;
uart_init(); /*串口初始化*/
for ( i=0;i<10;i++ )
I2C_Write ( i, 0x80+i );
delay_ms(1000);
while ( 1 )
{
for ( i=0; i<10; i++)
{
while ( ! ( UCSRA & ( 1<<UDRE ) ) ); /*等待接受准备好 即是数据寄存器为空?*/
delay_ms ( 10 ) ;
UDR=I2C_Read ( 0x80+i ) ;
}
}
}
for ( i=0;i<10;i++ )
I2C_Write ( i, 0x80+i );
delay_ms(1000);
while ( 1 )
{
for ( i=0; i<10; i++)
{
while ( ! ( UCSRA & ( 1<<UDRE ) ) ); /*等待接受准备好 即是数据寄存器为空?*/
delay_ms ( 10 ) ;
UDR=I2C_Read ( 0x80+i ) ;
}
}
}
//下面是主函数中调用的库函数
#ifndef I2C_H
#define I2C_H
#define I2C_H
#include < iom16v.h >
/****************************
I2C 状态定义
MT 主方式传输 MR 主方式接受
***************************/
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
I2C 状态定义
MT 主方式传输 MR 主方式接受
***************************/
#define START 0x08
#define RE_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NOACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NOACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
#define MR_SLA_NOACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NOACK 0x58
#define RD_DEVICE_ADDR 0xA1 /*前4位器件固定,后三位看连线,最后1位是读写指
令位*/
#define WD_DEVICE_ADDR 0xA0
#define WD_DEVICE_ADDR 0xA0
/*常用TWI操作(主模式写和读)*/
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) //启动I2C
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) //停止I2C
#define Wait() {while(!(TWCR&(1<<TWINT)));} //等待中断发生
#define TestAck() (TWSR&0xf8) //观察返回状态
#define SetAck (TWCR|=(1<<TWEA)) //做出ACK应答
#define SetNoAck (TWCR&=~(1<<TWEA)) //做出Not Ack应答
#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN)) //启动I2C
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} //写数据到TWDR
#define Start() (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)) //启动I2C
#define Stop() (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN)) //停止I2C
#define Wait() {while(!(TWCR&(1<<TWINT)));} //等待中断发生
#define TestAck() (TWSR&0xf8) //观察返回状态
#define SetAck (TWCR|=(1<<TWEA)) //做出ACK应答
#define SetNoAck (TWCR&=~(1<<TWEA)) //做出Not Ack应答
#define Twi() (TWCR=(1<<TWINT)|(1<<TWEN)) //启动I2C
#define Write8Bit(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} //写数据到TWDR
/*延时子程序*/
void delay_ms(int time)
{
int i;
for ( ;time>0;time-- )
for ( i=0;i<1000;i++ ) ;
}
void delay_ms(int time)
{
int i;
for ( ;time>0;time-- )
for ( i=0;i<1000;i++ ) ;
}
/*串口初始化*/
void uart_init()
{
UCSRA=0x02; //异步正常模式 即倍速模式
UCSRB=0x18; //允许发送接受中断和使能
UCSRC=0x06; //8位数据
UBRRH=0x00;
UBRRL=12; //波特率位9600
}
void uart_init()
{
UCSRA=0x02; //异步正常模式 即倍速模式
UCSRB=0x18; //允许发送接受中断和使能
UCSRC=0x06; //8位数据
UBRRH=0x00;
UBRRL=12; //波特率位9600
}
/*********************************************
I2C总线写一个字节
返回0:写成功
返回1:写失败
**********************************************/
unsigned char I2C_Write(unsigned char Wdata,unsigned char RegAddress)
{
Start(); //I2C启动
Wait();
if(TestAck()!=START)
return 1; //ACK
Write8Bit(WD_DEVICE_ADDR); //写I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK)
return 1; //ACK
Write8Bit(RegAddress); //写器件相应寄存器地址
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1; //ACK
Write8Bit(Wdata); //写数据到器件相应寄存器
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1; //ACK
Stop(); //I2C停止
delay_ms(100); //延时
return 0;
}
I2C总线写一个字节
返回0:写成功
返回1:写失败
**********************************************/
unsigned char I2C_Write(unsigned char Wdata,unsigned char RegAddress)
{
Start(); //I2C启动
Wait();
if(TestAck()!=START)
return 1; //ACK
Write8Bit(WD_DEVICE_ADDR); //写I2C从器件地址和写方式
Wait();
if(TestAck()!=MT_SLA_ACK)
return 1; //ACK
Write8Bit(RegAddress); //写器件相应寄存器地址
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1; //ACK
Write8Bit(Wdata); //写数据到器件相应寄存器
Wait();
if(TestAck()!=MT_DATA_ACK)
return 1; //ACK
Stop(); //I2C停止
delay_ms(100); //延时
return 0;
}
/*********************************************
I2C总线读一个字节
返回0:读成功
返回1:读失败
**********************************************/
unsigned char I2C_Read(unsigned RegAddress)
{
unsigned char temp;
Start();//I2C启动
Wait();
if (TestAck()!=START)
return 1; //ACK
Write8Bit(WD_DEVICE_ADDR); //写I2C从器件地址和写方式
Wait();
if (TestAck()!=MT_SLA_ACK)
return 1; //ACK
Write8Bit(RegAddress); //写器件相应寄存器地址
Wait();
if (TestAck()!=MT_DATA_ACK)
return 1;
Start(); //I2C重新启动
Wait();
if (TestAck()!=RE_START)
return 1;
Write8Bit(RD_DEVICE_ADDR); //写I2C从器件地址和读方式
Wait();
if(TestAck()!=MR_SLA_ACK)
return 1; //ACK
Twi(); //启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK)
return 1; //ACK
temp=TWDR; //读取I2C接收数据
Stop(); //I2C停止
return temp;
}
I2C总线读一个字节
返回0:读成功
返回1:读失败
**********************************************/
unsigned char I2C_Read(unsigned RegAddress)
{
unsigned char temp;
Start();//I2C启动
Wait();
if (TestAck()!=START)
return 1; //ACK
Write8Bit(WD_DEVICE_ADDR); //写I2C从器件地址和写方式
Wait();
if (TestAck()!=MT_SLA_ACK)
return 1; //ACK
Write8Bit(RegAddress); //写器件相应寄存器地址
Wait();
if (TestAck()!=MT_DATA_ACK)
return 1;
Start(); //I2C重新启动
Wait();
if (TestAck()!=RE_START)
return 1;
Write8Bit(RD_DEVICE_ADDR); //写I2C从器件地址和读方式
Wait();
if(TestAck()!=MR_SLA_ACK)
return 1; //ACK
Twi(); //启动主I2C读方式
Wait();
if(TestAck()!=MR_DATA_NOACK)
return 1; //ACK
temp=TWDR; //读取I2C接收数据
Stop(); //I2C停止
return temp;
}
转载于:https://blog.51cto.com/lengyiyun/197765