OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5592|回复: 7

模拟IIC通信的时候为什么先把SCL拉低再配置SDA的输出而反过来就不行

[复制链接]

18

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-11-28
在线时间
208 小时
发表于 2016-4-25 18:45:54 | 显示全部楼层 |阅读模式
1金钱
[mw_shl_code=c,true]//产生ACK应答
void CT_IIC_Ack(void)
{
        CT_IIC_SCL=0;
        CT_SDA_OUT();
        CT_Delay();
        CT_IIC_SDA=0;
        CT_Delay();
        CT_IIC_SCL=1;
        CT_Delay();
        CT_IIC_SCL=0;
}
//不产生ACK应答                    
void CT_IIC_NAck(void)
{
        CT_IIC_SCL=0;
        CT_SDA_OUT();
        CT_Delay();
        CT_IIC_SDA=1;
        CT_Delay();
        CT_IIC_SCL=1;
        CT_Delay();
        CT_IIC_SCL=0;
}                                        [/mw_shl_code]
源于正点原子的触摸屏实验当把代码改成下面这样。
[mw_shl_code=applescript,true]
//产生ACK应答
void CT_IIC_Ack(void)
{
        //CT_IIC_SCL=0;
        CT_SDA_OUT();
        CT_IIC_SCL=0;
        CT_Delay();
        CT_IIC_SDA=0;
        CT_Delay();
        CT_IIC_SCL=1;
        CT_Delay();
        CT_IIC_SCL=0;
}[/mw_shl_code]
。照理说我这个CT_SDA_OUT只是配置GPIOF 的MODER把IO方向设置为输出,对IO口并无影响。但是为什么我像下面这样写就不行呢? 照理说和上面写是一样的效果啊,求大神指教!

最佳答案

