void I2C_GPIO_init(void) { GPIO_InitPara GPIO_InitStructure; I2C_InitPara I2C_InitStructure; /* Enable GPIOB clock */ RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB,ENABLE); /* Enable BOARD_I2C APB1 clock */ RCC_APB1PeriphClock_Enable(I2C_RCC,ENABLE); /* BOARD_I2C GPIO ports*/ GPIO_InitStructure.GPIO_Pin = I2C_SCL_GPIO_PIN | I2C_SDA_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF; GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ; GPIO_InitStructure.GPIO_OType = GPIO_OTYPE_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB,I2C_SCL_GPIO_PINSOURCE,GPIO_AF_1); GPIO_PinAFConfig(GPIOB,I2C_SDA_GPIO_PINSOURCE,GPIO_AF_1); // In order to not encounter the I2C BUSY jam, Manually Reset the I2C after GPIO set, before I2C configure. I2C_SoftwareReset_Enable(BOARD_I2C, ENABLE); I2C_SoftwareReset_Enable(BOARD_I2C, DISABLE); I2C_InitStructure.I2C_Protocol = I2C_PROTOCOL_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE_2; I2C_InitStructure.I2C_BitRate = I2C_CLK_HZ; I2C_InitStructure.I2C_AddressingMode = I2C_ADDRESSING_MODE_7BIT; I2C_InitStructure.I2C_DeviceAddress = I2C_OWN_ADDRESS7; I2C_Init(BOARD_I2C, &I2C_InitStructure); I2C_Enable(BOARD_I2C,ENABLE); /* Enable I2C2 */ I2C_Acknowledge_Enable(BOARD_I2C,DISABLE); /* The software must wait until I2C Bus is idle */ #ifdef DBG_OLED_BLOCK while(I2C_GetBitState(BOARD_I2C,I2C_FLAG_I2CBSY)); #else I2C_GetBitState_Timeout(BOARD_I2C,I2C_FLAG_I2CBSY); #endif }
/** * @brief Main program. * @param None * @retval None */ int main(void) { int i; RCC_Configuration(); GPIO_Configuration(); I2C_Configuration(); i=0; /* Enable I2C2 */ I2C_Enable(BOARD_I2C,ENABLE); /* Enable Acknowledge */ I2C_Acknowledge_Enable(BOARD_I2C,ENABLE); /* Send a NACK for the next data byte which will be received into the shift register */ I2C_NACKPosition_Enable(BOARD_I2C,I2C_NACKPOSITION_NEXT); /* Wait until I2C Bus is idle */ while(I2C_GetBitState(BOARD_I2C, I2C_FLAG_I2CBSY)); /* Send a start condition to I2C bus */ I2C_StartOnBus_Enable(BOARD_I2C, ENABLE); /* Wait until SBSEND bit is set */ while(!I2C_StateDetect(BOARD_I2C, I2C_PROGRAMMINGMODE_MASTER_SBSEND)); /* Send slave address to I2C bus */ I2C_AddressingDevice_7bit(BOARD_I2C, SLAVE_ADDRESS7, I2C_DIRECTION_RECEIVER); /* Disable ACK before clearing ADDSEND bit */ I2C_Acknowledge_Enable(BOARD_I2C, DISABLE); /* Wait until ADDSEND bit is set and clear it */ while(!I2C_StateDetect(BOARD_I2C, I2C_PROGRAMMINGMODE_MASTER_RECEIVER_ADDSEND)); /* Wait until the last data byte is received into the shift register */ while(!I2C_GetBitState(BOARD_I2C, I2C_FLAG_BTC)); /* Send a stop condition */ I2C_StopOnBus_Enable(BOARD_I2C, ENABLE); /* Wait until the reception data register is not empty */ while(!I2C_GetBitState(BOARD_I2C, I2C_FLAG_RBNE)); /* Read a data from I2C_DTR */ BOARD_I2C_Buf_Read[i++]=I2C_ReceiveData(BOARD_I2C); /* Wait until the reception data register is not empty */ while(!I2C_GetBitState(BOARD_I2C, I2C_FLAG_RBNE)); /* Read a data from I2C_DTR */ BOARD_I2C_Buf_Read[i++]=I2C_ReceiveData(BOARD_I2C); while(BOARD_I2C->CTLR1&0x0200); I2C_NACKPosition_Enable(BOARD_I2C,I2C_NACKPOSITION_CURRENT); /* Enable Acknowledge */ I2C_Acknowledge_Enable(BOARD_I2C, ENABLE); while(1); }
void i2c_init(void) { // RCC_AHBPeriphClock_Enable(RCC_AHBPERIPH_GPIOB,ENABLE); RCC_APB1PeriphClock_Enable(RCC_APB1PERIPH_I2C1, ENABLE); GPIO_InitPara GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_IN; GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ; GPIO_InitStructure.GPIO_OType = GPIO_OTYPE_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLUP; GPIO_Init(GPIOB, &GPIO_InitStructure); // the following checks deal with issues arrising from i2c being stopped while the gyro is sending data // this happens mainly in debug mode and perhaps at low voltage reset int i2cfail = 0; // sda is set with pullup // if sda is low the gyro might have become stuck while waiting for clock(and is sending a "zero") if (Bit_RESET == GPIO_ReadInputBit(GPIOB, GPIO_PIN_7)) { i2cfail = 1; } delay(10); GPIO_InitStructure.GPIO_Pin = GPIO_PIN_7; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLDOWN; GPIO_Init(GPIOB, &GPIO_InitStructure); // sda is set with pulldown // if sda is high it could be because the gyro is stuck sending data if (Bit_SET == GPIO_ReadInputBit(GPIOB, GPIO_PIN_7)) { i2cfail = 1; } if (i2cfail) { // set sda pullup so it sends an ack GPIO_InitStructure.GPIO_Pin = GPIO_PIN_7; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLUP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_PIN_6; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLUP; GPIO_Init(GPIOB, &GPIO_InitStructure); delay(10); for (int i = 0; i < 18; i++) { // send 9 clock pulses on scl to clear any pending byte GPIO_WriteBit(GPIOB, GPIO_PIN_6, Bit_RESET); delay(25); GPIO_WriteBit(GPIOB, GPIO_PIN_6, Bit_SET); delay(5); if (Bit_RESET != GPIO_ReadInputBit(GPIOB, GPIO_PIN_7)) { break; } } } // actual i2c setup GPIO_InitStructure.GPIO_Pin = GPIO_PIN_6 | GPIO_PIN_7; GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF; GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_50MHZ; GPIO_InitStructure.GPIO_OType = GPIO_OTYPE_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PUPD_PULLUP; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PINSOURCE6, GPIO_AF_1); GPIO_PinAFConfig(GPIOB, GPIO_PINSOURCE7, GPIO_AF_1); I2C_InitPara I2C_InitStructure; I2C_InitStructure.I2C_Protocol = I2C_PROTOCOL_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE_2; I2C_InitStructure.I2C_BitRate = 400000; I2C_InitStructure.I2C_AddressingMode = I2C_ADDRESSING_MODE_7BIT; I2C_InitStructure.I2C_DeviceAddress = 0x24; I2C_Init(I2C1, &I2C_InitStructure); I2C_Enable(I2C1, ENABLE); I2C_Acknowledge_Enable(I2C1, DISABLE); I2C_NACKPosition_Enable(I2C1, I2C_NACKPOSITION_CURRENT); }
int i2c_readdata(int address, int reg, int *data, int size) { int index = 0; int error = 0; int i2ccount2 = 0; int byteerror = 0; i2c_sendheader(address); I2C_SendData(I2C1, reg); while (I2C_StateDetect(I2C1, I2C_PROGRAMMINGMODE_MASTER_BYTE_TRANSMITTED) == ERROR && I2CTIMEOUTCONDITION) i2ccount++; // restart I2C_StartOnBus_Enable(I2C1, ENABLE); while (!I2C_StateDetect(I2C1, I2C_PROGRAMMINGMODE_MASTER_SBSEND) && I2CTIMEOUTCONDITION) { i2ccount++; } // read address I2C_SendData(I2C1, (address << 1) + 1); I2C_Acknowledge_Enable(I2C1, ENABLE); while (!I2C_StateDetect(I2C1, I2C_PROGRAMMINGMODE_MASTER_RECEIVER_ADDSEND) && I2CTIMEOUTCONDITION) { i2ccount++; } while (index < size) { i2ccount2 = 0; while (!I2C_StateDetect(I2C1, I2C_PROGRAMMINGMODE_MASTER_BYTE_RECEIVED) && (i2ccount2 < 2048)) { i2ccount2++; } if (i2ccount2 >= 2048) byteerror = 1; data[index] = I2C_ReceiveData(I2C1); index++; if (index == size - 1) I2C_Acknowledge_Enable(I2C1, DISABLE); } I2C_StopOnBus_Enable(I2C1, ENABLE); // wait for stop #ifdef WAITFORSTOP while (I2C1->CTLR1 & 0x0200 && I2CTIMEOUTCONDITION) i2ccount++; #endif if (!I2CTIMEOUTCONDITION || byteerror) { liberror++; error = 1; } I2C_Acknowledge_Enable(I2C1, DISABLE); return error; }