硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1240|回复: 13
收起左侧

[I2C] [求助帖]STM32H745上实现I2C协议总是失败,求大神解答

[复制链接]

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
发表于 2022-7-19 10:48:27 | 显示全部楼层 |阅读模式
本帖最后由 泡泡茶壶 于 2022-7-19 10:56 编辑

  最近公司需要用到 IIC 协议通讯,我在验证 IIC 通讯时一直碰到验证不成功的问题,具体的信息如下:
  所用主芯片是 STM32H745XIH6U,FRAM 设备用的 FM24CL64B(从机)
协议代码使用 cubemx 生成,具体的软硬件配置如下图所示:

  这里配置圆圈内内容后,波浪线的数值变为红色提示错误,然后 cubemx 自动纠正了:

根据 H745 电路图中如下两图所示,得知 CN7 引出的 5 和 6 针脚就是 IIC 协议的 PD13,PD12:

下图为 FM24CL 的接线图,可知 3 5 是 I2C 协议所用针脚

于是开始配置 I2C4:

软件的配置我是参考了 https://jeckxu666.blog.csdn.net/article/details/117253441 做的,最后按配置生成代码
然后是物理连线,根据上图 H745 和 FM24 的电路图接线如下(棕色红色为地线和供电):

然后在 keil5 中打开上面生成的代码,main.c 中添加测试用例如下:
首先在 BEGIN PV 中定义传参

/* USER CODE BEGIN PV */#define Write_ADDR 0xAE
#define Read_ADDR 0xAF


unsigned char str1[]={"i2ctest1"};
unsigned char str2[]={"i2ctest2"};
unsigned char str3[]={"i2ctest3"};


uint8_t ReadBuffer[50];
然后在 main 函数中添加如下代码:
/* USER CODE BEGIN 2 */   
int i=5;int j =5;int k=5;   
HAL_Delay(100);   

//阻塞方式写入读取   
if(HAL_I2C_Mem_Write(&hi2c4,Write——ADDR,0,I2C_MEMADD_SIZE_8BIT,str1,sizeof(str1),1000)==HAL_OK)        
{i=6;}else{i=7;}   
HAL_Delay(1000);   
HAL_I2C_Mem_Read(&hi2c4,Read_ADDR,0,I2C_MEMADD_SIZE_8BIT,ReadBuffer,sizeof(str1),1000);   
HAL_Delay(1000);     


//中断方式写入读取   
if(HAL_I2C_Mem_Write_IT(&hi2c4,Write_ADDR,0,I2C_MEMADD_SIZE_8BIT,str2,sizeof(str2))==HAL_OK)        
{j=6;}else{j=7;}   
HAL_Delay(1000);   
HAL_I2C_Mem_Read_IT(&hi2c4,Read_ADDR,0,I2C_MEMADD_SIZE_8BIT,ReadBuffer,sizeof(str2));   
HAL_Delay(1000);     


//DMA中断方式写入读取   
if(HAL_I2C_Mem_Write_DMA(&hi2c4,Write_ADDR,0,I2C_MEMADD_SIZE_8BIT,str3,sizeof(str3))==HAL_OK)        
{k=6;}else{k=7;}   
HAL_Delay(1000);   
HAL_I2C_Mem_Read_DMA(&hi2c4,Read_ADDR,0,I2C_MEMADD_SIZE_8BIT,ReadBuffer,sizeof(str3));   
HAL_Delay(1000);  
/* USER CODE END 2 */

说明一下。读写地址为 AE 和 AF 是因为 FM24 的接线图如下图:
我的理解是用来决定从设备地址的那几根线全部接到供电线上了,所以全部是 1,也就是说地址是 0xAE 和 0xAF。

  然后编译,下载到 H745 中都没问题,最后跑起来调试时,watch 窗口查看 ijk 三个变量的值,结果全都从 5 变成了 7,说明确实被执行了但全都失败了。
  由于我本人之前是搞软件开发的没接触过嵌入式,所以偏向于从软件层面思考解决方案。我打断点调试,函数执行的路径如下:
  HAL_I2C_Mem_Write→I2C_RequestMemoryWrite→I2C_WaitOnTXISFlagUntilTimeout→I2C_IsErrorOccurred
  执行过程在 I2C_IsErrorOccurred 函数中的详细步骤如下:
    1. 进入 6423 行 while (__HAL_I2C_GET_FLAG (hi2c, I2C_FLAG_TXIS) == RESET) 语句,然后进行到 6432 行 if (Timeout != HAL_MAX_DELAY) 判断语句
    2. 循环至 6426 行 if (I2C_IsErrorOccurred (hi2c, Timeout, Tickstart) != HAL_OK) 语句并进入该函数
    3. 到达 6575 行 if (HAL_IS_BIT_SET (itflag, I2C_FLAG_AF)) 进入该语句,该语句最终导致了 I2C_IsErrorOccurred 函数返回 HAL_ERROR 导致写函数执行失败。
  失败的原因到底是什么?上面 define 的地址我不光试了 AE 和 AF,从 A0 到 A8 我也全部试了,全都不行。是因为 TXIS,itflag 或者 FALG_AF 这三个变量中的哪一个不对么?或者说不是软件的问题,是硬件上我哪里搞错了?也想过可能是时钟树配置的不对?或者是流传的 stm32 上的 I2C 不稳定的问题?第一次调试时地址没有写对,应该是 AE 和 AF 我写成了 A0 和 A1,我看别人说 stm32 上的 I2C 有个 bug 是只要你第一次输入的地址是错的那么后面就算输入对的地址,主机也无法识别,难道是因为这个?
  现在就想让 H745 和 FM24 成功用 I2C 协议通讯上,达成 H745 对 FM24 进行读和写的操作,请大佬赐教,万分感谢!!



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106840
QQ
发表于 2022-7-19 11:41:42 | 显示全部楼层
看了楼主的描述,我这里有个问题,就是楼主的代码扫描I2C设备,能扫描到不。也就是能正常应答不。
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
 楼主| 发表于 2022-7-19 11:49:43 | 显示全部楼层
