// -------------------------------------------------------------------------------- // init void CI2C::Robust_Init(void) { /* 1. Clocks aktivieren */ m_pscl->EnableClock(); m_psda->EnableClock(); RCC_APB1PeriphClockCmd(m_rcci2c, ENABLE); /* I2C_DEVICE Periph clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /* 2. Pins erstmal als GPIO OpenDrain (manuelle Bus Recovery) */ m_pscl->Configure(GPIO_Mode_Out_OD, GPIO_Speed_50MHz); m_psda->Configure(GPIO_Mode_Out_OD, GPIO_Speed_50MHz); m_pscl->Set(); m_psda->Set(); delay_us(100); /* Bus freitakten falls Slave hängt */ if (!m_psda->State()) // SDA LOW? { for (int i = 0; i < 9; i++) { m_pscl->Reset(); delay_us(100); m_pscl->Set(); delay_us(100); } } /* STOP Condition erzwingen */ m_psda->Reset(); delay_us(100); m_pscl->Set(); delay_us(100); /* 4. I2C Hardware Reset */ m_pI2C->CR1 |= I2C_CR1_SWRST; delay_us(100); m_pI2C->CR1 &= ~I2C_CR1_SWRST; /* 5. Pins auf I2C Alternate Function */ m_pscl->Configure(GPIO_Mode_AF_OD, GPIO_Speed_50MHz); m_psda->Configure(GPIO_Mode_AF_OD, GPIO_Speed_50MHz); /* 6. Peripheral Disable */ m_pI2C->CR1 &= ~I2C_CR1_PE; /* 7. Timing konfigurieren */ m_pI2C->CR2 = 36; // APB1 MHz m_pI2C->CCR = 180; // 100kHz @36MHz m_pI2C->TRISE = 37; // laut Datenblatt /* 8. Peripheral Enable */ m_pI2C->CR1 |= I2C_CR1_PE; /* 9. Dummy Read SR2 → Flags reset */ (void)m_pI2C->SR2; /* 10. BUSY prüfen */ if (m_pI2C->SR2 & I2C_SR2_BUSY) { /* letzter Rettungsversuch */ m_pI2C->CR1 &= ~I2C_CR1_PE; delay_us(100); m_pI2C->CR1 |= I2C_CR1_PE; } } // -------------------------------------------------------------------------------- // test void eetest() { uint8_t burst_data_write[5] = { 0x24, 0x48, 0x52, 0x59, 0x73 }, burst_data_read[6] = { 0 }; uint8_t single_data_read = 0; g_I2C.single_write(0x20, 0x15); delay_us(1000); g_I2C.burst_write(0x11, 5, burst_data_write); delay_us(1000); single_data_read = g_I2C.single_read(0x20); delay_us(1000); g_I2C.burst_read(0x11, 5, burst_data_read); delay_us(1000); } // -------------------------------------------------------------------------------- // scanner int CI2C::Scan_bus(void) { int a = 0; int count = 0; for (uint8_t i = 1; i < 128; i++) { m_pI2C->CR1 |= I2C_CR1_START; while (!(m_pI2C->SR1 & I2C_SR1_SB)) ; m_pI2C->DR = (i << 1 | 0); while (!(m_pI2C->SR1) | !(m_pI2C->SR2)) {} ; m_pI2C->CR1 |= I2C_CR1_STOP; delay_us(100); //minium wait time is 40 uS, but for sure, leave it 100 uS a = (m_pI2C->SR1 & I2C_SR1_ADDR); if (a == 2) { count++; // printf("Found I2C device at adress 0x%X (hexadecimal), or %d (decimal)\n\r", i, i); } } return count; } // -------------------------------------------------------------------------------- // I2C_readByte // Command for host to request one byte from the target device at the specified address. uint8_t CI2C::readByte(uint8_t address) { m_pI2C->CR1 |= I2C_CR1_START; // Set the START bit while (!(m_pI2C->SR1 & I2C_SR1_SB)) ; // Wait for SB to be set m_pI2C->DR = (address << 1) + 0x00; // Send address and read-bit // Wait for ADDR bit to be set indicating the address was transferred while (!(m_pI2C->SR1 & I2C_SR1_ADDR)) ; m_pI2C->CR1 &= ~(I2C_CR1_ACK); // Clear ACK bit // Read these regs to clear ADDR bit [EV6]. "__attribute__((unused))" is to avoid compiler // warning about unused variables. uint8_t temp __attribute__((unused)) = m_pI2C->SR1 | m_pI2C->SR2; m_pI2C->CR1 |= I2C_CR1_STOP; // Stop I2C // Wait for data register to have data while (!(m_pI2C->SR1 & (I2C_SR1_RXNE))) ; uint8_t data = (m_pI2C->DR & 0xFF); // Read received data m_pI2C->CR1 |= I2C_CR1_STOP; // Set STOP bit in CR1 indicating end of I2C transmission and // return to slave mode [EV8_2:2] while (!(m_pI2C->CR1 & I2C_CR1_STOP)) ; // Wait for stop bit to be set return data; // Return the received data } void CI2C::burst_write(uint8_t addr, uint8_t n_data, uint8_t *data) { m_pI2C->CR1 |= CR1_START_Set; // I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_MODE_SELECT)) ; I2C_Send7bitAddress(m_pI2C, m_slaveadress, I2C_Direction_Transmitter); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) ; m_pI2C->DR = addr; // I2C_SendData(I2Cx, addr); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) ; while (n_data--) { m_pI2C->DR = *data++; // I2C_SendData(I2Cx, *data++); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) ; } m_pI2C->CR1 |= CR1_STOP_Set; //I2C_GenerateSTOP(m_pI2C, ENABLE); while (I2C_GetFlagStatus(m_pI2C, I2C_FLAG_BUSY)) ; } void CI2C::single_write(uint8_t addr, uint8_t data) { m_pI2C->CR1 |= CR1_START_Set; // I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_MODE_SELECT)) ; /* BUSY, MSL and SB flag */ I2C_Send7bitAddress(m_pI2C, m_slaveadress, I2C_Direction_Transmitter); // hängt hier, wartet auf TxE while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) ; /* BUSY, MSL, ADDR, TXE and TRA flags */ m_pI2C->DR = addr; // I2C_SendData(I2Cx, addr); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) ; ///* TRA, BUSY, MSL, TXE and BTF flags */ m_pI2C->DR = data; // I2C_SendData(I2Cx, addr); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) ; m_pI2C->CR1 |= CR1_STOP_Set; // I2C_GenerateSTOP(m_pI2C, ENABLE); while (I2C_GetFlagStatus(m_pI2C, I2C_FLAG_BUSY)) ; } uint8_t CI2C::single_read(uint8_t addr) { uint8_t data; while (m_pI2C->SR1 & I2C_SR1_SB) ; // wait for busy flag m_pI2C->CR1 |= CR1_START_Set; // I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_MODE_SELECT)) ; I2C_Send7bitAddress(m_pI2C, m_slaveadress, I2C_Direction_Transmitter); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) ; m_pI2C->DR = (uint8_t)(addr >> 8); // I2C_SendData(I2Cx, addr); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) ; m_pI2C->CR1 |= CR1_START_Set; //I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_MODE_SELECT)) ; I2C_Send7bitAddress(m_pI2C, m_slaveadress, I2C_Direction_Receiver); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) ; data = (int8_t)m_pI2C->DR; // I2C_ReceiveData(m_pI2C); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) ; m_pI2C->CR1 &= CR1_ACK_Reset; // I2C_AcknowledgeConfig(m_pI2C, DISABLE); m_pI2C->CR1 |= CR1_STOP_Set; //I2C_GenerateSTOP(m_pI2C, ENABLE); while (I2C_GetFlagStatus(m_pI2C, I2C_FLAG_BUSY)) ; return data; } void CI2C::burst_read(uint8_t addr, uint8_t n_data, uint8_t *data) { while (m_pI2C->SR1 & I2C_SR1_SB) ; // wait for busy flag m_pI2C->CR1 |= CR1_START_Set; //I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_MODE_SELECT)) ; I2C_Send7bitAddress(m_pI2C, m_slaveadress, I2C_Direction_Transmitter); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) ; m_pI2C->DR = addr; // I2C_SendData(I2Cx, addr); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) ; m_pI2C->CR1 |= CR1_STOP_Set; //I2C_GenerateSTOP(I2Cx, ENABLE); m_pI2C->CR1 |= CR1_START_Set; //I2C_GenerateSTART(I2Cx, ENABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_MODE_SELECT)) ; I2C_Send7bitAddress(m_pI2C, m_slaveadress, I2C_Direction_Receiver); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) ; m_pI2C->CR1 &= CR1_ACK_Set; //I2C_AcknowledgeConfig(I2Cx, ENABLE); while (n_data--) { if (!n_data) m_pI2C->CR1 &= CR1_ACK_Reset; // I2C_AcknowledgeConfig(I2Cx, DISABLE); while (!I2C_CheckEvent(m_pI2C, I2C_EVENT_MASTER_BYTE_RECEIVED)) ; *data++ = m_pI2C->DR; // I2C_ReceiveData(I2Cx); } m_pI2C->CR1 &= CR1_ACK_Reset; //I2C_AcknowledgeConfig(I2Cx, DISABLE); m_pI2C->CR1 |= CR1_STOP_Set; // I2C_GenerateSTOP(I2Cx, ENABLE); while (m_pI2C->SR1 & I2C_SR1_SB) ; // wait for busy flag }