搜索
bottom↓
回复: 11
打印 上一主题 下一主题

STM32F1的I2C调试卡死,在AI中问怎么写I2C,有个函数库里没有

[复制链接]

出0入4汤圆

跳转到指定楼层
1
发表于 2024-4-19 11:51:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在网上找的例程LL_I2C_IsActiveFlag_SB总是卡死。
uint8_t I2C_Read(uint8_t addr, uint8_t reg)
{
    uint8_t data;
   
    while(LL_I2C_IsActiveFlag_BUSY(I2C1));
   
    LL_I2C_HandleTransfer(I2C1, addr, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
    while(!LL_I2C_IsActiveFlag_TXE(I2C1));
    LL_I2C_TransmitData8(I2C1, reg);
    while(!LL_I2C_IsActiveFlag_TC(I2C1));
   
    LL_I2C_HandleTransfer(I2C1, addr, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
    while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
    data = LL_I2C_ReceiveData8(I2C1);
    while(!LL_I2C_IsActiveFlag_STOP(I2C1));
   
    return data;
}
这个是AI的参考例程,F1的库里没有这个函数LL_I2C_HandleTransfer

出0入98汤圆

2
发表于 2024-4-19 12:47:59 | 只看该作者
这个看着是STM32的LL库
一般都是用标准库或者HAL库居多吧
你可以要求它写标准库或者LL库的
AI就是你输入越多,它输出越精确

出0入98汤圆

3
发表于 2024-4-19 12:52:34 | 只看该作者
我用ChatGLM联网版问了两个,你试试看
使用STM32的标准库(也称为STM32Cube FW_F1老版本库或STM32 Standard Peripheral Libraries)来实现`uint8_t I2C_Read(uint8_t addr, uint8_t reg)`函数,你需要按照以下步骤进行:
1. 初始化I2C接口。
2. 发送寄存器地址到设备。
3. 从设备读取数据。
以下是一个使用STM32标准库实现的示例代码:
```c
#include "stm32f10x.h"
#include "stdbool.h"
// 假设你已经定义了I2C_InitStructure结构体变量,并且已经初始化
I2C_InitTypeDef I2C_InitStructure;
uint8_t I2C_Read(uint8_t addr, uint8_t reg) {
    uint8_t data = 0;
   
    // 启动I2C传输,发送设备地址和写操作标志
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
   
    // 发送设备地址
    I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
   
    // 发送寄存器地址
    I2C_SendData(I2C1, reg);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
   
    // 重新启动I2C传输,发送设备地址和读操作标志
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
   
    // 发送设备地址
    I2C_Send7bitAddress(I2C1, addr, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
   
    // 禁止ACK,准备读取最后一个字节
    I2C_AcknowledgeConfig(I2C1, DISABLE);
   
    // 读取数据
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
    data = I2C_ReceiveData(I2C1);
   
    // 生成停止条件
    I2C_GenerateSTOP(I2C1, ENABLE);
   
    // 使能ACK,为下一次传输准备
    I2C_AcknowledgeConfig(I2C1, ENABLE);
   
    return data;
}
```
在这个例子中,`addr`是I2C设备的地址,`reg`是要读取的寄存器的地址。代码中使用了STM32标准库提供的函数来控制I2C总线,包括启动和停止传输、发送地址和数据、以及检查事件状态。
请注意,你可能需要根据你的具体硬件配置调整以上代码。例如,你可能需要根据你的STM32F103板上的硬件I2C接口(I2C1、I2C2等)来修改`I2C1`变量,并且确保你已经正确初始化了I2C接口。
确保在你的项目中包含了STM32标准库,并且正确配置了MCU和I2C相关的选项。如果你使用的是STM32CubeIDE或其他STM32Cube工具,这些步骤通常会在项目初始化过程中自动完成。如果你使用的是其他IDE,你可能需要手动添加标准库文件到你的项目中。

出0入475汤圆

4
发表于 2024-4-19 12:56:37 来自手机 | 只看该作者
随便找个普通老百姓用io模拟方式写的吧,只需要改一下io脚即可,难道也不方便哇?

出20入186汤圆

5
发表于 2024-4-19 13:41:26 | 只看该作者
其实很好解决的,在I2C初始化之前先将I2C两个引脚都初始化为普通 IO,并置高电平 ,然后再正常初始化I2C就可以了。

出200入2554汤圆

6
发表于 2024-4-19 13:48:47 | 只看该作者
2019 年就已经有回答了,结论就是不碰 STM32 硬件 I2C:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入4汤圆

7
 楼主| 发表于 2024-4-19 13:52:03 | 只看该作者
yuyu87 发表于 2024-4-19 13:41
其实很好解决的,在I2C初始化之前先将I2C两个引脚都初始化为普通 IO,并置高电平 ,然后再正常初始化I2C就 ...
(引用自5楼)

那个按照方法改了,正常是第一步LL_I2C_IsActiveFlag_BUSY就卡死了,按照你建议的,然后就后边_SB卡住。步步是坑

出0入4汤圆

8
 楼主| 发表于 2024-4-19 13:53:23 | 只看该作者
t3486784401 发表于 2024-4-19 13:48
2019 年就已经有回答了,结论就是不碰 STM32 硬件 I2C:
(引用自6楼)

我的mcu是GD的,用的ST的ll库。不行就模拟了

出0入0汤圆

9
发表于 2024-4-19 14:11:04 | 只看该作者
硬件12C的CLK在常用的100kHz和400KHz下工作,99%的概率下会在1小时之内卡住,甚至只有几十秒。
============这个是怎么测试的? 我用起来没有这么夸张呀。

出1310入193汤圆

10
发表于 2024-4-19 14:12:10 来自手机 | 只看该作者
据说是版权问题,独辟蹊径做一套硬件,然后有bug,后面f1系列也就不管了。

出200入2554汤圆

11
发表于 2024-4-19 14:14:26 来自手机 | 只看该作者
okplay 发表于 2024-4-19 14:11
硬件12C的CLK在常用的100kHz和400KHz下工作,99%的概率下会在1小时之内卡住,甚至只有几十秒。
=========== ...

(引用自9楼)

是scl抗毛刺做的不好,稍微有点干扰抖动或者竞争,就卡在了奇怪的地方。

这个问题和 rtc 不起振是当年 f1 系列经典的坑

出20入186汤圆

12
发表于 2024-4-19 17:11:29 | 只看该作者
clesun 发表于 2024-4-19 13:52
那个按照方法改了,正常是第一步LL_I2C_IsActiveFlag_BUSY就卡死了,按照你建议的,然后就后边_SB卡住。 ...
(引用自7楼)

  // 时钟
  rcu_periph_clock_enable(RCU_I2C0);
  rcu_periph_clock_enable(RCU_GPIOB);
  // 先初始化为普通IO,置1,再初始化为I2C,可避免I2C上次出错
  gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,        GPIO_PIN_6 | GPIO_PIN_7);
  gpio_bit_set(GPIOB, GPIO_PIN_6 | GPIO_PIN_7);
  Delay(10);
  // GPIO                PB6/SCL,PB7/SDA
  gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
  // I2C 0                        mcp432x        max=4.3MHZ  eeprom=1MHZ
  i2c_clock_config(I2C0, 400000, I2C_DTCY_2);
  i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0);
  i2c_enable(I2C0);

我的代码,这个代码不管在任何情况下复位,再启动都不会有问题,
就是开机强制变为普通IO。

SB是什么标志?我在手册没看到
我使用的是GD32F030,以及STM32F411以及STM32F103,三款芯片我都这样处理。100%没问题。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 14:56

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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