class CI2C { public: I2C_TypeDef *i2c; uint32_t timeout; CI2C(I2C_TypeDef *instance) { i2c = instance; timeout = 100000; } bool wait(uint32_t flag) { uint32_t t = timeout; while(!(i2c->SR1 & flag)) if(--t == 0) return false; return true; } void clearADDR() { volatile uint32_t tmp; tmp = i2c->SR1; tmp = i2c->SR2; (void)tmp; } void start() { i2c->CR1 |= I2C_CR1_START; wait(I2C_SR1_SB); } void stop() { i2c->CR1 |= I2C_CR1_STOP; } bool address(uint8_t addr, bool read) { i2c->DR = (addr<<1) | (read?1:0); if(!wait(I2C_SR1_ADDR)) return false; clearADDR(); return true; } bool tx(uint8_t b) { if(!wait(I2C_SR1_TXE)) return false; i2c->DR = b; if(!wait(I2C_SR1_BTF)) return false; return true; } uint8_t rx_ack() { i2c->CR1 |= I2C_CR1_ACK; wait(I2C_SR1_RXNE); return i2c->DR; } uint8_t rx_nack() { i2c->CR1 &= ~I2C_CR1_ACK; wait(I2C_SR1_RXNE); return i2c->DR; } // -------------------------------------------------- // INIT // -------------------------------------------------- void init(uint32_t pclk1_mhz) { i2c->CR1 |= I2C_CR1_SWRST; i2c->CR1 &= ~I2C_CR1_SWRST; i2c->CR1 &= ~I2C_CR1_PE; i2c->CR2 = pclk1_mhz; i2c->CCR = (pclk1_mhz * 1000000) / (2*100000); i2c->TRISE = pclk1_mhz + 1; i2c->CR1 |= I2C_CR1_PE; } // -------------------------------------------------- // WRITE BYTE // -------------------------------------------------- bool writeReg(uint8_t dev, uint8_t reg, uint8_t val) { start(); if(!address(dev,false)) { stop(); return false; } if(!tx(reg)) { stop(); return false; } if(!tx(val)) { stop(); return false; } stop(); return true; } // -------------------------------------------------- // READ BYTE // -------------------------------------------------- bool readReg(uint8_t dev,uint8_t reg,uint8_t &val) { start(); if(!address(dev,false)) { stop(); return false; } if(!tx(reg)) { stop(); return false; } start(); if(!address(dev,true)) { stop(); return false; } val = rx_nack(); stop(); return true; } // -------------------------------------------------- // BURST READ // -------------------------------------------------- bool readBuf(uint8_t dev,uint8_t reg,uint8_t *buf,uint8_t len) { start(); if(!address(dev,false)) { stop(); return false; } if(!tx(reg)) { stop(); return false; } start(); if(!address(dev,true)) { stop(); return false; } while(len--) { if(len) *buf++ = rx_ack(); else *buf++ = rx_nack(); } stop(); return true; } // -------------------------------------------------- // SCAN // -------------------------------------------------- uint8_t scan() { uint8_t found=0; for(uint8_t a=1;a<127;a++) { start(); bool ok = address(a,false); stop(); if(ok) found++; } return found; } };