微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > float型数据通过AT24C02存取的问题。

float型数据通过AT24C02存取的问题。

时间:10-02 整理:3721RD 点击:
将一个float型数据存到AT24C02中,再读出到串口显示,为啥串口显示的是一个错误的数呀?是我程序哪有问题吗?请各位大神指点。谢谢
#include<reg51.h>
#include <stdio.h>
#define write_c02 0xa0
#define read_c02 0xa1
typedef unsigned char uchar;
typedef unsigned int uint;
sbit sda = P2^0;
sbit scl = P2^1;
/*********延时**************/
void delay()           //约5us
{
    ;;
}
void delayms(uint xms)  //延时X毫秒
{
    uchar x,y;
        for(x=xms;x>0;x--)
            for(y=110;y>0;y--);        
}
/**********I2C子程序***************/
void i2c_init()          //I2C初始化
{
    sda=1;
        delay();
        scl=1;
        delay();
}
void start()      //启动I2C
{
    sda=1;
        scl=1;
        delay();    //在scl为高电平时,sda一个下降沿为启动信号
        sda=0;     
        delay();
}
void stop()        //停止I2C
{
    sda=0;
        scl=1;
        delay();
        sda=1;          //在scl为高电平时,sda一个上升沿为停止信号
        delay();
}
void ack()       //应答信号0
{
    uchar i=0;   //等待变量
        scl=1;       //在scl为高电平期间等待应答
        delay();
        while((sda=1)&&i<250)//若为应答0即退出,从机向主机发送应答信号
        i++;
        scl=0;       //应答之后将scl拉低
        delay();
}
void nack()      //非应答
{
    scl=1;       //在scl为高电平期间,由主机向从机发送一个1;非应答信号
        delay();
        sda=1;
        scl=0;       //应答之后将scl拉低
        delay();
}
void send_byte(uchar date)  //写一个字节
{
    uchar i , temp;
        temp=date;     //存入要写入的数据,即要发送到sda上的数据
        for(i=0;i<8;i++)
        {
            temp<<=1;
                scl=0;     //只有在scl为低电平时,才允许sda上的数据变化
                delay();
                sda=CY;    //将CY里的数据发送到sda数据线上
                delay();
                scl=1;     //在scl为高电平时,不允许sda上的数据变化,使数据稳定
                delay();
                scl=0;     //允许sda数据线的数据变化,等待下一个数据的传输
                delay();
        }//发送完一个字节数据后主机要等待从机的应答
        scl=0;//允许sda变化
        delay();
        sda=1;//sda拉高等待应答,当sda=0时,表示从机应答
        delay();
}                       
uchar read_byte()        //读一个字节数据
{
    uchar i,j,k;
        scl=0;         //读之前先允许sda变化
        delay();       //等待数据
        for(i=0;i<8;i++)
        {
            scl=1;     //不允许sda变化
                delay();
                j=sda;     //读出sda上的数据
                k=(k<<1)|j;//将数据通过|运算存入K中
            delay();
                scl=0;     //允许sda变化等待下一位数据的到来
                delay();
        }
        delay();
        return k;      //返回读出的数据
}
/*****************从AT24C02中存取数据***********************/
void write_at24c02(uchar address,uchar date)//在at24c02中的指定地址写入数据、
{
    start();         //启动I2C
        send_byte(write_c02); //写入期间地址和写操作
        ack();        //从机应答0
        send_byte(address);//写入写数据的单元地址
        ack();
        send_byte(date);//在指定地址中写入数据
        ack();
        stop();         //停止I2C
}
uchar read_at24c02(uchar address)//在at24c02的指定地址中读出写入的数据
{
    uchar dat;   //用来存储读出的数据
        start();     //启动I2C
        send_byte(write_c02);//写入at24c02期间地址和写操作
        ack();
        send_byte(address);  //写入要读取at24c02的数据的单元地址
        ack();
        start();          //再次启动I2C
        send_byte(read_c02);//写入at24c02期间地址和读操作
        ack();
        dat=read_byte();//读出指定地址中的数据
        nack();//主机发出非应答1
        stop();//停止I2C
        return dat;
}
/**********************从AT24C02中存取float型数据****************************/
void write_f_rom(uchar address,float date)//将系数存入AT24C02
{
    unsigned long d;
        unsigned char d0,d1,d2,d3;
        d=(unsigned long)(date);
        d0=(unsigned char)(d>>24);
        d1=(unsigned char)((d&0x00ff0000)>>16);
        d2=(unsigned char)((d&0x0000ff00)>>8);
        d3=(unsigned char)(d%256);
        delayms(10);
        write_at24c02(address,d0);
        delayms(10);
        write_at24c02(address+0x01,d1);
        delayms(10);
        write_at24c02(address+0x02,d2);
        delayms(10);
        write_at24c02(address+0x03,d3);
        delayms(10);
}
float read_f_rom(unsigned char address)        //从AT24C02中读取数据
{
    unsigned char i;
        float date;
        unsigned char c[4];
        unsigned long d[4];
        for(i=0;i<4;i++)
        {
            read_at24c02(address+i);
                c[i]=read_at24c02(address+i);      
        }
    for(i=0;i<4;i++)
        {
            d[i]=(unsigned long)c[i];
        }
        date=((float)((long)((d[0]<<24)+(d[1]<<16)+(d[2]<<8)+d[3])));
        return date;
}
/******************串口初始化**********************/
void uart_init(void) //串口的初始化
{
    TMOD=0x20;//即0010 0000,定时器/计数器1,工作方式2
    TH1=0xfd;//设置波特率为9600
    TL1=0xfd;
    TR1=1;//启动定时器/计数器1        
    SCON=0x50; //0101 0000.串口工作方式1,允许串行控制
    PCON=0x00;//设置SMOD=0
    IE=0x90; //CPU允许中断,串行允许中断     
    TI=1;//直接使用printf必须加入此句才能实现发送
        ES=1;//开串口中断
        EA=1;//开总中断
}
void main()
{
//    uchar i;
        float shuju=1.1;
        float shuju1;
        i2c_init();
        uart_init();
        start();
        while(1)
        {
                write_f_rom(0x00,shuju);
                delayms(100);
                shuju1=read_f_rom(0x00);
                delayms(100);
                printf("%f\n",shuju1);
                delayms(200);
        }
}

