gpt4 book ai didi

arm - 如何在STM32F0上初始化I2C?

转载 作者:行者123 更新时间:2023-12-02 07:24:56 26 4
gpt4 key购买 nike

最近我一直在尝试让 I2C 总线在 STM32F030F4P6 MCU 上工作,但运气不佳。

我正在使用 STM32F0 模块,并找到了大量用于 STM32F1 模块 I2C 初始化的资源,但没有关于 STM32F0 初始化/传输过程的具体信息。

这是我的初始化代码:

void i2c_init(uint8_t ownAddress)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;

// Enable GPIOA clocks

RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

// Configure I2C1 clock and GPIO

GPIO_StructInit(&GPIO_InitStructure);


/* I2C1 clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

/* I2C1 SDA and SCL configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* I2C1 Reset */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);


/* Configure I2C1 */

I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
//I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
//I2C_InitStructure.I2C_ClockSpeed = ClockSpeed;


I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);

}

为了测试我的设置是否正确,我设计了一些 I2C 传输代码,该代码将在永无休止的循环中传输数据。这是代码:

while(1)
{
I2C_SlaveAddressConfig(I2C1, RegName);
I2C_GenerateSTART(I2C1, ENABLE);
I2C_NumberOfBytesConfig(I2C1, 8);
I2C_SendData(I2C1,0b00000000);
I2C_GenerateSTOP(I2C1, ENABLE);
}

地点:

注册名称 = 0x75

GPIOA 上的 SDA = GPIO_PIN_10

GPIOA 上的 SCL = GPIO_PIN_9

I2C = I2C1

自己的地址 = 0x68

当我启动此代码后观察 I2C 线路时,​​我得到了大约 160mV 的 float 电压。当我单步执行代码时,每个 I2C 函数调用都会发生并完成,所以这就是为什么我认为它与我对引脚本身的初始化有更多的关系。

我的问题与此线程非常相似,但从未得到解答:

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSTM32F0%20I2C%20code%20doesn%27t%20work&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=1342

编辑1:这是我最新的代码;仍然无法工作(编辑 2:更新到我当前拥有的内容;将内容移到更正确的位置):

void i2c_init(uint8_t ownAddress)
{

/* TypeDefs for GPIOA and I2C1 */

GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;

/* Enable GPIOA clocks and I2C1 clock enable */

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

/* Configure I2C1 clock and GPIO */

GPIO_StructInit(&GPIO_InitStructure);

/* I2C1 SDA and SCL configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //UP
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

/* GPIO AF Configuration -> GPIO_AF_1: USART2, CEC, Tim3, USART1, USART2,EVENTOUT, I2C1, I2C2, TIM15 */

GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

GPIO_Init(GPIOA, &GPIO_InitStructure);

/* I2C1 Reset */

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);


//I2C_DeInit(I2C1);

/* Configure I2C1 */

I2C_StructInit(&I2C_InitStructure);

I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1 = ownAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
//I2C_AcknowledgeConfig(I2C1, ENABLE);

}

如您所见,我添加了两行 GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);我发现 GPIO_AF_1 具有 I2C1 的替代功能(来自 the STM32F0 Standard Peripheral bibliotheek) 。

还有其他想法吗?我一直在摆弄时钟,看看这是否改变了任何东西,并添加了其他人的代码片段,只是为了看看这是否对我的设备的输出有任何影响。

编辑 3: 我尝试按照本指南的说明,使用 1kohm 电阻将 SDA 和 SCL 线拉至 VCC:https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations

->(3.3V-0.4)/3mA ~= 1kohm

编辑4:在逐行查看代码后,我尝试输出各种标志位寄存器。具体来说,这些寄存器:isr = I2C1->ISR; , cr1 = I2C1->CR1; ,和cr2 = I2C1->CR2;

使用 I2C_TransferHandling(I2C1, 0x02, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Write); 启动 I2C 传输处理后获得的标志是0x8001可以将其解读为两个错误:

#define I2C_ISR_BUSY ((uint32_t)0x00008000) /*!< Bus busy */

#define I2C_ISR_TXE ((uint32_t)0x00000001) /*!< Transmit data register empty */

我在此链接中找到了一些解决方法(删除 https: 之后的空格以转到链接 -> 由于某种原因,堆栈溢出不会让我发布超过 1 个链接):https://my .st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=%2Fpublic%2FSTe2ecommunities%2Fmcu%2FLists%2Fcortex_mx_stm32%2FSTM32L151RB%20I2C%20Busy%20flag%20always%20set&FolderCTID =0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=690 我'我希望实现,并在尝试后立即报告。

最佳答案

我有 I2C 在 F0 上作为主设备和从设备工作。我在您的代码中看到的主要问题是,在主模式下,您绝对必须设置 I2C_Timing 初始化结构成员。请参阅 RM0091 以获取与您想要在 SCL 上生成的频率相对应的样本值。在从机模式下,时钟从主机恢复,因此计时成员似乎没有被使用。

正如其他人所说,SCL 和 SDA 上的 Vcc 外部上拉电阻不是可选的,并且必须在每个总线上出现一次,而不是每个外设,正如您在评论中错误指出的那样。您使用计算器选择合适的值是正确的,因为 STM32 中大约 30-50K 的内部上拉电阻太弱,无法用作 I2C 上拉电阻。

关于arm - 如何在STM32F0上初始化I2C?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26742873/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com