#include "system.h" #include "i2cmaster.h" #include "print.h" I2CMaster::I2CMaster() noexcept { RCC.APB1PCENR.B.I2C1EN = SET; RCC.APB2PCENR.B.IOPCEN = SET; // GPIO Alternate Config - default SCL/PC2, SDA/PC1 GPIOC.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto { r.B.CNF1 = 3u; r.B.MODE1 = 1u; r.B.CNF2 = 3u; r.B.MODE2 = 1u; return r.R; }); RCC.APB1PRSTR.B.I2C1RST = SET; RCC.APB1PRSTR.B.I2C1RST = RESET; I2C1.CTLR2.B.FREQ = 48u; I2C1.CKCFGR.B.CCR = 480u; I2C1.CTLR1.B.PE = SET; } bool I2CMaster::Send(const unsigned char addr, const unsigned char * data, const unsigned int len) { bool result = false; do { if (! send_address(addr & ~1u)) break; if (data == nullptr) { return stop_condition(); } for (unsigned n=0u; n bool { return I2C1.STAR1.B.TxE == RESET; })) break; I2C1.DATAR.B.DATAR = to_send; } if (! wait_for([]() -> bool { return I2C1.STAR1.B.BTF == RESET; })) break; result = true; } while (false); return result and stop_condition(); } bool I2CMaster::Receive (const unsigned char addr, unsigned char * data, const unsigned int len) { bool result = false; do { if (! send_address(addr | 1u)) break; I2C1.CTLR1.B.ACK = SET; for (unsigned n=0u; n bool { return I2C1.STAR1.B.RxNE == RESET; })) break; data [n] = I2C1.DATAR.B.DATAR; } I2C1.CTLR1.B.ACK = RESET; if (! wait_for([]() -> bool { return I2C1.STAR1.B.RxNE == RESET; })) break; data [len-1] = I2C1.DATAR.B.DATAR; result = true; } while (false); return result and stop_condition(); } bool I2CMaster::send_address(const unsigned char addr) { I2C1.CTLR1.B.START = SET; if (! wait_for([]() -> bool { return I2C1.STAR1.B.SB == RESET; })) return false; I2C1.DATAR.B.DATAR = addr; if (! wait_for([]() -> bool { return I2C1.STAR1.B.ADDR == RESET; })) return false; volatile unsigned x = I2C1.STAR2.R; (void) x; return true; } bool I2CMaster::stop_condition() { I2C1.CTLR1.B.STOP = SET; return wait_for([]() -> bool { return I2C1.CTLR1.B.STOP == SET; }); } void I2CMaster::FindActive(Print& print) { const char * blank = " \r"; for (unsigned addr = 0u; addr < 0xFF; addr += 2u) { print << "addr = " << (int) addr; if (send_address(addr & ~1u)) { print << " ... OK\r\n"; } else { print << blank; } stop_condition(); } print << blank; }