说到I2C很多用过STMF10X硬件I2C方式的工程师,都感觉有点头痛。大部分还是使用软件模拟的方式,I2C由于一般的工作频率是400,100KHz。所以在平凡读取,或所读数据量大时,使用这模拟的方式,还是比较浪费CPU有效工作时间的。

在之前的使用I2C的经历中,主要是I2C死锁问题让我也困扰了一段时间。不过后来经过多方资料,最后还是把这个问题解决了。以下驱动程序已集成了此功能。

什么是死锁,在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总线进入死锁状态。

解决死锁问题,我主要总结出两点:

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

2,通过图1官方所述进行软件复位。

图1:

如果您所选的芯片符合如下时序,那么就可以使用这个驱动程序。

图2:

这里对本驱动程序进行说明,主驱动程序主要使用中断的方式进行数据发送,官方列程是使用的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);

  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
 17 #include <string.h>
 18
 19 #include "misc.h"
 20 #include "stm32f4xx_i2c.h"
 21 #include "stm32f4xx_gpio.h"
 22 #include "stm32f4xx_rcc.h"
 23
 24 #include "BSP_I2c.h"
 25
 26
 27 static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam);
 28 static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam);
 29
 30
 31 static I2C_PARAM_TYPE I2C_PARAM[I2Cn] = {0};
 32
 33 static I2C_TypeDef* const I2C_NUM[I2Cn] = {
 34 #if I2C_1_EN
 35     BSP_I2C1,
 36 #endif
 37 #if I2C_2_EN
 38     BSP_I2C2,
 39 #endif
 40 #if I2C_3_EN
 41     BSP_I2C3,
 42 #endif
 43  };
 44 static const uint32_t I2C_CLK[I2Cn] = {
 45 #if I2C_1_EN
 46     BSP_I2C1_CLK,
 47 #endif
 48 #if I2C_2_EN
 49     BSP_I2C2_CLK,
 50 #endif
 51 #if I2C_3_EN
 52     BSP_I2C3_CLK,
 53 #endif
 54 };
 55
 56 static const uint32_t I2C_AF_PORT[I2Cn] = {
 57 #if I2C_1_EN
 58     BSP_I2C1_AF_Port,
 59 #endif
 60 #if I2C_2_EN
 61     BSP_I2C2_AF_Port,
 62 #endif
 63 #if I2C_3_EN
 64     BSP_I2C3_AF_Port,
 65 #endif
 66 };
 67 static const uint8_t I2C_SCL_AF_Source[I2Cn] = {
 68 #if I2C_1_EN
 69     BSP_I2C1_SCL_AF_Source,
 70 #endif
 71 #if I2C_2_EN
 72     BSP_I2C2_SCL_AF_Source,
 73 #endif
 74 #if I2C_3_EN
 75     BSP_I2C3_SCL_AF_Source,
 76 #endif
 77 };
 78 static const uint8_t I2C_SDA_AF_Source[I2Cn] = {
 79 #if I2C_1_EN
 80     BSP_I2C1_SDA_AF_Source,
 81 #endif
 82 #if I2C_2_EN
 83     BSP_I2C2_SDA_AF_Source,
 84 #endif
 85 #if I2C_3_EN
 86     BSP_I2C3_SDA_AF_Source,
 87 #endif
 88 };
 89
 90 static GPIO_TypeDef* const I2C_SCL_PORT[I2Cn]  = {
 91 #if I2C_1_EN
 92     BSP_I2C1_SCL_GPIO_PORT,
 93 #endif
 94 #if I2C_2_EN
 95     BSP_I2C2_SCL_GPIO_PORT,
 96 #endif
 97 #if I2C_3_EN
 98     BSP_I2C3_SCL_GPIO_PORT,
 99 #endif
100 };
101 static const uint32_t I2C_SCL_CLK[I2Cn] = {
102 #if I2C_1_EN
103     BSP_I2C1_SCL_GPIO_CLK,
104 #endif
105 #if I2C_2_EN
106     BSP_I2C2_SCL_GPIO_CLK,
107 #endif
108 #if I2C_3_EN
109     BSP_I2C3_SCL_GPIO_CLK,
110 #endif
111 };
112 static const uint16_t I2C_SCL_PIN[I2Cn] = {
113 #if I2C_1_EN
114     BSP_I2C1_SCL_PIN,
115 #endif
116 #if I2C_2_EN
117     BSP_I2C2_SCL_PIN,
118 #endif
119 #if I2C_3_EN
120     BSP_I2C3_SCL_PIN,
121 #endif
122 };
123
124 static GPIO_TypeDef* const I2C_SDA_PORT[I2Cn]  = {
125 #if I2C_1_EN
126     BSP_I2C1_SDA_GPIO_PORT,
127 #endif
128 #if I2C_2_EN
129     BSP_I2C2_SDA_GPIO_PORT,
130 #endif
131 #if I2C_3_EN
132     BSP_I2C3_SDA_GPIO_PORT,
133 #endif
134 };
135 static const uint32_t I2C_SDA_CLK[I2Cn] = {
136 #if I2C_1_EN
137     BSP_I2C1_SDA_GPIO_CLK,
138 #endif
139 #if I2C_2_EN
140     BSP_I2C2_SDA_GPIO_CLK,
141 #endif
142 #if I2C_3_EN
143     BSP_I2C3_SDA_GPIO_CLK,
144 #endif
145 };
146 static const uint16_t I2C_SDA_PIN[I2Cn] = {
147 #if I2C_1_EN
148     BSP_I2C1_SDA_PIN,
149 #endif
150 #if I2C_2_EN
151     BSP_I2C2_SDA_PIN,
152 #endif
153 #if I2C_3_EN
154     BSP_I2C3_SDA_PIN,
155 #endif
156 };
157
158 static const uint32_t I2C_IRQn[I2Cn] = {
159 #if I2C_1_EN
160     BSP_I2C1_IRQn,
161 #endif
162 #if I2C_2_EN
163     BSP_I2C2_IRQn,
164 #endif
165 #if I2C_3_EN
166     BSP_I2C3_IRQn,
167 #endif
168 };
169
170
171 /*******************************************************************************
172 * Function Name : void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed)
173 * Description   : 打开I2C口
174 * Input         :   I2C_x:      I2C_1, I2C_2
175                     clockSpeed: 时钟线频率
176 * Output        :
177 * Other         :
178 * Date          : 2013.07.24
179 *******************************************************************************/
180 void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed)
181 {
182     I2C_InitTypeDef  I2C_InitStructure;
183     GPIO_InitTypeDef GPIO_InitStructure;
184     NVIC_InitTypeDef NVIC_InitStructure;
185
186     /* Enable peripheral clocks ----------------------------------------------*/
187     /* Enable I2C clock */
188     RCC_APB1PeriphClockCmd(I2C_CLK[I2C_x], ENABLE);
189     /* Enable GPIOB clock */
190     RCC_AHB1PeriphClockCmd(I2C_SCL_CLK[I2C_x] | I2C_SDA_CLK[I2C_x], ENABLE);
191     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
192
193     I2C_Cmd(I2C_NUM[I2C_x], DISABLE);
194     I2C_DeInit(I2C_NUM[I2C_x]);
195
196     /* Connect I2C_SCL*/
197     GPIO_PinAFConfig(I2C_SCL_PORT[I2C_x], I2C_SCL_AF_Source[I2C_x], I2C_AF_PORT[I2C_x]);
198     /* Connect I2C_SDA*/
199     GPIO_PinAFConfig(I2C_SDA_PORT[I2C_x], I2C_SDA_AF_Source[I2C_x], I2C_AF_PORT[I2C_x]);
200
201     /* Configure I2C pins: SCL and SDA ---------------------------------------*/
202     GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
203     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
204     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
205     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
206     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
207     GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);
208
209     GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
210     GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);
211
212     /* DISABLE I2C event and buffer interrupt */
213     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
214
215     /* I2C configuration -----------------------------------------------------*/
216     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
217     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
218     I2C_InitStructure.I2C_OwnAddress1 = I2C_SLAVE_ADDRESS;
219     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
220     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
221     I2C_InitStructure.I2C_ClockSpeed = clockSpeed;
222     I2C_Init(I2C_NUM[I2C_x], &I2C_InitStructure);
223
224     memset (&I2C_PARAM[I2C_x], 0, sizeof(I2C_PARAM_TYPE));
225
226     /* Configure and enable I2C interrupt ------------------------------------*/
227     NVIC_InitStructure.NVIC_IRQChannel = I2C_IRQn[I2C_x];
228     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
229     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
230     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
231     NVIC_Init(&NVIC_InitStructure);
232
233     /* Enable I2C ------------------------------------------------------------*/
234     I2C_Cmd(I2C_NUM[I2C_x], ENABLE);
235 }
236
237 /*******************************************************************************
238 * Function Name : void _I2CDelay(volatile uint32_t count)
239 * Description   : 延迟程序
240 * Input         :
241 * Output        :
242 * Other         :
243 * Date          : 2013.08.15
244 *******************************************************************************/
245 void _I2CDelay(volatile uint32_t count)
246 {
247     for (; count > 0; count--);
248 }
249
250 /*******************************************************************************
251 * Function Name : void BSP_I2cClose(uint8_t I2C_x)
252 * Description   : 关闭I2C口 并释放总线
253 * Input         :
254 * Output        :
255 * Other         :
256 * Date          : 2013.07.24
257 *******************************************************************************/
258 void BSP_I2cClose(uint8_t I2C_x)
259 {
260     GPIO_InitTypeDef GPIO_InitStructure;
261     uint16_t i = 0;
262
263     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
264     RCC_APB1PeriphClockCmd(I2C_CLK[I2C_x], DISABLE);
265     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, DISABLE);
266
267     I2C_Cmd(I2C_NUM[I2C_x], DISABLE);
268     I2C_DeInit(I2C_NUM[I2C_x]);
269
270     /* Configure I2C pins: SCL and SDA ---------------------------------------*/
271     GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
272     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
273     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
274     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
275     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
276     GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);
277
278     GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
279     GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);
280
281     _I2CDelay(100);
282     for (i = 16; i > 0; i--) //16个时钟 脉冲 释放I2C总线
283     {
284         GPIO_ResetBits(I2C_SCL_PORT[I2C_x], I2C_SCL_PIN[I2C_x]);
285         _I2CDelay(100);
286         GPIO_SetBits(I2C_SCL_PORT[I2C_x], I2C_SCL_PIN[I2C_x]);
287         _I2CDelay(100);
288     }
289
290     GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN[I2C_x];
291     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
292     GPIO_Init(I2C_SCL_PORT[I2C_x], &GPIO_InitStructure);
293
294     GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN[I2C_x];
295     GPIO_Init(I2C_SDA_PORT[I2C_x], &GPIO_InitStructure);
296
297     memset (&I2C_PARAM[I2C_x], 0, sizeof(I2C_PARAM_TYPE));
298 }
299
300 /*******************************************************************************
301 * Function Name : uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen)
302 * Description   : I2C向从机发送数据
303 * Input         :   I2C_x:          I2C_1,  I2C_2
304                     buff:           要发送的数据
305                     i2cSaleAddress: 从机ID号
306                     writeAddress:   写入的地址
307                     writeLen:       要写入的数据长度
308 * Output        :
309 * Other         : 本函数为非阻塞式 执行完后调用BSP_I2cIdleState 是否执行完毕
310 * Date          : 2013.07.24
311 *******************************************************************************/
312 uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen)
313 {
314     if (I2C_x >= I2C_MAX)
315         return 0;
316
317     if (NULL == buff)
318         return 0;
319
320     if (0 == writeLen)
321         return 0;
322
323     if (0 != I2C_PARAM[I2C_x].idle)
324         return 0;
325
326     I2C_PARAM[I2C_x].idle       = 1;
327     I2C_PARAM[I2C_x].id         = i2cSaleAddress;
328     I2C_PARAM[I2C_x].addr       = writeAddress;
329     I2C_PARAM[I2C_x].index      = 0;
330     I2C_PARAM[I2C_x].r_w        = 0;
331     I2C_PARAM[I2C_x].bufLen     = writeLen;
332     I2C_PARAM[I2C_x].pBuff      = buff;
333     I2C_PARAM[I2C_x].FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;
334
335     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, ENABLE);
336     I2C_AcknowledgeConfig(I2C_NUM[I2C_x], ENABLE);
337     /* Send I2C START condition */
338     I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
339     return writeLen;
340 }
341
342 /*******************************************************************************
343 * Function Name : uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen)
344 * Description   : I2C 读取数据
345 * Input         :   I2C_x:          I2C_1,  I2C_2
346                     buff:           读数缓冲区
347                     i2cSaleAddress: 从机ID号
348                     readAddress:    读取的地址
349                     readLen:        要读取的数据长度
350 * Output        :
351 * Other         : 本函数为非阻塞式 执行完后调用BSP_I2cIdleState 是否执行完毕
352 * Date          : 2013.07.24
353 *******************************************************************************/
354 uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen)
355 {
356     if (I2C_x >= I2C_MAX)
357         return 0;
358
359     if (NULL == buff)
360         return 0;
361
362     if (0 == readLen)
363         return 0;
364
365     if (0 != I2C_PARAM[I2C_x].idle)
366         return 0;
367
368     I2C_PARAM[I2C_x].idle       = 1;
369     I2C_PARAM[I2C_x].id         = i2cSaleAddress;
370     I2C_PARAM[I2C_x].addr       = readAddress;
371     I2C_PARAM[I2C_x].index      = 0;
372     I2C_PARAM[I2C_x].r_w        = 1;
373     I2C_PARAM[I2C_x].bufLen     = readLen;
374     I2C_PARAM[I2C_x].pBuff      = buff;
375     I2C_PARAM[I2C_x].FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;
376
377     I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, ENABLE);
378     I2C_AcknowledgeConfig(I2C_NUM[I2C_x], ENABLE);
379     /* Send I2C START condition */
380     I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
381     return readLen;
382 }
383
384 /*******************************************************************************
385 * Function Name : uint32_t BSP_I2cIdleState(uint8_t I2C_x)
386 * Description   : 查询是否总线空闲 如果为空闲则读取参数
387 * Input         :   I2C_x:      I2C_1,      I2C_2
388 * Output        :   return:     0)空闲      1)忙碌
389 * Other         :
390 * Date          : 2013.07.24
391 *******************************************************************************/
392 uint32_t BSP_I2cIdleState(uint8_t I2C_x)
393 {
394     return (I2C_PARAM[I2C_x].idle || I2C_GetFlagStatus(I2C_NUM[I2C_x], I2C_FLAG_BUSY));
395 }
396
397 /*******************************************************************************
398 * Function Name : static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
399 * Description   : 发送数据中断函数
400 * Input         :
401 * Output        :
402 * Other         :
403 * Date          : 2013.07.24
404 *******************************************************************************/
405 static void _I2cTxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
406 {
407     switch (I2C_GetLastEvent(I2C_NUM[I2C_x]))
408     {
409     /* Test on I2Cx EV5 and clear it */
410     case I2C_EVENT_MASTER_MODE_SELECT:
411         I2C_Send7bitAddress(I2C_NUM[I2C_x], pParam->id, I2C_Direction_Transmitter);
412         break;
413
414     /* Test on I2Cx EV6 and first EV8 and clear them */
415     case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
416         /* Send the first data */
417         I2C_SendData(I2C_NUM[I2C_x], pParam->addr);  /* EV8 just after EV6 */
418         break;
419
420     case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
421         if((pParam->index < pParam->bufLen) && (pParam->r_w == 0))
422         {
423             /* Transmit buffer data */
424             I2C_SendData(I2C_NUM[I2C_x], pParam->pBuff[pParam->index++]);
425         }
426         else
427         {
428             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_BUF, DISABLE);
429         }
430         break;
431
432     /* Test on I2Cx EV8 and clear it */
433     case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
434         if (pParam->r_w != 0)
435         {
436             pParam->FunCallBack = (void (*)(uint8_t, void *))_I2cRxIRQ;
437             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_BUF, ENABLE);
438             I2C_GenerateSTART(I2C_NUM[I2C_x], ENABLE);
439         }
440         else
441         {
442             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
443             I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
444             I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
445             pParam->idle = 0;            //接收结束标志
446         }
447         break;
448     }
449 }
450
451 /*******************************************************************************
452 * Function Name : static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
453 * Description   : 接收数据中断函数
454 * Input         :
455 * Output        :
456 * Other         :
457 * Date          : 2013.07.24
458 *******************************************************************************/
459 static void _I2cRxIRQ(uint8_t I2C_x, I2C_PARAM_TYPE *pParam)
460 {
461     switch (I2C_GetLastEvent(I2C_NUM[I2C_x]))
462     {
463     /* Test on I2Cx EV5 and clear it */
464     case I2C_EVENT_MASTER_MODE_SELECT:
465         /* Send I2Cx slave Address for write */
466         I2C_Send7bitAddress(I2C_NUM[I2C_x], pParam->id, I2C_Direction_Receiver);
467         break;
468
469     /* Test on I2Cx EV6 and first EV8 and clear them */
470     case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED:
471         if (pParam->index == (pParam->bufLen - 1))
472         {
473             I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
474             I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
475         }
476         break;
477
478     /* Test on I2Cx EV2 and clear it */
479     case I2C_EVENT_MASTER_BYTE_RECEIVED:
480         pParam->pBuff[pParam->index++] = I2C_ReceiveData(I2C_NUM[I2C_x]);
481
482         if (pParam->index == (pParam->bufLen - 1))
483         {
484             I2C_AcknowledgeConfig(I2C_NUM[I2C_x], DISABLE);
485             I2C_GenerateSTOP(I2C_NUM[I2C_x], ENABLE);
486         }
487         else if (pParam->index >= pParam->bufLen)
488         {
489             pParam->FunCallBack = (void (*)(uint8_t, void *))_I2cTxIRQ;    //默认进接收中断
490             I2C_ITConfig(I2C_NUM[I2C_x], I2C_IT_EVT | I2C_IT_BUF, DISABLE);
491             pParam->idle = 0;
492         }
493         break;
494     }
495 }
496
497 #if I2C_1_EN
498 /*******************************************************************************
499 * Function Name : void I2C1_EV_IRQHandler(void)
500 * Description   : I2C1中断函数
501 * Input         :
502 * Output        :
503 * Other         :
504 * Date          : 2013.07.24
505 *******************************************************************************/
506 void I2C1_EV_IRQHandler(void)
507 {
508     if (I2C_PARAM[I2C_1].FunCallBack)
509     {
510         I2C_PARAM[I2C_1].FunCallBack(I2C_1, &I2C_PARAM[I2C_1]);
511     }
512 }
513 #endif
514
515 #if I2C_2_EN
516 /*******************************************************************************
517 * Function Name : void I2C2_EV_IRQHandler(void)
518 * Description   : I2C2中断函数
519 * Input         :
520 * Output        :
521 * Other         :
522 * Date          : 2013.07.24
523 *******************************************************************************/
524 void I2C2_EV_IRQHandler(void)
525 {
526     if (I2C_PARAM[I2C_2].FunCallBack)
527     {
528         I2C_PARAM[I2C_2].FunCallBack(I2C_2, &I2C_PARAM[I2C_2]);
529     }
530 }
531 #endif
532
533 #if I2C_3_EN
534 /*******************************************************************************
535 * Function Name : void I2C3_EV_IRQHandler(void)
536 * Description   : I2C3中断函数
537 * Input         :
538 * Output        :
539 * Other         :
540 * Date          : 2013.07.24
541 *******************************************************************************/
542 void I2C3_EV_IRQHandler(void)
543 {
544     if (I2C_PARAM[I2C_3].FunCallBack)
545     {
546         I2C_PARAM[I2C_3].FunCallBack(I2C_3, &I2C_PARAM[I2C_3]);
547     }
548 }
549 #endif

