#include "i2c.h" #include #include #if defined(STM32F1) I2C_t I2C1(0x40005400, 36000000, Interrupt::I2C1_EV, Interrupt::I2C1_ER); I2C_t I2C2(0x40005800, 36000000, Interrupt::I2C2_EV, Interrupt::I2C2_ER); #elif defined(STM32F4) I2C_t I2C1(0x40005400, 42000000, Interrupt::I2C1_EV, Interrupt::I2C1_ER); I2C_t I2C2(0x40005800, 42000000, Interrupt::I2C2_EV, Interrupt::I2C2_ER); //I2C_t I2C3(0x40005c00, 42000000, Interrupt::I2C3_EV, Interrupt::I2C3_ER); #endif #if defined(STM32F1) || defined(STM32F4) void I2C_t::irq_ev() { uint32_t sr1 = reg.SR1; reg.SR2; // EV5, SB = 1: Start condition sent. if(sr1 & 0x01) { // Send address. reg.DR = (addr << 1) | (writing ? 0 : 1); } // EV6, ADDR = 1: Address sent. if(sr1 & 0x02) { if(writing) { reg.DR = *write_p++; writing--; } else { if(reading > 1) { reg.CR1 |= 0x400; // Set ACK. } else { reg.CR1 |= 0x200; // Set STOP. } } } // EV7, RxNE = 1: Receive buffer not empty. if(sr1 & 0x40) { *read_p++ = reg.DR; reading--; if(reading == 1) { // Unset ACK, set STOP. reg.CR1 = (reg.CR1 & ~0x400) | 0x200; } if(reading == 0) { busy = 0; } } //reg.CR1 &= ~0x400; // EV8, TxE = 1, BTF = 0: Transmit buffer empty, still writing. if(sr1 & 0x80 && !(sr1 & 0x04)) { if(writing) { // Send data. reg.DR = *write_p++; writing--; } else { // All data sent. if(reading) { // Send repeat start. reg.CR1 |= 0x100; } else { // Send stop. reg.CR1 |= 0x200; busy = 0; } } } } void I2C_t::irq_er() { handle_error(); } void I2C_t::handle_error() { reg.SR1; reg.SR2; //while(1); reg.SR1 = 0; reg.CR1 |= 0x200; busy = 0; } void I2C_t::enable() { reg.CR1 = 0x8000; reg.CR1 = 0; reg.CR2 = 0x700 | (clk / 1000000); reg.TRISE = clk / 1000000 + 1; reg.CCR = clk / 2 / 100000; Interrupt::enable(irq_ev_n, &I2C_t::irq_ev, this); Interrupt::enable(irq_er_n, &I2C_t::irq_er, this); reg.CR1 = 1; } void I2C_t::write_reg(uint8_t addr_, uint8_t reg_, uint8_t data) { addr = addr_; writing = 2; reading = 0; volatile uint8_t buf[] = {reg_, data}; write_p = buf; busy = 1; reg.CR1 |= 0x100; while(busy) { Thread::yield(); } } void I2C_t::read_reg(uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf) { addr = addr_; writing = 1; reading = len; write_p = ®_; read_p = buf; busy = 1; reg.CR1 |= 0x100; while(busy) { Thread::yield(); } } #endif