查看完整内容[请看2#楼]

从上图可以看出应答和非应答的时序; 应答和非应答是由我们的主机发送的,而且是在接收完一个字节发送的。我们接收字节的时候会把 CT_SDA_IN();也就是说会把SDA线设置为输入状态这个时候IO口是高阻状态的,从外面看上去是逻辑1. 我们的时序要求在接收到一个字节后就立马发送应答信号。 由于之前我们的IO是配置为读取状态是高阻状态也就是逻辑1 我们读取的代码是这么写的,读完过后SCL=1; SDA=1;(这里SDA我不清楚是不是1了 ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

18

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-11-28
在线时间
208 小时
 楼主| 发表于 2016-4-25 18:45:55 | 显示全部楼层
QQ截图20160426134502.jpg
   从上图可以看出应答和非应答的时序;
应答和非应答是由我们的主机发送的,而且是在接收完一个字节发送的。我们接收字节的时候会把 CT_SDA_IN();也就是说会把SDA线设置为输入状态这个时候IO口是高阻状态的,从外面看上去是逻辑1.   我们的时序要求在接收到一个字节后就立马发送应答信号。 由于之前我们的IO是配置为读取状态是高阻状态也就是逻辑1  我们读取的代码是这么写的,读完过后SCL=1; SDA=1;(这里SDA我不清楚是不是1了,只是猜测我脑袋有限只能想到这个解释办法)
[mw_shl_code=c,true]
u8 CT_IIC_Read_Byte(unsigned char ack)
{
        u8 i,receive=0;
        CT_SDA_IN();//SDA设置为输入
        delay_us(4);
        for(i=0;i<8;i++ )
        {
                CT_IIC_SCL=0;                       
                CT_Delay();
                CT_IIC_SCL=1;         
                receive<<=1;
                if(CT_READ_SDA)receive++;  
        //receive|=CT_READ_SDA;               
        }                                           
        if (!ack)CT_IIC_NAck();//发送nACK
        else CT_IIC_Ack(); //发送ACK   
        return receive;
}[/mw_shl_code]
)如果是这样的话那么这就是一个非应答信号了只能收到头1个字节就非应答了。事实上串口也只输出了头一个正确的字节。
[mw_shl_code=c,true]
//产生ACK应答
void CT_IIC_Ack(void)
{
        CT_SDA_OUT();
CT_IIC_SCL=0;
CT_Delay();
        CT_IIC_SDA=0;
        CT_Delay();
        CT_IIC_SCL=1;
        CT_Delay();
        CT_IIC_SCL=0;
}[/mw_shl_code]

。一个非应答的信号需要4US,上面的CT_SDA_OUT();可能就4US了。造成了非应答。
[mw_shl_code=c,true]
//产生ACK应答
void CT_IIC_Ack(void)
{
        CT_IIC_SCL=0;
        CT_SDA_OUT();
CT_Delay();
        CT_IIC_SDA=0;
        CT_Delay(); //延迟4US
        CT_IIC_SCL=1;
        CT_Delay();
        CT_IIC_SCL=0;
}[/mw_shl_code]
  如果在CT_SDA_OUT();前把SCL拉低就不会造成非应答,非应答是指SCL为高的时候SDA有4US的高电平。
这个时候把SDA配置为输出,SDA拉低过后延迟4US拉高SCL延迟4US(在SCL为高的时候有4us的低电平)形成了应答信号。 这个时候时序才正确程序才能正常进行。


                                     当然以上的推断仅仅是在IO口配置成输入,IO口会呈现高阻状态而且IIC通信器件会把这个状态当成是逻辑1以上推论才正确。 如果哪位大神觉得我这错得像耍猴一样,请不要吝啬您的教诲!请帮我指出错误。谢谢!
回复

使用道具 举报

18

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-11-28
在线时间
208 小时
 楼主| 发表于 2016-4-25 18:48:04 | 显示全部楼层
我只是把这个CT_IIC_SCL=0放到CT_SDA_OUT下面来不应该会出现问题啊。不都是一样的效果吗?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165377
金钱
165377
注册时间
2010-12-1
在线时间
2111 小时
发表于 2016-4-25 21:48:18 | 显示全部楼层
没这么试过,去看看IIC协议吧
回复

使用道具 举报

43

主题

481

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1352
金钱
1352
注册时间
2014-12-24
在线时间
321 小时
发表于 2016-4-25 23:05:54 | 显示全部楼层
只知道看代码乱猜,而不知道看看协议以及电路硬件?
回复

使用道具 举报

18

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-11-28
在线时间
208 小时
 楼主| 发表于 2016-4-25 23:17:36 | 显示全部楼层
正点原子 发表于 2016-4-25 21:48
没这么试过,去看看IIC协议吧

原子哥你好,协议我都懂。可是这两种写法本质上是没有区别才对啊。以前用51写的IIC通信过的。STM32就搞不懂了。明明CT_SDA_OUT只是设定一下IO方向而已又没有操作IO口但是把
            CT_IIC_SCL=0写在它的下面却不行。这个不科学啊!
回复

使用道具 举报

18

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-11-28
在线时间
208 小时
 楼主| 发表于 2016-4-25 23:27:01 | 显示全部楼层
jinggx 发表于 2016-4-25 23:05
只知道看代码乱猜,而不知道看看协议以及电路硬件?

首先并非乱猜,可能我有点乱。你没明白我在说什么!
   这么解释吧。
        PBout(0)=0;
        CT_SDA_OUT;  //把PF13配置为输出
       ……

      先配置输出CT_SDA_OUT;
                        PBout(0)=0;
  这两者反应在硬件上有没有区别。是这个意思。 硬件和IIC协议我都明白。但是这两种写法效果却不一样那一定是原因的。
回复

使用道具 举报

18

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
764
金钱
764
注册时间
2015-11-28
在线时间
208 小时
 楼主| 发表于 2016-4-26 11:08:23 | 显示全部楼层
奇怪呢。先输出PB0再配置PF13为输出和
                                                             先配置PF13再输出PB0居然有不同的效果?他们先后顺序反应在IO口中到底有什么不同?
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 01:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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