BSP_I2c.c

  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
 17 #ifndef _BSP_I2C_H_
 18 #define _BSP_I2C_H_
 19
 20 #include <stdint.h>
 21
 22 #define I2C_1_EN                        1
 23 #define I2C_2_EN                        1
 24 #define I2C_3_EN                        1
 25
 26 #if !(I2C_1_EN || I2C_2_EN ||I2C_3_EN)
 27 #error  "请至少打开一路I2C"
 28 #endif
 29
 30 typedef enum {
 31 #if I2C_1_EN
 32     I2C_1,
 33 #endif
 34 #if I2C_2_EN
 35     I2C_2,
 36 #endif
 37 #if I2C_3_EN
 38     I2C_3,
 39 #endif
 40     I2C_MAX
 41 }I2C_ENUM;
 42
 43 #define I2Cn                            I2C_MAX
 44 #define I2C_1_0                         //无映射:I2C_1_0,映射1:I2C_1_1
 45 #define I2C_2_0
 46 #define I2C_3_0                         //无映射:I2C_3_0,映射1:I2C_3_1
 47
 48 #define I2C_SLAVE_ADDRESS                   0x30        //本STM32芯片地址
 49
 50
 51 /******************************类型声明****************************************/
 52
 53 typedef struct {
 54     volatile uint8_t idle;    //空闲标志  0)空闲   1)忙碌
 55     uint8_t r_w;              //读写标志  0)写     1)读
 56     uint8_t id;               //从机设备ID号
 57     uint8_t addr;             //要读写的地址
 58     volatile uint16_t index;  //当前缓冲区数据长度
 59     uint16_t bufLen;          //要发送或接收的数据长度
 60     uint8_t * volatile pBuff; //缓冲区首地址
 61     void (* volatile FunCallBack)(uint8_t, void *);//中断回调函数
 62 }I2C_PARAM_TYPE;
 63
 64 /******************************************************************************/
 65
 66
 67 /**
 68   * @brief  I2C1 Interface pins
 69   */
 70 #define BSP_I2C1                            I2C1
 71 #define BSP_I2C1_CLK                        RCC_APB1Periph_I2C1
 72 #define BSP_I2C1_AF_Port                    GPIO_AF_I2C1
 73 #define BSP_I2C1_IRQn                       I2C1_EV_IRQn
 74
 75 #if defined(I2C_1_2)                        //自由组合区
 76 #define BSP_I2C1_SCL_AF_Source              GPIO_PinSource8
 77 #define BSP_I2C1_SCL_PIN                    GPIO_Pin_8
 78 #define BSP_I2C1_SCL_GPIO_PORT              GPIOB
 79 #define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB
 80
 81 #define BSP_I2C1_SDA_AF_Source              GPIO_PinSource9
 82 #define BSP_I2C1_SDA_PIN                    GPIO_Pin_9
 83 #define BSP_I2C1_SDA_GPIO_PORT              GPIOB
 84 #define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
 85
 86 #elif defined(I2C_1_1)
 87 #define BSP_I2C1_SCL_AF_Source              GPIO_PinSource8
 88 #define BSP_I2C1_SCL_PIN                    GPIO_Pin_8
 89 #define BSP_I2C1_SCL_GPIO_PORT              GPIOB
 90 #define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB
 91
 92 #define BSP_I2C1_SDA_AF_Source              GPIO_PinSource9
 93 #define BSP_I2C1_SDA_PIN                    GPIO_Pin_9
 94 #define BSP_I2C1_SDA_GPIO_PORT              GPIOB
 95 #define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
 96
 97 #else
 98 #define BSP_I2C1_SCL_AF_Source              GPIO_PinSource6
 99 #define BSP_I2C1_SCL_PIN                    GPIO_Pin_6
