OpenEdv-开源电子网

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

IIC调试一直读回的都是0xff

[复制链接]

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
发表于 2018-7-12 09:16:59 | 显示全部楼层 |阅读模式
1金钱
本帖最后由 dragonFANG 于 2018-7-12 09:23 编辑

小弟我用STM32模拟IIC的端口,读AT24C02时一直都是返回值是0xff,查了好久都没有查到原因。我也参考了原子哥的程序了。原子哥程序里的us级的延时是需要的吗?我程序里用了没有用到这个,但是我用了几个nop还是不行,后来又改回来了。小弟用的是hal库写的。现在将代码附上,麻烦各位有空的帮我看一下问题出在哪?

[mw_shl_code=c,true]#include "includes.h"

At24c02 At24c02Obj;

/**
  *@ 函数名:At24c02_Init
  *@ 功能:AT24C02初始化
  */
void At24c02_Init(void)
{
    GPIO_InitTypeDef At24c02_InitStruct;
    __HAL_RCC_GPIOB_CLK_ENABLE();
    At24c02_InitStruct.Pin = IIC_SDA_PIN;
    At24c02_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    At24c02_InitStruct.Pull = GPIO_PULLUP;
        At24c02_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(IIC_SDA_PORT, &At24c02_InitStruct);
   
    At24c02_InitStruct.Pin = IIC_SCL_PIN;
    At24c02_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    At24c02_InitStruct.Pull = GPIO_PULLUP;
        At24c02_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(IIC_SCL_PORT, &At24c02_InitStruct);
   
    At24c02Obj.Address = 0;
    At24c02Obj.Dat = 0;
}

/**
  *@ 函数名:I2C_Start
  *@ 功能:I2C初始化
  *@ 备注:在时钟线高的时候数据线电平由高变低后时钟线再变低
  */
void I2C_Start(void)
{
        IIC_SDA_IN(1);//数据线输出
        IIC_SDA_SET;
    IIC_SCL_SET;

    IIC_SDA_RESET;

    IIC_SCL_RESET;
}

/**
  *@ 函数名:I2C_Stop
  *@ 功能:I2C结束
  *@ 备注:在时钟线低的时候数据线电平由低变高后时钟线再变高
  */
void I2C_Stop(void)
{
        IIC_SDA_IN(1);//数据线输出
    IIC_SCL_RESET;
    IIC_SDA_RESET;

    IIC_SCL_SET;
        IIC_SDA_SET;

}

/**
  *@ 函数名:I2C_Ack
  *@ 功能:I2C等待应答
  *@ 备注:等待SDA数据线上应答
  */
uint8_t I2C_Wait_Ack(void)
{
        uint8_t Err_Time = 0;
        IIC_SDA_IN(0);//数据线方向为输入
        IIC_SDA_SET;

        IIC_SCL_SET;

        while(SDA_READ == GPIO_PIN_SET)//低为应答
        {
                Err_Time ++;
                if(Err_Time > 250)
                {
                        I2C_Stop();
                        return 1;//中断函数
                }
        }
        IIC_SCL_RESET;
        return 0;
}

/**
  *@ 函数名:I2C_Ack
  *@ 功能:I2C应答
  *@ 备注:SDA数据线上应答
  */
void I2C_Ack(void)
{
        IIC_SCL_RESET;
        IIC_SDA_IN(1);//数据线方向为输出
        IIC_SDA_RESET;

        IIC_SCL_SET;

        IIC_SCL_RESET;
}

/**
  *@ 函数名:I2C_NAck
  *@ 功能:I2C不应答
  *@ 备注:SDA数据线上不应答
  */
void I2C_NAck(void)
{
        IIC_SCL_RESET;
        IIC_SDA_IN(1);//数据线方向为输出
        IIC_SDA_SET;

        IIC_SCL_SET;

        IIC_SCL_RESET;
}

/**
  *@ 函数名:I2C_WriteByte
  *@ 功能:I2C发送一个字节
  *@ 备注:在时钟线低的时候数据线电平由低变高后时钟线再变高
  */
void I2C_WriteByte(uint8_t Dat)
{
    uint8_t i = 0;
        IIC_SDA_IN(1);//数据线方向为输出
        IIC_SCL_RESET;
    for(i = 0; i < 8; i++)
    {
        if((Dat & 0x80) >> 7)
            IIC_SDA_SET;
        else
            IIC_SDA_RESET;
        Dat <<= 1;

        IIC_SCL_SET;

                IIC_SCL_RESET;

    }
}

