[应用相关] STM32F4XX高效驱动篇2 I2C

[复制链接]
 楼主| condition 发表于 2019-6-18 10:08 | 显示全部楼层 |阅读模式
说到I2C很多用过STMF10X硬件I2C方式的工程师,都感觉有点头痛。大部分还是使用软件模拟的方式,I2C由于一般的工作频率是400,100KHz。所以在平凡读取,或所读数据量大时,使用这模拟的方式,还是比较浪费CPU有效工作时间的。
         在之前的使用I2C的经历中,主要是I2C死锁问题让我也困扰了一段时间。不过后来经过多方资料,最后还是把这个问题解决了。以下驱动程序已集成了此功能。

 楼主| condition 发表于 2019-6-18 10:08 | 显示全部楼层
什么是死锁,在I2C主设备进行读写操作的过程中.主设备在开始信号后控制SCL产生8个时钟脉冲,然后拉低SCL信号为低电平,在这个时候,从设备输出应答信号,将SDA信号拉为低电平。如果这个时候主设备异常复位,SCL就会被释放为高电平。此时,如果从设备没有复位,就会继续I2C的应答,将SDA一直拉为低电平,直到SCL变为低电平,才会结束应答信号。 而对于I2C主设备来说.复位后检测SCL和SDA信号,如果发现SDA信号为低电平,则会认为I2C总线被占用,会一直等待SCL和SDA信号变为高电 平。这样,I2C主设备等待从设备释放SDA信号,而同时I2C从设备又在等待主设备将SCL信号拉低以释放应答信号,两者相互等待,I2C总线进人一种 死锁状态。同样,当I2C进行读操作,I2C从设备应答后输出数据,如果在这个时刻I2C主设备异常复位而此时I2C从设备输出的数据位正好为0,也会导 致I2C总线进入死锁状态。
 楼主| condition 发表于 2019-6-18 10:09 | 显示全部楼层
解决死锁问题,我主要总结出两点:

1,连接MCU和I2C从机的复位引脚。(保证同时复位)

2,通过下图官方所述进行软件复位。
769385d0847d90262c.png
 楼主| condition 发表于 2019-6-18 10:09 | 显示全部楼层
如果您所选的芯片符合如下时序,那么就可以使用这个驱动程序。
217175d0847ef4e727.png
 楼主| condition 发表于 2019-6-18 10:10 | 显示全部楼层
这里对本驱动程序进行说明,主驱动程序主要使用中断的方式进行数据发送,官方列程是使用的DMA方式,在大数据量传送时使用DMA还是比较好的,这里使用中断方式,主要是为了方便操作。如果是小数据大量传送时,中断方式要更高效。

打开I2C

void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed);

关闭I2C

void BSP_I2cClose(uint8_t I2C_x);

向I2C从设备写数据

uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen);

从I2C从设备读数据

uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen);

读取I2C总线空闲状态

