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

关于STM32F103硬件IIC程序异常的问题的一个解决方法

[复制链接]
lastimy 发布时间:2016-7-23 17:31
在做公司项目的时候,需要用到陀螺仪、加速度、地磁三类传感器,可以知道这三个传感器可以通过IIC总线的方式进行访问,但是中间总是出现各种问题,特别是无法初始化后无法进行启动总线的动作,卡死在查询语句中,经过不断的测试与摸索,终于在网上受到了启发;
下面是我写的一个示例,注意goto语句的用法。
库文件
  1. <p class="MsoNormal"><span lang="EN-US">#ifndef __HW_IIC_H</span></p>

  2. <p class="MsoNormal"><span lang="EN-US">#define __HW_IIC_H</span></p>

  3. <p class="MsoNormal"><span lang="EN-US"> </span></p>

  4. <p class="MsoNormal"><span lang="EN-US">#include "stm32f10x.h"</span></p>

  5. <p class="MsoNormal"><span lang="EN-US"> </span></p>

  6. <p class="MsoNormal"><span lang="EN-US">void I2C_Configuration(void);</span></p>

  7. <p class="MsoNormal"><span lang="EN-US"> </span></p>

  8. <p class="MsoNormal"><span lang="EN-US">uint8_t I2C_Read(I2C_TypeDef *I2Cx,uint8_t
  9. I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num);</span></p>

  10. <p class="MsoNormal"><span lang="EN-US">uint8_t I2C_Write(I2C_TypeDef *I2Cx,uint8_t
  11. I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num);</span></p>

  12. <p class="MsoNormal"><span lang="EN-US">uint8_t I2C_WriteOneByte(I2C_TypeDef
  13. *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t value);</span></p>

  14. <p class="MsoNormal"><span lang="EN-US"> </span></p>

  15. <p class="MsoNormal"><span lang="EN-US">#endif</span></p>
