最近刚买回一块AT24C256 EEPROM ,容量为32K Byte ,数据地址宽度为 16Bit ,支撑IIC 1M (5V)400K (2.7V) 速度形式 ,使用AVR M16 片内IIC 能够高速稳定地读取数据! 通过调试的,与各位大虾共享共享。
程序如下:(winavr)
#include
#include
#include
#include
#define FREQ 8
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//管脚界说
#define pinSCL 0 //PC0 SCL
#define pinSDA 1 //PC1 SDA
//为稳妥起见,最好在SCL/SDA接上1~10K的外部上拉电阻到VCC。
#define fSCL 1000000 //TWI时钟为1000KHz
//预分频系数=1(TWPS=0)
#if F_CPU 《 fSCL*36
#define TWBR_SET 2; //TWBR有必要大于等于10
#else
#define TWBR_SET (F_CPU/fSCL-16)/2; //核算TWBR值
#endif
#define TW_ACT (1《//TWCR只能IN/OUT,直接赋值比逻辑运算(|= &=)更节约空间
#define SLA_24CXX 0xA0 //24Cxx系列的厂商器材地址(高四位)
#define ADDR_24C256 0x00
// AT24C256的地址线A2/1/0悉数接地,SLAW=0xA0+0x00《《1+0x00,SLAR=0xA0+0x00《《1+0x01
//TWI_操作状况
#define TW_BUSY 0
#define TW_OK 1
#define TW_FAIL 2
//TWI_读写指令状况
#define OP_BUSY 0
#define OP_RUN 1
//TWI读写操作公共过程
#define ST_FAIL 0 //犯错状况
#define ST_START 1 //START状况查看
#define ST_SLAW 2 //SLAW状况查看
#define ST_WADDR_H 3 //ADDR状况查看
#define ST_WADDR_L 4 //ADDR状况查看
//TWI读操作过程
#define ST_RESTART 5 //RESTART状况查看
#define ST_SLAR 6 //SLAR状况查看
#define ST_RDATA 7 //读取数据状况查看,循环n字节
//TWI写操作过程
#define ST_WDATA 8 //写数据状况查看,循环n字节
#define FAIL_MAX 1 //重试次数最大值
void delay_nms(uint ms)//若干毫秒延时
{
int i;
for(i=0;i{
_delay_loop_2(FREQ*250);
}
}
unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len);
unsigned char BUFFER[256]; //缓冲区
void Test(void);
struct str_TWI //TWI数据结构
{
volaTIle unsigned char STATUS; //TWI_操作状况
unsigned char SLA; //从设备的器材地址
unsigned char ADDR_H; //从设备的数据地址
unsigned char ADDR_L; //从设备的数据地址
unsigned char *pBUF; //数据缓冲区指针
unsigned int DATALEN; //数据长度
unsigned char STATE; //TWI读写操作过程
unsigned char FAILCNT; //失利重试次数
};
struct str_TWI strTWI; //TWI的数据结构变量
//AT24C256的读写函数(包含随机读,连续读,字节写,页写)
//依据sla的最低位决议(由中止程序中判别)
//bit0=1 TW_READ 读
//bit0=0 TW_WRITE 写
// sla 器材地址(不能搞错)
// addr EEPROM地址(0~32767)
// *ptr 读写数据缓冲区
// len 读数据长度(1~32768),写数据长度(1 or 8 or 16 or 32 or 64)
// 返回值 是否能履行当时操作
unsigned char TWI_RW(unsigned char sla,unsigned int addr,unsigned char *ptr,unsigned int len)
{
// unsigned char i;
if (strTWI.STATUS==TW_BUSY)
{//TWI忙,不能进行操作
return OP_BUSY;
}
strTWI.STATUS=TW_BUSY;
strTWI.SLA=sla;
strTWI.ADDR_H=(unsigned char)((addr》》8)&0xff);
strTWI.ADDR_L=(unsigned char)(addr&0xff);
strTWI.pBUF=ptr;
strTWI.DATALEN=len;
strTWI.STATE=ST_START;
strTWI.FAILCNT=0;
TWCR=(1《 return OP_RUN;
}
SIGNAL(SIG_2WIRE_SERIAL)
{//IIC中止
unsigned char acTIon,state,status;
acTIon=strTWI.SLA&TW_READ; //取操作形式
state=strTWI.STATE;
status=TWSR&0xF8; //屏蔽预分频位
if ((status》=0x60)||(status==0x00))
{//总线过错或从机形式引发的中止,不予处理
return;
}
switch(state)
{
case ST_START: //START状况查看
if(status==TW_START)
{//发送start信号成功
TWDR=strTWI.SLA&0xFE; //发送器材地址写SLAW
TWCR=TW_ACT; //触发下一步动作,一起清start发送标志
}
else
{//发送start信号犯错
state=ST_FAIL;
}
break;
case ST_SLAW: //SLAW状况查看
if(status==TW_MT_SLA_ACK)
{//发送器材高位地址成功
TWDR=strTWI.ADDR_H; //发送eeprom地址
TWCR=TW_ACT; //触发下一步动作
}
else
{//发送器材地址犯错
state=ST_FAIL;
}
break;
case ST_WADDR_H: //ADDR状况查看
if(status==TW_MT_DATA_ACK)
{//发送器材低位地址成功
TWDR=strTWI.ADDR_L; //发送eeprom地址
TWCR=TW_ACT; //触发下一步动作
}
else
{//发送器材地址犯错
state=ST_FAIL;
}
break;
case ST_WADDR_L: //ADDR状况查看
if(status==TW_MT_DATA_ACK)
{//发送eeprom地址成功
if (acTIon==TW_READ)
{//读操作形式
TWCR=(1《 }
else
{//写操作形式
TWDR=*strTWI.pBUF++; //写第一个字节
strTWI.DATALEN–;
state=ST_WDATA-1; //下一步将跳到WDATA分支
TWCR=TW_ACT; //触发下一步动作
}
}
else
{//发送eeprom地址犯错
state=ST_FAIL;
}
break;
case ST_RESTART: //RESTART状况查看,只要读操作形式才干跳到这儿
if(status==TW_REP_START)
{//发送restart信号成功
TWDR=strTWI.SLA; //发器材地址读SLAR
TWCR=TW_ACT; //触发下一步动作,一起清start发送标志
}
else
{//重发start信号犯错
state=ST_FAIL;
}
break;
case ST_SLAR: //SLAR状况查看,只要读操作形式才干跳到这儿
if(status==TW_MR_SLA_ACK)
{//发送器材地址成功
if (strTWI.DATALEN–)
{//多个数据
TWCR=(1《 }
else
{//只要一个数据
TWCR=TW_ACT; //设定NAK,触发下一步动作
}
}
else
{//发送器材地址犯错
state=ST_FAIL;
}
break;
case ST_RDATA: //读取数据状况查看,只要读操作形式才干跳到这儿
state–; //循环,直到读完指定长度数据
if(status==TW_MR_DATA_ACK)
{//读取数据成功,但不是最终一个数据
*strTWI.pBUF++=TWDR;
if (strTWI.DATALEN–)
{//还有多个数据
TWCR=(1《 }
else
{//预备读最终一个数据
TWCR=TW_ACT; //设定NAK,触发下一步动作
}
}
else if(status==TW_MR_DATA_NACK)
{//现已读完最终一个数据
*strTWI.pBUF++=TWDR;
TWCR=(1《 strTWI.STATUS=TW_OK;
}
else
{//读取数据犯错
state=ST_FAIL;
}
break;
case ST_WDATA: //写数据状况查看,只要写操作形式才干跳到这儿
state–; //循环,直到写完指定长度数据
if(status==TW_MT_DATA_ACK)
{//写数据成功
if (strTWI.DATALEN)
{//还要写
TWDR=*strTWI.pBUF++;
strTWI.DATALEN–;
TWCR=TW_ACT; //触发下一步动作
}
else
{//写够了
TWCR=(1《 strTWI.STATUS=TW_OK;
//发动写指令后需求10ms(最大)的编程时刻才干真实的把数据记录下来
//编程期间器材不响应任何指令
}
}
else
{//写数据失利
state=ST_FAIL;
}
break;
default:
//过错状况
state=ST_FAIL;
break;
}