历史上的今天
返回首页

历史上的今天

今天是:2025年01月15日(星期三)

正在发生

2020年01月15日 | 如何利用AVR单片机实现AT24C256的数据高速稳定的读取

2020-01-15 来源:elecfans

最近刚买回一块AT24C256 EEPROM ,容量为32K Byte ,数据地址宽度为 16Bit ,支持IIC 1M (5V)400K (2.7V) 速度模式 ,利用AVR M16 片内IIC 可以高速稳定地读取数据! 经过调试的,与各位大虾分享分享。

如何利用AVR单片机实现AT24C256的数据高速稳定的读取
 

程序如下:(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;

}

推荐阅读

史海拾趣

Denyo Europa Gmbh公司的发展小趣事

Denyo Europa Gmbh公司一直将产品质量视为企业的生命线。公司建立了严格的质量管理体系,从原材料采购到生产流程,再到产品检测,每一个环节都严格把关。公司还定期对员工进行质量意识培训,确保每一个员工都能深刻理解质量对于企业发展的重要性。这种对质量的执着追求,使公司的产品在市场上赢得了良好的口碑。

DBM REFLEX公司的发展小趣事

DBM REFLEX公司成立于本世纪初,初期以提供光学组件的小规模定制服务为主。创始人对光学技术的深刻理解和对市场的精准把握,使公司迅速在光学器件领域崭露头角。随着技术的不断积累和市场需求的增长,DBM REFLEX逐渐扩大了产品线,开始为LED市场设计、铸模和生产高质量的光学器件。

Fullywell Semiconductor Co Ltd公司的发展小趣事

面对市场需求的不断变化和技术的不断进步,Fullywell始终保持着对研发的重视和投入。在2020年,公司研发团队经过数年的努力,成功攻克了多项关键技术难题,推出了新一代的智能电源管理芯片。这款芯片在能效比、集成度和可靠性等方面均达到了行业领先水平,赢得了市场的广泛好评。Fullywell借此机会实现了产品的迭代升级,进一步巩固了其在电源管理芯片市场的领先地位。

芯源半导体(CW)公司的发展小趣事

为了进一步提升公司的竞争力,芯源半导体(CW)公司开始实施国际化战略。公司积极拓展海外市场,参加国际展会和论坛,与国际同行进行交流与合作。同时,公司还设立了海外研发中心,引进国际优秀人才和技术资源,以加强公司的研发实力和市场竞争力。这些举措使芯源半导体(CW)公司在国际市场上逐渐崭露头角。

振华新云(CEC)公司的发展小趣事

背景:在快速发展的同时,振华新云注重法治建设和企业文化建设,努力营造良好的经营环境。

内容:公司严格按照法治央企的各项建设要求,积极推进企业法治文化建设。同时,注重加强企业文化建设,弘扬“自力更生、艰苦奋斗、大力协同、无私奉献”的精神。通过开展各种文化活动和培训等方式,提高员工的文化素养和综合素质。

成果:法治建设和企业文化建设的不断推进,为公司的健康稳定发展提供了有力保障。同时,也增强了公司的凝聚力和向心力,激发了员工的积极性和创造力。

请注意,以上故事仅为概述,具体细节和内容需要根据实际情况进行补充和完善。

Fillfactory Nv公司的发展小趣事

FIDELIX公司成立于1990年,是一家专注于存储芯片研发与销售的韩国企业。在公司成立初期,FIDELIX凭借对技术的深入研究和对市场的敏锐洞察,成功推出了多款性能优越的NAND FLASH(闪存)和SDR/DDR(单/双数率同步动态存储器)等存储芯片产品。这些产品不仅在韩国市场上获得了良好的口碑,同时也开始逐步进入国际市场。

随着技术的不断进步和市场的不断扩大,FIDELIX逐渐在韩国存储芯片领域崭露头角。公司不断投入研发资金,加强技术创新,努力提升产品的性能和品质。同时,FIDELIX也积极拓展销售渠道,与多家国内外知名厂商建立了合作关系,为公司的持续发展奠定了坚实的基础。

问答坊 | AI 解惑

ARM培训视频-dsp-CPLD-FPGA开发视频-嵌入式系统开发-单片机开发视频

ARM培训视频-dsp-CPLD-FPGA开发视频-嵌入式系统开发-单片机开发视频 ------------------------------------------------------------------ 【ARM培训视频】课程主要内容 1.概念和基本工具: 嵌入式系统基本概念、嵌入式操作系统介绍 嵌入式系 ...…

查看全部问答>

特性阻抗公式

 a.微带线(microstrip) Z={87/[sqrt(Er+1.41)]}ln[5.98H/(0.8W+T)] 其中,W为线宽,T为走线的铜皮厚度,H为走线到参考平面的距离,Er是PCB板材质的介电常数(dielectric constant)。此公式必须在0.1…

查看全部问答>

我该怎么办啊?迷茫。。。

我03年毕业于一所普通的本科院校,学的是机械工程自动化专业,毕业后即来到了现在工作的这家在全国还算比较有名的大型家电制造企业从事生产工艺工作。每天的工作枯燥乏味,工艺巡检,要么就是这个零部件尺寸长了,装不进去,或者那个零部件短了需要 ...…

查看全部问答>

wince 设置默认输入法问题!

最近接手一个wince项目,使用QT4.4.3做的,现在要解决的问题是在控件上输入的时候,调用出wince自带的手写输入法 我现在的设想是 做一个Dll,用SipEnumIM枚举所有的输入法,然后查找出的wince自带的手写输入法的CLSID,将手写输入法的CLSID设置为 ...…

查看全部问答>

LM3S9B96 EM2扩展板用户指南

LM3S9B96 EM2扩展板用户指南 9B96的数据表坛子里有,就不重复了哈…

查看全部问答>

版主呀,或者管理员呀,快进来看看呀!

好了,欢迎进来,某某某,你好!      想请版主或者管理员等等有能力回答的人告诉我们大家一个问题,那就是:      这个用户组头衔是怎么升级的?      跟积分有关系? 还是跟威望 ...…

查看全部问答>

Sitara AM355x低成本新手套件概述

在德州仪器额微博中看到了这个评估套件的视频,分享给大家! 视频内容简要介绍了这款强大的评估套件 [ 本帖最后由 IC爬虫 于 2012-10-24 12:11 编辑 ]…

查看全部问答>

工作无成就感

目前的工作提不起激情,轻闲的空虚,无聊的总跑厕所抽闷烟,前段时间还可以搞搞AVR,现在板子不好打了,流程特多,学习很是不方便,为了上班而上班,我不要这样过   80后!一个沉重的代名词,仿佛一切定格!如何找回存在的价值! [ 本帖 ...…

查看全部问答>

控制芯片的选择

电子设计大赛中的控制类说是四轴飞行器,控制芯片都是用的STM32,我想问一下,MSP430F149可以吗?姿态算法可以实现吗? 希望各位大神指点。 谢谢啦。…

查看全部问答>

从MSP430F149转到G2553,快把我搞疯了。

发现所有的手册中说明的寄存器名称,MSP430G2553.H中就找不到。不知道是我找错资料了还是怎么了,麻烦大家给我个好资料。…

查看全部问答>