微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 一个I2C总线的问题,有个错误找不出来,求指点

一个I2C总线的问题,有个错误找不出来,求指点

时间:10-02 整理:3721RD 点击:
小弟初学者,要在数码管上显示从0加一到99,大概每秒加一次,并使用E2PROM实时保存技术值,使掉电后接着掉电前的数开始加一计数,程序如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
sbit sda=P2^0;
sbit scl=P2^1;
sbit dula=P2^6;
sbit wela=P2^7;
uchar sec=0,t=0,E0;
bit flag=0;
void delay()        //短延时
{;;}
void delay1(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void init()    //初始化
{
        scl=1;
        delay();
        sda=1;
        delay();
}
void start()        //起始信号
{
        scl=1;
        delay();
        sda=1;
        delay();
        sda=0;
        delay();
        scl=0;                //钳住I2C总线,准备发送或接收数据
        delay();
}
void stop()                //终止信号
{
        scl=1;
        delay();
        sda=0;
        delay();
        sda=1;
        delay();
}
void Ack()    //发送应答位子程序
{
   sda=0;
   scl=1;
   delay();
   scl=0;
   sda=1;
}
void NoAck()   //发送非应答位子程序
{
   sda=1;
   scl=1;
   delay();
   scl=0;
   sda=0;
}
uchar TestAck() //应答位检查子程序,若检测不到非应答信号,置位E0
{
   sda=1;
   scl=1;
   E0=0;
   _nop_(); //短延时
   if(sda==1) //如果SDA为1,表明非应答,置位非应答标志E0
      E0=1;
   scl=0;
   return E0;
}
void writebyte(uchar n) //写一个字节数据子程序,n为待发送的数据
{
   uchar i;
   for(i=8;i>0;i--)
   {
      sda=(bit)(n&0x80);
   scl=1;
   delay();
   scl=0;
   sda=0;
   n=n<<1;
   }
}
uchar readbyte(void)   //读一个字节数据子程序
{
    uchar temp,rbyte=0;
        for(temp=8;temp>0;temp--)
        {
            sda=1;
            scl=1;
            _nop_(); //短延时
               rbyte=rbyte<<1;
            rbyte=rbyte|((uchar)(sda));
            scl=0;
        }
    return(rbyte);
}
void write_add(uchar date,uchar RomAddress) // 写n个字节数据子程序
{   
        Start(); //启动
        writebyte(0xa0); //写入器件的寻址地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        writebyte(RomAddress); //写入I2C器件的数据存储首地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        
        
            writebyte(date); //写一个字节
            TestAck();    //应答检查
            if(E0==1)
            {
               NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
               return;
            }
            
        
                Stop();     //全部发送完则停止
}

void read_add(uchar RomAddress) // 读n个字节数据子程序
{   
    //RamAddress为接收数据缓冲区的首地址,RomAddress为待I2C外围器件的数据读取首地址,bytes为写字节的个数
        uchar date;
           Start(); //启动
        writebyte(0xa0); //写入器件的寻址地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        writebyte(RomAddress); //写入I2C器件内部数据的读取首地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        Start(); //重新启动
        writebyte(0xa1); //写入器件的寻址地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        date=readbyte();
        NoAck();   //非应答
        Stop();   
}
void display(uchar sec)      //数码管显示函数
{        uchar shi,ge;
        shi=sec/10;
        ge=sec%10;
         dula=1;
         P0=table[shi];
         dula=0;
         P0=0xff;
         wela=1;
         P0=0xfe;
         wela=0;
         delay1(10);
         dula=1;
         P0=table[ge];
         dula=0;
         P0=0xff;
         wela=1;
         P0=0xfd;
         wela=0;
         delay1(10);
}
void main()
{
        init();
        sec=read_add(0x02);
        if(sec>=100)
                sec=0;
        TMOD=0x01;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        ET0=1;
        EA=1;
        TR0=1;
        while(1)
        {
        
                display(sec);
                if(flag==1)
                {        
                        flag=0;
                        write_add(0x02,sec);
                }
        }
}
void timer0() interrupt 1
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        t++;
        if(t==20)
        {
            t=0;
                sec++;
                if(sec==100)
                        sec=0;
                flag=1;
        }
}
错误提示:I2C.C(67): error C129: missing ';' before 'SCL'      
关于I2C的程序我是在网上抄的,原先我自己写的没有实现实时保存技术值,由于它的SCL是大写,为了跟我原来的一样,我把它全部改成了小写,但不知为什么他还提示有大写SCL,还少了分号。求大神指点菜鸟。

