你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F030开发日志之I2C

[复制链接]
背包旅行码农 发布时间:2017-4-8 23:28
本帖最后由 背包旅行码农 于 2017-4-8 23:31 编辑

最近调试 一款 IQS333 电容触摸按键芯片IC,调了好几天发现I2C端口上没数据。最后追STM Clock tree 和STM 提供的I2C_Timing_Configuration工具解决了这个问题。现在分享给大家。
1. 首先我们观察Clock tree 查看 I2C clock source的缘由。
由 Clock tree可以得出I2C clock source 可以选择使用内部8MHz时钟,还是选用的系统SYSCLK.
本人选用的是STM32F030开发板。开发使用的是8MHz的外部晶振。所以采用外部8MHz时钟为例。
根据下面的 clock source时钟走势进行RCC 模块配置:
从走势我们可以看出我们需要确定PREDIV,PLLSRC,PLLMUL,SW和I2C1的源输入选择。
Clock configuration register 2 (RCC_CFGR2)
Clock configuration register (RCC_CFGR)
最后配置RCC相应的PREDIV,PLLSRC,PLLMUL,SW得到PLLCLK为48MHz.
并且STM32厂商提供得了I2C时钟配置的工具。I2C_Timing_Configuration_V1.0.0.xls
Note: The “Reset” button resets the input parameters to their default configuration.
To get the value of the timing register, follow these steps:
1. Select device mode by choosing “Master” or “Slave” in the list box.
2. Configure the speed mode by selecting one of the following modes in the list box:
– Standard mode: maximum frequency is 100 KHz.
– Fast mode: maximum frequency is 400 KHz.
– Fast mode Plus: maximum frequency is 1000 KHz.
3. Set the desired I2C speed frequency (master clock).
4. Set the value of I2C clock source frequency.
5. Specify if analog noise filter is enabled or not.
6. Specify if digital noise filter is used or not by setting the filter coefficient (this coefficient
should be an integer from 0 to 15).
7. Set the value of rise time.
8. Set the value of fall time.
9. Click the RUN button:
a) If the calculation of the timing register is completed, the following message is
displayed:
根据STM32厂商提供的配置I2C时钟说明,根据自己的应用我的配置如下:
因此在配置I2C的使用Timing的值如下
然后配置相应的I2C管脚,代码如下:
  1. /*******************************************************************************
  2. * Function Name  : I2C_DevInit
  3. * Description    : Initializes peripherals used by the I2C EEPROM driver.
  4. * Input          : None
  5. * Output         : None
  6. * Return         : None
  7. *******************************************************************************/
  8. void I2C_DevInit(void)
  9. {       
  10.            I2C_InitTypeDef I2C_InitStructure;
  11.         GPIO_InitTypeDef GPIO_InitStructure;
  12.        
  13.         /** I2C1 GPIO Configuration                         
  14.         PB8         ------> I2C1_SCL                 
  15.         PB9         ------> I2C1_SDA        */       
  16.         /*Enable or disable the AHB peripheral clock */       
  17.         RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);        /*Configure GPIO pin */
  18.        
  19.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;       
  20.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;       
  21.         GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;       
  22.         GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;       
  23.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  24.        
  25.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  26.        
  27.         /*Configure GPIO pin alternate function */       
  28.         GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1);       
  29.         GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_1);

  30.         RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
  31.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
  32.        
  33.         I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  34.         I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;       
  35.         I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  36.         I2C_InitStructure.I2C_DigitalFilter = 0x01;
  37.         I2C_InitStructure.I2C_OwnAddress1=0x00;
  38.         //I2C_InitStructure.I2C_Timing = 0x40B22536;//100Khz
  39.         I2C_InitStructure.I2C_Timing =0x10950C27;//400Khz
  40.         I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
  41.        
  42.         I2C_Init(I2C1, &I2C_InitStructure);       
  43.         I2C_Cmd(I2C1, ENABLE);
  44.         return;
  45. }
复制代码

