STM32F4XX I2C驱动

http://www.cnblogs.com/hiker-blogs/p/3694576.html

 

说到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官方所述进行软件复位。

 

 

 

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

图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);

 

 

/*
  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.h * * File : BSP_I2c.h * Version : V1.0 * Author : whq * Mode : Thumb2 * Toolchain : * Description : I2C驱动头文件 * * History : * Date : 2013.07.24 *******************************************************************************/ #ifndef _BSP_I2C_H_ #define _BSP_I2C_H_ #include <stdint.h> #define I2C_1_EN 1 #define I2C_2_EN 1 #define I2C_3_EN 1 #if !(I2C_1_EN || I2C_2_EN ||I2C_3_EN) #error "请至少打开一路I2C" #endif typedef enum { #if I2C_1_EN I2C_1, #endif #if I2C_2_EN I2C_2, #endif #if I2C_3_EN I2C_3, #endif I2C_MAX }I2C_ENUM; #define I2Cn I2C_MAX #define I2C_1_0 //无映射:I2C_1_0,映射1:I2C_1_1 #define I2C_2_0 #define I2C_3_0 //无映射:I2C_3_0,映射1:I2C_3_1 #define I2C_SLAVE_ADDRESS 0x30 //本STM32芯片地址 /******************************类型声明****************************************/ typedef struct { volatile uint8_t idle; //空闲标志 0)空闲 1)忙碌 uint8_t r_w; //读写标志 0)写 1)读 uint8_t id; //从机设备ID号 uint8_t addr; //要读写的地址 volatile uint16_t index; //当前缓冲区数据长度 uint16_t bufLen; //要发送或接收的数据长度 uint8_t * volatile pBuff; //缓冲区首地址 void (* volatile FunCallBack)(uint8_t, void *);//中断回调函数 }I2C_PARAM_TYPE; /******************************************************************************/ /** * @brief I2C1 Interface pins */ #define BSP_I2C1 I2C1 #define BSP_I2C1_CLK RCC_APB1Periph_I2C1 #define BSP_I2C1_AF_Port GPIO_AF_I2C1 #define BSP_I2C1_IRQn I2C1_EV_IRQn #if defined(I2C_1_2) //自由组合区 #define BSP_I2C1_SCL_AF_Source GPIO_PinSource8 #define BSP_I2C1_SCL_PIN GPIO_Pin_8 #define BSP_I2C1_SCL_GPIO_PORT GPIOB #define BSP_I2C1_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define BSP_I2C1_SDA_AF_Source GPIO_PinSource9 #define BSP_I2C1_SDA_PIN GPIO_Pin_9 #define BSP_I2C1_SDA_GPIO_PORT GPIOB #define BSP_I2C1_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB #elif defined(I2C_1_1) #define BSP_I2C1_SCL_AF_Source GPIO_PinSource8 #define BSP_I2C1_SCL_PIN GPIO_Pin_8 #define BSP_I2C1_SCL_GPIO_PORT GPIOB #define BSP_I2C1_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define BSP_I2C1_SDA_AF_Source GPIO_PinSource9 #define BSP_I2C1_SDA_PIN GPIO_Pin_9 #define BSP_I2C1_SDA_GPIO_PORT GPIOB #define BSP_I2C1_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB #else #define BSP_I2C1_SCL_AF_Source GPIO_PinSource6 #define BSP_I2C1_SCL_PIN GPIO_Pin_6 #define BSP_I2C1_SCL_GPIO_PORT GPIOB #define BSP_I2C1_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define BSP_I2C1_SDA_AF_Source GPIO_PinSource7 #define BSP_I2C1_SDA_PIN GPIO_Pin_7 #define BSP_I2C1_SDA_GPIO_PORT GPIOB #define BSP_I2C1_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB #endif /** * @brief I2C2 Interface pins */ #define BSP_I2C2 I2C2 #define BSP_I2C2_CLK RCC_APB1Periph_I2C2 #define BSP_I2C2_AF_Port GPIO_AF_I2C2 #define BSP_I2C2_IRQn I2C2_EV_IRQn #if defined(I2C_2_3) //自由组合区 #define BSP_I2C2_SCL_AF_Source GPIO_PinSource4 #define BSP_I2C2_SCL_PIN GPIO_Pin_4 #define BSP_I2C2_SCL_GPIO_PORT GPIOH #define BSP_I2C2_SCL_GPIO_CLK RCC_AHB1Periph_GPIOH #define BSP_I2C2_SDA_AF_Source GPIO_PinSource5 #define BSP_I2C2_SDA_PIN GPIO_Pin_5 #define BSP_I2C2_SDA_GPIO_PORT GPIOH #define BSP_I2C2_SDA_GPIO_CLK RCC_AHB1Periph_GPIOH #elif defined(I2C_2_2) #define BSP_I2C2_SCL_AF_Source GPIO_PinSource4 #define BSP_I2C2_SCL_PIN GPIO_Pin_4 #define BSP_I2C2_SCL_GPIO_PORT GPIOH #define BSP_I2C2_SCL_GPIO_CLK RCC_AHB1Periph_GPIOH #define BSP_I2C2_SDA_AF_Source GPIO_PinSource5 #define BSP_I2C2_SDA_PIN GPIO_Pin_5 #define BSP_I2C2_SDA_GPIO_PORT GPIOH #define BSP_I2C2_SDA_GPIO_CLK RCC_AHB1Periph_GPIOH #elif defined(I2C_2_1) #define BSP_I2C2_SCL_AF_Source GPIO_PinSource1 #define BSP_I2C2_SCL_PIN GPIO_Pin_1 #define BSP_I2C2_SCL_GPIO_PORT GPIOF #define BSP_I2C2_SCL_GPIO_CLK RCC_AHB1Periph_GPIOF #define BSP_I2C2_SDA_AF_Source GPIO_PinSource0 #define BSP_I2C2_SDA_PIN GPIO_Pin_0 #define BSP_I2C2_SDA_GPIO_PORT GPIOF #define BSP_I2C2_SDA_GPIO_CLK RCC_AHB1Periph_GPIOF #else #define BSP_I2C2_SCL_AF_Source GPIO_PinSource10 #define BSP_I2C2_SCL_PIN GPIO_Pin_10 #define BSP_I2C2_SCL_GPIO_PORT GPIOB #define BSP_I2C2_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define BSP_I2C2_SDA_AF_Source GPIO_PinSource11 #define BSP_I2C2_SDA_PIN GPIO_Pin_11 #define BSP_I2C2_SDA_GPIO_PORT GPIOB #define BSP_I2C2_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB #endif /** * @brief I2C3 Interface pins */ #define BSP_I2C3 I2C3 #define BSP_I2C3_CLK RCC_APB1Periph_I2C3 #define BSP_I2C3_AF_Port GPIO_AF_I2C3 #define BSP_I2C3_IRQn I2C3_EV_IRQn #if defined(I2C_3_2) //自由组合区 #define BSP_I2C3_SCL_AF_Source GPIO_PinSource8 #define BSP_I2C3_SCL_PIN GPIO_Pin_8 #define BSP_I2C3_SCL_GPIO_PORT GPIOA #define BSP_I2C3_SCL_GPIO_CLK RCC_AHB1Periph_GPIOA #define BSP_I2C3_SDA_AF_Source GPIO_PinSource8 #define BSP_I2C3_SDA_PIN GPIO_Pin_8 #define BSP_I2C3_SDA_GPIO_PORT GPIOH #define BSP_I2C3_SDA_GPIO_CLK RCC_AHB1Periph_GPIOH #elif defined(I2C_3_1) #define BSP_I2C3_SCL_AF_Source GPIO_PinSource8 #define BSP_I2C3_SCL_PIN GPIO_Pin_8 #define BSP_I2C3_SCL_GPIO_PORT GPIOA #define BSP_I2C3_SCL_GPIO_CLK RCC_AHB1Periph_GPIOA #define BSP_I2C3_SDA_AF_Source GPIO_PinSource9 #define BSP_I2C3_SDA_PIN GPIO_Pin_9 #define BSP_I2C3_SDA_GPIO_PORT GPIOC #define BSP_I2C3_SDA_GPIO_CLK RCC_AHB1Periph_GPIOC #else #define BSP_I2C3_SCL_AF_Source GPIO_PinSource7 #define BSP_I2C3_SCL_PIN GPIO_Pin_7 #define BSP_I2C3_SCL_GPIO_PORT GPIOH #define BSP_I2C3_SCL_GPIO_CLK RCC_AHB1Periph_GPIOH #define BSP_I2C3_SDA_AF_Source GPIO_PinSource8 #define BSP_I2C3_SDA_PIN GPIO_Pin_8 #define BSP_I2C3_SDA_GPIO_PORT GPIOH #define BSP_I2C3_SDA_GPIO_CLK RCC_AHB1Periph_GPIOH #endif /******************************函数声明****************************************/ void BSP_I2cOpen(uint8_t I2C_x, uint32_t clockSpeed); void BSP_I2cClose(uint8_t I2C_x); uint32_t BSP_I2cWrite(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t writeAddress, uint16_t writeLen); uint32_t BSP_I2cRead(uint8_t I2C_x, uint8_t *buff, uint16_t i2cSaleAddress, uint8_t readAddress, uint16_t readLen); uint32_t BSP_I2cIdleState(uint8_t I2C_x); #endif 
 
 

 

 

以上代码亲测好用,在此做个标记。

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值