|
|
  |
STM32F0 и I2C, передача/прием нескольких байт |
|
|
|
Sep 23 2015, 10:46
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
В общем у меня вот такое родилось, работает. На шине одновременно висят EEPROM 24LC16 и LIS3DH CODE // ================================================== void I2C_Start_Direction_Adress_Size (I2C_TypeDef* Port, uint32_t Direction, uint8_t Adress, uint8_t Size) { Port->CR2 &= ~I2C_CR2_AUTOEND; // Stop by siftware Port->CR2 &= ~I2C_CR2_RELOAD; // No reload if (Direction == I2C_CR2_RD_WRN) Port->CR2 |= I2C_CR2_RD_WRN; // receive mode else Port->CR2 &= ~I2C_CR2_RD_WRN; // transmit mode Port->CR2 &= ~I2C_CR2_NBYTES; // clear NBYTES field Port->CR2 |= Size<<16; // Set NBYTES Port->CR2 &= ~I2C_CR2_SADD; // clear slave address field Port->CR2 |= Adress; // Set slave address Port->CR2 |= I2C_CR2_START; // Transmit START bit while ((Port->ISR & I2C_ISR_BUSY)==0) {}; // Wait for done } // ==================================================
// ================================================== void I2C_Stop (I2C_TypeDef* Port) { Port->CR2 |= I2C_CR2_STOP; // Stop to bus while (Port->ISR & I2C_ISR_BUSY) {}; // wait for stop transmitted // Clear flags Port->ICR |= I2C_ICR_STOPCF; Port->ICR |= I2C_ICR_NACKCF; // Clear errors flags if (Port->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR)) { Port->ICR |= I2C_ICR_ARLOCF; Port->ICR |= I2C_ICR_BERRCF; } } // ==================================================
i2c_operate_t I2C_Operate(I2C_TypeDef* Port, uint8_t addr, void* trsm, uint8_t tcount, void* rcv, uint8_t rcount) { uint8_t *u8_ptr; uint32_t status; if (((tcount==0) && (rcount==0)) || (tcount)) // tcount== 0 and rcount==0 for device presence check { I2C_Start_Direction_Adress_Size(Port, 0, addr, tcount); // Check for status while (!(Port->ISR & (I2C_ISR_TC | I2C_ISR_TXIS | I2C_ISR_NACKF) && (Port->ISR & I2C_ISR_BUSY))) {}; if (Port->ISR & I2C_ISR_NACKF) { I2C_Stop(Port); return I2C_OPERATE_NO_DEVICE; } } // Transmit part if (tcount) { u8_ptr = (uint8_t*)trsm; while ((((Port->ISR & I2C_ISR_TC)==0) && ((Port->ISR & I2C_ISR_NACKF)==0)) && (Port->ISR & I2C_ISR_BUSY)) { if (Port->ISR & I2C_ISR_TXIS) Port->TXDR = *u8_ptr++; // Send data }
status = Port->ISR; if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ISR_NACKF)) // some errors { I2C_Stop(Port); if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF)) return I2C_BUS_ERROR; if (status & I2C_ISR_NACKF) return I2C_OPERATE_WRITE_NACK; } } // Receive part if (rcount) { u8_ptr = (uint8_t*)rcv; I2C_Start_Direction_Adress_Size (Port, I2C_CR2_RD_WRN, addr, rcount); if (Port->ISR & I2C_ISR_NACKF) { I2C_Stop(Port); return I2C_OPERATE_NO_DEVICE; } u8_ptr = (uint8_t*)rcv; while (!(Port->ISR & (I2C_ISR_TC | I2C_ISR_NACKF)) && (Port->ISR & I2C_ISR_BUSY)) { if (Port->ISR & I2C_ISR_RXNE) *u8_ptr++ = Port->RXDR; // Receive data } } status = Port->ISR;
I2C_Stop(Port); if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ISR_NACKF)) // some errors { I2C_Stop(Port); if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF)) return I2C_BUS_ERROR; if (status & I2C_ISR_NACKF) return I2C_OPERATE_READ_NACK; }
return I2C_OPERATE_OK; }
|
|
|
|
|
Sep 24 2015, 21:11
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(Genadi Zawidowski @ Sep 24 2015, 10:01)  А в чем идея передачи tcount в I2C_Operate? Что-то он там только на ноль/не-ноль проверяется... Или так и задумано? Пока устройство не начнет в ответ что=то слать, передаем ему данные... ну здрасте! Код I2C_Start_Direction_Adress_Size(Port, 0, addr, tcount); если 0, то просто проверится ACK от устройства на шине, а если не 0, так данные и будут вгоняться в соответствии с этим количеством (пока флаг TC не поднимется, а поднимется он после передачи tcount байт)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|