- void drv_i2c_gpio_init( void )
- {
- GPIO_Config_T gpioConfigStruct;
- /* Enable I2C related Clock */
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
-
- #ifdef I2C_USE_GPIO
- #else
- I2C_Config_T i2cConfigStruct;
-
- gpioConfigStruct.mode = GPIO_MODE_AF;
- gpioConfigStruct.speed = GPIO_SPEED_50MHz;
- gpioConfigStruct.pin = GPIO_PIN_8 | GPIO_PIN_9;
- gpioConfigStruct.otype = GPIO_OTYPE_OD;
- gpioConfigStruct.pupd = GPIO_PUPD_UP;
- GPIO_Config(GPIOB, &gpioConfigStruct);
-
- /* Free I2C_SCL and I2C_SDA */
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_8, GPIO_AF_I2C1);
- GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_9, GPIO_AF_I2C1);
-
- /* Config I2C1 */
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_I2C1);
- I2C_Reset(I2C1);
- i2cConfigStruct.mode = I2C_MODE_I2C;
- i2cConfigStruct.dutyCycle = I2C_DUTYCYCLE_2;
- i2cConfigStruct.ackAddress = I2C_ACK_ADDRESS_7BIT;
- i2cConfigStruct.ownAddress1 = 0XA0;
- i2cConfigStruct.ack = I2C_ACK_DISABLE;
- i2cConfigStruct.clockSpeed = 100000;
- I2C_Config(I2C1, &i2cConfigStruct);
-
- I2C_DisableDualAddress(I2C1);
- /* Enable I2Cx */
- I2C_Enable(I2C1);
- #endif
- }
下面就是我的I2C读写接口:
- static int __CheckErrFlag(I2C_T* i2c)
- {
- int bflag;
- bflag = 0;
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_BERR)) //
- {
- bflag =1;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_BERR); //
- }
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_AL)) //
- {
- bflag =2;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_AL); //
- }
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_AE)) //
- {
- bflag =3;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_AE); //
- }
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_OVRUR)) //
- {
- bflag =4;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_OVRUR); //
- }
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_PECE)) //
- {
- bflag =5;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_PECE); //
- }
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_TTE)) //
- {
- bflag =6;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_TTE); //
- }
- if(I2C_ReadStatusFlag(i2c, I2C_FLAG_SMBALT)) //
- {
- bflag =7;
- I2C_ClearStatusFlag(i2c, I2C_FLAG_SMBALT); //
- }
- return bflag;
- }
- static int __WaitEvtTimeout(I2C_T* i2c, I2C_EVENT_T evt)
- {
- volatile uint32_t timeout;
- timeout = 10000;
- while (!I2C_ReadEventStatus(i2c, evt))
- {
- timeout--;
- if(timeout == 0)
- {
- return -1;
- }
- if(__CheckErrFlag(i2c))
- {
- return 1;
- }
- }
- return 0;
- }
- uint8_t I2C_WriteByte(uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t Byte)
- {
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET) //bus busy
- {
- I2C_EnableGenerateStop(I2C1);
- delay_us(15);
- break;
- }
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //wait flag
- /* Send the current byte */
- I2C_TxData(I2C1,addr &0xff);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
- /* Send the current byte */
- I2C_TxData(I2C1,Byte);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
- I2C_EnableGenerateStop(I2C1);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
-
- return 0;
- }
- uint8_t I2C_ReadByte (uint8_t index,uint32_t dev_addr, uint32_t addr)
- {
- uint8_t buff;
-
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET) //bus busy
- {
- I2C_EnableGenerateStop(I2C1);
- delay_us(15);
- break;
- }
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //wait flag
- /* Send the current byte */
- I2C_TxData(I2C1,addr &0xff);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
-
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_RX);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //wait flag
-
- I2C_DisableAcknowledge(I2C1);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
- /* Recv the current byte */
- buff = I2C_RxData(I2C1);
-
- I2C_EnableGenerateStop(I2C1);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
-
- return buff;
- }
- uint8_t I2C_PageWrite(uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t *str,uint32_t num)
- {
- uint32_t i;
-
- if((num == 0)||(str==NULL)) return 1;
-
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET) //bus busy
- {
- I2C_EnableGenerateStop(I2C1);
- delay_us(15);
- break;
- }
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //wait flag
- /* Send the current byte */
- I2C_TxData(I2C1,addr &0xff);
- for(i=num;i>0;i--)
- {
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
- /* Send the current byte */
- I2C_TxData(I2C1,*str++);
- }
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
- I2C_EnableGenerateStop(I2C1);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
-
- return 0;
- }
- uint8_t I2C_PageRead (uint8_t index,uint32_t dev_addr, uint32_t addr,uint8_t *str,uint32_t num)
- {
- uint32_t i;
-
- if((num == 0)||(str==NULL)) return 1;
-
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET) //bus busy
- {
- I2C_EnableGenerateStop(I2C1);
- delay_us(15);
- break;
- }
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_TX);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //wait flag
- /* Send the current byte */
- I2C_TxData(I2C1,addr &0xff);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
-
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, dev_addr << 1, I2C_DIRECTION_RX);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //wait flag
-
- for(i=num-1;i>0;i--)
- {
- I2C_EnableAcknowledge(I2C1);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
- /* Recv the current byte */
- *str++ = I2C_RxData(I2C1);
- }
-
- I2C_DisableAcknowledge(I2C1);
- __WaitEvtTimeout(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED);
- /* Recv the current byte */
- *str++ = I2C_RxData(I2C1);
-
- I2C_EnableGenerateStop(I2C1);
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET);
- return 0;
- }
调试这个I2C花了不少时间,主要是这个时序状态。我这里是用逻辑分析仪一步步慢慢调试出来的。
下面是一个检测I2C设备地址的函数,检测总线上设备。通过shell来检查地址状态。
- static int __AddrDetect(uint8_t addr)
- {
- uint32_t bflag;
- while (I2C_ReadStatusFlag(I2C1, I2C_FLAG_BUSBSY) == SET) //bus busy
- {
- I2C_EnableGenerateStop(I2C1);
- delay_us(15);
- break;
- }
- /* Send START condition */
- I2C_EnableGenerateStart(I2C1);
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); //wait flag
- /* Send address for write */
- I2C_Tx7BitAddress(I2C1, addr << 1, I2C_DIRECTION_TX);
- bflag = 0;
- while (! I2C_ReadEventStatus(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
- {
- delay_us(25);
- bflag = __CheckErrFlag(I2C1);
- if(bflag) break;
- }
- delay_us(10);
- I2C_EnableGenerateStop(I2C1);
-
- return bflag;
- }
- #if UART_SHELL == 2
- #include "nr_micro_shell.h"
- void I2C_AddrDetect(char argc, char *argv)
- {
- int i,j;
-
- printf("Detect I2C addr:\r\n");
-
- for(i=0;i<8;i++)
- {
- for(j=0;j<16;j++)
- {
- if(__AddrDetect(j + i*16) == 0) printf("%02X ",j + i*16);
- else printf("-- ");
- delay_ms(1);
- }
- printf("\r\n");
- }
- printf("\r\nDetect I2C addr over.\r\n");
- }
- NR_SHELL_CMD_EXPORT(i2c_detect, I2C_AddrDetect, "I2C detect device address");
- #endif
这里我板子上接了4个I2C设备。分别是光照的RPR0521RS,3轴加速度BM1422,气压BM1383,和温湿度SHTC3。
接下来我们看看设备检测效果:
可以看到检测了4个地址设备了。
设备驱动都写好了测试成功,也可以通过shell读取数据了: