//0900-AT24C02.c
//IIC硬件读写实验
//akuei2 11-01-10
#define BIT(X) (1<<X)
#include <avr/io.h>
#define F_CPU 12000000UL
#include <util/delay.h>
#include "LED7.h"
//主模式启动状态
#define IIC_START 0x08 //启动总线
#define IIC_RESTART 0x10 //再启动总线
//主发送模式各种状态
#define MT_SLA_ACK 0x18 //SLA_W写地址已发送,收到应答位
#define MT_SLA_NACK 0x20 //SLA_W写地址已发送,收到非应答位
#define MT_DATA_ACK 0x28 //写入数据已发送,收到应答位
#define MT_DATA_NACK 0x30 //写入数据已发送,收到非应答位
#define MT_ARB_LOST 0x38 //SLA_W或数据仲裁失败
//主接收模式各种状态
#define MR_ARB_LOST 0x38 //SLA_W或数据仲裁失败
#define MR_SLA_ACK 0x40 //SLA_R已发送,收到应答位
#define MR_SLA_NACK 0x48 //SLA_R已发送,收到非应答位
#define MR_DATA_ACK 0x50 //接收到数据,应答位已返回
#define MR_DATA_NACK 0x58 //接收到数据,非应答位已返回
//IIC操作
#define IIC_Start() (TWCR=BIT(TWINT)|BIT(TWSTA)|BIT(TWEN))
#define IIC_Stop() (TWCR=BIT(TWINT)|BIT(TWSTO)|BIT(TWEN))
#define IIC_STATUS (TWSR & 0xf8) //屏蔽低3位,bit2空,1,0比特率预分频
#define IIC_Send() (TWCR=BIT(TWINT)|BIT(TWEN)) //数据放入TWDR,启动发送
#define IIC_SendAck() (TWCR|=BIT(TWEA)) //使能TWI应答:地址匹配和收到数据时及从机收到广播时发出ACK
#define IIC_SendNoAck() (TWCR&=~BIT(TWEA)) //关闭TWI应答
#define IIC_ReadNoAck() (TWCR=BIT(TWINT)|BIT(TWEN))
#define IIC_ReadAck() (TWCR=BIT(TWINT)|BIT(TWEN)|BIT(TWEA))
#define IIC_Wait() while(!( TWCR & BIT(TWINT)))
//IIC配置
#define HARDADD 0xA0 //AT24C02的硬件地址
//IIC写函数
//硬件地址,写页地址,数据
void IIC_Write(unsigned char HardAdd,unsigned char PageAdd,unsigned char Data)
{
unsigned char Error_Flag=0; //声明并且初始化错误标志
while(!Error_Flag) //写入过程是否有错误?有:重新一次
{
//起始信号
IIC_Start(); //起始, TWINT=1,TWEN=1,TWSTA=1
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=IIC_START) Error_Flag=1; //查询TWSR,是否起始错误
//写硬件地址 SLA+W
HardAdd&=0xfe; //xxxx xxx0,AT24c02A:1010 xxx0;bit(0)1为读,0为写
TWDR=HardAdd; //将要访问硬件地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_SLA_ACK) Error_Flag=1; //查询TWSR,是否写地址无应答
//写页地址
TWDR=PageAdd; //将要写入页地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_DATA_ACK) Error_Flag=1; //查询TWSR,是否写数据无应答
//写数据
TWDR=Data; //将数据写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_DATA_ACK) Error_Flag=1; //查询TWSR,是否写数据无应答
}
IIC_Stop(); //终止信号 TWINT=1,TWSTO=1,TWEN=1
}
//IIC N次写函数
//硬件地址,写页地址, 数组指针,N次
void IIC_N_Write(unsigned char HardAdd,unsigned char PageAdd,unsigned char *pTable,unsigned char N)
{
unsigned char Error_Flag=0,i; //声明并且初始化错误标志
while(!Error_Flag) //写入N次过程是否有错误?有:重新一次
{
Error_Flag=0; //错误标志清零
//起始信号
IIC_Start(); //起始, TWINT=1,TWEN=1,TWSTA=1
IIC_Wait(); //等待 TWINT==1;
//TWCR&=~BIT(TWSTA);
if(IIC_STATUS!=IIC_START) Error_Flag=1; //查询TWSR,是否起始错误
//写硬件地址 SLA+W
HardAdd&=0xfe; //xxxx xxx0,AT24c02A:1010 xxx0
TWDR=HardAdd; //将要访问硬件地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1 ;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_SLA_ACK) Error_Flag=1; //查询TWSR,是否写地址无应答
//写页地址
TWDR=PageAdd; //将要写入的页地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_DATA_ACK) Error_Flag=1; //查询TWSR,是否写数据无应答
//写N数据
for(i=0;i<N;i++)
{
TWDR=pTable[i]; //将数据一一写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_DATA_ACK) Error_Flag=1; //查询TWSR,是否写数据无应答
}
}
IIC_Stop(); //终止信号 TWINT=1,TWSTO=1,TWEN=1
}
//IIC读函数
//硬件地址,写页地址?
//返回读取数据
unsigned char IIC_Read(unsigned char HardAdd,unsigned char PageAdd)
{
unsigned char Temp,Error_Flag=0; //声明并且初始化错误标志
while(!Error_Flag) //读过程是否有错误?有:重新一次
{
Error_Flag=0; //错误标志清零
//起始信号
IIC_Start(); //起始, TWINT=1,TWEN=1,TWSTA=1
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=IIC_START) Error_Flag=1; //查询TWSR,是否起始错误
//写硬件地址 SLA+W
HardAdd&=0xfe; //xxxx xxx0,AT24c02A:1010 xxx0
TWDR=HardAdd; //将要访问硬件地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_SLA_ACK) Error_Flag=1; //查询TWSR,是否写地址无应答
//写页地址
TWDR=PageAdd; //将要读取页地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1?
if(IIC_STATUS!=MT_DATA_ACK) Error_Flag=1; //查询TWSR,是否写数据无应答
//再一次起始信号,改变方向(写-读)
IIC_Start(); //IIC发送, TWINT=1,TWEN=1,TWSTA=1;
IIC_Wait(); //等待 TWINT==1?
if(IIC_STATUS!=IIC_RESTART) Error_Flag=1; //查询TWSR,是否再起始错误
//写硬件地址,这一回是读取 SLA+R
HardAdd|=0x01; //xxxx xxx1, AT24c02A: 1010 xxx1
TWDR=HardAdd; //将要访问硬件地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MR_SLA_ACK) Error_Flag=1; //查询TWSR,是否写地址无应答
//无应答,接收数据
IIC_ReadNoAck(); //无应答接收,TWINT=1,TWEN=1
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MR_DATA_NACK) Error_Flag=1; //查询TWSR,是否读数据无视应答错误
}
Temp=TWDR; //从数据寄存器读取数据
IIC_Stop(); //终止信号
return Temp; //返回数据
}
//IIC N读函数
//硬件地址,写页地址,数组指针,N次?
void IIC_N_Read(unsigned char HardAdd,unsigned char PageAdd,unsigned char *pTable,unsigned char N)
{
unsigned char Error_Flag=0,i; //声明并且初始化错误标志
while(!Error_Flag)
{
Error_Flag=0; //错误标志清零
//起始信号
IIC_Start(); //IIC发送, TWINT=1,TWEN=1,TWSTA=1;
IIC_Wait(); //等待 TWINT==1;
//TWCR&=~BIT(TWSTA);
if(IIC_STATUS!=IIC_START) Error_Flag=1; //查询TWSR,是否起始错误
//写硬件地址 SLA+W
HardAdd&=0xfe; //xxxx xxx0,AT24c02A:1010 xxx0
TWDR=HardAdd; //将要访问硬件地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_SLA_ACK) Error_Flag=1; //查询TWSR,是否写地址无应答
//写页地址
TWDR=PageAdd; //将要读取页地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MT_DATA_ACK) Error_Flag=1; //查询TWSR,是否写数据无应答
//再启动起始信号
IIC_Start(); //TWINT=1,TWEN=1,TWSTA=1;
IIC_Wait(); //等待 TWINT==1;
//TWCR&=~BIT(TWSTA);
if(IIC_STATUS!=IIC_RESTART) Error_Flag=1; //查询TWSR,是否再起始有误
//写硬件地址,这一回是读取 SLA+R
HardAdd|=0x01; //xxxx xxx1, AT24c02A: 1010 xxx1
TWDR=HardAdd; //将要访问硬件地址写入数据寄存器
IIC_Send(); //IIC发送, TWINT=1,TWEN=1;
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MR_SLA_ACK) Error_Flag=1; //查询TWSR,是否写地址无应答
//N次读取
//前N次读取为响应应答
for(i=0;i<N-1;i++)
{
IIC_ReadAck(); //TWINT=1,TWEN=1,TWEA=1
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MR_DATA_ACK) Error_Flag=1; //查询TWSR,是否读数据响应应答错误
pTable[i]=TWDR; //从数据寄存器读入数组
}
//最后N次读取为不响应应答
IIC_ReadNoAck(); //TWINT=1,TWEN=1
IIC_Wait(); //等待 TWINT==1;
if(IIC_STATUS!=MR_DATA_NACK) Error_Flag=1; //查询TWSR,是否读数据无响应应答错误
pTable[i]=TWDR; //从数据寄存器读入数组
}
IIC_Stop(); //终止信号
}
//IIC初始化函数
void IIC_Init()
{
TWBR=12; //晶振为11.0592Mhz,99kHz的波特率
TWSR=0; //无预分频
TWCR=0x84; //TWINT位清零,TWWC位清零
}
//主函数
void main()
{
unsigned char Temp1;
unsigned char Table1[]={0x05,0x02,0x03}; //N次写入数组
unsigned char Table2[]={0x00,0x00,0x00}; //N次读取数组
LED7_Init(); //数码管初始化
IIC_Init(); //IIC初始化
//一次写入和读取 AT24C02
//IIC_Write(HARDADD,1,0x05); //硬件地址为 0xA0,选择第1页,写入数据0x05 ?
// Delay(1000); //适当的延迟很重要,不让访问AT24C02会无效
//Temp1=IIC_Read(HARDADD,1); //硬件地址为 0xA0,选择第1页,读出数据0x05
// Delay(1000); //适当的延迟很重要,不让访问AT24C02会无效
//N次写入和N次读取
IIC_N_Write(HARDADD,0,Table1,3); //硬件地址为 0xA0,从第0页开始,写入数组Table1,数组长度为3 ?
_delay_ms(2); //适当的延迟很重要,不让访问AT24C02会无效
IIC_N_Read(HARDADD,0,Table2,3); //硬件地址为 0xA0,从第0页开始,读取数据到数组Table2,读取数组长度为3 ?
_delay_ms(2); //适当的延迟很重要,不让访问AT24C02会无效
Temp1=Table2[0]; //Table2[0]的数据赋予Temp1,数据位0x01
while(1)
{
Number_Show(Temp1); //显示读取的结果
}
} |