打印
[51单片机]

通过串口发送数据到24c02中存储起来

[复制链接]
2637|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
万人帝|  楼主 | 2015-9-29 14:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序调试时读出来的数据和存储的数据是一样的但是,掉电后再开机数据会丢失。
#include <reg52.h>
#define AddWr 0xa0   //器件读写地址
#define AddRd 0xa1
unsigned char a[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};   //0-10在数码管上的显示
unsigned char b[8]={0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c};      //选择数码管
sbit SDA=P2^0;              //模拟I2C数据传送位
sbit SCL=P2^1;              //模拟I2C时钟控制位
unsigned char display;
unsigned char num,flag;
void init()    //定时器初始化
{
     TMOD=0x20;  //定时器1工作方式2
     TH1=0xfd;   //高八位数据不断地重装入低八位
     TL1=0xfd;
     TR1=1;         //定时器中断允许
     REN=1;          //允许接收
     SM0=0;       //串口工作方式1
     SM1=1;
     EA=1;           //总中断允许
     ES=1;           //串口允许中断
}
void Delay(unsigned int t)    //延时
{
    int i;
    for(i=0;i<t;i++) ;
}
void Start_I2C()   //启动总线
{
    SDA=1;
Delay(1);
SCL=1;
Delay(5);
SDA=0;
Delay(5);
SCL=0;
Delay(5);
}
void Stop_I2C()     //停止总线
{
    SDA=0;
Delay(1);
SCL=1;
Delay(5);
SDA=1;
Delay(5);
}
void SendByte(unsigned char d)   //发送数据
{
    unsigned char send;
for(send=0;send<8;send++)
{
    if((d<<send)&0x80)
    {
       SDA=1;
    }
    else
    {
        SDA=0;
    }
    Delay(1);
    SCL=1;
    Delay(5);
    SCL=0;
}
Delay(2);
SDA=1;   //应答 条件SCL为高电平时,接收设备将SDA拉低
Delay(2);
SCL=1;
Delay(3);
while(SDA)
{
      Delay(1);
}
SCL=0;    //SDA线上的数据必须在SCL时钟的高电平保持稳定,只有在SCL为低电平才能改变
Delay(2);
}
unsigned char Write24c02(unsigned char dat)    //写
{
        
   Start_I2C();
   SendByte(AddWr);
   SendByte(0x02);
   SendByte(dat);
   Stop_I2C();
   return(0);
}
unsigned char RceiveByte()   //读
{
        unsigned char retc;
        unsigned char BitCnt;
        retc=0;
        SDA=1;         
        for(BitCnt=0;BitCnt<8;BitCnt++)
        {
           Delay(1);         
           SCL=0;      
           Delay(5);
           SCL=1;      
           Delay(2);
           retc=retc<<1;
           if(SDA==1)   
           {
              retc=retc+1;
           }
           Delay(2);
        }
        SCL=0;   
        Delay(1);
        return(retc);
}
void NoAck_I2C(void)
{
  
    SDA=1;
    Delay(2);     
    SCL=1;      
    Delay(5);
    SCL=0;     
    Delay(2);
}
unsigned char Read24c02()
{
        unsigned char Val;
        Start_I2C();        //启动总线
        SendByte(AddWr);    //发送器件地址 写命令
     SendByte(0x02);    //发送地址
        Start_I2C();
        SendByte(AddRd);    //发送器件地址 读命令
        Val=RceiveByte();      //读AD转值程序
        NoAck_I2C();        //发送非应位
        Stop_I2C();         //结束总线   
        return(Val);
}
void main ()
{
   
unsigned char i,t;
init();
while(1)
{   
    Write24c02(num);
    Delay(100);
    display=Read24c02();
    for(i=7;i>4;i--)     //读取存储的数据,使用三位数码管显示存储的数字  P2控制选择数码管,P0控制显示数字
    {
       P2=b[i];
    t=display%10;
    P0=a[t];
    Delay(200);
    display=display/10;
    }
         }
}
void ser() interrupt 4    //串口中断
{
    RI=0;
    num=SBUF;
}

以上是程序代码,求大侠解释

相关帖子

沙发
qjshenwen11| | 2015-9-29 16:57 | 只看该作者
1,不管怎么说,在对SDA操作时,要确保SCL是低电平,除了启动和停止外。
2,在从机ACK时,不能简单的用while(sda)来处理,这样会导致死机和复位等现象发生。
3,24C02不能这样一直不停的写,也不能这样一直不停的读。比如最简单的实验是在初始化时,先写,等待100MS左右然后再读。在WHILE里面一直写,容易把24C02写坏。
4,为了提高效率,一般用页写和页读。

使用特权

评论回复
板凳
qjshenwen11| | 2015-9-29 16:59 | 只看该作者
5,另外再搞不定,就用双踪示波器查看波形,SCL,SDA最好带上拉。

使用特权

评论回复
地板
NE5532| | 2015-9-30 08:51 | 只看该作者
读出数据之前,把缓冲区全部填充为00或者FF再度,看看到底数据写进E2没有。

使用特权

评论回复
5
万人帝|  楼主 | 2015-10-3 14:55 | 只看该作者
找到原因了,我的程序是先写进数据再读取,在每次断电开机后,就会直接将num的本身值写进去,所以掉电再上电时都会显示255,因此需要判断是否收到数据,收到则将数据发送给单片机写进24c02,否则不做任何处理。

使用特权

评论回复
6
dirtwillfly| | 2015-10-3 16:28 | 只看该作者
万人帝 发表于 2015-10-3 14:55
找到原因了,我的程序是先写进数据再读取,在每次断电开机后,就会直接将num的本身值写进去,所以掉电再上 ...

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

8

帖子

0

粉丝