/**
  *@ 函数名:IIC_ReadByte
  *@ 功能:I2C的数据口读数据
  */
uint8_t IIC_ReadByte(uint8_t Ack)
{
    uint8_t i, Temp = 0;
    IIC_SDA_IN(0);
    for(i = 0; i < 8; i ++)
    {
        IIC_SCL_RESET;

        IIC_SCL_SET;
        Temp <<= 1;
        if(SDA_READ == GPIO_PIN_SET)
            Temp ++;

    }
        if(!Ack)
                I2C_NAck();
        else
                I2C_Ack();
        return Temp;       
}

/**
  *@ 函数名:IIC_SDA_IN
  *@ 功能:I2C的数据口改为输入或输出
  *@ 备注:输入参数为1时是SDA输出模式,为0时是SDA输入模式
  */
void IIC_SDA_IN(uint8_t Dir)
{
    GPIO_InitTypeDef At24c02_SDAStruct;
    if(Dir == 0)
    {
        At24c02_SDAStruct.Pin = IIC_SDA_PIN;
        At24c02_SDAStruct.Mode = GPIO_MODE_INPUT;
        At24c02_SDAStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(IIC_SDA_PORT, &At24c02_SDAStruct);
    }
        if(Dir == 1)
        {
                At24c02_SDAStruct.Pin = IIC_SDA_PIN;
                At24c02_SDAStruct.Mode = GPIO_MODE_OUTPUT_PP;
                At24c02_SDAStruct.Pull = GPIO_PULLUP;
                HAL_GPIO_Init(IIC_SDA_PORT, &At24c02_SDAStruct);
        }
}

/**
  *@ 函数名:At24c02_Write
  *@ 功能:At24c02写入数据
  *@ 输入:地址Addr,数据Dat
  *@ 备注:如果返回的值不是Ack_No说明应答成功
  */
void At24c02_Write(uint8_t Addr, uint8_t Dat)
{
        I2C_Start();
        I2C_WriteByte(0xa0);//器件地址为0xa0,命令为写
        I2C_Wait_Ack();
        I2C_WriteByte(Addr);//写的地址
        I2C_Wait_Ack();
        I2C_WriteByte(Dat);//写的数据
        I2C_Wait_Ack();
        I2C_Stop();       

}

/**
  *@ 函数名:At24c02_Read
  *@ 功能:At24c02读取数据
  *@ 输入:地址Addr
  *@ 备注:如果返回的值不是Ack_No说明应答成功
  */
uint8_t At24c02_Read(uint8_t Addr)
{
        uint8_t Temp;
        I2C_Start();
        I2C_WriteByte(0xa0);//器件地址为0xa1,命令为读
        I2C_Wait_Ack();
        I2C_WriteByte(Addr);//写的地址
        I2C_Wait_Ack();
        I2C_Start();
        I2C_WriteByte(0xa1);//器件地址为0xa1,命令为读
        I2C_Wait_Ack();
        Temp = IIC_ReadByte(0);
        I2C_Stop();
        return Temp;
}
[/mw_shl_code]

最佳答案

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

找到问题了,在设置IO口方向的函数里,我忘记将结构体里的speed赋值了导致的,添加后现在可以了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 09:17:00 | 显示全部楼层
找到问题了,在设置IO口方向的函数里,我忘记将结构体里的speed赋值了导致的,添加后现在可以了
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13123
金钱
13123
注册时间
2012-11-26
在线时间
3813 小时
发表于 2018-7-12 09:23:34 | 显示全部楼层
1、引脚初始化对不对
2、STM32的IO是有方向的,你有没有在用到的时候改变方向
学无止境
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 09:25:29 | 显示全部楼层
jermy_z 发表于 2018-7-12 09:23
1、引脚初始化对不对
2、STM32的IO是有方向的,你有没有在用到的时候改变方向

初始化脚是对的,IO口方向也没问题。这是我宏定义的
[mw_shl_code=c,true]#define IIC_SDA_PIN     GPIO_PIN_7
#define IIC_SDA_PORT    GPIOB

#define IIC_SCL_PIN     GPIO_PIN_6
#define IIC_SCL_PORT    GPIOB

