MSP430平台下实现AT24C02的读写操作
来源:互联网 发布:网络通信有哪些方式 编辑:程序博客网 时间:2024/06/05 17:26
EEPROM可以随机访问和修改其中的任何一个字节,可以往每个bit中写入0或者1,掉电后数据不丢失,可以保存100年,可以擦写100w次。具有较高的可靠性,但是电路复杂/成本也高。因此目前的EEPROM都是几十千字节到几百千字节的,绝少有超过512K的,常用来保存用户数据,运行过程中可以改变。
下面在MSP430平台下以AT24C02为例说明该类可擦除ROM的使用。AT24C02的存储容量为2K bits,内容分成32页,每页8 bytes,共256 bytes。
AT24C02对外以I2C总线形式传输数据,外观如下图所示:
A0、A1和A2三个引脚作寻址用;SDA和SCL即I2C总线的数据与时钟引脚;WP作写保护用,即WP在保持高电平时,MCU对AT24C02 的读写操作无效;VCC和GND分别接电源和接地。
MCU在挂载多片AT24C02时,其器件地址由8位构成,除A0、A1和A2三位外,其他位都被锁定为如下所示:
最低位为R/W,进行读操作时,该位 = 1,写操作时,该位 = 0。地址写入正确时,AT24C02将会应答以”0”。
AT24C02的读写遵循I2C总线的相关规范,所以有传输的开始条件和停止条件。每一次正常的读写均以开始条件开始,停止条件结束,这两者的时序如下图所示:
其软件模拟的实现为:
void start(void){ SCL_H; SDA_H; _NOP(); SDA_L; _NOP(); SCL_L; _NOP();}void stop(void){ SDA_L; _NOP(); SCL_H; _NOP(); SDA_H; _NOP(); }
SCL_H、SDA_H、SDA_L和SCL_L均为宏定义,分别表示MCU向AT24C02相应引脚输出高电平和低电平。
AT24C02的写操作分两种模式,分别为字节写入和页写入两种。
1、字节写入
该写操作需要以MCU写入开始条件开始,继以器件地址,收到AT24C02的应答后继续写入要进行写操作的字地址(即要将数据写入该AT24C02的什么位置),收到应答后才正式写入一个字节的数据,收到应答后写入停止条件,一个完整的字节写入才算完成。
其软件模拟的实现为:
uchar Write_1Byte(uchar wdata,uchar dataaddress){ start(); write1byte(deviceaddress); if(check()) write1byte(dataaddress); else return 0; if(check()) write1byte(wdata); else return 0; if(check()) stop(); else return 0; delay_10ms(); //等待EEPROM完成内部写入 return 1;}
delay_10ms()是因为AT24C02的每两次写操作之间存在一个写入时间周期tWR,其最大值为5 ms。check()检查AT24C02的应答操作,收到AT24C02回复的0,则应答正确,其软件模拟实现为:
uchar check(void){ uchar slaveack; SDA_H; _NOP(); _NOP(); SCL_H; _NOP(); _NOP(); SDA_in; _NOP(); _NOP(); slaveack = SDA_val; //读入SDA数值 SCL_L; _NOP(); SDA_out; if(slaveack) return FALSE; else return TRUE;}
SDA_in和SDA_out分别表示MCU(MSP430)连接AT24C02的I/O引脚方向改为输入或输出,此处SDA_in的作用是为MCU接收AT24C02的应答信号做准备,接收完成后改回SDA_out。SDA_val = P2IN&BIT5,P2.5连接AT24C02的SDA引脚,接收应答信号。
write1byte()向I2C总线写一个字节的数据,其软件模拟实现为:
void write1byte(uchar wdata){ uchar i; for(i = 8;i > 0;i--) { if(wdata & 0x80) write1(); else write0(); wdata <<= 1; } SDA_H; _NOP(); }
write1()向I2C总线写一位“1”的数据,其软件模拟实现为:
void write1(void){ SDA_H; _NOP(); SCL_H; _NOP(); SCL_L; _NOP();}
write0()向I2C总线写一位“0”的数据,其软件模拟实现为:
void write0(void){ SDA_L; _NOP(); SCL_H; _NOP(); SCL_L; _NOP();}
2、页写入
AT24C02可以实现8位的页写入操作。页写入的形式大体和字节写入类似,只是在MCU写入第一个字节的数据后将会继续写入第二个数据,而不会像字节写入一样写入停止条件。如果写入AT24C02的数据超过8位,超过的数据将会覆盖已被写入的部分。
其软件模拟的实现为:
uchar Write_NByte(uchar * outbuf,uchar n,uint dataaddress){ uchar flag,dataaddressl,dataaddressh; dataaddressl = dataaddress; dataaddressh = dataaddress>>8; start(); write1byte(deviceaddress); //写入器件地址 if(check() == 1) write1byte(dataaddressh); //写入数据字地址 else return 0; if(check()) write1byte(dataaddressl); else return 0; if(check()) flag=writeNbyte(outbuf,n); else return 0; delay_10ms(); //等待EEPROM完成内部写入 if(flag) return 1; else return 0;}
writeNbyte()向I2C总线写N个字节(对于AT24C02,N = 8)的数据,其软件模拟实现为:
uchar writeNbyte(uchar * outbuffer,uchar n){ uchar i; for(i = 0;i < n;i++) { write1byte(* outbuffer); if(check()) { outbuffer++; } else { stop(); return FALSE; } } stop(); return TRUE; }
AT24C02的读操作分三种模式,分别为当前地址读取、随机读取和顺序读取。
1、当前地址读取
上一次读写操作完成后,数据地址计数器加1,并停留在当前位置。这一位置只要不掉电就会一直有效。当R/W = 1时,就可以将当前地址位置的数据读出。
其软件模拟的实现为:
uchar Read_1Byte_currentaddress(void){ uchar temp; start(); write1byte((deviceaddress|0x01)); if(check()) temp = read1byte(); else return 0; mnack(); stop(); return temp;}uchar Read_NByte_currentaddress(uchar * readbuf,uchar n){ start(); write1byte((deviceaddress|0x01)); if(check()) readNbyte(readbuf,n); else return 0; return 1;}
read1byte()从I2C总线读取一个字节,其软件模拟的实现为:
uchar read1byte(void){ uchar rdata = 0x00,i; uchar flag; for(i = 0;i < 8;i++) { SDA_H; _NOP(); SCL_H; SDA_in; _NOP(); flag = SDA_val; rdata <<= 1; if(flag) rdata |= 0x01; SDA_out; SCL_L; _NOP(); } return rdata;}
readNbyte()从I2C总线读取一个字节,其软件模拟的实现为:
void readNbyte(uchar * inbuffer,uchar n){ uchar i; for(i = 0;i < n;i++) { inbuffer[i] = read1byte(); if(i < (n-1)) mack(); else mnack(); } stop();}
mack()完成I2C的MCU应答操作,其软件模拟的实现为:
void mack(void){ SDA_L; _NOP(); _NOP(); SCL_H; _NOP(); SCL_L; _NOP();_NOP(); SDA_H; _NOP(); }
mnack()完成I2C的MCU无应答操作,其软件模拟的实现为:
void mnack(void){ SDA_H; _NOP(); _NOP(); SCL_H; _NOP(); SCL_L; _NOP(); _NOP(); SDA_L; _NOP(); }
2、随机读取
从AT24C02的指定地址读取1个字节的数据。随机读取的操作先发送一个写操作来骗过AT24C02器件,使其内部的数据地址值修改,但是发送完毕数据地址后并不发送数据,而是发送一个开始信号,此时AT24C02中的数据地址值已经被修改了,然后通过“当前地址读取”去读取此地址上的数据。如下图所示:
其软件模拟的实现为:
uchar Read_1Byte_Randomaddress(unsigned int dataaddress){ uchar temp,dataaddressh,dataaddressl; dataaddressl = dataaddress; dataaddressh = dataaddress>>8; start(); write1byte(deviceaddress); if(check()) write1byte(dataaddressh); else return 0; if(check()) write1byte(dataaddressl); else return 0; if(check()) { start(); write1byte((deviceaddress|0x01)); } else return 0; if(check()) temp = read1byte(); else return 0; mnack(); stop(); return temp;}uchar Read_NByte_Randomaddress(uchar * readbuf,uchar n,uchar dataaddress){ start(); write1byte(deviceaddress); if(check()) write1byte(dataaddress); else return 0; if(check()) { start(); write1byte(deviceaddress|0x01); } else return 0; if(check()) readNbyte(readbuf,n); else return 0; return 1; }
read1byte()从I2C总线读取一个字节,其软件模拟的实现为:
uchar read1byte(void){ uchar rdata = 0x00,i; uchar flag; for(i = 0;i < 8;i++) { SDA_H; _NOP(); SCL_H; SDA_in; _NOP(); flag = SDA_val; rdata <<= 1; if(flag) rdata |= 0x01; SDA_out; SCL_L; _NOP(); } return rdata;}
readNbyte()从I2C总线读取N个字节,其软件模拟的实现为:
void readNbyte(uchar * inbuffer,uchar n){ uchar i; for(i = 0;i < n;i++) { inbuffer[i] = read1byte(); if(i < (n-1)) mack(); else mnack(); } stop();}
2、顺序读取
顺序读取的中的第一个字节既可以以“当前位置读取”实现,也可以以“随机读取”实现,只要读取完毕后MCU给AT24C02回复应答信号而不发送停止条件,读取操作一直持续下去。当然,每一次读取都会使数据地址计数器加1。当读到计数器的边界时,数据地址值就会翻转到最开始的位置继续读取下去,直到AT24C02收到MCU发送的停止条件。
- MSP430平台下实现AT24C02的读写操作
- 根据AT24C02的手册读写AT24C02
- MSP430平台下实现Si4432的收发数据
- AT24C02串行E2PROM的读写
- AT24C02串行E2PROM的读写
- 基于51汇编的at24c02读写程序
- AT24C02的Stm32模拟读写IIC程序
- 学习笔记——51通过IO口模拟IIC实现AT24C02的读写
- MSP430 flash的操作
- MSP430的Flash操作
- AT24C02 IIC读写
- tq2440下的i2c驱动at24c02
- MSP430 SD卡SPI读写操作(4) —— FatFs文件系统实现(以MSP430F5438A为例)
- MSP430下TB产生两路PWM波的操作
- AVR(M48)的i2c程序,读写at24c02
- AT24C02的Stm32模拟读写IIC程序(续)
- MSP430 SD卡SPI读写操作(3) —— SD卡读写实现(以MSP430F5438A为例)
- Windows平台下的读写锁
- Oracle数据库丢失控制文件的恢复四则
- 内网与外网的区别
- dubbo标签报错问题
- Jacob安装
- 【洛谷P3383】【模板】线性筛素数
- MSP430平台下实现AT24C02的读写操作
- 微信公众平台开发接口配置URL index.php和token,
- plsql 调用存储过程
- 机器学习(一)----k-近邻算法
- 理解RESTful架构
- laravel 5.3 GROUP BY 问题
- C++算法之二叉树
- 在同个输出如何同时输出a和b
- BugFree的7种解决方案各自的含义是什么?