I2C多字节写实现
  1. /*******************************************************************************
  2. * Function Name  : I2C_Write
  3. * Description    : Writes more than one byte to the Device with a single WRITE
  4. *                  cycle. The number of byte can't exceed the Device page size.
  5. * Input          : - pBuffer : pointer to the buffer containing the data to be
  6. *                    written to the Device.
  7. *                  - WriteAddr : Device's internal address to write to.
  8. *                  - NumByteToWrite : number of bytes to write to the Device.
  9. * Output         : None
  10. * Return         : None
  11. *******************************************************************************/
  12. BOOLEAN  I2C_Write(INT8U DevAddr, INT8U RegAddr,INT8U* pBuffer, INT8U NumByteToWrite)
  13. {
  14.         INT16U timeout = I2C_TIMEOUT;
  15.        
  16.         /* While the bus is busy */
  17.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
  18.         {
  19.                 if((timeout--) == 0)
  20.                 {
  21.                         return false;
  22.                 }
  23.         }
  24.        
  25.         /* Send Touch address for write */       
  26.         I2C_TransferHandling(I2C1, (DevAddr<<1), 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
  27.        
  28.         timeout = I2C_TIMEOUT;
  29.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS)==RESET)
  30.         {
  31.                 if((timeout--) == 0)
  32.                 {
  33.                         return false;
  34.                 }
  35.         }
  36.        
  37.         I2C_SendData(I2C1, RegAddr);

  38.         timeout = I2C_TIMEOUT;
  39.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TCR) == RESET)
  40.         {
  41.                 if((timeout--) == 0)
  42.                 {
  43.                         return false;
  44.                 }
  45.         }
  46.        
  47.         I2C_TransferHandling(I2C1, (DevAddr<<1), NumByteToWrite, I2C_AutoEnd_Mode, I2C_No_StartStop);
  48.        
  49.         /* While there is data to be written */
  50.         while(NumByteToWrite--)  
  51.         {
  52.                 timeout = I2C_TIMEOUT;
  53.                 /* Test on EV8 and clear it */
  54.                 while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
  55.                 {
  56.                         if((timeout--) == 0)
  57.                         {
  58.                                 return false;
  59.                         }
  60.                 }
  61.                 /* Send the current byte */
  62.                 I2C_SendData(I2C1, *pBuffer);

  63.                 /* Point to the next byte to be written */
  64.                 pBuffer++;                
  65.         }
  66.         /* Send STOP condition */
  67.         timeout = I2C_TIMEOUT;
  68.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
  69.         {
  70.                 if((timeout--) == 0)
  71.                 {
  72.                         return false;
  73.                 }
  74.         }
  75.        
  76.         return true;
  77.        
  78. }
复制代码

I2C多字节读实现
  1. /*******************************************************************************
  2. * Function Name  : I2C_Read
  3. * Description    : Reads a block of data from the Device.
  4. * Input          : - pBuffer : pointer to the buffer that receives the data read
  5. *                    from the Device.
  6. *                  - ReadAddr : EEPROM's internal address to read from.
  7. *                  - NumByteToRead : number of bytes to read from the Device.
  8. * Output         : None
  9. * Return         : None
  10. *******************************************************************************/
  11. BOOLEAN  I2C_Read(INT8U DevAddr, INT8U RegAddr, INT8U* pBuffer, INT8U NumByteToRead)
  12. {  
  13.         INT16U timeout = 60;

  14.         /* While the bus is busy */
  15.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET)
  16.         {
  17.                 if((timeout--) == 0)
  18.                 {
  19.                         return false;
  20.                 }
  21.         }

  22.         /* Generate start & wait event detection */
  23.         I2C_TransferHandling(I2C1, (DevAddr<<1), 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);


  24.         timeout = I2C_TIMEOUT;
  25.         while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXIS) == RESET)
  26.         {
  27.                 if((timeout--) == 0)
  28.                 {
  29.                         return false;
  30.                 }
  31.         }

  32.         I2C_SendData(I2C1, RegAddr);

  33.         timeout = I2C_TIMEOUT;       
  34.         while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TC) == RESET)
  35.         {
  36.                 if((timeout--) == 0)
  37.                 {
  38.                         return false;
  39.                 }
  40.         }

  41.         /* Send STRAT condition a second time */  
  42.         I2C_TransferHandling(I2C1, (DevAddr<<1), NumByteToRead,  I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
  43.        
  44.         /* While there is data to be read */
  45.         while(NumByteToRead)  
  46.         {       
  47.                 timeout = I2C_TIMEOUT;
  48.                
  49.                 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)
  50.                 {
  51.                         if((timeout--) == 0)
  52.                         {
  53.                                 return false;
  54.                         }
  55.                 }

  56.                 /* Read a byte from the EEPROM */
  57.                 *pBuffer = I2C_ReceiveData(I2C1);

  58.                 /* Point to the next location where the byte read will be saved */
  59.                 pBuffer++;

  60.                 /* Decrement the read bytes counter */
  61.                 NumByteToRead--;        
  62.         }
  63.        
  64.         /* Enable Acknowledgement to be ready for another reception */
  65.         timeout = I2C_TIMEOUT;
  66.         while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF) == RESET)
  67.         {
  68.                 if((timeout--) == 0)
  69.                 {
  70.                         return false;
  71.                 }
  72.         }
  73.         return true;
  74. }
复制代码
收藏 1 评论3 发布时间:2017-4-8 23:28

举报

3个回答
lisingch 回答时间:2017-4-9 08:59:43
图片打不开。
suoma 回答时间:2017-4-9 08:59:57
谢谢分享学习一下
大海-399550 回答时间:2018-1-27 22:30:19
感谢分享。MARK,用到时来取。

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版