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
以上代码亲测好用,在此做个标记。