OpenEdv-开源电子网

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

关于MPU6050的IIC时序的疑问!?

[复制链接]

6

主题

60

帖子

0

精华

高级会员

Rank: 4

积分
863
金钱
863
注册时间
2016-2-17
在线时间
192 小时
发表于 2017-1-5 22:51:19 | 显示全部楼层 |阅读模式
5金钱
大家好,情况是这样的:
今天我自己写了一遍MPU6050的IIC时序, 写完后发现调不通, 调试了一番后发现是void IIC_Ack(void);和void IIC_NAck(void);这两个函数出了问题。函数原型是
void IIC_Ack(void)
{
        IIC_SCL=0;
        SDA_OUT();
        IIC_SDA=0;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
}

这样。 而我把第一句和第二句位置写反了,是写成了
void IIC_Ack(void)
{
        SDA_OUT();
        IIC_SCL=0;
        IIC_SDA=0;
        delay_us(2);
        IIC_SCL=1;
        delay_us(2);
        IIC_SCL=0;
}

IIC_NAck()函数也是这样的错误,然后我不明白这两句的前后位置为什么有影响。 然后我猜想是不是第二句IIC_SCL=0;和第三句IIC_SDA=0;之间需要一点延时,然后测试发现不是这样。
然后我又想到是不是因为 在SCL高电平下SDA不可以变化,在执行这个应答函数之前SDA线是输入状态,而在SCL是高电平情况下把SDA设置为输出,因为ODR寄存器有值所以改变了SDA线的电平造成的。 然后我想测试这一点,发现void IIC_Send_Byte(u8 txd);和u8 IIC_Read_Byte(unsigned char ack);这两个函数中也有设置SDA线输入,输出状态的语句,贴出函数原型:
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
        SDA_OUT();             
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        //IIC_SDA=(txd&0x80)>>7;
                if((txd&0x80)>>7)
                        IIC_SDA=1;
                else
                        IIC_SDA=0;
                txd<<=1;           
                delay_us(2);   //对TEA5767这三个延时都是必须的
                IIC_SCL=1;
                delay_us(2);
                IIC_SCL=0;       
                delay_us(2);
    }         
}


u8 IIC_Read_Byte(unsigned char ack)
{
        unsigned char i,receive=0;
        SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
        {
        IIC_SCL=0;
        delay_us(2);
                IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
                delay_us(1);
    }                                         
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

我发现这两个函数设置SDA输入,输出状态语句之前没有加IIC_SCL=0; 于是我在这两个函数中的SDA_OUT();和SDA_IN(); 语句之前分别加了IIC_SCL=0; delay_us(2);  发现在SDA_OUT();之前加没问题,在SDA_IN(); 前加就出问题了。所以我认为我这个想法也不对。

现在想不出来原因了,于是来论坛发帖问问大家,求大家帮帮忙,感谢

我的问题: 为什么应答与非应答函数中 第一句和第二句位置不能调换?

最佳答案

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

你这样修改,是有可能影响时序的。 进入ACK之前,SDA的状态是不定的,当你此时先把SCL拉低,再设置SDA的输入输出状态,那么SDA原来是什么状态,并不会在SCL拉低之前修改。 但是如果你先设置SDA的输入输出状态,就会导致在SCL拉低之前,SDA可能会有一个状态的改变。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-1-5 22:51:20 | 显示全部楼层
你这样修改,是有可能影响时序的。 进入ACK之前,SDA的状态是不定的,当你此时先把SCL拉低,再设置SDA的输入输出状态,那么SDA原来是什么状态,并不会在SCL拉低之前修改。  但是如果你先设置SDA的输入输出状态,就会导致在SCL拉低之前,SDA可能会有一个状态的改变。
回复

使用道具 举报

6

主题

60

帖子

0

精华

高级会员

Rank: 4

积分
863
金钱
863
注册时间
2016-2-17
在线时间
192 小时
 楼主| 发表于 2017-1-5 22:52:26 | 显示全部楼层
@正点原子 原子哥求助
回复

使用道具 举报

3

主题

7

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2017-3-1
在线时间
18 小时
发表于 2017-3-2 19:58:30 | 显示全部楼层
我也查了查时序的问题,为何用延时函数,好像是说IIC分为几种速度,低速是100kHz,也就是说一个高低电平10us,一个高电平或者低电平持续时间要5us,有的设备可能不支持高速模式,我觉得有可能是这个原因,你可以改改delay_us来测试一下,我没实际尝试不确定这是不是原因
回复

使用道具 举报

6

主题

60

帖子

0

精华

高级会员

Rank: 4

积分
863
金钱
863
注册时间
2016-2-17
在线时间
192 小时
 楼主| 发表于 2017-3-11 12:14:29 | 显示全部楼层
忽悠死他 发表于 2017-3-2 19:58
我也查了查时序的问题,为何用延时函数,好像是说IIC分为几种速度,低速是100kHz,也就是说一个高低电平10u ...

感谢回答!
回复

使用道具 举报

6

主题

60

帖子

0

精华

高级会员

Rank: 4

积分
863
金钱
863
注册时间
2016-2-17
在线时间
192 小时
 楼主| 发表于 2017-3-11 12:14:50 | 显示全部楼层
正点原子 发表于 2017-3-6 20:38
你这样修改,是有可能影响时序的。 进入ACK之前,SDA的状态是不定的,当你此时先把SCL拉低,再设置SDA的输 ...

我明白了,谢谢原子哥
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-13 13:21

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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