#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
sbit sda=P2^0;
sbit scl=P2^1;
sbit dula=P2^6;
sbit wela=P2^7;
uchar sec=0,t=0,E0,NACK;
bit flag=0;
void delay()        //短延时
{;;}
void delay1(uint z)
{
        uint x,y;
        for(x=z;x>0;x--)
                for(y=110;y>0;y--);
}
void init()    //初始化
{
        scl=1;
        delay();
        sda=1;
        delay();
}
void start()        //起始信号
{
        scl=1;
        delay();
        sda=1;
        delay();
        sda=0;
        delay();
        scl=0;                //钳住I2C总线,准备发送或接收数据
        delay();
}
void stop()                //终止信号
{
        scl=1;
        delay();
        sda=0;
        delay();
        sda=1;
        delay();
}
void Ack()    //发送应答位子程序
{
   sda=0;
   scl=1;
   delay();
   scl=0;
   sda=1;
}
void NoAck()   //发送非应答位子程序
{
   sda=1;
   scl=1;
   delay();
   scl=0;
   sda=0;
}
uchar TestAck() //应答位检查子程序,若检测不到非应答信号,置位E0
{
   sda=1;
   scl=1;
   E0=0;
   _nop_(); //短延时
   if(sda==1) //如果SDA为1,表明非应答,置位非应答标志E0
      E0=1;
   scl=0;
   return E0;
}
void writebyte(uchar n) //写一个字节数据子程序,n为待发送的数据
{
   uchar i;
   for(i=8;i>0;i--)
   {
      sda=(bit)(n&0x80);
   scl=1;
   delay();
   scl=0;
   sda=0;
   n=n<<1;
   }
}
uchar readbyte(void)   //读一个字节数据子程序
{
    uchar temp,rbyte=0;
        for(temp=8;temp>0;temp--)
        {
            sda=1;
            scl=1;
            _nop_(); //短延时
               rbyte=rbyte<<1;
            rbyte=rbyte|((uchar)(sda));
            scl=0;
        }
    return(rbyte);
}
void write_add(uchar date,uchar RomAddress) // 写n个字节数据子程序
{   
        start(); //启动
        writebyte(0xa0); //写入器件的寻址地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        writebyte(RomAddress); //写入I2C器件的数据存储首地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        
        
            writebyte(date); //写一个字节
            TestAck();    //应答检查
            if(E0==1)
            {
               NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
               return;
            }
            
        
                stop();     //全部发送完则停止
}

int read_add(uchar RomAddress) // 读n个字节数据子程序
{   
    //RamAddress为接收数据缓冲区的首地址,RomAddress为待I2C外围器件的数据读取首地址,bytes为写字节的个数
        uchar date;
           start(); //启动
        writebyte(0xa0); //写入器件的寻址地址
        TestAck();    //应答检查
        if(E0==1)
        {
                    NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        writebyte(RomAddress); //写入I2C器件内部数据的读取首地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        start(); //重新启动
        writebyte(0xa1); //写入器件的寻址地址
        TestAck();    //应答检查
        if(E0==1)
        {
            NACK=1;   //若非应答表明器件错误或已坏,置错误标志位NACK
            return;
        }
        date=readbyte();
        NoAck();   //非应答
        stop();   
}
void display(uchar sec)      //数码管显示函数
{        uchar shi,ge;
        shi=sec/10;
        ge=sec%10;
         dula=1;
         P0=table[shi];
         dula=0;
         P0=0xff;
         wela=1;
         P0=0xfe;
         wela=0;
         delay1(10);
         dula=1;
         P0=table[ge];
         dula=0;
         P0=0xff;
         wela=1;
         P0=0xfd;
         wela=0;
         delay1(10);
}
void main()
{
        init();
        sec=read_add(0x02);
        if(sec>=100)
                sec=0;
        TMOD=0x01;
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        ET0=1;
        EA=1;
        TR0=1;
        while(1)
        {
        
                display(sec);
                if(flag==1)
                {        
                        flag=0;
                        write_add(0x02,sec);
                }
        }
}
void timer0() interrupt 1
{
        TH0=(65536-50000)/256;
        TL0=(65536-50000)%256;
        t++;
        if(t==20)
        {
            t=0;
                sec++;
                if(sec==100)
                        sec=0;
                flag=1;
        }
}
编译无错误 ,小编的只是有些地方大小写写错了,我还改了read_add函数的类型为int    不知道对不对,我对程序还勉强看得懂...

谢谢大神花时间看这个,不过很奇怪,我重新打开一次工程原来的错误就没了,换了很多大小写,可是改好后程序还是没有把时间写进E2PROM,每次重新上电都是从0开始计数

哦 你不说我还忘记了。我也是刚学的,你程序好像没有任何关于那个外部存储器的吧,肯定就没记录了。这就是纯粹I2c...

没没,有往里写东西,E2PROM是一个I2c器件,有地址,那句有0xa0的就是往里写,我原本就是照着李想那个视频写的,但是他视频里成功了,我没成功。

因为同样是新手,我看的是郭天祥的书,里面用到外部存储器的话,要设置很多东西,还要在你的程序显示的数据变化一次就要写到存储器里一次,有点麻烦,你这个啊,我不是很明白...

器件地址有没对?

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

网站地图

Top