100 #define BSP_I2C1_SCL_GPIO_PORT              GPIOB
101 #define BSP_I2C1_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB
102
103 #define BSP_I2C1_SDA_AF_Source              GPIO_PinSource7
104 #define BSP_I2C1_SDA_PIN                    GPIO_Pin_7
105 #define BSP_I2C1_SDA_GPIO_PORT              GPIOB
106 #define BSP_I2C1_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
107 #endif
108
109 /**
110   * @brief  I2C2 Interface pins
111   */
112 #define BSP_I2C2                            I2C2
113 #define BSP_I2C2_CLK                        RCC_APB1Periph_I2C2
114 #define BSP_I2C2_AF_Port                    GPIO_AF_I2C2
115 #define BSP_I2C2_IRQn                       I2C2_EV_IRQn
116
117 #if defined(I2C_2_3)                        //自由组合区
118 #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource4
119 #define BSP_I2C2_SCL_PIN                    GPIO_Pin_4
120 #define BSP_I2C2_SCL_GPIO_PORT              GPIOH
121 #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH
122
123 #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource5
124 #define BSP_I2C2_SDA_PIN                    GPIO_Pin_5
125 #define BSP_I2C2_SDA_GPIO_PORT              GPIOH
126 #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH
127
128 #elif defined(I2C_2_2)
129 #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource4
130 #define BSP_I2C2_SCL_PIN                    GPIO_Pin_4
131 #define BSP_I2C2_SCL_GPIO_PORT              GPIOH
132 #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH
133
134 #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource5
135 #define BSP_I2C2_SDA_PIN                    GPIO_Pin_5
136 #define BSP_I2C2_SDA_GPIO_PORT              GPIOH
137 #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH
138
139 #elif defined(I2C_2_1)
140 #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource1
141 #define BSP_I2C2_SCL_PIN                    GPIO_Pin_1
142 #define BSP_I2C2_SCL_GPIO_PORT              GPIOF
143 #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOF
144
145 #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource0
146 #define BSP_I2C2_SDA_PIN                    GPIO_Pin_0
147 #define BSP_I2C2_SDA_GPIO_PORT              GPIOF
148 #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOF
149
150 #else
151 #define BSP_I2C2_SCL_AF_Source              GPIO_PinSource10
152 #define BSP_I2C2_SCL_PIN                    GPIO_Pin_10
153 #define BSP_I2C2_SCL_GPIO_PORT              GPIOB
154 #define BSP_I2C2_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOB
155
156 #define BSP_I2C2_SDA_AF_Source              GPIO_PinSource11
157 #define BSP_I2C2_SDA_PIN                    GPIO_Pin_11
158 #define BSP_I2C2_SDA_GPIO_PORT              GPIOB
159 #define BSP_I2C2_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOB
160 #endif
161
162 /**
163   * @brief  I2C3 Interface pins
164   */
165 #define BSP_I2C3                            I2C3
166 #define BSP_I2C3_CLK                        RCC_APB1Periph_I2C3
167 #define BSP_I2C3_AF_Port                    GPIO_AF_I2C3
168 #define BSP_I2C3_IRQn                       I2C3_EV_IRQn
169
170 #if defined(I2C_3_2)                        //自由组合区
171 #define BSP_I2C3_SCL_AF_Source              GPIO_PinSource8
172 #define BSP_I2C3_SCL_PIN                    GPIO_Pin_8
173 #define BSP_I2C3_SCL_GPIO_PORT              GPIOA
174 #define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOA
175
176 #define BSP_I2C3_SDA_AF_Source              GPIO_PinSource8
177 #define BSP_I2C3_SDA_PIN                    GPIO_Pin_8
178 #define BSP_I2C3_SDA_GPIO_PORT              GPIOH
179 #define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH
180
181 #elif defined(I2C_3_1)
182 #define BSP_I2C3_SCL_AF_Source              GPIO_PinSource8
183 #define BSP_I2C3_SCL_PIN                    GPIO_Pin_8
184 #define BSP_I2C3_SCL_GPIO_PORT              GPIOA
185 #define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOA
186
187 #define BSP_I2C3_SDA_AF_Source              GPIO_PinSource9
188 #define BSP_I2C3_SDA_PIN                    GPIO_Pin_9
189 #define BSP_I2C3_SDA_GPIO_PORT              GPIOC
190 #define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOC
191
192 #else
193 #define BSP_I2C3_SCL_AF_Source              GPIO_PinSource7
194 #define BSP_I2C3_SCL_PIN                    GPIO_Pin_7
195 #define BSP_I2C3_SCL_GPIO_PORT              GPIOH
196 #define BSP_I2C3_SCL_GPIO_CLK               RCC_AHB1Periph_GPIOH
197
198 #define BSP_I2C3_SDA_AF_Source              GPIO_PinSource8
199 #define BSP_I2C3_SDA_PIN                    GPIO_Pin_8
200 #define BSP_I2C3_SDA_GPIO_PORT              GPIOH
201 #define BSP_I2C3_SDA_GPIO_CLK               RCC_AHB1Periph_GPIOH
202 #endif
203
204
205
206 /******************************函数声明****************************************/
207 void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed);
208 void BSP_I2cClose(uint8_t I2C_x);
209 uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen);
210 uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen);
211 uint32_t BSP_I2cIdleState(uint8_t I2C_x);
212
213
214
215 #endif

