打印
[51单片机]

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

[复制链接]
2390|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
highman|  楼主 | 2013-7-21 15:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
小弟初学者,要在数码管上显示从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,还少了分号。。。求大神指点菜鸟。。。。


相关帖子

沙发
南宫云明| | 2013-7-21 17:45 | 只看该作者
我编译了一下,除了start(),stop()函数你名字调用错了的警告,read_add()函数返回值是void的错误,没出现你说的错误呀

使用特权

评论回复
板凳
黄昏初见| | 2013-7-21 19:59 | 只看该作者
必定是楼主遗漏了哪个SCL没有改成小写,可用Ctrl+F查找下试试看。

使用特权

评论回复
地板
ning@2013| | 2013-7-21 21:02 | 只看该作者
错误129一般都是些奇形怪状的语法问题,建议看看拉的时候是不是把一些中文空格之类的玩意拉过去了。感觉2楼说的是对的。。

使用特权

评论回复
5
reille| | 2013-7-22 09:36 | 只看该作者
I2C.C(67): error C129: missing ';' before 'SCL'

看下I2C.C这个文件的67行,缺少";"

使用特权

评论回复
6
airwill| | 2013-7-22 10:07 | 只看该作者
I2C.C(67): error C129: missing ';' before 'SCL'      

少了分号, 估计是中文输入的全角问题, 一定要输入 半角的分号, 编译器才认识.

使用特权

评论回复
7
tergy2012| | 2013-7-22 11:47 | 只看该作者
路过学习的

使用特权

评论回复
8
highman|  楼主 | 2013-7-22 15:30 | 只看该作者
南宫云明 发表于 2013-7-21 17:45
我编译了一下,除了start(),stop()函数你名字调用错了的警告,read_add()函数返回值是void的错误,没出现你 ...

不知道为什么我重新打开工程后原来说少了分号的错误没了,改了很多大小写,可是我改好没有错误了以后,还是没有把计数值实时写入E2PROM,每次重新上电还是从0开始计数。。。

使用特权

评论回复
9
highman|  楼主 | 2013-7-22 15:31 | 只看该作者
黄昏初见 发表于 2013-7-21 19:59
必定是楼主遗漏了哪个SCL没有改成小写,可用Ctrl+F查找下试试看。

这个提示有点怪,我已经把大写SCL全换成小写了,他还这么提示。。。

使用特权

评论回复
10
highman|  楼主 | 2013-7-22 15:33 | 只看该作者
ning@2013 发表于 2013-7-21 21:02
错误129一般都是些奇形怪状的语法问题,建议看看拉的时候是不是把一些中文空格之类的玩意拉过去了。感觉2楼 ...

有些代码是我直接从网页上copy的,可能问题出在这

使用特权

评论回复
评论
老鱼探戈 2013-7-22 18:32 回复TA
这个真晕 
11
highman|  楼主 | 2013-7-22 15:36 | 只看该作者
airwill 发表于 2013-7-22 10:07
I2C.C(67): error C129: missing ';' before 'SCL'      

少了分号, 估计是中文输入的全角问题, 一定要输 ...

这个也有可能,我是从网页上直接粘过去的,不过问题是我把错误全改好后还是没有实现重新上电接着计数,我原本照着李想那个视频写的,他视频里实现了,但我照着写的不知道为什么不行。。。

使用特权

评论回复
12
飞扬跋扈| | 2013-7-22 16:15 | 只看该作者
我照着郭天祥的视频写的I2C总线,一样是实现不了。。。

使用特权

评论回复
13
南宫云明| | 2013-7-22 18:46 | 只看该作者
highman 发表于 2013-7-22 15:30
不知道为什么我重新打开工程后原来说少了分号的错误没了,改了很多大小写,可是我改好没有错误了以后,还 ...

你先试试看最简单的程序,写一个字节到eeprom中,再读出来,先保证eeprom能读写

再调试IIC通信,看能否通信,如果以上两者都可以,再放在一起联调,一大堆代码放在一起调,根本找不出原因来。。。

使用特权

评论回复
14
highman|  楼主 | 2013-7-25 12:19 | 只看该作者
南宫云明 发表于 2013-7-22 18:46
你先试试看最简单的程序,写一个字节到eeprom中,再读出来,先保证eeprom能读写

再调试IIC通信,看能否 ...

我知道了,谢谢,我再试试

使用特权

评论回复
15
highman|  楼主 | 2013-7-25 12:31 | 只看该作者
飞扬跋扈 发表于 2013-7-22 16:15
我照着郭天祥的视频写的I2C总线,一样是实现不了。。。

郭天祥的我也试了试,你写的是不是就是那个先写到E2PROM,然后读出来送到P1口让发光二极管点亮的那个?这个我好像成功了,我回头不照李想的那个写,把这个改改再试试

使用特权

评论回复
16
highman|  楼主 | 2013-7-25 12:33 | 只看该作者
多谢各位的回复,最近两天忙着复习,忘了回复你们了,请大家见谅

使用特权

评论回复
17
ccxlslr| | 2013-7-25 14:19 | 只看该作者
其实“万恶”的 proteus这个时候是有用的。你可用它来打印逻辑图,它还有专门的I2C监视的。

使用特权

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

本版积分规则

3

主题

15

帖子

0

粉丝