Реализовано асинхронное чтение IMU
This commit is contained in:
@@ -36,15 +36,12 @@ void i2c_gpio_init()
|
||||
|
||||
void i2c1_init()
|
||||
{
|
||||
// enable I2C1
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_I2C1EN;
|
||||
|
||||
// 0x00303D5B - 100 kHz
|
||||
|
||||
// 400 kHz @ 16 MHz
|
||||
I2C1->TIMINGR = 0x10802D9BUL;
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_I2C1EN; // enable I2C1
|
||||
|
||||
I2C1->CR1 |= I2C_CR1_PE;
|
||||
I2C1->TIMINGR = 0x10802D9BUL; // 400 kHz @ 16 MHz
|
||||
|
||||
I2C1->CR1 |= I2C_CR1_PE;
|
||||
}
|
||||
|
||||
void imu_init()
|
||||
@@ -68,13 +65,14 @@ void imu_init()
|
||||
i2c_write(ICM_ADDR, REG_BANK_SEL, ~(3 << 4));
|
||||
}
|
||||
|
||||
void imu_tim6_init()
|
||||
void imu_tim6_init(const uint16_t freq)
|
||||
{
|
||||
RCC->APB1ENR1 |= RCC_APB1ENR1_TIM6EN;
|
||||
|
||||
TIM6->PSC = 16000 - 1; // 16 MHz / 16000 = 1000 Hz (1 ms)
|
||||
TIM6->ARR = 2 - 1; // 2 ms
|
||||
|
||||
TIM6->CR1 = 0;
|
||||
TIM6->ARR = 1000 - 1;
|
||||
TIM6->PSC = (SystemCoreClock / 1000 / freq) - 1;
|
||||
|
||||
TIM6->DIER |= TIM_DIER_UIE; // interrupt enable
|
||||
TIM6->CR1 |= TIM_CR1_CEN; // counter enable
|
||||
|
||||
@@ -105,6 +103,27 @@ void i2c_read(uint8_t addr, uint8_t reg, uint8_t* buf, uint8_t len)
|
||||
I2C1->ICR |= I2C_ICR_STOPCF;
|
||||
}
|
||||
|
||||
uint8_t i2c_read_async(uint8_t addr, uint8_t reg, uint8_t len, void (*cb)(uint8_t*))
|
||||
{
|
||||
if (i2c_busy) return 0;
|
||||
|
||||
i2c_busy = 1;
|
||||
|
||||
i2c_addr = addr;
|
||||
i2c_reg = reg;
|
||||
i2c_len = len;
|
||||
i2c_callback = cb;
|
||||
|
||||
// включаем прерывания
|
||||
I2C1->CR1 |= I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_TCIE | I2C_CR1_STOPIE;
|
||||
NVIC_EnableIRQ(I2C1_EV_IRQn);
|
||||
|
||||
// старт записи регистра
|
||||
I2C1->CR2 = (addr << 1) | (1 << I2C_CR2_NBYTES_Pos) | I2C_CR2_START;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void i2c_write(uint8_t addr, uint8_t reg, uint8_t data)
|
||||
{
|
||||
i2c_wait_idle(I2C1);
|
||||
@@ -122,6 +141,51 @@ void i2c_write(uint8_t addr, uint8_t reg, uint8_t data)
|
||||
I2C1->CR2 |= I2C_CR2_STOP;
|
||||
}
|
||||
|
||||
void I2C1_EV_IRQHandler()
|
||||
{
|
||||
static uint8_t index = 0;
|
||||
static uint8_t stage = 0; // 0 = send reg, 1 = read
|
||||
|
||||
// TX — отправляем регистр
|
||||
if (I2C1->ISR & I2C_ISR_TXIS)
|
||||
{
|
||||
I2C1->TXDR = i2c_reg;
|
||||
}
|
||||
|
||||
// переход к чтению
|
||||
if (I2C1->ISR & I2C_ISR_TC)
|
||||
{
|
||||
I2C1->CR2 = (i2c_addr << 1) |
|
||||
I2C_CR2_RD_WRN |
|
||||
(i2c_len << I2C_CR2_NBYTES_Pos) |
|
||||
I2C_CR2_AUTOEND |
|
||||
I2C_CR2_START;
|
||||
|
||||
index = 0;
|
||||
stage = 1;
|
||||
}
|
||||
|
||||
// чтение данных
|
||||
if (I2C1->ISR & I2C_ISR_RXNE)
|
||||
{
|
||||
i2c_buf[index++] = I2C1->RXDR;
|
||||
}
|
||||
|
||||
// завершение
|
||||
if (I2C1->ISR & I2C_ISR_STOPF)
|
||||
{
|
||||
I2C1->ICR |= I2C_ICR_STOPCF;
|
||||
|
||||
i2c_busy = 0;
|
||||
|
||||
// отключаем IRQ
|
||||
I2C1->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_TCIE | I2C_CR1_STOPIE);
|
||||
|
||||
if (i2c_callback)
|
||||
i2c_callback(i2c_buf);
|
||||
}
|
||||
}
|
||||
|
||||
void imu_read_raw(imu_raw_t* data)
|
||||
{
|
||||
uint8_t buf[12];
|
||||
@@ -139,7 +203,17 @@ void imu_read_raw(imu_raw_t* data)
|
||||
|
||||
static void i2c_wait_idle(I2C_TypeDef* i2c)
|
||||
{
|
||||
while (i2c->ISR & I2C_ISR_BUSY);
|
||||
int timeout = 100000;
|
||||
while ((i2c->ISR & I2C_ISR_BUSY) && --timeout);
|
||||
|
||||
if (timeout == 0)
|
||||
{
|
||||
// сброс I2C
|
||||
i2c->CR1 &= ~I2C_CR1_PE;
|
||||
i2c->CR1 |= I2C_CR1_PE;
|
||||
}
|
||||
|
||||
// while (i2c->ISR & I2C_ISR_BUSY);
|
||||
|
||||
i2c->ICR = I2C_ICR_STOPCF |
|
||||
I2C_ICR_NACKCF |
|
||||
|
||||
Reference in New Issue
Block a user