uint32_t BSP_I2cIdleState(uint8_t I2C_x);
 楼主| condition 发表于 2019-6-18 10:11 | 显示全部楼层
  1. /*
  2. ********************************************************************************
  3. *
  4. *                                 BSP_I2c.c
  5. *
  6. * File          : BSP_I2c.c
  7. * Version       : V1.0
  8. * Author        : whq
  9. * Mode          : Thumb2
  10. * Toolchain     :
  11. * Description   : STM32F4xx I2C驱动程序
  12. *                  
  13. * History       :
  14. * Date          : 2013.07.24
  15. *******************************************************************************/

  16. #include <string.h>

  17. #include "misc.h"
  18. #include "stm32f4xx_i2c.h"
  19. #include "stm32f4xx_gpio.h"
  20. #include "stm32f4xx_rcc.h"

  21. #include "BSP_I2c.h"


  22. static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam);
  23. static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam);


  24. static I2C_PARAM_TYPE I2C_PARAM[I2Cn] = {0};

  25. static I2C_TypeDef* const I2C_NUM[I2Cn] = {
  26. #if I2C_1_EN
  27.     BSP_I2C1,
  28. #endif
  29. #if I2C_2_EN
  30.     BSP_I2C2,
  31. #endif
  32. #if I2C_3_EN
  33.     BSP_I2C3,
  34. #endif
  35. };
  36. static const uint32_t I2C_CLK[I2Cn] = {
  37. #if I2C_1_EN
  38.     BSP_I2C1_CLK,
  39. #endif
  40. #if I2C_2_EN
  41.     BSP_I2C2_CLK,
  42. #endif
  43. #if I2C_3_EN
  44.     BSP_I2C3_CLK,
  45. #endif
  46. };

  47. static const uint32_t I2C_AF_PORT[I2Cn] = {
  48. #if I2C_1_EN
  49.     BSP_I2C1_AF_Port,
  50. #endif
  51. #if I2C_2_EN
  52.     BSP_I2C2_AF_Port,
  53. #endif
  54. #if I2C_3_EN
  55.     BSP_I2C3_AF_Port,
  56. #endif
  57. };
  58. static const uint8_t I2C_SCL_AF_Source[I2Cn] = {
  59. #if I2C_1_EN
  60.     BSP_I2C1_SCL_AF_Source,
  61. #endif
  62. #if I2C_2_EN
  63.     BSP_I2C2_SCL_AF_Source,
  64. #endif
  65. #if I2C_3_EN
  66.     BSP_I2C3_SCL_AF_Source,
  67. #endif
  68. };
  69. static const uint8_t I2C_SDA_AF_Source[I2Cn] = {
  70. #if I2C_1_EN
  71.     BSP_I2C1_SDA_AF_Source,
  72. #endif
  73. #if I2C_2_EN
  74.     BSP_I2C2_SDA_AF_Source,
  75. #endif
  76. #if I2C_3_EN
  77.     BSP_I2C3_SDA_AF_Source,
  78. #endif
  79. };

  80. static GPIO_TypeDef* const I2C_SCL_PORT[I2Cn]  = {
  81. #if I2C_1_EN
  82.     BSP_I2C1_SCL_GPIO_PORT,
  83. #endif
  84. #if I2C_2_EN
  85.     BSP_I2C2_SCL_GPIO_PORT,
  86. #endif
  87. #if I2C_3_EN
  88.     BSP_I2C3_SCL_GPIO_PORT,
  89. #endif
  90. };
  91. static const uint32_t I2C_SCL_CLK[I2Cn] = {
  92. #if I2C_1_EN
  93.     BSP_I2C1_SCL_GPIO_CLK,
  94. #endif
  95. #if I2C_2_EN
  96.     BSP_I2C2_SCL_GPIO_CLK,
  97. #endif
  98. #if I2C_3_EN
  99.     BSP_I2C3_SCL_GPIO_CLK,
  100. #endif
  101. };
  102. static const uint16_t I2C_SCL_PIN[I2Cn] = {
  103. #if I2C_1_EN
  104.     BSP_I2C1_SCL_PIN,
  105. #endif
  106. #if I2C_2_EN
  107.     BSP_I2C2_SCL_PIN,
  108. #endif
  109. #if I2C_3_EN
  110.     BSP_I2C3_SCL_PIN,
  111. #endif
  112. };

  113. static GPIO_TypeDef* const I2C_SDA_PORT[I2Cn]  = {
  114. #if I2C_1_EN
  115.     BSP_I2C1_SDA_GPIO_PORT,
  116. #endif
  117. #if I2C_2_EN
  118.     BSP_I2C2_SDA_GPIO_PORT,
  119. #endif
  120. #if I2C_3_EN
  121.     BSP_I2C3_SDA_GPIO_PORT,
  122. #endif
  123. };
  124. static const uint32_t I2C_SDA_CLK[I2Cn] = {
  125. #if I2C_1_EN
  126.     BSP_I2C1_SDA_GPIO_CLK,
  127. #endif
  128. #if I2C_2_EN
  129.     BSP_I2C2_SDA_GPIO_CLK,
  130. #endif
  131. #if I2C_3_EN
  132.     BSP_I2C3_SDA_GPIO_CLK,
  133. #endif
  134. };
  135. static const uint16_t I2C_SDA_PIN[I2Cn] = {
  136. #if I2C_1_EN
  137.     BSP_I2C1_SDA_PIN,
  138. #endif
  139. #if I2C_2_EN
  140.     BSP_I2C2_SDA_PIN,
  141. #endif
  142. #if I2C_3_EN
  143.     BSP_I2C3_SDA_PIN,
  144. #endif
  145. };

  146. static const uint32_t I2C_IRQn[I2Cn] = {
  147. #if I2C_1_EN
  148.     BSP_I2C1_IRQn,
  149. #endif
  150. #if I2C_2_EN
  151.     BSP_I2C2_IRQn,
  152. #endif
  153. #if I2C_3_EN
  154.     BSP_I2C3_IRQn,
  155. #endif
  156. };


  157. /*******************************************************************************
  158. * Function Name : void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed)
  159. * Description   : 打开I2C口  
  160. * Input         :   I2C_x:      I2C_1, I2C_2
  161.                     clockSpeed: 时钟线频率
  162. * Output        :
  163. * Other         :
  164. * Date          : 2013.07.24
  165. *******************************************************************************/
  166. void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed)
  167. {
  168.     I2C_InitTypeDef  I2C_InitStructure;
  169.     GPIO_InitTypeDef GPIO_InitStructure;
  170.     NVIC_InitTypeDef NVIC_InitStructure;

  171.     /* Enable peripheral clocks ----------------------------------------------*/
  172.     /* Enable I2C clock */
  173.     RCC_APB1PeriphClockCmd(I2C_CLK[I2C_x], ENABLE);
  174.     /* Enable GPIOB clock */
  175.     RCC_AHB1PeriphClockCmd(I2C_SCL_CLK[I2C_x] | I2C_SDA_CLK[I2C_x], ENABLE);
  176.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  177.     I2C_Cmd(I2C_NUM[I2C_x], DISABLE);
  178.     I2C_DeInit(I2C_NUM[I2C_x]);   

  179.     /* Connect I2C_SCL*/   
  180.     GPIO_PinAFConfig(I2C_SCL_PORT[I2C_x], I2C_SCL_AF_Source[I2C_x], I2C_AF_PORT[I2C_x]);
  181.     /* Connect I2C_SDA*/
  182.     GPIO_PinAFConfig(I2C_SDA_PORT[I2C_x], I2C_SDA_AF_Source[I2C_x], I2C_AF_PORT[I2C_x]);

  183.     /* Configure I2C pins: SCL and SDA ---------------------------------------*/
  184.     GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
  185.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  186.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  187.     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  188.     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  189.     GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);

  190.     GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
  191.     GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);

  192.     /* DISABLE I2C event and buffer interrupt */
  193.     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);

  194.     /* I2C configuration -----------------------------------------------------*/
  195.     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  196.     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  197.     I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS;
  198.     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  199.     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  200.     I2C_InitStructure.I2C_ClockSpeed = clockSpeed;
  201.     I2C_Init(I2C_NUM[I2C_x], &I2C_InitStructure);

  202.     memset (&I2C_PARAM[I2C_x], 0, sizeof(I2C_PARAM_TYPE));

  203.     /* Configure and enable I2C interrupt ------------------------------------*/
  204.     NVIC_InitStructure.NVIC_IRQChannel = I2C_IRQn[I2C_x];
  205.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  206.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  207.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  208.     NVIC_Init(&NVIC_InitStructure);   

  209.     /* Enable I2C ------------------------------------------------------------*/   
  210.     I2C_Cmd(I2C_NUM[I2C_x], ENABLE);
  211. }

  212. /*******************************************************************************
  213. * Function Name : void _I2CDelay(volatile uint32_t count)
  214. * Description   : 延迟程序
  215. * Input         :
  216. * Output        :
  217. * Other         :
  218. * Date          : 2013.08.15
  219. *******************************************************************************/
  220. void _I2CDelay(volatile uint32_t count)
  221. {
  222.     for (; count > 0; count--);
  223. }

  224. /*******************************************************************************
  225. * Function Name : void BSP_I2cClose(uint8_t I2C_x)
  226. * Description   : 关闭I2C口 并释放总线
  227. * Input         :
  228. * Output        :
  229. * Other         :
  230. * Date          : 2013.07.24
  231. *******************************************************************************/
  232. void BSP_I2cClose(uint8_t I2C_x)
  233. {
  234.     GPIO_InitTypeDef GPIO_InitStructure;
  235.     uint16_t i = 0;

  236.     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
  237.     RCC_APB1PeriphClockCmd(I2C_CLK[I2C_x], DISABLE);
  238.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, DISABLE);

  239.     I2C_Cmd(I2C_NUM[I2C_x], DISABLE);
  240.     I2C_DeInit(I2C_NUM[I2C_x]);

  241.     /* Configure I2C pins: SCL and SDA ---------------------------------------*/
  242.     GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
  243.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  244.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  245.     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  246.     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  247.     GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);

  248.     GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
  249.     GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);

  250.     _I2CDelay(100);
  251.     for (i = 16; i > 0; i--) //16个时钟 脉冲 释放I2C总线
  252.     {
  253.         GPIO_ResetBits(I2C_SCL_PORT[I2C_x], I2C_SCL_PIN[I2C_x]);
  254.         _I2CDelay(100);  
  255.         GPIO_SetBits(I2C_SCL_PORT[I2C_x], I2C_SCL_PIN[I2C_x]);
  256.         _I2CDelay(100);        
  257.     }

  258.     GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
  259.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  260.     GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);

  261.     GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
  262.     GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);

  263.     memset (&I2C_PARAM[I2C_x], 0, sizeof(I2C_PARAM_TYPE));
  264. }

  265. /*******************************************************************************
  266. * Function Name : uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen)
  267. * Description   : I2C向从机发送数据
  268. * Input         :   I2C_x:          I2C_1,  I2C_2
  269.                     buff:           要发送的数据
  270.                     i2cSaleAddress: 从机ID号
  271.                     writeAddress:   写入的地址
  272.                     writeLen:       要写入的数据长度
  273. * Output        :
  274. * Other         : 本函数为非阻塞式 执行完后调用BSP_I2cIdleState 是否执行完毕
  275. * Date          : 2013.07.24
  276. *******************************************************************************/
  277. uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen)
  278. {
  279.     if (I2C_x >= I2C_MAX)
  280.         return 0;

  281.     if (NULL == buff)
  282.         return 0;

  283.     if (0 == writeLen)
  284.         return 0;

  285.     if (0 != I2C_PARAM[I2C_x].idle)
  286.         return 0;

  287.     I2C_PARAM[I2C_x].idle       = 1;
  288.     I2C_PARAM[I2C_x].id         = i2cSaleAddress;
  289.     I2C_PARAM[I2C_x].addr       = writeAddress;
  290.     I2C_PARAM[I2C_x].index      = 0;
  291.     I2C_PARAM[I2C_x].r_w        = 0;
  292.     I2C_PARAM[I2C_x].bufLen     = writeLen;
  293.     I2C_PARAM[I2C_x].pBuff      = buff;
  294.     I2C_PARAM[I2C_x].FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;

  295.     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, ENABLE);
  296.     I2C_AcknowledgeConfig(I2C_NUM[I2C_x], ENABLE);
  297.     /* Send I2C START condition */
  298.     I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
  299.     return writeLen;
  300. }

  301. /*******************************************************************************
  302. * Function Name : uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen)
  303. * Description   : I2C 读取数据
  304. * Input         :   I2C_x:          I2C_1,  I2C_2
  305.                     buff:           读数缓冲区
  306.                     i2cSaleAddress: 从机ID号
  307.                     readAddress:    读取的地址
  308.                     readLen:        要读取的数据长度
  309. * Output        :
  310. * Other         : 本函数为非阻塞式 执行完后调用BSP_I2cIdleState 是否执行完毕
  311. * Date          : 2013.07.24
  312. *******************************************************************************/
  313. uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen)
  314. {
  315.     if (I2C_x >= I2C_MAX)
  316.         return 0;

  317.     if (NULL == buff)
  318.         return 0;

  319.     if (0 == readLen)
  320.         return 0;

  321.     if (0 != I2C_PARAM[I2C_x].idle)
  322.         return 0;
  323.         
  324.     I2C_PARAM[I2C_x].idle       = 1;
  325.     I2C_PARAM[I2C_x].id         = i2cSaleAddress;
  326.     I2C_PARAM[I2C_x].addr       = readAddress;
  327.     I2C_PARAM[I2C_x].index      = 0;
  328.     I2C_PARAM[I2C_x].r_w        = 1;
  329.     I2C_PARAM[I2C_x].bufLen     = readLen;
  330.     I2C_PARAM[I2C_x].pBuff      = buff;
  331.     I2C_PARAM[I2C_x].FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;

  332.     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, ENABLE);
  333.     I2C_AcknowledgeConfig(I2C_NUM[I2C_x], ENABLE);
  334.     /* Send I2C START condition */
  335.     I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
  336.     return readLen;
  337. }

  338. /*******************************************************************************
  339. * Function Name : uint32_t BSP_I2cIdleState(uint8_t I2C_x)
  340. * Description   : 查询是否总线空闲 如果为空闲则读取参数
  341. * Input         :   I2C_x:      I2C_1,      I2C_2
  342. * Output        :   return:     0)空闲      1)忙碌
  343. * Other         :
  344. * Date          : 2013.07.24
  345. *******************************************************************************/
  346. uint32_t BSP_I2cIdleState(uint8_t I2C_x)
  347. {
  348.     return (I2C_PARAM[I2C_x].idle || I2C_GetFlagStatus(I2C_NUM[I2C_x], I2C_FLAG_BUSY));
  349. }

  350. /*******************************************************************************
  351. * Function Name : static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
  352. * Description   : 发送数据中断函数
  353. * Input         :
  354. * Output        :
  355. * Other         :
  356. * Date          : 2013.07.24
  357. *******************************************************************************/
  358. static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
  359. {
  360.     switch (I2C_GetLastEvent(I2C_NUM[I2C_x]))
  361.     {
  362.     /* Test on I2Cx EV5 and clear it */
  363.     case I2C_EVENT_MASTER_MODE_SELECT:
  364.         I2C_Send7bitAddress(I2C_NUM[I2C_x], pParam->id, I2C_Direction_Transmitter);
  365.         break;

  366.     /* Test on I2Cx EV6 and first EV8 and clear them */
  367.     case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
  368.         /* Send the first data */
  369.         I2C_SendData(I2C_NUM[I2C_x], pParam->addr);  /* EV8 just after EV6 */
  370.         break;

  371.     case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
  372.         if((pParam->index < pParam->bufLen) && (pParam->r_w == 0))
  373.         {
  374.             /* Transmit buffer data */
  375.             I2C_SendData(I2C_NUM[I2C_x], pParam->pBuff[pParam->index++]);
  376.         }
  377.         else
  378.         {   
  379.             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_BUF, DISABLE);
  380.         }
  381.         break;

  382.     /* Test on I2Cx EV8 and clear it */
  383.     case I2C_EVENT_MASTER_BYTE_TRANSMITTED:     
  384.         if (pParam->r_w != 0)
  385.         {
  386.             pParam->FunCallBack = (void (*)(uint8_t, void *))_I2cRxIRQ;            
  387.             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_BUF, ENABLE);
  388.             I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
  389.         }
  390.         else
  391.         {
  392.             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
  393.             I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
  394.             I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);            
  395.             pParam->idle = 0;            //接收结束标志
  396.         }
  397.         break;
  398.     }
  399. }

  400. /*******************************************************************************
  401. * Function Name : static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
  402. * Description   : 接收数据中断函数
  403. * Input         :
  404. * Output        :
  405. * Other         :
  406. * Date          : 2013.07.24
  407. *******************************************************************************/
  408. static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
  409. {
  410.     switch (I2C_GetLastEvent(I2C_NUM[I2C_x]))
  411.     {
  412.     /* Test on I2Cx EV5 and clear it */
  413.     case I2C_EVENT_MASTER_MODE_SELECT:  
  414.         /* Send I2Cx slave Address for write */
  415.         I2C_Send7bitAddress(I2C_NUM[I2C_x], pParam->id, I2C_Direction_Receiver);
  416.         break;

  417.     /* Test on I2Cx EV6 and first EV8 and clear them */
  418.     case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
  419.         if (pParam->index == (pParam->bufLen - 1))
  420.         {
  421.             I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
  422.             I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
  423.         }
  424.         break;

  425.     /* Test on I2Cx EV2 and clear it */
  426.     case I2C_EVENT_MASTER_BYTE_RECEIVED:
  427.         pParam->pBuff[pParam->index++] = I2C_ReceiveData(I2C_NUM[I2C_x]);
  428.             
  429.         if (pParam->index == (pParam->bufLen - 1))
  430.         {
  431.             I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
  432.             I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
  433.         }
  434.         else if (pParam->index >= pParam->bufLen)
  435.         {
  436.             pParam->FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;    //默认进接收中断      
  437.             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
  438.             pParam->idle = 0;            
  439.         }
  440.         break;
  441.     }
  442. }

  443. #if I2C_1_EN
  444. /*******************************************************************************
  445. * Function Name : void I2C1_EV_IRQHandler(void)
  446. * Description   : I2C1中断函数
  447. * Input         :
  448. * Output        :
  449. * Other         :
  450. * Date          : 2013.07.24
  451. *******************************************************************************/
  452. void I2C1_EV_IRQHandler(void)
  453. {
  454.     if (I2C_PARAM[I2C_1].FunCallBack)
  455.     {
  456.         I2C_PARAM[I2C_1].FunCallBack(I2C_1, &I2C_PARAM[I2C_1]);
  457.     }
  458. }
  459. #endif

  460. #if I2C_2_EN
  461. /*******************************************************************************
  462. * Function Name : void I2C2_EV_IRQHandler(void)
  463. * Description   : I2C2中断函数
  464. * Input         :
  465. * Output        :
  466. * Other         :
  467. * Date          : 2013.07.24
  468. *******************************************************************************/
  469. void I2C2_EV_IRQHandler(void)
  470. {
  471.     if (I2C_PARAM[I2C_2].FunCallBack)
  472.     {
  473.         I2C_PARAM[I2C_2].FunCallBack(I2C_2, &I2C_PARAM[I2C_2]);
  474.     }
  475. }
  476. #endif

  477. #if I2C_3_EN
  478. /*******************************************************************************
  479. * Function Name : void I2C3_EV_IRQHandler(void)
  480. * Description   : I2C3中断函数
  481. * Input         :
  482. * Output        :
  483. * Other         :
  484. * Date          : 2013.07.24
  485. *******************************************************************************/
  486. void I2C3_EV_IRQHandler(void)
  487. {
  488.     if (I2C_PARAM[I2C_3].FunCallBack)
  489.     {
  490.         I2C_PARAM[I2C_3].FunCallBack(I2C_3, &I2C_PARAM[I2C_3]);
  491.     }
  492. }
  493. #endif

  494. BSP_I2c.c
 楼主| condition 发表于 2019-6-18 10:11 | 显示全部楼层
  1. /*
  2. ********************************************************************************
  3. *
  4. *                                 BSP_I2c.h
  5. *
  6. * File          : BSP_I2c.h
  7. * Version       : V1.0
  8. * Author        : whq
  9. * Mode          : Thumb2
  10. * Toolchain     :
  11. * Description   : I2C驱动头文件
  12. *               
  13. * History       :
  14. * Date          : 2013.07.24
  15. *******************************************************************************/

  16. #ifndef _BSP_I2C_H_
  17. #define _BSP_I2C_H_

  18. #include <stdint.h>

  19. #define I2C_1_EN                        1   
  20. #define I2C_2_EN                        1
  21. #define I2C_3_EN                        1

  22. #if !(I2C_1_EN || I2C_2_EN ||I2C_3_EN)
  23. #error  "请至少打开一路I2C"
  24. #endif

  25. typedef enum {
  26. #if I2C_1_EN
  27.     I2C_1,
  28. #endif
  29. #if I2C_2_EN
  30.     I2C_2,
  31. #endif
  32. #if I2C_3_EN
  33.     I2C_3,
  34. #endif
  35.     I2C_MAX
  36. }I2C_ENUM;

  37. #define I2Cn                            I2C_MAX
  38. #define I2C_1_0                         //无映射:I2C_1_0,映射1:I2C_1_1
  39. #define I2C_2_0
  40. #define I2C_3_0                         //无映射:I2C_3_0,映射1:I2C_3_1

  41. #define I2C_SLAVE_ADDRESS                   0x30        //本STM32芯片地址


  42. /******************************类型声明****************************************/

  43. typedef struct {
  44.     volatile uint8_t idle;    //空闲标志  0)空闲   1)忙碌
  45.     uint8_t r_w;              //读写标志  0)写     1)读
  46.     uint8_t id;               //从机设备ID号
  47.     uint8_t addr;             //要读写的地址
  48.     volatile uint16_t index;  //当前缓冲区数据长度
  49.     uint16_t bufLen;          //要发送或接收的数据长度   
  50.     uint8_t * volatile pBuff; //缓冲区首地址   
  51.     void (* volatile FunCallBack)(uint8_t, void *);//中断回调函数
  52. }I2C_PARAM_TYPE;

  53. /******************************************************************************/


  54. /**
  55.   * [url=home.php?mod=space&uid=247401]@brief[/url]  I2C1 Interface pins
  56.   */  
  57. #define BSP_I2C1                            I2C1
  58. #define BSP_I2C1_CLK                        RCC_APB1Periph_I2C1
  59. #define BSP_I2C1_AF_Port                    GPIO_AF_I2C1
  60. #define BSP_I2C1_IRQn                       I2C1_EV_IRQn

  61. #if defined(I2C_1_2)                        //自由组合区
  62. #define BSP_I2C1_SCL_AF_Source              GPIO_PinSource8
  63. #define BSP_I2C1_SCL_PIN                    GPIO_Pin_8
  64. #define BSP_I2C1_SCL_GPIO_PORT              GPIOB
  65. #define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

  66. #define BSP_I2C1_SDA_AF_Source              GPIO_PinSource9
  67. #define BSP_I2C1_SDA_PIN                    GPIO_Pin_9
  68. #define BSP_I2C1_SDA_GPIO_PORT              GPIOB
  69. #define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB

  70. #elif defined(I2C_1_1)
  71. #define BSP_I2C1_SCL_AF_Source              GPIO_PinSource8
  72. #define BSP_I2C1_SCL_PIN                    GPIO_Pin_8
  73. #define BSP_I2C1_SCL_GPIO_PORT              GPIOB
  74. #define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

  75. #define BSP_I2C1_SDA_AF_Source              GPIO_PinSource9
  76. #define BSP_I2C1_SDA_PIN                    GPIO_Pin_9
  77. #define BSP_I2C1_SDA_GPIO_PORT              GPIOB
  78. #define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB

  79. #else
  80. #define BSP_I2C1_SCL_AF_Source              GPIO_PinSource6
  81. #define BSP_I2C1_SCL_PIN                    GPIO_Pin_6
  82. #define BSP_I2C1_SCL_GPIO_PORT              GPIOB
  83. #define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

  84. #define BSP_I2C1_SDA_AF_Source              GPIO_PinSource7
  85. #define BSP_I2C1_SDA_PIN                    GPIO_Pin_7
  86. #define BSP_I2C1_SDA_GPIO_PORT              GPIOB
  87. #define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
  88. #endif

  89. /**
  90.   * @brief  I2C2 Interface pins
  91.   */  
  92. #define BSP_I2C2                            I2C2
  93. #define BSP_I2C2_CLK                        RCC_APB1Periph_I2C2
  94. #define BSP_I2C2_AF_Port                    GPIO_AF_I2C2
  95. #define BSP_I2C2_IRQn                       I2C2_EV_IRQn

  96. #if defined(I2C_2_3)                        //自由组合区
  97. #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource4
  98. #define BSP_I2C2_SCL_PIN                    GPIO_Pin_4
  99. #define BSP_I2C2_SCL_GPIO_PORT              GPIOH
  100. #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH

  101. #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource5
  102. #define BSP_I2C2_SDA_PIN                    GPIO_Pin_5
  103. #define BSP_I2C2_SDA_GPIO_PORT              GPIOH
  104. #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH

  105. #elif defined(I2C_2_2)
  106. #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource4
  107. #define BSP_I2C2_SCL_PIN                    GPIO_Pin_4
  108. #define BSP_I2C2_SCL_GPIO_PORT              GPIOH
  109. #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH

  110. #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource5
  111. #define BSP_I2C2_SDA_PIN                    GPIO_Pin_5
  112. #define BSP_I2C2_SDA_GPIO_PORT              GPIOH
  113. #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH

  114. #elif defined(I2C_2_1)
  115. #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource1
  116. #define BSP_I2C2_SCL_PIN                    GPIO_Pin_1
  117. #define BSP_I2C2_SCL_GPIO_PORT              GPIOF
  118. #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOF

  119. #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource0
  120. #define BSP_I2C2_SDA_PIN                    GPIO_Pin_0
  121. #define BSP_I2C2_SDA_GPIO_PORT              GPIOF
  122. #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOF

  123. #else
  124. #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource10
  125. #define BSP_I2C2_SCL_PIN                    GPIO_Pin_10
  126. #define BSP_I2C2_SCL_GPIO_PORT              GPIOB
  127. #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB

  128. #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource11
  129. #define BSP_I2C2_SDA_PIN                    GPIO_Pin_11
  130. #define BSP_I2C2_SDA_GPIO_PORT              GPIOB
  131. #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
  132. #endif

  133. /**
  134.   * @brief  I2C3 Interface pins
  135.   */  
  136. #define BSP_I2C3                            I2C3
  137. #define BSP_I2C3_CLK                        RCC_APB1Periph_I2C3
  138. #define BSP_I2C3_AF_Port                    GPIO_AF_I2C3
  139. #define BSP_I2C3_IRQn                       I2C3_EV_IRQn

  140. #if defined(I2C_3_2)                        //自由组合区
  141. #define BSP_I2C3_SCL_AF_Source              GPIO_PinSource8
  142. #define BSP_I2C3_SCL_PIN                    GPIO_Pin_8
  143. #define BSP_I2C3_SCL_GPIO_PORT              GPIOA
  144. #define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOA

  145. #define BSP_I2C3_SDA_AF_Source              GPIO_PinSource8
  146. #define BSP_I2C3_SDA_PIN                    GPIO_Pin_8
  147. #define BSP_I2C3_SDA_GPIO_PORT              GPIOH
  148. #define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH

  149. #elif defined(I2C_3_1)
  150. #define BSP_I2C3_SCL_AF_Source              GPIO_PinSource8
  151. #define BSP_I2C3_SCL_PIN                    GPIO_Pin_8
  152. #define BSP_I2C3_SCL_GPIO_PORT              GPIOA
  153. #define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOA

  154. #define BSP_I2C3_SDA_AF_Source              GPIO_PinSource9
  155. #define BSP_I2C3_SDA_PIN                    GPIO_Pin_9
  156. #define BSP_I2C3_SDA_GPIO_PORT              GPIOC
  157. #define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOC

  158. #else
  159. #define BSP_I2C3_SCL_AF_Source              GPIO_PinSource7
  160. #define BSP_I2C3_SCL_PIN                    GPIO_Pin_7
  161. #define BSP_I2C3_SCL_GPIO_PORT              GPIOH
  162. #define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH

  163. #define BSP_I2C3_SDA_AF_Source              GPIO_PinSource8
  164. #define BSP_I2C3_SDA_PIN                    GPIO_Pin_8
  165. #define BSP_I2C3_SDA_GPIO_PORT              GPIOH
  166. #define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH
  167. #endif



  168. /******************************函数声明****************************************/
  169. void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed);
  170. void BSP_I2cClose(uint8_t I2C_x);
  171. uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen);
  172. uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen);
  173. uint32_t BSP_I2cIdleState(uint8_t I2C_x);



  174. #endif

  175. BSP_I2c.h
heimaojingzhang 发表于 2019-7-8 11:15 | 显示全部楼层
非常感谢楼主分享
keaibukelian 发表于 2019-7-8 11:27 | 显示全部楼层
感谢楼主分享啊
labasi 发表于 2019-7-8 11:30 | 显示全部楼层

非常感谢楼主分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

256

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部