微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 请求大侠帮助解决 24C02不能正确读存储和读取数据

请求大侠帮助解决 24C02不能正确读存储和读取数据

时间:10-02 整理:3721RD 点击:
      原本是89c52、ds1302,ds18b20,at2402,lcd1602组成的显示温度、时间的程序,设计断电记忆当前时间的时候发现只能正确存储小时和秒,不能正确显示分钟,为了进一步验证有简单设计了一个程序:按下K1时候h,m,s分别自增1,把h,m,s的值写入24C02,并h,m,s的值显示在LCD1602的第一行,同时24C02里读取h,m,s的值,显示在LCD1602的第二行。实验结果发现,下载到开发板立即显示第一行:h00  m00  s00;第二行:h00  m26  s00;按K1按键时候第一行的h,m,s自动增1,第二行的h,s与第一行的h,s同步,没问题,但是第二行的m一直显示26,没有随第一行的m变化。请教大虾们两个问题:
     1、第二行的m为什么初始化后显示26,而不是显示00,如果原来24C02里有数据,那么也不应该每次都显示26。
     2、为什么m没有写入24C02,或者没有正确读取24C02的数据,程序在哪出了问题。
main.c文件:
#include<reg52.h>
#include"IIC.h"
#include"LCD.h"
sbit K1 = P1^0;                //按键定义
uchar h = 0,                   //写入变量
         m = 0,                   //写入变量
          s = 0,                   //写入变量
          hh   ,                   //读取变量
          mm   ,                   //读取变量
          ss   ;                   //读取变量
/*主函数*/
void main()
{
       
        InitLCD();                 //初始换LCD
        while(1)
        {
                if(K1 == 0)            //按键按下
                {
                        DelayMS(10);       //消抖
                        while(!K1);        //松开检测
                        s++;               //自增
                        m++;               //自增
                        h++;               //自增
                        IIC_Write(1,s);    //变量写入指定位置 地址1
                        IIC_Write(2,m);    //变量写入指定位置 地址2
                        IIC_Write(3,h);    //变量写入指定位置 地址3
                }
                hh = IIC_Read(1);      //地址1读取数据
                mm = IIC_Read(2);      //地址2读取数据
                ss = IIC_Read(3);      //地址3读取数据
               
                /*显示写入的数据*/
                WriteCOM(0x80);        //显示位置
                WriteDAT('h');         //显示字母
                WriteDAT(0x30+(h/10)); //显示十位
                WriteDAT(0x30+(h%10)); //显示个位
                WriteCOM(0x80+5);      //显示位置
                WriteDAT('m');         //显示字母
                WriteDAT(0x30+(m/10)); //显示十位
                WriteDAT(0x30+(m%10)); //显示个位
                WriteCOM(0x80+10);     //显示位置
                WriteDAT('s');         //显示字母
                WriteDAT(0x30+(s/10)); //显示十位
                WriteDAT(0x30+(s%10)); //显示个位
               
                /*显示读取的数据*/
                WriteCOM(0x80+0x40);   //显示位置
                WriteDAT('h');         //显示字母
                WriteDAT(0x30+(hh/10));//显示十位
                WriteDAT(0x30+(hh%10));//显示个位
                WriteCOM(0x80+0x40+5); //显示位置
                WriteDAT('m');         //显示字母
                WriteDAT(0x30+(mm/10));//显示十位
                WriteDAT(0x30+(mm%10));//显示个位
                WriteCOM(0x80+0x40+10);//显示位置
                WriteDAT('s');         //显示字母
                WriteDAT(0x30+(ss/10));//显示十位
                WriteDAT(0x30+(ss%10));//显示个位
        }
}               