eric2013 发表于 2022-7-19 11:41
看了楼主的描述,我这里有个问题,就是楼主的代码扫描I2C设备,能扫描到不。也就是能正常应答不。

我的理解是调用的Write函数不是要求从设备地址了么,然后从设备地址是0xAE,这样传进去参数的话应该就能在总线上广播,然后I2C设备应该就能回应主机了
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
 楼主| 发表于 2022-7-19 11:50:33 | 显示全部楼层
eric2013 发表于 2022-7-19 11:41
看了楼主的描述,我这里有个问题,就是楼主的代码扫描I2C设备,能扫描到不。也就是能正常应答不。

主要是我看很多网上的步骤都是这样搞的,调用个write函数就可以读写了
回复

使用道具 举报

10

主题

18

回帖

48

积分

新手上路

积分
48
发表于 2022-7-19 12:50:39 | 显示全部楼层
hal库读函数里地址不用自己加一,HAL_I2C_Mem_Read函数里面已经与上1了,直接用i2c设备的7位地址左移一位后的结果即可,全都用0xAE
回复

使用道具 举报

39

主题

198

回帖

325

积分

高级会员

积分
325
发表于 2022-7-19 13:51:43 | 显示全部楼层
帮顶。
没玩过硬件IIC不太清楚。
或者可以直接用开发板的模拟IIC驱动得了。


我个人想法是这样的。我把可能导致IIC通讯失败的原因分为以下两大类:
1.IIC总线配置本身就有问题,导致了失败。
2.IIC总线配置没问题,但是没搞明白这个IIC外设到底是咋玩的,导致的失败。

你看看你是否能判断出你现在的情况,属于1,还是2?
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
 楼主| 发表于 2022-7-19 14:13:56 | 显示全部楼层
spear47 发表于 2022-7-19 12:50
hal库读函数里地址不用自己加一,HAL_I2C_Mem_Read函数里面已经与上1了,直接用i2c设备的7位地址左移一位后 ...

刚试了一下,读和写地址全改成0xAE了,没用
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
 楼主| 发表于 2022-7-20 09:27:51 | 显示全部楼层
会飞的猪_2020 发表于 2022-7-19 13:51
帮顶。
没玩过硬件IIC不太清楚。
或者可以直接用开发板的模拟IIC驱动得了。

感觉越来越确信是stm32的问题了。。。好几天了实在是找不出来其他原因了,而且stm32本身自己的I2C就有bug,和我这个情况一模一样
I2C外设的话就是个简单的FRAM,连上数据线,电压线应该就行了吧。。。?还需要搞其他东西么?
回复

使用道具 举报

0

主题

29

回帖

29

积分

新手上路

积分
29
发表于 2022-7-20 09:58:37 | 显示全部楼层
泡泡茶壶 发表于 2022-7-20 09:27
感觉越来越确信是stm32的问题了。。。好几天了实在是找不出来其他原因了,而且stm32本身自己的I2C就有bug ...

比较简单的方法,用逻辑分析仪,或者示波器,把波形发上来。方便确定问题。
回复

使用道具 举报

2

主题

10

回帖

16

积分

新手上路

积分
16
发表于 2022-7-20 11:17:11 | 显示全部楼层
最有效的定位方式:抓波形看一下
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
 楼主| 发表于 2022-7-21 08:59:30 | 显示全部楼层
boclandc 发表于 2022-7-20 09:58
比较简单的方法,用逻辑分析仪,或者示波器,把波形发上来。方便确定问题。

一个接地一个接SDA或者SCL对吧?示波一直处于高电平,F5运行后也一直是高电平根本没变化
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
QQ
 楼主| 发表于 2022-7-21 08:59:56 | 显示全部楼层
TechDP 发表于 2022-7-20 11:17
最有效的定位方式:抓波形看一下

一个接地一个接SDA或者SCL对吧?示波一直处于高电平,F5运行后也一直是高电平根本没变化
回复

使用道具 举报

7

主题

42

回帖

63

积分

初级会员

积分
63
发表于 2022-7-25 15:41:39 | 显示全部楼层
泡泡茶壶 发表于 2022-7-19 14:13
刚试了一下,读和写地址全改成0xAE了,没用

用软件模拟i2c试试?
回复

使用道具 举报

7

主题

42

回帖

63

积分

初级会员

积分
63
发表于 2022-7-25 15:42:15 | 显示全部楼层
泡泡茶壶 发表于 2022-7-21 08:59
一个接地一个接SDA或者SCL对吧?示波一直处于高电平,F5运行后也一直是高电平根本没变化

用逻辑分析仪吧。这种标准协议,逻辑分析仪看起来方便
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-7 01:31 , Processed in 0.268901 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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