单片机
返回首页

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--;

  }

 }

 


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 设计汽车集群电源

  • 6晶体管H桥

  • 温度控制风扇

  • USB LED调光器

  • AVR PC步进电机驱动器

  • AVR温度计TCN75

    相关电子头条文章