说到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
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
STM32F4XX高效驱动篇2 I2C,布布扣,bubuko.com
原文:http://www.cnblogs.com/hiker-blogs/p/3694576.html