#ifndef _I2C_BITBANG_H #define _I2C_BITBANG_H #include #include #include "ch32fun.h" #ifndef I2C_SDA_PIN #define I2C_SDA_PIN PA1 #endif #ifndef I2C_SCL_PIN #define I2C_SCL_PIN PA0 #endif // decrease to 1 or 0 for Fast Mode (400kHz) #ifndef I2C_DELAY_US #define I2C_DELAY_US 3 #endif #define I2C_ACK 0 #define I2C_NACK 1 #define SCL_HIGH() funDigitalWrite(I2C_SCL_PIN, 1) #define SCL_LOW() funDigitalWrite(I2C_SCL_PIN, 0) #define SDA_HIGH() funDigitalWrite(I2C_SDA_PIN, 1) #define SDA_LOW() funDigitalWrite(I2C_SDA_PIN, 0) #define SDA_READ() funDigitalRead(I2C_SDA_PIN) static inline void i2c_delay(void) { Delay_Us(I2C_DELAY_US); } static inline void i2c_init(void) { funGpioInitAll(); funPinMode(I2C_SDA_PIN, GPIO_CFGLR_OUT_10Mhz_OD); funPinMode(I2C_SCL_PIN, GPIO_CFGLR_OUT_10Mhz_OD); // idle bus state SDA_HIGH(); SCL_HIGH(); } static inline void i2c_start(void) { SDA_HIGH(); SCL_HIGH(); i2c_delay(); SDA_LOW(); i2c_delay(); SCL_LOW(); } static inline void i2c_stop(void) { SDA_LOW(); i2c_delay(); SCL_HIGH(); i2c_delay(); SDA_HIGH(); i2c_delay(); } // returns 0 (I2C_ACK) if acknowledged, 1 (I2C_NACK) if not static inline uint8_t i2c_write_byte(uint8_t byte) { for (uint8_t i = 0; i < 8; i++) { if (byte & 0x80) { SDA_HIGH(); } else { SDA_LOW(); } byte <<= 1; i2c_delay(); SCL_HIGH(); i2c_delay(); SCL_LOW(); i2c_delay(); } // ACK/NACK processing SDA_HIGH(); // release SDA line for slave i2c_delay(); SCL_HIGH(); i2c_delay(); uint8_t ack = SDA_READ(); SCL_LOW(); i2c_delay(); return ack; } // I2C_ACK (0) to request more data, I2C_NACK (1) to end tx static inline uint8_t i2c_read_byte(uint8_t ack_control) { uint8_t byte = 0; SDA_HIGH(); for (uint8_t i = 0; i < 8; i++) { byte <<= 1; i2c_delay(); SCL_HIGH(); // slave writes data here i2c_delay(); if (SDA_READ()) { byte |= 1; } SCL_LOW(); } // send ACK/NACK to slave if (ack_control == I2C_ACK) { SDA_LOW(); } else { SDA_HIGH(); } i2c_delay(); SCL_HIGH(); i2c_delay(); SCL_LOW(); SDA_HIGH(); // release bus i2c_delay(); return byte; } static inline void i2c_scan(void) { printf("--- I2C Scan Start ---\n"); uint8_t found = 0; for (uint8_t addr = 0x08; addr < 0x78; addr++) { i2c_start(); // try to write to the address uint8_t ack = i2c_write_byte((addr << 1) | 0); i2c_stop(); if (ack == I2C_ACK) { printf("Device found at 0x%02X\n", addr); found++; Delay_Ms(1); } } if (found == 0) { printf("No I2C devices found.\n"); } printf("--- I2C Scan End ---\n"); } #endif // _I2C_BITBANG_H