找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1646|回复: 5
打印 上一主题 下一主题
收起左侧

单片机+iic仿真的困惑

[复制链接]
跳转到指定楼层
楼主
ID:881715 发表于 2021-10-31 11:20 来自手机 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
       各位大神大家好,谁有时间帮我解答一下这个问题,我写了一个iic的小程序,可为什仿真时iic监视器显示有数据,而芯片AT24C02C的存储器里显示的全是FF,我程序在18号地址写的是20,是程序的事吗
  1. #include<STC12C5A60S2.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define ui unsigned int
  5. sbit sda=P2^1;
  6. sbit scl=P2^0;
  7. uchar c=20;
  8. void delay7us()  //  延时函数
  9. {                                                
  10.     unsigned char a;
  11.     for(a=2;a>0;a--);
  12. }
  13.    void init()
  14. {sda=1;
  15.   delay7us();
  16.    scl=1;
  17. delay7us();
  18. }         
  19. /*启动信号函数*/
  20. void start()  //启动信号函数
  21. { scl=1;         
  22.    sda=1;
  23.    delay7us();
  24.   sda=0;
  25.    delay7us();        
  26. }        
  27. /*写一个字节的函数*/
  28. void write_iic_byte(uchar dat)        
  29.                               
  30. { uchar i;
  31.    scl=0;  /*主机拉低为的是SDA数据线
  32.                    可以发生变化并为SDA拉高,让
  33.                    接受设备接收数据做准备*/
  34.         /*发送八位数据*/
  35.    for(i=0;i<8;i++)
  36.     { if(dat&0X80)
  37.              sda=1;/*主机将数据1存入SDA*/
  38.          else
  39.                  sda=0;/*主机将数据0存入SDA
  40.                                 ,也可认为是存入一个
  41.                                 存储器*/
  42.           scl=1;  /*主机将时钟数据线拉高*/
  43.            delay7us(); /*延时接收设备在此期间
  44.                                   自动取走*/
  45.            dat=dat<<1;/* 数据左移一位,次高位
  46.                               变成发送数据位*/
  47.                 scl=0;/*时钟线拉低为更改发送数据
  48.                            位做准备,只有其为低数据线
  49.                            上的数据才会发生改变。*/
  50. }         
  51.      sda=1;/*释放数据线*/        
  52.   }                        
  53. /*读一个字节的函数*/
  54. uchar read_iic_byte()
  55. { uchar i,v;/*暂时为空变量,8次后
  56.                              存储要保存的数据*/
  57.    sda=1;/*主机释放数据线,这数据
  58.                   状态以后有发送设备决定*/
  59.    scl=0;/*主机将时钟信号线拉低,
  60.                    /*SDA线上的数据才会改变*/
  61.    /*从设备发送八位数据*/
  62.    for(i=0;i<8;i++)
  63.         { v=v<<1; /*第一次循环无意义,以后
  64.                           发送用*/
  65.           scl=1;  /*以后发送期间数据稳定*/
  66.          delay7us();/*延时使主机有时间取走
  67.                            数据*/
  68.          if(sda) /*SDA发送从设备里最高位数据
  69.                           1,第一次循环从此发送第一
  70.                           位数据*/
  71.                 v=v|0X01;/*把1传入变量V的最低位*/
  72.         scl=0;         /*时钟线拉低发送数据由发送
  73.                            设备自动改变*/

  74.         delay7us();/*延时使时钟线可靠拉低
  75.                                  ,有充足时间数据被读走
  76.                                  */
  77.         }
  78.         return v; /*被读的数据存在V中,
  79.                           作为返回值/*返回*/
  80. }         
  81.            
  82. void stop()//停止信号函数
  83. {scl=1;
  84.   sda=0;
  85.   delay7us();
  86.   sda=1;
  87.   delay7us();
  88. }           
  89.   /*产生和检测应答信号        */
  90. uchar ack()
  91. {uchar i;
  92.   scl=0;
  93.   sda=0;
  94.   delay7us();        
  95.   scl=1;        
  96.   delay7us();
  97.   while(sda==1)
  98.    { i++;
  99.             if(i>260)
  100.            {
  101.                     stop();
  102.                  return 1;
  103.            }
  104.    }
  105.         return 0;
  106.   }
  107. /* 产生非应答信号*/         
  108. void noack()
  109. {scl=0;
  110.   sda=1;
  111.   delay7us();
  112.   scl=1;
  113.   delay7us();
  114.   scl=0;
  115. }
  116. void main()
  117. {         do
  118.     {init();
  119.          start();
  120.          write_iic_byte(0XA0);
  121.          ack();
  122.          write_iic_byte(0X18);
  123.           ack();
  124.           write_iic_byte(c);
  125.           ack();
  126.           stop();
  127.                 delay7us();
  128.         }
  129.   while(0);
  130.   while(1);
  131. }
复制代码

IMG_20211031_110437.jpg (632.98 KB, 下载次数: 38)