BSP_I2c.h

转载于:https://www.cnblogs.com/hiker-blogs/p/3694576.html

STM32F4XX高效驱动篇2 I2C相关推荐

  1. Linux 设备驱动篇之I2c设备驱动

    ******************************************************************************************** 装载声明:希望 ...

  2. Android上层与驱动交互完整篇(一)I2C设备驱动篇

    Android上层与驱动交互完整篇(一) 驱动篇 以I2C设备驱动为例,创建与上层交互节点,解析数据并与设备进行通讯. kernel中编程如同站在巨人肩膀上,有时候,我们并不需要理解I2C总线是如何工 ...

  3. Linux设备驱动篇——[I2C设备驱动-1]

    Linux 设备驱动篇之I2c设备驱动 fulinux 一.I2C驱动体系 虽然I2C硬件体系结构和协议都很容易理解,但是Linux I2C驱动体系结构却有相当的复杂度,它主要由3部分组成,即I2C设 ...

  4. Linux驱动子系统之I2C(一)

    主要是参考http://blog.csdn.net/cjok376240497/article/details/6972305,对I2C子系统讲解的很透彻的一篇文章,值得一读. 1 硬件特性 1.1 ...

  5. 零基础学Linux内核之设备驱动篇(8)_设备模型

    零基础学Linux内核系列文章目录 前置知识篇 1. 进程 2. 线程 进程间通信篇 1. IPC概述 2. 信号 3. 消息传递 4. 同步 5. 共享内存区 编译相关篇 1. GCC编译 2. 静 ...

  6. Linux驱动篇之内核模块

    Linux驱动篇之内核模块 1.基本概念 模块与驱动: Linux中,将设备分为三种基本的类型. 字符设备 块设备 网络接口 Linux中还有一个很重要的概念,模块.可在运行时添加到内核中的代码被称为 ...

  7. HwBinder驱动篇-Android10.0 HwBinder通信原理(十)

    摘要:本节主要来讲解Android10.0 HwBinder驱动的流程 阅读本文大约需要花费24分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...

  8. 如何运维能让网站稳定高效--稳定篇

    如何运维能让网站稳定高效--稳定篇 浏览:50 发布日期:2015/08/13 分类:技术分享 本文由 Alan 投稿 作为一名运维工程师,工作中最大的希望就是自己运维的网站能够稳定高效运行,但理想很 ...

  9. linux驱动篇之 driver_register 过程分析(二)bus_add_driver

    linux驱动篇之 driver_register 过程分析(二) 个人笔记,欢迎转载,请注明出处,共同分享 共同进步 http://blog.csdn.net/richard_liujh/artic ...

  10. 2440 6.0BSP 移植过程之显示驱动篇

    2440 6.0BSP 移植过程之显示驱动篇 //--------------------------------------------------------------------------- ...

