first commit
This commit is contained in:
157
inc/i2c_bitbang.h
Normal file
157
inc/i2c_bitbang.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user