#define IIC_SDA_SET         HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET)
#define IIC_SDA_RESET       HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET)
#define IIC_SDA_TOG         HAL_GPIO_TogglePin(IIC_SDA_PORT, IIC_SDA_PIN)
#define SDA_READ            HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN)

#define IIC_SCL_SET         HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET)
#define IIC_SCL_RESET       HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET)
#define IIC_SCL_TOG         HAL_GPIO_TogglePin(IIC_SCL_PORT, IIC_SCL_PIN)[/mw_shl_code]
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13123
金钱
13123
注册时间
2012-11-26
在线时间
3813 小时
发表于 2018-7-12 09:28:09 | 显示全部楼层
dragonFANG 发表于 2018-7-12 09:25
初始化脚是对的,IO口方向也没问题。这是我宏定义的
[mw_shl_code=c,true]#define IIC_SDA_PIN     GPIO ...

没看到你设定IO方向
学无止境
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13123
金钱
13123
注册时间
2012-11-26
在线时间
3813 小时
发表于 2018-7-12 09:28:40 | 显示全部楼层
dragonFANG 发表于 2018-7-12 09:25
初始化脚是对的,IO口方向也没问题。这是我宏定义的
[mw_shl_code=c,true]#define IIC_SDA_PIN     GPIO ...

另外你的toggle对于IIC纯粹多此一举吧
学无止境
回复

使用道具 举报

3

主题

144

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
498
金钱
498
注册时间
2018-3-5
在线时间
59 小时
发表于 2018-7-12 09:31:27 | 显示全部楼层
延时还是要的,STM32的IO翻转速度还是很快的,你这个速度我看是要上天,用逻辑分析仪或者示波器看一下
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 12:13:08 | 显示全部楼层
jermy_z 发表于 2018-7-12 09:28
没看到你设定IO方向

这个就是啊,设置方向的

[mw_shl_code=c,true]/**
  *@ 函数名:IIC_SDA_IN
  *@ 功能:I2C的数据口改为输入或输出
  *@ 备注:输入参数为1时是SDA输出模式,为0时是SDA输入模式
  */
void IIC_SDA_IN(uint8_t Dir)
{
    GPIO_InitTypeDef At24c02_SDAStruct;
    if(Dir == 0)
    {
        At24c02_SDAStruct.Pin = IIC_SDA_PIN;
        At24c02_SDAStruct.Mode = GPIO_MODE_INPUT;
        At24c02_SDAStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(IIC_SDA_PORT, &At24c02_SDAStruct);
    }
    if(Dir == 1)
    {
        At24c02_SDAStruct.Pin = IIC_SDA_PIN;
        At24c02_SDAStruct.Mode = GPIO_MODE_OUTPUT_PP;
        At24c02_SDAStruct.Pull = GPIO_PULLUP;
        HAL_GPIO_Init(IIC_SDA_PORT, &At24c02_SDAStruct);
    }
}[/mw_shl_code]
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 12:14:14 | 显示全部楼层
动次打次歌 发表于 2018-7-12 09:31
延时还是要的,STM32的IO翻转速度还是很快的,你这个速度我看是要上天,用逻辑分析仪或者示波器看一下

用HAL库延时us级的怎么延时,小弟只会延时ms级的
回复

使用道具 举报

70

主题

6763

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13123
金钱
13123
注册时间
2012-11-26
在线时间
3813 小时
发表于 2018-7-12 12:26:49 | 显示全部楼层
dragonFANG 发表于 2018-7-12 12:14
用HAL库延时us级的怎么延时,小弟只会延时ms级的

跟不是hal库的一样,把hal库自己生成的注释掉
学无止境
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 12:37:49 | 显示全部楼层
jermy_z 发表于 2018-7-12 12:26
跟不是hal库的一样,把hal库自己生成的注释掉

除了我延时没加,您还看到我有什么逻辑错误吗?
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 15:16:37 | 显示全部楼层
奇怪了,我加了us的延时还是不行?
回复

使用道具 举报

12

主题

54

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1070
金钱
1070
注册时间
2015-10-21
在线时间
128 小时
 楼主| 发表于 2018-7-12 16:05:53 | 显示全部楼层
设置SDA数据方向的函数里面缺少了对GPIO结构体的speed的设置,加上去现在可以了
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-15 13:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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