clesun 发表于 2024-4-19 11:51:55

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

在网上找的例程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

rclong 发表于 2024-4-19 12:47:59

这个看着是STM32的LL库
一般都是用标准库或者HAL库居多吧
你可以要求它写标准库或者LL库的
AI就是你输入越多,它输出越精确

rclong 发表于 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,你可能需要手动添加标准库文件到你的项目中。

1a2b3c 发表于 2024-4-19 12:56:37

随便找个普通老百姓用io模拟方式写的吧,只需要改一下io脚即可,难道也不方便哇?

yuyu87 发表于 2024-4-19 13:41:26

其实很好解决的,在I2C初始化之前先将I2C两个引脚都初始化为普通 IO,并置高电平 ,然后再正常初始化I2C就可以了。

t3486784401 发表于 2024-4-19 13:48:47

2019 年就已经有回答了,结论就是不碰 STM32 硬件 I2C:

clesun 发表于 2024-4-19 13:52:03

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

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

clesun 发表于 2024-4-19 13:53:23

t3486784401 发表于 2024-4-19 13:48
2019 年就已经有回答了,结论就是不碰 STM32 硬件 I2C:
(引用自6楼)

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

okplay 发表于 2024-4-19 14:11:04

硬件12C的CLK在常用的100kHz和400KHz下工作,99%的概率下会在1小时之内卡住,甚至只有几十秒。
============这个是怎么测试的? 我用起来没有这么夸张呀。

lb0857 发表于 2024-4-19 14:12:10

据说是版权问题,独辟蹊径做一套硬件,然后有bug,后面f1系列也就不管了。

t3486784401 发表于 2024-4-19 14:14:26

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

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

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

yuyu87 发表于 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.3MHZeeprom=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%没问题。
页: [1]
查看完整版本: STM32F1的I2C调试卡死,在AI中问怎么写I2C,有个函数库里没有