Files
lishanpi/drv/i2c/i2c_driver.cpp
T
hm cbad06d616 refactor(touch): 集成硬件 I2C 驱动并添加 EXTI 中断支持
- 将 touch 底层从软件 I2C 位冲切换为硬件 I2C0 (PB6/PB7)
- 修复 i2c_driver I2C0 引脚映射 (PB8/PB9 -> PB6/PB7)
- 重写 master_write_read() 实现正确的重复起始条件
- 添加 i2c_driver.h C API 声明供 C 代码调用
- 添加 GT1151 EXTI 中断 (PD11, EXTI11 下降沿触发)
- 删除 touch.h 中废弃的软件 I2C 函数声明
- test_touch() 改为中断驱动,无触摸时 I2C 总线空闲
2026-04-26 20:36:54 +08:00

373 lines
8.8 KiB
C++

#include "i2c_driver.h"
#include "gd32f4xx.h"
#include <cstddef>
#define I2C_TIMEOUT 50000
struct i2c_hw_config_t
{
uint32_t i2c_periph;
rcu_periph_enum rcu_clock;
uint32_t gpio_port;
uint32_t scl_pin;
uint32_t sda_pin;
uint32_t af;
rcu_periph_enum gpio_rcu;
};
static constexpr i2c_hw_config_t i2c_hw_map[] = {
{I2C0, RCU_I2C0, GPIOB, GPIO_PIN_6, GPIO_PIN_7, GPIO_AF_4, RCU_GPIOB},
{I2C1, RCU_I2C1, GPIOB, GPIO_PIN_10, GPIO_PIN_11, GPIO_AF_4, RCU_GPIOB},
{I2C2, RCU_I2C2, GPIOC, GPIO_PIN_4, GPIO_PIN_5, GPIO_AF_4, RCU_GPIOC},
};
static RetCode wait_flag(uint32_t i2c_periph, i2c_flag_enum flag)
{
uint32_t timeout = I2C_TIMEOUT;
while (RESET == i2c_flag_get(i2c_periph, flag))
{
if (--timeout == 0)
{
return RET_ERROR;
}
}
return RET_OK;
}
extern "C"
{
static I2cBus i2c_0(I2cPort::_0);
static I2cBus i2c_1(I2cPort::_1);
static I2cBus i2c_2(I2cPort::_2);
static I2cBus *i2c_instances[] = {&i2c_0, &i2c_1, &i2c_2};
static uint8_t i2c_inited[3] = {0};
int i2c_init(uint8_t port, uint32_t speed_hz)
{
if (port >= 3)
return -1;
I2cConfig cfg;
cfg.speed_hz = speed_hz;
RetCode ret = i2c_instances[port]->init(cfg);
i2c_inited[port] = (ret == RET_OK) ? 1 : 0;
return i2c_inited[port] ? 0 : -1;
}
int i2c_master_write(uint8_t port, uint16_t dev_addr, const uint8_t *data, uint32_t len)
{
if (port >= 3 || !i2c_inited[port])
return -1;
I2cDevice dev(dev_addr);
return i2c_instances[port]->master_write(dev, data, len) == RET_OK ? 0 : -1;
}
int i2c_master_read(uint8_t port, uint16_t dev_addr, uint8_t *data, uint32_t len)
{
if (port >= 3 || !i2c_inited[port])
return -1;
I2cDevice dev(dev_addr);
return i2c_instances[port]->master_read(dev, data, len) == RET_OK ? 0 : -1;
}
int i2c_master_write_read(uint8_t port, uint16_t dev_addr, const uint8_t *wdata, uint32_t wlen, uint8_t *rdata, uint32_t rlen)
{
if (port >= 3 || !i2c_inited[port])
return -1;
I2cDevice dev(dev_addr);
return i2c_instances[port]->master_write_read(dev, wdata, wlen, rdata, rlen) == RET_OK ? 0 : -1;
}
} /* extern "C" */
I2cDevice::I2cDevice(uint16_t dev_addr)
: dev_addr_(dev_addr)
{
}
RetCode I2cDevice::init()
{
return RET_OK;
}
I2cBus::I2cBus(I2cPort port)
: port_(port)
{
}
I2cBus::~I2cBus()
{
if (initialized_)
{
deinit();
}
}
RetCode I2cBus::init(const I2cConfig &config)
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(i2c_hw_map) / sizeof(i2c_hw_map[0]))
{
return RET_INVALID_PARAM;
}
const i2c_hw_config_t &hw = i2c_hw_map[port_idx];
if (hw.i2c_periph == 0)
{
return RET_NOT_SUPPORTED;
}
config_ = config;
rcu_periph_clock_enable(hw.rcu_clock);
rcu_periph_clock_enable(hw.gpio_rcu);
gpio_af_set(hw.gpio_port, hw.af, hw.scl_pin | hw.sda_pin);
gpio_mode_set(hw.gpio_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, hw.scl_pin | hw.sda_pin);
gpio_output_options_set(hw.gpio_port, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, hw.scl_pin | hw.sda_pin);
i2c_deinit(hw.i2c_periph);
uint32_t speed = config.speed_hz;
if (speed == 0)
{
speed = 100000;
}
i2c_clock_config(hw.i2c_periph, speed, I2C_DTCY_2);
i2c_mode_addr_config(hw.i2c_periph, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x00);
i2c_enable(hw.i2c_periph);
i2c_ack_config(hw.i2c_periph, I2C_ACK_ENABLE);
initialized_ = true;
return RET_OK;
}
RetCode I2cBus::deinit()
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(i2c_hw_map) / sizeof(i2c_hw_map[0]))
{
return RET_INVALID_PARAM;
}
const i2c_hw_config_t &hw = i2c_hw_map[port_idx];
i2c_deinit(hw.i2c_periph);
rcu_periph_clock_disable(hw.rcu_clock);
initialized_ = false;
return RET_OK;
}
static RetCode i2c_master_start(uint32_t i2c_periph, uint16_t addr, uint32_t direction)
{
uint32_t timeout = I2C_TIMEOUT;
while (i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY))
{
if (--timeout == 0)
{
return RET_TIMEOUT;
}
}
i2c_start_on_bus(i2c_periph);
if (wait_flag(i2c_periph, I2C_FLAG_SBSEND) != RET_OK)
{
return RET_TIMEOUT;
}
i2c_master_addressing(i2c_periph, addr, direction);
if (wait_flag(i2c_periph, I2C_FLAG_ADDSEND) != RET_OK)
{
return RET_TIMEOUT;
}
i2c_flag_clear(i2c_periph, I2C_FLAG_ADDSEND);
return RET_OK;
}
RetCode I2cBus::master_write(I2cDevice &dev, const uint8_t *data, uint32_t len)
{
if (data == nullptr || len == 0)
{
return RET_INVALID_PARAM;
}
if (!initialized_)
return RET_NOT_INITIALIZED;
uint8_t port_idx = static_cast<uint8_t>(port_);
const i2c_hw_config_t &hw = i2c_hw_map[port_idx];
uint32_t i2c = hw.i2c_periph;
RetCode ret = i2c_master_start(i2c, dev.dev_addr_, I2C_TRANSMITTER);
if (ret != RET_OK)
{
i2c_stop_on_bus(i2c);
return ret;
}
for (uint32_t i = 0; i < len; i++)
{
if (wait_flag(i2c, I2C_FLAG_TBE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_data_transmit(i2c, data[i]);
}
if (wait_flag(i2c, I2C_FLAG_TBE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_stop_on_bus(i2c);
return RET_OK;
}
RetCode I2cBus::master_read(I2cDevice &dev, uint8_t *data, uint32_t len)
{
if (data == nullptr || len == 0)
{
return RET_INVALID_PARAM;
}
if (!initialized_)
return RET_NOT_INITIALIZED;
uint8_t port_idx = static_cast<uint8_t>(port_);
const i2c_hw_config_t &hw = i2c_hw_map[port_idx];
uint32_t i2c = hw.i2c_periph;
if (len == 1)
{
i2c_ack_config(i2c, I2C_ACK_DISABLE);
}
else
{
i2c_ack_config(i2c, I2C_ACK_ENABLE);
}
RetCode ret = i2c_master_start(i2c, dev.dev_addr_, I2C_RECEIVER);
if (ret != RET_OK)
{
i2c_stop_on_bus(i2c);
return ret;
}
for (uint32_t i = 0; i < len; i++)
{
if (i == len - 1)
{
i2c_ack_config(i2c, I2C_ACK_DISABLE);
i2c_stop_on_bus(i2c);
}
if (wait_flag(i2c, I2C_FLAG_RBNE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
data[i] = i2c_data_receive(i2c);
}
return RET_OK;
}
RetCode I2cBus::master_write_read(I2cDevice &dev, const uint8_t *wdata, uint32_t wlen, uint8_t *rdata, uint32_t rlen)
{
if (wdata == nullptr || wlen == 0 || rdata == nullptr || rlen == 0)
{
return RET_INVALID_PARAM;
}
if (!initialized_)
return RET_NOT_INITIALIZED;
uint8_t port_idx = static_cast<uint8_t>(port_);
const i2c_hw_config_t &hw = i2c_hw_map[port_idx];
uint32_t i2c = hw.i2c_periph;
// === 写阶段:发送寄存器地址(不发 STOP) ===
uint32_t timeout = I2C_TIMEOUT;
while (i2c_flag_get(i2c, I2C_FLAG_I2CBSY))
{
if (--timeout == 0)
return RET_TIMEOUT;
}
i2c_start_on_bus(i2c);
if (wait_flag(i2c, I2C_FLAG_SBSEND) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_master_addressing(i2c, dev.dev_addr_, I2C_TRANSMITTER);
if (wait_flag(i2c, I2C_FLAG_ADDSEND) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_flag_clear(i2c, I2C_FLAG_ADDSEND);
for (uint32_t i = 0; i < wlen; i++)
{
if (wait_flag(i2c, I2C_FLAG_TBE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_data_transmit(i2c, wdata[i]);
}
if (wait_flag(i2c, I2C_FLAG_TBE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
// === 读阶段:以重复起始条件开始(无 STOP 间隔) ===
if (rlen == 1)
{
i2c_ack_config(i2c, I2C_ACK_DISABLE);
}
else
{
i2c_ack_config(i2c, I2C_ACK_ENABLE);
}
i2c_start_on_bus(i2c);
if (wait_flag(i2c, I2C_FLAG_SBSEND) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_master_addressing(i2c, dev.dev_addr_, I2C_RECEIVER);
if (wait_flag(i2c, I2C_FLAG_ADDSEND) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
i2c_flag_clear(i2c, I2C_FLAG_ADDSEND);
for (uint32_t i = 0; i < rlen; i++)
{
if (i == rlen - 1)
{
i2c_ack_config(i2c, I2C_ACK_DISABLE);
i2c_stop_on_bus(i2c);
}
if (wait_flag(i2c, I2C_FLAG_RBNE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
rdata[i] = i2c_data_receive(i2c);
}
return RET_OK;
}