打印

有关单片机做I2C从设备和有源晶振的问题

[复制链接]
3116|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zuidaeji|  楼主 | 2010-4-1 09:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
系统是一个ARM+DSP双核的系统,因要接收韦根和遥控器信号,加了一个2051。
使用无源晶振(无论是12M还是11.0592M)都可以正常接收红外信号。后面新一版本客户
要求使用有源晶振,结果上12M的晶振收红外就会出错,其他功能正常,用11.0592M都正常。当初设计是按11.0592计算的,稍微做了点冗余可以支持到12M,用示波器可以确定有源晶振的频率都很正确,在此请教高手,用无源和用有源晶振,在单片机内分频会差别很大吗??

另,因主CPU的UART口都已用完,单片机就模拟了了一个I2C从设备,红外数据和IO状态模拟成I2C设备的寄存器供主CPU读取。又因中断口用来做韦根读取了,就采用查询等待主机I2C的起始信号,但在测试中发现单片机经常检测不到起始信号,丢失率达50%以上。
下面是我检测起始信号的代码

相关帖子

沙发
zuidaeji|  楼主 | 2010-4-1 09:40 | 只看该作者
本帖最后由 zuidaeji 于 2010-4-1 09:53 编辑

bit  I2C_DEV_strat(void)
{
       unsigned char CPC=100;
       bit pre_SDA;
       pre_SDA=SDA;
     while(SCL&&CPC--)
     {
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          if((!SDA)&&SCL&&pre_SDA)
          {
               while(SCL){}

                return TRUE;
           }
          else
           pre_SDA=SDA;
      }
      return FLASE;
}

使用特权

评论回复
板凳
zuidaeji|  楼主 | 2010-4-1 09:44 | 只看该作者
按照现在这样查询,单片机的一个循环已经是接近3ms在查询起始信号,20us在检测其他状态,就这样的时间分配还是经常查不到,而I2C总线的频率才20K,就算在10K下成功率也达不到80%,尤其是读,因为读需要2个起始,有高人研究过这个东西么,还请指点指点。

使用特权

评论回复
地板
ShakaLeo| | 2010-4-1 10:17 | 只看该作者
本帖最后由 ShakaLeo 于 2010-4-1 10:21 编辑

检测I2C起始条件的部分好像有问题,本身这就是一个函数,在主程序不调用它的时候肯定是检测不到的,并且这个函数本身也有问题,尤其是那几个nop,如果SCL在那几个nop的时间内变为低电平肯定就检测不到了。

使用特权

评论回复
5
zuidaeji|  楼主 | 2010-4-1 10:33 | 只看该作者
主程序就是不停的调用起始检测,而且是先检测SDA为高的时候才调用,加那几个nop就是为了加长主程序检测起始的时间

使用特权

评论回复
6
ShakaLeo| | 2010-4-1 10:45 | 只看该作者
在那几个nop期间,不仅SDA有可能变为低电平,SCL也有可能变低电平,如果两个都变低电平了而且是SDA先变的,那就是起始条件,可按用你的程序就检测不到了。

使用特权

评论回复
7
zuidaeji|  楼主 | 2010-4-1 10:58 | 只看该作者
我测过了,在20K的频率下,起始信号的SCL要在SDA变低后28个us才变低,而在10K的时候,这个时间有56个us

使用特权

评论回复
8
zdhlixiang2006| | 2010-4-1 11:02 | 只看该作者
没用过有源晶振,不过不至于出现这种错误把,人家FPGA不都是用的有源晶振吗?

使用特权

评论回复
9
ShakaLeo| | 2010-4-1 11:24 | 只看该作者
我测过了,在20K的频率下,起始信号的SCL要在SDA变低后28个us才变低,而在10K的时候,这个时间有56个us
zuidaeji 发表于 2010-4-1 10:58


若如你所说,只有在进入循环while(SCL&&CPC--)之后的第一次循环能够确定在nop期间SCL不会变为低电平,第二次循环在nop期间就没法确定SCL不会变低啦,而第一次循环就检测到起始条件的可能性不大。

使用特权

评论回复
10
lebolkf| | 2010-4-1 11:57 | 只看该作者
楼上理解错了,他那个函数里while循环一次都不需要28个us。如楼主所说,SCL要在28us后才跟着变低的话,应该可以检测到,程序看起来好像没什么问题

使用特权

评论回复
11
ShakaLeo| | 2010-4-1 12:31 | 只看该作者
本帖最后由 ShakaLeo 于 2010-4-1 13:17 编辑

理论上在if((!SDA)&&SCL&&pre_SDA)和else pre_SDA=SDA之间SDA也有可能变低,这样if测试到的SDA是1,而pre_SDA会是0,这样也会丢失起始条件,只是发生的概率不大。还有就是如果被中断打断的时间比较长也会有丢失的情况。

使用特权

评论回复
12
linqing171| | 2010-4-1 20:34 | 只看该作者
还是用中断吧。模拟主i2c简单,模拟从的太难。
如果只有两个io还要通讯..... 还是要用中断。。

使用特权

评论回复
13
贺信| | 2010-4-1 21:58 | 只看该作者
这样子不是高手是肯定会出错

使用特权

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

本版积分规则

9

主题

79

帖子

0

粉丝