51单片机IIC协议 & EEPROM读写程序

[复制链接]
查看0 | 回复0 | 2021-5-10 00:42:33 | 显示全部楼层 |阅读模式
IIC读写EEPROM的源码,经过编译和烧录,成功在开发板上实现。一个00~99的计数器,每秒计数一次,具有断电记忆功能(开机后,从关机前的最新数值继续计数),软件模拟IIC协议。
源码以及开发板上的与本源码相关的电路部分如下
image.jpg
数码管
image.jpg
EEPROM模块以及受影响的DS1302模块
image.png
单片机源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>

  3. bit x=0;                //将计时值写入EEPROM的标志位
  4. sbit SCL=P2^1;
  5. sbit SDA=P2^0;
  6. sbit X=P2^4;                //引脚P2^4为开发板上DS1302模块的复位引脚
  7. sbit DU=P2^6;                //数码管模块段选位
  8. sbit WE=P2^7;                //数码管模块位选位

  9. unsigned char num=0;
  10. unsigned char i=0;

  11. unsigned char LEDS[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};                //共阴数码管的段码

  12. void LEDS_IO()                //数码管锁存
  13. {
  14.         WE=1;
  15.         P0=1;
  16.         WE=0;
  17.         DU=1;
  18.         P0=0;
  19.         DU=0;
  20. }

  21. void Delay5ms()
  22. {
  23.         unsigned char i,j;
  24.         i=9;
  25.         j=244;
  26.         do
  27.         {
  28.                 while(--j);
  29.         }
  30.         while(--i);
  31. }

  32. void IIC_Delay()
  33. {
  34.         _nop_();
  35.         _nop_();
  36. }

  37. void IIC_INIT()                //IIC初始化
  38. {
  39.         X=0;                //DS1302模块的复位电平为低电平,令DS1302模块一直处于复位状态,使其I/O端口(P2^0)不输出,避免干扰EEPROM模块的SDA端口(P2^0)
  40.         SDA=1;
  41.         IIC_Delay();
  42.         SCL=1;
  43.         IIC_Delay();
  44. }

  45. void IIC_Start()                //IIC起始信号
  46. {
  47.         SDA=1;
  48.         IIC_Delay();
  49.         SCL=1;
  50.         IIC_Delay();
  51.         SDA=0;
  52.         IIC_Delay();
  53. }

  54. void IIC_Stop()                //IIC停止信号
  55. {
  56.         SDA=0;
  57.         IIC_Delay();
  58.         SCL=1;
  59.         IIC_Delay();
  60.         SDA=1;
  61.         IIC_Delay();
  62. }

  63. void IIC_ACK()                //等待应答信号;“应答”信号:SDA=0;“非应答”信号:SDA=1
  64. {
  65.         unsigned char i;
  66.         SCL=1;
  67.         IIC_Delay();
  68.         while((SDA==1)&&(i<256))                //若超时,则视为“非应答”
  69.         {
  70.                 i++;
  71.         }
  72.         SCL=0;
  73.         IIC_Delay();
  74. }

  75. void IIC_Write(unsigned char DATA)                //IIC发送数据
  76. {
  77.         unsigned char i;
  78.         unsigned char temp;
  79.         temp=DATA;
  80.         for(i=0;i<8;i++)
  81.         {
  82.                 temp=temp<<1;
  83.                 SCL=0;
  84.                 IIC_Delay();
  85.                 SDA=CY;                //IIC数据的发送从高位开始,需要使用左移指令,而C语言的左移和右移指令,CY参与其中(CY并不是只有在进位和借位中用到),左移出来的一位赋给CY
  86.                 IIC_Delay();
  87.                 SCL=1;
  88.                 IIC_Delay();
  89.         }
  90.         SCL=0;                //将SCL置低电平,准备接收应答信号
  91.         IIC_Delay();
  92.         SDA=1;                //释放SDA,准备接收从器件反馈的应答信号
  93.         IIC_Delay();
  94. }

  95. unsigned char IIC_Read()                //IIC接收数据
  96. {
  97.         unsigned char i;
  98.         unsigned char DATA;
  99.         SCL=0;
  100.         IIC_Delay();
  101.         SDA=1;
  102.         IIC_Delay();
  103.         for(i=0;i<8;i++)
  104.         {
  105.                 SCL=1;
  106.                 IIC_Delay();
  107.                 DATA=(DATA<<1)|SDA;
  108.                 SCL=0;
  109.                 IIC_Delay();
  110.         }
  111.         return DATA;
  112. }

  113. void EEPROM_Write(unsigned char ADDRESS,unsigned char DATA)                //写入EEPROM
  114. {
  115.         IIC_Start();
  116.         IIC_Write(0xa0);                //发送IIC从器件(EEPROM)地址,并选择“写”操作
  117.         IIC_ACK();
  118.         IIC_Write(ADDRESS);                //发送将要写入的EEPROM的存储地址
  119.         IIC_ACK();
  120.         IIC_Write(DATA);                //发送写入EEPROM的数据
  121.         IIC_ACK();
  122.         IIC_Stop();
  123. }

  124. unsigned char EEPROM_Read(unsigned char ADDRESS)                //读取EEPROM
  125. {
  126.         unsigned char DATA;
  127.         IIC_Start();
  128.         IIC_Write(0xa0);
  129.         IIC_ACK();
  130.         IIC_Write(ADDRESS);
  131.         IIC_ACK();
  132.         IIC_Start();
  133.         IIC_Write(0xa1);                //发送IIC从器件(EEPROM)地址,并选择“读”操作
  134.         IIC_ACK();
  135.         DATA=IIC_Read();
  136.         IIC_Stop();
  137.         return DATA;
  138. }

  139. void LEDS_OUTPUT(unsigned char m,unsigned char n)                //数码管显示
  140. {
  141.         DU=0;
  142.         P0=LEDS[m];
  143.         DU=1;
  144.         DU=0;
  145.         WE=0;
  146.         P0=0x3e;
  147.         WE=1;
  148.         WE=0;
  149.         Delay5ms();
  150.         DU=0;
  151.         P0=LEDS[n];
  152.         DU=1;
  153.         DU=0;
  154.         WE=0;
  155.         P0=0x3d;
  156.         WE=1;
  157.         WE=0;
  158.         Delay5ms();
  159. }

  160. void main()
  161. {
  162.         IIC_INIT();
  163.         LEDS_IO();
  164.         num=EEPROM_Read(0x00);
  165.         TMOD=0x01;
  166.         TH0=0x4c00;
  167.         TL0=0x4c00;
  168.         TR0=1;
  169.         ET0=1;
  170.         EA=1;
  171.         while(1)
  172.         {
  173.                 LEDS_OUTPUT(num/10,num%10);
  174.                 if(x==1)
  175.                 {
  176.                         x=0;
  177.                         EEPROM_Write(0x00,num);
  178.                 }
  179.         }
  180. }

  181. void T() interrupt 1                //每0.05秒中断一次
  182. {
  183.         TH0=0x4c00;
  184.         TL0=0x4c00;
  185.         i++;
  186.         if(i==20)                //中断20次,即1秒
  187.         {
  188.                 i=0;
  189.                 num++;
  190.                 x=1;
  191.                 if(num==100)
  192.                 {
  193.                         num=0;
  194.                 }
  195.         }
  196. }
复制代码

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则