IIC.c文件:
#include "IIC.h"
/*延时函数*/
void DelayUS()
{
        uchar a, b;
        for(b=1; b>0; b--)
        {
                for(a=2; a>0; a--);
        }
}
/*起始信号*/
void IIC_Start()
{
        SDA = 1;
        DelayUS();
        SCL = 1;
        DelayUS();                           //建立时间是SDA保持时间>4.7us
        SDA = 0;
        DelayUS();                          //保持时间是>4us
        SCL = 0;                       
        DelayUS();               
}
/*停止信号*/
void IIC_Stop()
{
        SDA = 0;
        DelayUS();
        SCL = 1;
        DelayUS();                          //建立时间大于4.7us
        SDA = 1;
        DelayUS();               
}
/*发送一个字节*/
uchar IIC_SendByte(uchar dat, uchar ack)
{
        uchar a = 0,b = 0;                 //最大255,一个机器周期为1us,最大延时255us。
                       
        for(a=0; a<8; a++)                 //要发送8位,从最高位开始
        {
                SDA = dat >> 7;                       //起始信号之后SCL=0,所以可以直接改变SDA信号
                dat = dat << 1;
                DelayUS();
                SCL = 1;
                DelayUS();                     //建立时间>4.7us
                SCL = 0;
                DelayUS();                     //时间大于4us               
        }
        SDA = 1;
        DelayUS();
        SCL = 1;
        while(SDA && (ack == 1))          //等待应答,也就是等待从设备把SDA拉低
        {
                b++;
                if(b > 200)                          //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
                {
                        SCL = 0;
                        DelayUS();
                        return 0;
                }
        }
        SCL = 0;
        DelayUS();
        return 1;               
}
/*读取一个字节*/
uchar IIC_ReadByte()
{
        uchar a = 0,dat = 0;
        SDA = 1;                                      //起始和发送一个字节之后SCL都是0
        DelayUS();
        for(a=0; a<8; a++)                //接收8个字节
        {
                SCL = 1;
                DelayUS();
                dat <<= 1;
                dat |= SDA;
                DelayUS();
                SCL = 0;
                DelayUS();
        }
        return dat;               
}
/*写数据*/
void IIC_Write(uchar addr,uchar dat)
{
        IIC_Start();
        IIC_SendByte(0xA0, 1);          //发送写器件地址
        IIC_SendByte(addr, 1);          //发送要写入内存地址
        IIC_SendByte(dat, 0);                //发送数据
        IIC_Stop();
}
/*读数据*/
uchar IIC_Read(uchar addr)
{
        uchar num;
        IIC_Start();
        IIC_SendByte(0xA0, 1);         //发送写器件地址,器件子地址全接地000
        IIC_SendByte(addr, 1);         //发送要读取的地址
        IIC_Start();
        IIC_SendByte(0xA1, 1);         //发送读器件地址
        num=IIC_ReadByte();            //读取数据
        IIC_Stop();
        return num;       
}       

现在出现什么现象呢?

两个写两个读之间加个延迟?

存入数据需要固化,资料上显示需要10ms,本程序中连续写入三个地址的数据,所以出现没有写入成功。

只要
IIC_Write(1,s);    //变量写入指定位置 地址1
IIC_Write(2,m);    //变量写入指定位置 地址2
IIC_Write(3,h);    //变量写入指定位置 地址3
改为
IIC_Write(1,s);    //变量写入指定位置 地址1
DelayMS(10);      //延时固化数据
IIC_Write(2,m);    //变量写入指定位置 地址2
DelayMS(10);       //延时固化数据
IIC_Write(3,h);    //变量写入指定位置 地址3
DelayMS(10);      //延时固化数据
就OK了

只要
IIC_Write(1,s);    //变量写入指定位置 地址1
IIC_Write(2,m);    //变量写入指定位置 地址2
IIC_Write(3,h);    //变量写入指定位置 地址3
改为
IIC_Write(1,s);    //变量写入指定位置 地址1
DelayMS(10);      //延时固化数据
IIC_Write(2,m);    //变量写入指定位置 地址2
DelayMS(10);       //延时固化数据
IIC_Write(3,h);    //变量写入指定位置 地址3
DelayMS(10);      //延时固化数据
就OK了

只要
IIC_Write(1,s);    //变量写入指定位置 地址1
IIC_Write(2,m);    //变量写入指定位置 地址2
IIC_Write(3,h);    //变量写入指定位置 地址3
改为
IIC_Write(1,s);    //变量写入指定位置 地址1
DelayMS(10);      //延时固化数据
IIC_Write(2,m);    //变量写入指定位置 地址2
DelayMS(10);       //延时固化数据
IIC_Write(3,h);    //变量写入指定位置 地址3
DelayMS(10);      //延时固化数据
就OK了

只要
IIC_Write(1,s);    //变量写入指定位置 地址1
IIC_Write(2,m);    //变量写入指定位置 地址2
IIC_Write(3,h);    //变量写入指定位置 地址3
改为
IIC_Write(1,s);    //变量写入指定位置 地址1
DelayMS(10);      //延时固化数据
IIC_Write(2,m);    //变量写入指定位置 地址2
DelayMS(10);       //延时固化数据
IIC_Write(3,h);    //变量写入指定位置 地址3
DelayMS(10);      //延时固化数据
就OK了

事实上在本程序中(STC89C52RC  11.0592M)
IIC_Write(1,s);    //变量写入指定位置 地址1
DelayMS(3);
IIC_Write(2,m);    //变量写入指定位置 地址2
DelayMS(3);
IIC_Write(3,h);    //变量写入指定位置 地址3
就可以运行正常了,在实际应用中根据程序设计不是连续写入的话不需要延时的。

就是延时固化的问题,谢谢您的帮助。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top