OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子全套STM32开发资料,上千讲STM32视频教程,RT1052教程免费下载啦...
查看: 207|回复: 12

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

[复制链接]

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

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

[C] 纯文本查看 复制代码
#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; 
}


最佳答案

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

找到问题了,在设置IO口方向的函数里,我忘记将结构体里的speed赋值了导致的,添加后现在可以了
回复

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

使用道具 举报

  离线 

61

主题

4965

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

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

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

初始化脚是对的,IO口方向也没问题。这是我宏定义的
[C] 纯文本查看 复制代码
#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)
回复

使用道具 举报

  离线 

61

主题

4965

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

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

没看到你设定IO方向
道不同,不相与为谋
回复

使用道具 举报

  离线 

61

主题

4965

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
6217
金钱
6217
注册时间
2012-11-26
在线时间
1318 小时
发表于 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

主题

143

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

这个就是啊,设置方向的

[C] 纯文本查看 复制代码
/**
  *@ 函数名: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);
    }
}
回复

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

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

使用道具 举报

  离线 

61

主题

4965

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

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

跟不是hal库的一样,把hal库自己生成的注释掉
道不同,不相与为谋
回复

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

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

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

使用道具 举报

  离线 

6

主题

31

帖子

0

精华

高级会员

Rank: 4

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

使用道具 举报

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

本版积分规则




关闭

必看,必学:"原子哥”力荐上一条 /1 下一条

正点原子公众号

QQ|联系我们|手机版|官方淘宝店|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-9-22 03:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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