通过IIC总线读写AT24C512存储器

今天要讲的是通过iic总线来读写at24c512存储。我们在开发一些项目的时候,如果要求对有些参数进行存储,且掉电不丢失的话,我们就需要一些外部存储器件,比如说今天要讲的at24c512存储器。下面就来看一下今天的例程吧!
一、硬件电路
实现仿真电路如下,图中u1为at89c51,其中u1扫描p1口的输入,并根据不同的按键执行不同的操作,并显示运行结果。本实验中,液晶模块挂接在单片机的总线上,用读(rd)和写(wr)信号实现数据的传输;用u2即74ls373锁存低位地址(a0~a1)u4为24c02器件,其a0、a1、a2引脚接地,故其写地址为0xa0,读地址为0xa1。sck接p3.4,sda接p3.5。wp接地。另外原理图中增加了iic调试器。
二、软件程序
c程序:
#include #include #define reg0 xbyte[0x0000] //lcd写指令寄存器的地址,可根据配置修改#define reg1 xbyte[0x0001] //lcd读出数据到d0~d7的地址,可根据配置修改#define reg2 xbyte[0x0002] //lcd写数据寄存器的地址,可根据配置修改#define reg3 xbyte[0x0003] //lcd读数据寄存器的地址,可根据配置修改unsigned char bdata busyflag;unsigned char dat,datn;unsigned char word1[16]={ this programm }; //第1行显示缓存unsigned char word2[16]={ by lixueli }; //第2行显示缓存code unsigned char word3[16]={www.bitc.edu.cn!}; //用于固定显示的数据,固化到rom中code unsigned char word4[16]={bitclxl@126.com!}; //用于固定显示的数据,固化到rom中code unsigned char word5[16]={ wellcome to }; //用于固定显示的数据,固化到rom中code unsigned char word6[16]={ proteus tools!}; //用于固定显示的数据,固化到rom中sbit busyflag_7=busyflag^7;sbit p10=p1^0;sbit p11=p1^1;sbit p12=p1^2;sbit p13=p1^3;sbit p14=p1^4;sbit p15=p1^5;sbit p16=p1^6;sbit p17=p1^7;//////////////////////////////////////start of iic ////////////////////////////#define uchar unsigned char#define uint unsigned int#include reg51.h#include intrins.hsbit scl=p3^4; //串行时钟sbit sda=p3^5; //串行数据/*发送起始条件*/void start(void) /*起始条件*/{ sda=1; scl=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); sda=0; _nop_ (); _nop_ (); _nop_ (); _nop_ ();}void stop(void) /*停止条件*/{ sda=0; scl=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); sda=1; _nop_ (); _nop_ (); _nop_ (); _nop_ ();}void ack(void) /*应答位*/{ sda=0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); scl=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); scl=0;}void noack(void) /*反向应答位*/{ sda=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); scl=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); scl=0;}void send(uchar data) /*发送数据子程序,data为要求发送的数据*/{ uchar bitcounter=8; /*位数控制*/ uchar temp; /*中间变量控制*/ do { temp=data; scl=0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); if((temp&0x80)==0x80)/* 如果最高位是1*/ sda=1; else sda=0; scl=1; temp=data< <1; /*rlc*/ data=temp; bitcounter--; }while(bitcounter); scl=0;}uchar read(void) /*读一个字节的数据,并返回该字节值*/{ uchar temp=0; uchar temp1=0; uchar bitcounter=8; sda=1; do{ scl=0; _nop_ (); _nop_ (); _nop_ (); _nop_ (); scl=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); if(sda) /*如果sda=1;*/ temp=temp|0x01; /*temp的最低位置1*/ else temp=temp&0xfe; /*否则temp的最低位清0*/ if(bitcounter-1) { temp1=temp< <1; temp=temp1; } bitcounter--; }while(bitcounter); return(temp);}void wrtorom(uchar data[],uchar address,uchar num)//写入一组数据到at24c02中{ //参数为数组的首地址,数据在at24c02中的开始地址,数据个数 uchar i=0; uchar *pdata; pdata=data; start(); send(0xa0); //a0、a1、a2接地,固at24c02的写地址为0xa0 ack(); send(address); ack(); for(i=0;i< num;i++) { send(*(pdata+i)); ack(); } stop();}void rdfromrom(uchar data[],uchar address,uchar num)//读出一组数据到at24c02中 //参数为数组的首地址,数据在at24c02中的开始地址,数据个数{ uchar i=0; uchar *pdata; pdata=data; for(i=0;i< num;i++) { start(); send(0xa0); //a0、a1、a2接地,固at24c02的写地址为0xa0 ack(); send(address+i); ack(); start(); send(0xa1); //a0、a1、a2接地,固at24c02读地址为0xa1 ack(); *(pdata+i)=read(); scl=0; noack(); stop(); }}/////////////////////////////////end of iic/////////////////////////////////void busy() //查询lcd是否忙碌子程序{ do { busyflag=reg1; }while(busyflag_7);}void wrc(unsigned char wcon) //写控制指令子程序{ busy(); reg0=wcon;}void wrd(unsigned char wdat) //写数据寄存器子程序{ busy(); reg2=wdat;}void rdd() //读数据寄存器子程序{ busy(); dat=reg3;}void lcdint() //lcd初始化子程序{ wrc(0x38); wrc(0x01); wrc(0x06); wrc(0x0c);}void wrn(unsigned char word[]) //连续写n个字符数据到lcd的数据寄存器中{ unsigned char i; for(i=0;i< 16;i++) { wrd(word[i]); }}void main(){ unsigned char i; lcdint(); //初始化 wrc(0x80); //显示第1行的第1个字符 wrn(word1); wrc(0xc0); //显示第2行的第1个字符 wrn(word2); while(1) { if(p10==0) //判断p1.0是否按下,写入数据到eeprom中 { for(i=0;i< 16;i++) word1[i]='d'; wrtorom(word1,0x00,16); wrc(0x80); wrn(word1); } if(p11==0) //判断p1.1是否按下,并显示数据 { rdfromrom(word2,0x00,16); wrtorom(word2,0x80,16); wrc(0x80); wrn(word1); wrc(0xc0); wrn(word2); } if(p12==0) //判断p1.2是否按下,并显示数据 { wrc(0x80); wrn(word3); wrc(0xc0); wrn(word4); } if(p13==0) //判断p1.3是否按下,并显示数据 { wrc(0x80); wrn(word5); wrc(0xc0); wrn(word6); } if(p14==0) //判断p1.4是否按下,并显示数据 { wrc(0x80); wrn(word3); wrc(0xc0); wrn(word4); } if(p15==0) //判断p1.5是否按下,并显示数据 { wrc(0x80); wrn(word5); wrc(0xc0); wrn(word6); } if(p16==0)//判断p1.6是否按下,并显示数据 { wrc(0x80); wrn(word3); wrc(0xc0); wrn(word4); } if(p17==0)//判断p1.7是否按下,并显示数据 { wrc(0x80); wrn(word5); wrc(0xc0); wrn(word6); } }}三、仿真展示
程序很简单,小伙伴们可以根据需要自己修改程序,然后进行验证哦!

你学对专业了吗?机器人将替代这些工作
【世说芯品】Microchip推出全新VSC8574RT PHY器件进一步扩大耐辐射千兆以太网PHY产品阵容
医疗领域中温湿度传感器的应用
防伪和追溯最好的技术是哪一种技术
为什么使用电驱动?变频驱动器如何控制扭矩/速度和方向
通过IIC总线读写AT24C512存储器
面向增值服务,IDT单芯片统计引擎提高90%处理周期
特斯拉车载电池的寿命有多长?
研究首次实现高通量小RNA芯片非标记检测
AfterShokz骨传导耳机评测 给你一种很真实的感觉
目前哪些地方是需要应用到访客登记机器人
如何提高防爆LED手电筒的显色指数
雷军:iPhone8概念机不靠谱, 小米MIX才代表未来
还不了解5G会为我们带来什么?这篇文章告诉你答案
意法半导体近日宣布产品部门将进行重组!
三星Galaxy A72 5G高清渲染图曝光
通信电源要用48v或24v电源的原因
基尔霍夫定律适用于非线性电路吗
荣耀V30 PRO图赏 首次将5G Modem集成到SOC中去
易于设计RGB多种颜色的LED驱动器方案