Files
hp3478a_ext/inc/i2c_bitbang.h
2025-11-30 04:47:14 +06:00

157 lines
2.7 KiB
C

#ifndef _I2C_BITBANG_H
#define _I2C_BITBANG_H
#include <stdint.h>
#include <stdio.h>
#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