IMG_20211031_110437.jpg
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:881715 发表于 2021-10-31 11:24 | 只看该作者
  1. #include<STC12C5A60S2.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define ui unsigned int
  5. sbit sda=P2^1;
  6. sbit scl=P2^0;
  7. uchar c=20;
  8. void delay7us()  //  延时函数
  9. {                                                 
  10.     unsigned char a;
  11.     for(a=2;a>0;a--);
  12. }
  13.    void init()
  14. {sda=1;
  15.   delay7us();
  16.    scl=1;
  17. delay7us();
  18. }        
  19. /*启动信号函数*/
  20. void start()  //启动信号函数
  21. { scl=1;         
  22.    sda=1;
  23.    delay7us();
  24.   sda=0;
  25.    delay7us();       
  26. }       
  27. /*写一个字节的函数*/
  28. void write_iic_byte(uchar dat)       
  29.                               
  30. { uchar i;
  31.    scl=0;  /*主机拉低为的是SDA数据线
  32.                    可以发生变化并为SDA拉高,让
  33.                    接受设备接收数据做准备*/
  34.         /*发送八位数据*/
  35.    for(i=0;i<8;i++)
  36.     { if(dat&0X80)
  37.              sda=1;/*主机将数据1存入SDA*/
  38.          else
  39.                  sda=0;/*主机将数据0存入SDA
  40.                                 ,也可认为是存入一个
  41.                                 存储器*/
  42.           scl=1;  /*主机将时钟数据线拉高*/
  43.            delay7us(); /*延时接收设备在此期间
  44.                                   自动取走*/
  45.            dat=dat<<1;/* 数据左移一位,次高位
  46.                               变成发送数据位*/
  47.                 scl=0;/*时钟线拉低为更改发送数据
  48.                            位做准备,只有其为低数据线
  49.                            上的数据才会发生改变。*/
  50. }         
  51.      sda=1;/*释放数据线*/       
  52.   }                        
  53. /*读一个字节的函数*/
  54. uchar read_iic_byte()
  55. { uchar i,v;/*暂时为空变量,8次后
  56.                              存储要保存的数据*/
  57.    sda=1;/*主机释放数据线,这数据
  58.                   状态以后有发送设备决定*/
  59.    scl=0;/*主机将时钟信号线拉低,
  60.                    /*SDA线上的数据才会改变*/
  61.    /*从设备发送八位数据*/
  62.    for(i=0;i<8;i++)
  63.         { v=v<<1; /*第一次循环无意义,以后
  64.                           发送用*/
  65.           scl=1;  /*以后发送期间数据稳定*/
  66.          delay7us();/*延时使主机有时间取走
  67.                            数据*/
  68.          if(sda) /*SDA发送从设备里最高位数据
  69.                           1,第一次循环从此发送第一
  70.                           位数据*/
  71.                 v=v|0X01;/*把1传入变量V的最低位*/
  72.         scl=0;         /*时钟线拉低发送数据由发送
  73.                            设备自动改变*/

  74.         delay7us();/*延时使时钟线可靠拉低
  75.                                  ,有充足时间数据被读走
  76.                                  */
  77.         }
  78.         return v; /*被读的数据存在V中,
  79.                           作为返回值/*返回*/
  80. }        
  81.           
  82. void stop()//停止信号函数
  83. {scl=1;
  84.   sda=0;
  85.   delay7us();
  86.   sda=1;
  87.   delay7us();
  88. }          
  89.   /*产生和检测应答信号        */
  90. uchar ack()
  91. {uchar i;
  92.   scl=0;
  93.   sda=0;
  94.   delay7us();       
  95.   scl=1;       
  96.   delay7us();
  97.   while(sda==1)
  98.    { i++;
  99.             if(i>260)
  100.            {
  101.                     stop();
  102.                  return 1;
  103.            }
  104.    }
  105.         return 0;
  106.   }
  107. /* 产生非应答信号*/         
  108. void noack()
  109. {scl=0;
  110.   sda=1;
  111.   delay7us();
  112.   scl=1;
  113.   delay7us();
  114.   scl=0;
  115. }
  116. void main()
  117. {
  118.     {init();
  119.          start();
  120.          write_iic_byte(0XA0);
  121.          ack();
  122.          write_iic_byte(0X18);
  123.           ack();
  124.           write_iic_byte(c);
  125.           ack();
  126.           stop();
  127.                 delay7us();
  128.         }
  129.   while(1);
  130. }
复制代码
回复

使用道具 举报

板凳
ID:46065 发表于 2021-10-31 20:39 | 只看该作者
我们都是延时5US,不知道7US会不会影响,手册上是4.7和4US
回复

使用道具 举报

地板
ID:401564 发表于 2021-10-31 21:17 | 只看该作者
你的应答是错误的,SDA=1才是对的,这叫释放SDA端口
SDA=0了就无法检测电平状态了
有电脑,有开发板,不是复杂运算,仿真没有用,仿真要用在真正需要的地方IIC写入字节是可以很简单的,不需要那么复杂

void Write_Byte(unsigned char Byte)                        //写入器件的应答信号由从机给出
{
        unsigned char i;
        unsigned int k;               
        SCL=0;
        Delay();
        for(i=0;i<8;i++)
                         {
                                if(Byte&0x80)SDA=1;
                                else SDA=0;
                                Delay();
                                SCL=1;
                                Delay();               
                                SCL=0;
                                Byte<<=1;
                        }
        SCL=1;                                                   //给出一个上升沿,用于产生应答信号
        Delay();
        SDA=1;
        while((SDA==1)&(k<1000))         //超时就不再等待应答
                {
                        k++;
                        Delay();
                }                                                 //等待SDA出现低电平,出现低电平就表示器件已经应答
        SCL=0;
}

回复

使用道具 举报

5#
ID:420836 发表于 2021-11-1 08:21 | 只看该作者
向I2C总线写入一个字节时,在FOR循环中,每次左移一位,将SCL设置为高电平,必须延迟7微秒,然后将SCL拉低。 并重复下一个数位。
回复

使用道具 举报

6#
ID:881715 发表于 2021-11-1 17:31 来自手机 | 只看该作者
多谢大师们指教
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表