2014-11-04 244 views
2

最近我一直在尝试使用STM32F030F4P6 MCU工作的I2C总线,但运气不大。如何在STM32F0上初始化I2C?

我正在使用一个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

SDA = GPIO_PIN_10上GPIOA

SCL = GPIO_PIN_9上GPIOA

I2C = I2C1

ownAdrress = 0x68

当我在启动此代码后对I2C线进行范围调整时,我会获得大约160mV的浮动电压。当我逐步完成代码时,每一个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:我曾尝试用1kΩ的电阻上拉SDA和SCL线至VCC通过本指南的指示:https://electronics.stackexchange.com/questions/57121/i2c-pullup-resistor-calculations

- >(3.3V-0.4)/3毫安〜=1kΩ的

编辑4:经过我的代码行,我试着输出各种标志位寄存器。特别是这些寄存器:isr = I2C1->ISR;cr1 = I2C1->CR1;,并且cr2 = I2C1->CR2;

发起I2C传输与I2C_TransferHandling(I2C1, 0x02, 1, I2C_AutoEnd_Mode, I2C_Generate_Start_Write);处理后,我得到的标志是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,我正在寻找实施和将只要我尝试一下就回报。

+0

可能是一个愚蠢的问题。你有SDA和SDL上的pullups吗?你运行这段代码之前它们高吗? – DoxyLover 2014-11-04 20:18:32

+0

嘿有DoxyLover, 试过这个,并没有工作。在我运行此代码之前,不要相信它们被设置得很高。 – Stroodlemuffin 2014-11-04 22:15:44

+0

你有什么精确连接到I2C线?什么是从属设备?您是否知道每条I2C线和Vcc之间必须连接上拉电阻? – DoxyLover 2014-11-04 22:37:46

回答

0

问题是,您没有为I2C引脚配置适当的AF(备用功能)源。在配置AF的寄存器全部为0并且I2C的功能为1后,您的I2C外设实际上与GPIO断开连接。

从技术上讲,配置时没有什么区别,但在GPIO配置之前最好这样做,以尽量减少引脚上的任何不需要的转换。

编辑:您必须对I2C引脚上拉电阻 - 你有“低”的水平有没有他们,和I2C周边检测到的总线错误,这显然阻止其正常工作。要么连接外部电阻,要么至少启用内部上拉,而不是“无上拉/无拉”配置。

此外 - “漏极开路”引脚不能上拉无法正常工作。

+0

如果你指的是我的评论,那么“must”这个词不会出现在那里,所以你不能说这个评论是误导性的(事实上,你应该给这个评论一些信用,因为你的答案是基本相同)。 – 2014-11-05 08:45:38

+0

好吧,我可能误读了“可能”的“必须” - 这是早...(无论如何 - 你的评论并没有解释问题和解决方案,并可能(我不使用SPL作为废话)代码是错误的 - 你应该给自动对焦源而不是“GPIO_Pin_9” - 有一些像AF_SOURCE_I2C这样的宏或者这样的代码 – 2014-11-05 09:08:26

+0

增加了这些代码行;请参阅我上面编辑的回应以获取更新情况。 – Stroodlemuffin 2014-11-05 19:06:08

1

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

正如其他人所说,外部上拉至Vcc在SCL和SDA是不可选的,当你错误地评论说必须出现一次,每个总线每外设。你正确的使用计算器来选择合适的值,因为在大约30-50K的STM32内部上拉电阻对于I2C上拉电路来说太弱。

+0

所以我发现了一些其他的代码,所有的时序计算都已完成,并将此行插入到我的I2C总线设置中:'I2C_InitStructure.I2C_Timing = 0x50330309; // 400kHz'然而,SCL和SDA线路上仍然没有收到任何信息。我现在只有一个主设备,并且有上拉功能,但我会记住,我只需要每个总线一个上拉电阻以供将来参考。 – Stroodlemuffin 2014-11-06 15:11:59

+0

现在来看看你的传输逻辑,指的是ST如何在他们的示例代码中完成它。传输地址的基本伪代码序列为:I2C_TransferHandling() - >等待TXIS - > I2C_SendData(地址) - >等待TCR。 – 2014-11-06 15:52:01

+0

从理论上说,如果我是跳过等待TXIS和TCR位,将我的车不只是传输数据,而不管任何形式的确认从奴隶?到目前为止,为了简单起见,我只在整个公共汽车上有一个主人,而只是试图查看公共汽车是否会输出某些东西。在我的主循环中,上面的代码是不是很重要,只是为了获得我可以研究的范围? – Stroodlemuffin 2014-11-06 16:11:17

0

Cortex M0的核心与Cortex M3的核心不同,STM32f030f4只有AHB和APB1(桥接)。 STM32f1xx的C代码不能在STM32f0xx下运行。 使用STM32F0xx_Snippets_Package解决您的关键问题。

0

我注意到您正在将引脚映射到AF_1,这是针对UART函数。

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

你需要将它们映射到AF_4使用I2C功能。

GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_4); 
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_4); 
0

我只注意到这个太:

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

所以,你已经禁用了时钟已启用后。我没有看到你以后重新启用它的位置。