应该跟数据处理有关吧

不加下面的程序,单独存取char型数据没有问题,比如‘A’。存取float型数据通过串口显示的也是错误的数。加了下面的程序存取float型数据,显示到串口助手上就变成其他数据了。感觉思路应该没有问题吧。请大神指点。谢谢。
void write_f_rom(uchar address,float date)//将系数存入AT24C02
{
    unsigned long d;
        unsigned char d0,d1,d2,d3;
        d=(unsigned long)(date);
        d0=(unsigned char)(d>>24);
        d1=(unsigned char)((d&0x00ff0000)>>16);
        d2=(unsigned char)((d&0x0000ff00)>>8);
        d3=(unsigned char)(d%256);
        delayms(10);
        write_at24c02(address,d0);
        delayms(10);
        write_at24c02(address+0x01,d1);
        delayms(10);
        write_at24c02(address+0x02,d2);
        delayms(10);
        write_at24c02(address+0x03,d3);
        delayms(10);
}
float read_f_rom(unsigned char address)        //从AT24C02中读取数据
{
    unsigned char i;
        float date;
        unsigned char c[4];
        unsigned long d[4];
        for(i=0;i<4;i++)
        {
            read_at24c02(address+i);
                c=read_at24c02(address+i);      
        }
    for(i=0;i<4;i++)
        {
            d=(unsigned long)c;
        }
        date=((float)((long)((d[0]<<24)+(d[1]<<16)+(d[2]<<8)+d[3])));
        return date;
}

楼上正解收藏了先。

你怎么判断串口助手接收到的数据是错误的,其实只要串口助手接收到的数据和你储存的一样就可以了

(?。?)串口助手接收到的数据和我存储的不一样,我又试了改变我给定的float型数据,无论是给的1.1还是3.4最后串口助手显示的都是4325.6。

存储时应该直接把float分四个字节存储就好了,不应该做数据格式转换。

(?。?)好的,我试试。谢谢

从你这情况看确实是数据处理的问题,你好好了解一下float型数据在单片机内部如何存储的,然后依照此方式存储和读取即可

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

网站地图

Top