复制代码
源文件
  1. #include "hw_iic.h"
  2. #include "stm32f10x_i2c.h"
  3. #include "stdio.h"
  4. #include "delay.h"


  5. /*******************************************************************************
  6. * Function Name  : I2C_Configuration
  7. * Description    :
  8. * Input          : None
  9. * Output         : None
  10. * Return         : None
  11. * Attention                 : None
  12. *******************************************************************************/

  13. void I2C_Configuration(void)
  14. {
  15.    I2C_InitTypeDef  I2C_InitStructure;
  16.    GPIO_InitTypeDef  GPIO_InitStructure;

  17.    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
  18.    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);

  19.    /* Configure I2C1 pins: PB10->SCL and PB11->SDA */
  20.    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
  21.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  22.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  23.    GPIO_Init(GPIOB, &GPIO_InitStructure);
  24.                
  25.    I2C_DeInit(I2C1);
  26.    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  27.    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  28.    I2C_InitStructure.I2C_OwnAddress1 = 0x30;
  29.    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  30.    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  31.    I2C_InitStructure.I2C_ClockSpeed = 400000;  //400K全速
  32.    
  33.    I2C_Cmd(I2C1, ENABLE);
  34.    I2C_Init(I2C1, &I2C_InitStructure);

  35.    I2C_AcknowledgeConfig(I2C1, ENABLE);
  36. }


  37. /*******************************************************************************
  38. * Function Name  : I2C_delay
  39. * Description    :
  40. * Input          : None
  41. * Output         : None
  42. * Return         : None
  43. * Attention                 : None
  44. *******************************************************************************/
  45. static void I2C_delay(uint16_t cnt)
  46. {
  47.         while(cnt--);
  48. }

  49. /*******************************************************************************
  50. * Function Name  : I2C_AcknowledgePolling
  51. * Description    :
  52. * Input          : I2C_TypeDef * , uint8_t
  53. * Output         : None
  54. * Return         : None
  55. * Attention                 : None
  56. *******************************************************************************/
  57. static void I2C_AcknowledgePolling(I2C_TypeDef *I2Cx,uint8_t I2C_Addr)
  58. {
  59.   vu16 SR1_Tmp;
  60.   do
  61.   {   
  62.     I2C_GenerateSTART(I2Cx, ENABLE);

  63.     SR1_Tmp = I2C_ReadRegister(I2Cx, I2C_Register_SR1);

  64. //#ifdef AT24C01A

  65.         I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);
  66. /*
  67. #else

  68.         I2C_Send7bitAddress(I2Cx, 0, I2C_Direction_Transmitter);
  69. #endif
  70. */
  71.   }while(!(I2C_ReadRegister(I2Cx, I2C_Register_SR1) & 0x0002));
  72.   
  73.   I2C_ClearFlag(I2Cx, I2C_FLAG_AF);
  74.    
  75.   I2C_GenerateSTOP(I2Cx, ENABLE);
  76. }


  77. /*******************************************************************************
  78. * Function Name  : I2C_Read
  79. * Description    :
  80. * Input          :
  81. * Output         :
  82. * Return         :
  83. * Attention                 : None
  84. *******************************************************************************/
  85. uint8_t I2C_Read(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num)
  86. {
  87.     if(num==0)
  88.         return 1;
  89.        
  90.         while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
  91.                
  92.         I2C_AcknowledgeConfig(I2Cx, ENABLE);


  93.     I2C_GenerateSTART(I2Cx, ENABLE);
  94.     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

  95. //#ifdef AT24C01A       
  96.     I2C_Send7bitAddress(I2Cx,  I2C_Addr, I2C_Direction_Transmitter);
  97.     while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  98.         I2C_SendData(I2Cx, addr);
  99.     while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  100.                
  101.         I2C_GenerateSTART(I2Cx, ENABLE);
  102.         while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
  103.        
  104.         I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Receiver);
  105.         while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
  106. /*       
  107. #else       
  108.         I2C_Send7bitAddress(I2Cx, addr<<1, I2C_Direction_Receiver);
  109.         while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
  110. #endif
  111. */       
  112.     while (num)
  113.     {
  114.                 if(num==1)
  115.                 {
  116.                      I2C_AcknowledgeConfig(I2Cx, DISABLE);
  117.                     I2C_GenerateSTOP(I2Cx, ENABLE);
  118.                 }
  119.             
  120.                 while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));  /* EV7 */
  121.             *buf = I2C_ReceiveData(I2Cx);
  122.             buf++;
  123.             /* Decrement the read bytes counter */
  124.             num--;
  125.     }

  126.         I2C_AcknowledgeConfig(I2Cx, ENABLE);

  127.         return 0;
  128. }       

  129. /*******************************************************************************
  130. * Function Name  : I2C_WriteOneByte
  131. * Description    :
  132. * Input          :
  133. * Output         : None
  134. * Return         :
  135. * Attention                 : None
  136. *******************************************************************************/
  137. uint8_t I2C_WriteOneByte(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t value)
  138. {
  139.         int cnt = 0;
  140.         MY_IIC_START_LABLE:
  141.           I2C_GenerateSTART(I2Cx, ENABLE);
  142.         cnt = 0;
  143.           while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT))
  144.     {
  145.         delay_ms(10);     //必须延时 否则很容易死机
  146. //        printf("9XX");
  147.       
  148.                 if(cnt ++ > 10)
  149.                 {
  150.                         cnt = 0;
  151.                         I2C_Configuration();   //重新进行初始化
  152.                         goto MY_IIC_START_LABLE;  //跳到本函数的开头
  153.                 }
  154.     }
  155.    
  156.   
  157. //#ifdef AT24C01A
  158.           I2C_Send7bitAddress(I2Cx, I2C_Addr, I2C_Direction_Transmitter);
  159.           while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  160.           I2C_SendData(I2Cx, addr);
  161.         while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  162. /*
  163. #else       
  164.         I2C_Send7bitAddress(I2Cx, addr<<1, I2C_Direction_Transmitter);
  165.         while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  166. #endif
  167. */
  168.           I2C_SendData(I2Cx, value);
  169.           while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  170.        
  171.           I2C_GenerateSTOP(I2Cx, ENABLE);
  172.   
  173.           I2C_AcknowledgePolling(I2Cx,I2C_Addr);

  174.         I2C_delay(1000);

  175.         return 0;
  176. }


  177. /*******************************************************************************
  178. * Function Name  : I2C_Write
  179. * Description    :
  180. * Input          :
  181. * Output         : None
  182. * Return         :
  183. * Attention                 : None
  184. *******************************************************************************/
  185. uint8_t I2C_Write(I2C_TypeDef *I2Cx,uint8_t I2C_Addr,uint8_t addr,uint8_t *buf,uint16_t num)
  186. {
  187.         uint8_t err=0;
  188.        
  189.         while(num--)
  190.         {
  191.                 if(I2C_WriteOneByte(I2Cx, I2C_Addr,addr++,*buf++))
  192.                 {
  193.                         err++;
  194.                 }
  195.         }
  196.         if(err)
  197.                 return 1;
  198.         else
  199.                 return 0;       
  200. }
复制代码


收藏 评论3 发布时间:2016-7-23 17:31

举报

3个回答
stary666 回答时间:2016-7-24 14:17:28
moyanming2013 回答时间:2016-7-24 16:47:17
首先看到了不精确的延时函数,再就是用了goto。
你的程序建议最好通过严格的测试,其实理论上讲,在I2C中,使用这种延时是个最大的隐患,一旦cpu因温度、环境电磁干扰等你的程序就挂了。
stickvc 回答时间:2019-4-26 10:01:51
看到了不精确的延时函数,再就是用了goto

所属标签

相似分享

官网相关资源

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