51单片机day10——模拟IIC操作EEPROM
2025-09-30 来源:bilibili
/***
*模拟IIC操作EEPROM
*顺序:
* 1.在液晶1602上显示存入到EEPROM内的ABCD字符
* 2.若是读写过程出现错误程序停止,蜂鸣器响
*接口:
* 1.EEPROM的A0-A2接地(EEPROM的七位地址为1010000(A0-A2接地所以最后三位为0))
* 2.EEPROM的SCL(时钟)接P2^1
* 3.EEPROM的SDA(数据引脚)接P2^0
* 4.EEPROM的WP(写保护)接地,WP接地时可读写,WP接VCC时可以读取数据、无法写入
* 5.LCD1602第四管脚RS(操作指令/数据控制端)接P2^6
* 6.LCD1602第五管脚WR(读/写控制端)接P2^5
* 7.LCD1602第六管脚E(使能端)接P2^7
* 8.LCD1602第七到十四管脚(并行数据端)接P0^0-P0^7
* 9.蜂鸣器接P1^5
*原理:
* 1.IIC进行通信时要先发送一个起始信号
* 2.起始信号发送后发送器件地址0XA0(器件地址为7位,最后一位是读/写位读为1、写为0,本次无论读写读写位都要发送0)
* 3.若进行写操作的话直接发送数据,若进行读操作的话发送要读的EEPROM内数据的地址后发送一个停止信号在发送器件地址(读写位为读)
* 4.发送终止信号
*
***/
#include "reg52.h"
#include <stdio.h>
#include <intrins.h> //此头文件中定义了_nop_();延时函数
void eepxrkz(char,char); //写入控制,将EEPROM的写入过程整合(EEPROM内数据地址,数据内容)
char eepdqkz(char); //读取控制,将EEPROM的读取过程整合(要读取的数据地址)返回数据地址内的数据
void eepqsxh(); //发送启动信号
void eepfssj(char); //向EEPROM发送数据(数据内容)
char eepdqsj(); //读取EEPROM内的数据返回读取后的内容
void eeptzxh(); //发送停止信号
void delay(int); //延时
void cshlcd(); //初始化lcd
void lcdxml(char); //向lcd中写命令
void lcdxsj(char); //向lcd中写数据
void lcdxs(char*,int); //显示函数(显示字符数组的指针,有效数组的个数)
sbit EEPSCL=P2^1;
sbit EEPSDA=P2^0;
sbit FMQ=P1^5; //链接到蜂鸣器
sbit LCDRS=P2^6; //LCD的操作指令/数据控制端(高为数据,低为指令)
sbit LCDRW=P2^5; //LCD的读/写控制端(高为读,低为写)
sbit LCDE=P2^7; //LCD的使能端(上升沿时数据被写入到LCD1602芯片内)
char lcdxssz[17]; //定义一个LCD用来显示的数组
void main(void)
{
char *plcd,eppjg; //定义一个传输数组地址的指针和接受EEPROM返回数据的变量
eepxrkz(1,'A'); //向向写入控制内传入要写入的地址和数值
eepxrkz(2,'B'); //向向写入控制内传入要写入的地址和数值
eepxrkz(3,'C'); //向向写入控制内传入要写入的地址和数值
eepxrkz(4,'D'); //向向写入控制内传入要写入的地址和数值
lcdxssz[0]=eepdqkz(1); //把读取控制内返回的结果赋值给数组
lcdxssz[1]=eepdqkz(2); //把读取控制内返回的结果赋值给数组
lcdxssz[2]=eepdqkz(3); //把读取控制内返回的结果赋值给数组
lcdxssz[3]=eepdqkz(4); //把读取控制内返回的结果赋值给数组
plcd=&lcdxssz[0]; //数组地址传给指针
cshlcd(); //初始化液晶
lcdxs(plcd,4); //显示指针指向的数组,显示4个字符
plcd=NULL; //清空指针
while(1);
}
char eepdqkz(char dz) //读取控制,将EEPROM的读取过程整合(要读取的数据地址)返回数据地址内的数据
{
char jg; //定义一个变量保存读取的结果
eepqsxh(); //发送启动信号
eepfssj(0XA0); //发送器件地址
eepfssj(dz); //发送要读的数据地址
eeptzxh(); //发送停止信号
eepqsxh(); //发送启动信号
eepfssj(0xA1); //发送器件地址(读写模式改为读)
jg=eepdqsj(); //把读取的结果放到jg变量内
return jg; //返回结果
}
void eepxrkz(char dz,char sj) //写入控制,将EEPROM的写入过程整合(EEPROM内数据地址,数据内容)
{
eepqsxh(); //发送启动信号
eepfssj(0XA0); //发送器件地址
eepfssj(dz); //发送要写入的地址
eepfssj(sj); //发送要写入的数据
eeptzxh(); //发送停止信号
}
char eepdqsj() //读取EEPROM内的内容
{
int i;
char sj; //定义一个存放结果的变量
EEPSCL=0; //拉低时钟才可以改变SDA的数值
delay(20); //延时
EEPSDA=1; //SDA为高才可以正常应答/发送数据
delay(20); //延时
for(i=0;i<8;i++)
{
sj=sj<<1; //sj向前移一位留出接收的一位数据存放的位置
EEPSCL=1; //拉高时钟
delay(20); //延时
sj|=EEPSDA; //EEPROM的数值放到sj内
delay(20); //延时
EEPSCL=0; //拉低时钟,拉低时钟后下个被读取的数值会到SDA上
delay(20); //延时
}
return sj; //完成,返回数据
}
void eepqsxh(void) //发送启动信号
{
EEPSCL=0; //拉低时钟以改变SDA的值
EEPSDA=1; //拉高SDA(启动信号为下降沿)
delay(20); //延时
EEPSCL=1; //拉高时钟(SDA的下降沿要在时钟为高时)
delay(20); //延时
EEPSDA=0; //拉低SDA(造成下降沿)
delay(20); //延时
EEPSCL=0; //拉低时钟结束
}
void eepfssj(char sj) //向EEPROM发送数据(数据内容)
{
int i,jc=0; //jc:定义一个几次的变量
EEPSCL=0; //确保时钟是低的
for(i=0;i<8;i++) //重复发送数据(8次,每次1位)
{
EEPSDA=sj>>7; //把最高位数据放到SDA上
sj=sj<<1; //移掉最高位数据
delay(20); //改变SDA后延时
EEPSCL=1; //拉高时钟,EEPROM读走数据
delay(20); //延时
EEPSCL=0; //拉低时钟,可以把第二个数据放入SDA
delay(20); //延时
}
EEPSDA=1; //发送数据结束,拉高SDA等待EEPROM应答
delay(20); //延时
EEPSCL=1; //拉高时钟
delay(20); //延时
while(EEPSDA) //如果EEPROM拉低时钟(应答)的话发送数据结束否则进入函数
{
jc++; //计数+1
delay(20); //延时
if(jc>200) //结果200以上
{
while(1) //死循环
{
FMQ=~FMQ; //蜂鸣器响
delay(4); //延时
}
}
}
}
void eeptzxh(void) //发送停止信号
{
EEPSCL=0; //拉低时钟以改变SDA
delay(20); //延时
EEPSDA=0; //拉低SDA(上升沿停止)
delay(20); //延时
EEPSCL=1; //拉高时钟
delay(20); //延时
EEPSDA=1; //在时钟为高时拉高SDA(上升沿)
delay(20); //延时
EEPSCL=0; //拉低时钟结束
}
void cshlcd(void) //初始化液晶
{
LCDRW=0; //让液晶在写状态
lcdxml(0X38); //设置16*2显示,5*7点阵,8位数据口
lcdxml(0X0F); //开显示、光标、光标闪烁
lcdxml(0X06); //当读/写一个字符之后地址指针+1,光标+1
lcdxml(0X01); //数据指针和所有显示清零
delay(200); //延时
lcdxml(0X80); //把指针放到第一行第一列
}
void lcdxml(char ml) //向lcd写入传入的命令
{
LCDRS=0; //写指令时RS为低
LCDE=0; //拉低使能端确保为低
P0=ml; //放入数值
delay(3); //延时
LCDE=1; //使能端为上升沿
delay(3); //延时
LCDE=0; //拉低使能端完成一次写命令
}
void lcdxsj(char sj) //向lcd写入传入的数据
{
LCDRS=1; //写数据时RS为低
LCDE=0; //拉低使能端确保为低
P0=sj; //放入数值
delay(3); //延时
LCDE=1; //使能端为上升沿
delay(3); //延时
LCDE=0; //拉低使能端完成一次写命令
}
void lcdxs(char *p,int gs) //把输入的字符数组显示(*p(字符数组),gs(有效个数))
{
int i;
for(i=0;i<gs;i++) //把数组内的数据挨个显示传入的有效数据个
{
lcdxsj(*(p+i)); //把数组内的字符传入显示数据中,每显示一个数组字符指针+1
}
}
void delay(int i) //延时
{
while(i>0)
{
_nop_();
i--;
}
}
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析
- 意法半导体中国本地造STM32微控制器启动规模量产
- 蓝牙信道探测技术原理与开发套件实践




