| 
 
| 将一个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("%.1f\n",shuju1);
 delayms(200);
 }
 }
 
 | 
 |