最新文章

  1. Only POT texture can be compressed to PVRTC format
  2. 使用变量对象引出作用域链
  3. 关于.net standard 与 .net core, net framework
  4. stanford-chinese-corenlp-yyyy-MM-dd-models.jar not exists解决
  5. SAP UI5 scroll down to get more
  6. Linux 命令之 which -- 查找并显示给定命令的绝对路径(查找命令的位置/查询命令的位置/搜索命令的位置/查看命令的位置)
  7. 【洛谷2986】【USACO10MAR】伟大的奶牛聚集
  8. python创建socket对象_python---一个简单的socket
  9. centos禁用exec_CentOS停用按下Ctrl-Alt-Del 重启系统的功能
  10. vuetify-icon图标显示不正常
  11. 图片处理--处理成灰色图片,高斯模糊
  12. CSDN ARIMA R语言_R语言时间序列:ARIMA / GARCH模型的交易策略在外汇市场预测应用...
  13. windbg解决程序CPU占用率高,内存占用时高时低现象
  14. matlab symadd,信号调理器设计—大二暑期信号分析实习报告精选多篇
  15. cinder卷删除不掉解决方法
  16. C语言的运算符及优先级
  17. 已经有几百个制造企业的痛点问题在这了,你的在哪?
  18. access violation c语言,请教大家:出现Access violation怎么办?
  19. Online Meetup DevOps World 社区议程和 CFP
  20. 简单的ATM机代码实现

热门文章

  1. django 1366, “Incorrect string value: for column ‘‘ at row
  2. DevOps、CI、CD是什么关系
  3. javascript 为对象中的二级元素赋值 1006 Uncaught TypeError: Cannot set property ‘‘ of undefined
  4. Html5变量游戏,第三章语法、关键保留字及变量
  5. mysql 连接 互联网_互联网技术分享社区 MySQL字符串连接函数
  6. 开发板Linux内核,芯灵思SinlinxA33开发板Linux内核workqueue(附实测代码)
  7. Matlab 单形法原理,实验报告(单纯形法的matlab程序).doc
  8. Hbase权威指南(含目录,高清,免费)
  9. 数论——同余和费马小定理
  10. spring学习笔记一(基于xml)