51单片机关于EEPROM的读和写的问题

```#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include"temp.h"
#include"i2c.h"

typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3; //定义按键端口

int temp;
char xianshizhi=0;
u16 zhuangtai=0;
u8 DisplayData[8];
u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

/*******************************************************************************

  • 函 数 名 : delay
  • 函数功能 : 延时函数,i=1时,大约延时10us *******************************************************************************/ void delay(u16 i) { while(i--); }

/*******************************************************************************

  • 函 数 名 : datapros()
  • 函数功能 : 温度读取处理转换函数
  • 输 入 : temp
  • 输 出 : 无 *******************************************************************************/

void datapros(int temp)

{
float tp;

if(temp< 0)

{
DisplayData[0] = 0x40;

temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;

}
else
{           
    DisplayData[0] = 0x00;
    tp=temp;
    temp=tp*0.0625*100+0.5; 
}
DisplayData[1] = smgduan[temp / 10000];
DisplayData[2] = smgduan[temp % 10000 / 1000];
DisplayData[3] = smgduan[temp % 1000 / 100] | 0x80;
DisplayData[4] = smgduan[temp % 100 / 10];
DisplayData[5] = smgduan[temp % 10];

}

/*******************************************************************************

  • 函数名 :DigDisplay()
  • 函数功能 :数码管显示函数
  • 输入 : 无
  • 输出 : 无 *******************************************************************************/ void DigDisplay() { u8 i; for(i=0;i<6;i++) { switch(i) //位选,选择点亮的数码管, { case(0): LSA=0;LSB=0;LSC=0; break;//显示第0位 case(1): LSA=1;LSB=0;LSC=0; break;//显示第1位 case(2): LSA=0;LSB=1;LSC=0; break;//显示第2位 case(3): LSA=1;LSB=1;LSC=0; break;//显示第3位 case(4): LSA=0;LSB=0;LSC=1; break;//显示第4位 case(5): LSA=1;LSB=0;LSC=1; break;//显示第5位
    } P0=DisplayData[5-i];//发送数据 delay(100); //间隔一段时间扫描
    P0=0x00;//消隐 }
    }

void Int1Init()
{
//设置INT1
IT1=1;//跳变沿出发方式(下降沿)
EX1=1;//打开INT1的中断允许。

EA=1;//打开总中断

}

//这块是按键记忆函数 摁下K1键记忆当前温度值 K2是显示写入EEPROM的温度值 K3是对温度值加1 K4是对当前显示的值清零
//K4的意义后期可以改一下

void Keypros()

{
int i=0,j,temp,tp;
int num;
if(k1==0)
{
delay(1000); //消抖处理
if(k1==0)
{
//zhuangtai=0;
temp=Ds18b20ReadTemp();

        if(temp< 0)         
{
    DisplayData[0] = 0x40;   
    temp=temp-1;
    temp=~temp;
    tp=temp;
    temp=tp*0.0625*100+0.5; 

}
else
{           
    DisplayData[0] = 0x00;
    tp=temp;
    temp=tp*0.0625*100+0.5; 
}


        At24c02Write(1,temp);   //在地址1内写入数据num
    }
    while(!k1);
}

if(k2==0)
{
    delay(1000);  //消抖处理
    if(k2==0)
    {
        //zhuangtai=2;
        num=At24c02Read(1);         //读取EEPROM地址1内的数据保存在num中


                //num=temp;

                DisplayData[1] = smgduan[num / 10000];
        DisplayData[2] = smgduan[num % 10000 / 1000];
        DisplayData[3] = smgduan[num % 1000 / 100] | 0x80;
        DisplayData[4] = smgduan[num % 100 / 10];
        DisplayData[5] = smgduan[num% 10];
        for(i;i<500;i++){
                DigDisplay();
        }


       //Int1Init();
    }
    while(!k2);
}

}

/*******************************************************************************

  • 函 数 名 : main
  • 函数功能 : 主函数
  • 输 入 : 无
  • 输 出 : 无
    *******************************************************************************/
    void main()
    {

    while(1)
    {

    datapros(Ds18b20ReadTemp());     //数据处理函数
    

    DigDisplay();//数码管显示函数
    Keypros();

    }

    }



**接下来是EEPROM函数**
#include"i2c.h"

/*******************************************************************************
* 函数名         : Delay10us()
* 函数功能         : 延时10us
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void Delay10us()
{
    unsigned char a,b;
    for(b=1;b>0;b--)
        for(a=2;a>0;a--);

}
/*******************************************************************************
* 函数名         : I2cStart()
* 函数功能       : 起始信号:在SCL时钟信号在高电平期间SDA信号产生一个下降沿
* 输入           : 无
* 输出             : 无
* 备注           : 起始之后SDA和SCL都为0
*******************************************************************************/

void I2cStart()
{
    SDA=1;
    Delay10us();
    SCL=1;
    Delay10us();//建立时间是SDA保持时间>4.7us
    SDA=0;
    Delay10us();//保持时间是>4us
    SCL=0;          
    Delay10us();        
}
/*******************************************************************************
* 函数名         : I2cStop()
* 函数功能       : 终止信号:在SCL时钟信号高电平期间SDA信号产生一个上升沿
* 输入           : 无
* 输出             : 无
* 备注           : 结束之后保持SDA和SCL都为1;表示总线空闲
*******************************************************************************/

void I2cStop()
{
    SDA=0;
    Delay10us();
    SCL=1;
    Delay10us();//建立时间大于4.7us
    SDA=1;
    Delay10us();        
}
/*******************************************************************************
* 函数名         : I2cSendByte(unsigned char dat)
* 函数功能       : 通过I2C发送一个字节。在SCL时钟信号高电平期间,保持发送信号SDA保持稳定
* 输入           : num
* 输出             : 0或1。发送成功返回1,发送失败返回0
* 备注           : 发送完一个字节SCL=0,SDA=1
*******************************************************************************/

unsigned char I2cSendByte(unsigned char dat)
{
    unsigned char a=0,b=0;//最大255,一个机器周期为1us,最大延时255us。     
    for(a=0;a<8;a++)//要发送8位,从最高位开始
    {
        SDA=dat>>7;  //起始信号之后SCL=0,所以可以直接改变SDA信号
        dat=dat<<1;
        Delay10us();
        SCL=1;
        Delay10us();//建立时间>4.7us
        SCL=0;
        Delay10us();//时间大于4us       
    }
    SDA=1;
    Delay10us();
    SCL=1;
    while(SDA)//等待应答,也就是等待从设备把SDA拉低
    {
        b++;
        if(b>200)    //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束
        {
            SCL=0;
            Delay10us();
            return 0;
        }
    }
    SCL=0;
    Delay10us();
    return 1;       
}
/*******************************************************************************
* 函数名         : I2cReadByte()
* 函数功能         : 使用I2c读取一个字节
* 输入           : 无
* 输出             : dat
* 备注           : 接收完一个字节SCL=0,SDA=1.
*******************************************************************************/

unsigned char I2cReadByte()
{
    unsigned char a=0,dat=0;
    SDA=1;          //起始和发送一个字节之后SCL都是0
    Delay10us();
    for(a=0;a<8;a++)//接收8个字节
    {
        SCL=1;
        Delay10us();
        dat<<=1;
        dat|=SDA;
        Delay10us();
        SCL=0;
        Delay10us();
    }
    return dat;     
}


/*******************************************************************************
* 函数名         : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能         : 往24c02的一个地址写入一个数据
* 输入           : 无
* 输出             : 无
*******************************************************************************/

void At24c02Write(unsigned char addr,unsigned char dat)
{
    I2cStart();
    I2cSendByte(0xa0);//发送写器件地址
    I2cSendByte(addr);//发送要写入内存地址
    I2cSendByte(dat);   //发送数据
    I2cStop();
}
/*******************************************************************************
* 函数名         : unsigned char At24c02Read(unsigned char addr)
* 函数功能         : 读取24c02的一个地址的一个数据
* 输入           : 无
* 输出             : 无
*******************************************************************************/

unsigned char At24c02Read(unsigned char addr)
{
    unsigned char num;
    I2cStart();
    I2cSendByte(0xa0); //发送写器件地址
    I2cSendByte(addr); //发送要读取的地址
    I2cStart();
    I2cSendByte(0xa1); //发送读器件地址
    num=I2cReadByte(); //读取数据
    I2cStop();
    return num; 
}

## 程序烧录之后温度能正常显示,可以实现记忆,但是就是无法记忆当前的温度值![图片说明](https://img-ask.csdn.net/upload/201905/24/1558630299_754452.jpg)![图片说明](https://img-ask.csdn.net/upload/201905/24/1558630312_935153.jpg) 请那位大神帮忙看一下Keypros()那块的代码,还有为什么会出现这种情况

1个回答

测温程序有一定的时间,按下记忆不该再去测量,用已经测到的值直接去存测试看存储程序是否正常,另外看消抖时间似乎少了 .总之调试程序采用排除法,一步步调试排除,单片机时间的协调尤其侧重.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问