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 总线空闲
This commit is contained in:
2026-04-26 20:36:54 +08:00
parent 851c3db56e
commit cbad06d616
6 changed files with 560 additions and 464 deletions
+103
View File
@@ -6,6 +6,7 @@
#include "sdram_manager.h"
#include "flash_manager.h"
#include "lcd.h"
#include "touch.h"
#include <cstdio>
#include <cstring>
@@ -345,6 +346,105 @@ static void concurrent_loop(void)
delay_1ms(1000);
}
// =============================================================
// Touch 测试
// =============================================================
static void test_touch(void)
{
printf("\r\n===== Touch 测试 (中断驱动) =====\r\n");
uint8_t ret = GT1151_Init();
if (ret != 0)
{
printf(" Touch 初始化失败 (ret=%d)\r\n", ret);
return;
}
printf(" Touch 初始化成功,等待触摸中断...\r\n");
LCD_Clear(0x0841);
POINT_COLOR = CYAN;
LCD_ShowString(10, 10, 460, 24, 16, 0, (uint8_t *)"=== Touch Test (IRQ) ===");
POINT_COLOR = WHITE;
LCD_ShowString(10, 35, 460, 24, 16, 0, (uint8_t *)"Touch screen now");
LCD_ShowString(10, 55, 300, 24, 16, 0, (uint8_t *)"IRQ driven, watch UART");
LCD_ShowString(10, 75, 200, 24, 16, 0, (uint8_t *)"X:0 Y:0");
uint16_t last_x = 0xFFFF;
uint16_t last_y = 0xFFFF;
uint32_t idle_counter = 0;
bool was_touching = false;
uint32_t iter = 0;
g_touch_irq_flag = 0;
while (1)
{
if (g_touch_irq_flag)
{
g_touch_irq_flag = 0;
delay_1ms(5);
GT1151_Scan(0);
if (tp_dev.sta & TP_PRES_DOWN)
{
idle_counter = 0;
uint16_t x = tp_dev.x[0];
uint16_t y = tp_dev.y[0];
printf("[TOUCH] iter=%lu sta=0x%02X x=%u y=%u\r\n",
(unsigned long)iter, tp_dev.sta, x, y);
if (x < lcddev.width && y < lcddev.height)
{
POINT_COLOR = BLACK;
LCD_FillRectangle(10, 75, 200, 95);
POINT_COLOR = GREEN;
char buf[24];
sprintf(buf, "X:%-3d Y:%-3d", x, y);
LCD_ShowString(10, 75, 200, 24, 16, 0, (uint8_t *)buf);
if (was_touching && last_x != 0xFFFF)
{
POINT_COLOR = MAGENTA;
LCD_DrawLine(last_x, last_y, x, y);
}
POINT_COLOR = YELLOW;
LCD_FillCircle(x, y, 4);
last_x = x;
last_y = y;
was_touching = true;
}
}
else
{
was_touching = false;
last_x = 0xFFFF;
last_y = 0xFFFF;
}
iter++;
}
else
{
idle_counter++;
delay_1ms(10);
if (idle_counter > 500)
{
printf(" 无触摸超过 5 秒,退出 Touch 测试\r\n");
break;
}
}
}
LCD_Clear(BLUE);
printf(" Touch 测试完成\r\n");
delay_1ms(500);
}
// =============================================================
// 主函数
// =============================================================
@@ -438,6 +538,9 @@ int main(void)
concurrent_loop();
delay_1ms(500);
test_touch();
delay_1ms(500);
// ---- 主循环 ----
led_pattern(0x0F);
printf("\r\n===== 所有外设测试完成 =====\r\n");
+81 -199
View File
@@ -1,150 +1,34 @@
#include "touch.h"
#include "i2c_driver.h"
#include "stdio.h"
#include "string.h"
_m_tp_dev tp_dev;
volatile uint8_t g_touch_irq_flag = 0;
void delay_1us(uint16_t us)
#define TOUCH_I2C_PORT 0
#define TOUCH_DEV_ADDR 0x28
uint8_t GT1151_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
while(us--)
uint8_t tmp[2 + 256];
tmp[0] = (uint8_t)(reg >> 8);
tmp[1] = (uint8_t)(reg & 0xFF);
for (uint8_t i = 0; i < len; i++)
{
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
tmp[2 + i] = buf[i];
}
int ret = i2c_master_write(TOUCH_I2C_PORT, TOUCH_DEV_ADDR, tmp, 2 + len);
return (ret == 0) ? 0 : 1;
}
void CT_Delay(void)
void GT1151_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
delay_1us(2);
}
void CT_IIC_Init(void)
{
rcu_periph_clock_enable(SCL_RCU);
gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP,SCL_PIN);
gpio_output_options_set(SCL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SCL_PIN);
rcu_periph_clock_enable(SDA_RCU);
gpio_mode_set(SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP,SDA_PIN);
gpio_output_options_set(SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SDA_PIN);
}
void CT_IIC_Start(void)
{
CT_SDA_OUT();
SDA_ON;
SCL_ON;
delay_1us(30);
SDA_OFF;
CT_Delay();
SCL_OFF;
}
void CT_IIC_Stop(void)
{
CT_SDA_OUT();
SCL_ON;
delay_1us(30);
SDA_OFF;
CT_Delay();
SDA_ON;
}
uint8_t CT_IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
CT_SDA_IN();
SDA_ON;
SCL_ON;
CT_Delay();
while(CT_READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
CT_IIC_Stop();
return 1;
}
CT_Delay();
}
SCL_OFF;
return 0;
}
void CT_IIC_Ack(void)
{
SCL_OFF;
CT_SDA_OUT();
CT_Delay();
SDA_OFF;
CT_Delay();
SCL_ON;
CT_Delay();
SCL_OFF;
}
void CT_IIC_NAck(void)
{
SCL_OFF;
CT_SDA_OUT();
CT_Delay();
SDA_ON;
CT_Delay();
SCL_ON;
CT_Delay();
SCL_OFF;
}
void CT_IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
CT_SDA_OUT();
SCL_OFF;
CT_Delay();
for(t=0;t<8;t++)
{
if((txd&0x80)>>7)
{
gpio_bit_set(SDA_PORT,SDA_PIN);
}
else
{
gpio_bit_reset(SDA_PORT,SDA_PIN);
}
txd<<=1;
SCL_ON;
CT_Delay();
SCL_OFF;
CT_Delay();
}
}
uint8_t CT_IIC_Read_Byte(unsigned char ack)
{
uint8_t i,receive=0;
CT_SDA_IN();
delay_1us(30);
for(i=0;i<8;i++ )
{
SCL_OFF;
CT_Delay();
SCL_ON;
receive<<=1;
if(CT_READ_SDA)receive++;
}
if (!ack)CT_IIC_NAck();
else CT_IIC_Ack();
return receive;
uint8_t reg_bytes[2];
reg_bytes[0] = (uint8_t)(reg >> 8);
reg_bytes[1] = (uint8_t)(reg & 0xFF);
i2c_master_write_read(TOUCH_I2C_PORT, TOUCH_DEV_ADDR, reg_bytes, 2, buf, len);
}
const uint8_t GT1151_CFG_TBL[] =
@@ -172,8 +56,7 @@ const uint8_t GT1151_CFG_TBL[]=
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xC4, 0x09, 0x23, 0x23, 0x50, 0x5D, 0x54, 0x4B, 0x3C, 0x0F,
0x32, 0xFF, 0xE4, 0x04, 0x40, 0x00, 0x8A, 0x05, 0x40, 0x00,
0xAA,0x00,0x22,0x22,0x00,0x00,0x73,0x22,0x01
};
0xAA, 0x00, 0x22, 0x22, 0x00, 0x00, 0x73, 0x22, 0x01};
uint16_t CRC16(uint8_t *srcdata, uint16_t length)
{
@@ -222,85 +105,65 @@ uint8_t GT1151_Send_Cfg(uint8_t mode)
return 0;
}
uint8_t GT1151_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
static void GT1151_EXTI_Init(void)
{
uint8_t i;
uint8_t ret=0;
CT_IIC_Start();
CT_IIC_Send_Byte(GT_CMD_WR);
CT_IIC_Wait_Ack();
CT_IIC_Send_Byte(reg>>8);
CT_IIC_Wait_Ack();
CT_IIC_Send_Byte(reg&0XFF);
CT_IIC_Wait_Ack();
for(i=0;i<len;i++)
{
CT_IIC_Send_Byte(buf[i]);
ret=CT_IIC_Wait_Ack();
if(ret)break;
}
CT_IIC_Stop();
return ret;
rcu_periph_clock_enable(RCU_SYSCFG);
syscfg_exti_line_config(EXTI_SOURCE_GPIOD, EXTI_SOURCE_PIN11);
exti_init(TOUCH_EXTI_LINE, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
exti_interrupt_enable(TOUCH_EXTI_LINE);
nvic_irq_enable(TOUCH_EXTI_IRQn, 2, 0);
}
void GT1151_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
uint8_t i;
CT_IIC_Start();
CT_IIC_Send_Byte(GT_CMD_WR);
CT_IIC_Wait_Ack();
CT_IIC_Send_Byte(reg>>8);
CT_IIC_Wait_Ack();
CT_IIC_Send_Byte(reg&0XFF);
CT_IIC_Wait_Ack();
CT_IIC_Start();
CT_IIC_Send_Byte(GT_CMD_RD);
CT_IIC_Wait_Ack();
for(i=0;i<len;i++)
{
buf[i]=CT_IIC_Read_Byte(i==(len-1)?0:1);
}
CT_IIC_Stop();
}
uint8_t Cfg_Info1[239] = {0};
uint8_t GT1151_Init(void)
{
uint8_t temp[6] = {0};
uint8_t i=0;
uint8_t retry = 3;
// RST_PIN (PD12) 与 LCD 共享,LCD_Init 已完成硬件复位
// 通过 INT 引脚对 GT1151 做 I2C 复位握手
rcu_periph_clock_enable(INT_RCU);
gpio_mode_set(INT_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, INT_PIN);
gpio_output_options_set(INT_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, INT_PIN);
gpio_bit_reset(INT_PORT, INT_PIN);
delay_1ms(20);
CT_IIC_Init();
// 初始化硬件 I2C0 (PB6=SCL, PB7=SDA)
i2c_init(TOUCH_I2C_PORT, 100000);
// 释放 INT(设为浮空输入),等待 GT1151 就绪
gpio_mode_set(INT_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, INT_PIN);
delay_1ms(150);
delay_1ms(100);
// 读取产品 ID,带重试
do
{
GT1151_RD_Reg(GT_PID_REG, temp, 4);
if (temp[0] != 0 && temp[0] != 0xFF)
break;
delay_1ms(50);
} while (--retry > 0);
printf("CTP ID: GT%s\r\n", temp);
check_sum();
if(strcmp((char*)temp,"1158")==0)
if (strcmp((char *)temp, "1158") == 0 || strcmp((char *)temp, "1151") == 0)
{
GT1151_RD_Reg(GT_CFGS_REG, temp, 1);
printf("Default Ver:0x%x\r\n",temp[0]);
printf("GT Config Version: 0x%02X\r\n", temp[0]);
#if 1
GT1151_RD_Reg(0x8050,Cfg_Info1,239);
printf("Config Info:\r\n");
for( i = 0; i < 239; i++ )
{
printf("0x%02X,",Cfg_Info1[i]);
if((i+1)%10==0)
printf("\r\n");
}
printf("\r\n");
#endif
GT1151_Send_Cfg(0);
delay_1ms(50);
GT1151_EXTI_Init();
printf("GT EXTI initialized\r\n");
return 0;
}
printf("GT Init: unknown ID, will still attempt to use touch\r\n");
return 1;
}
@@ -339,7 +202,8 @@ uint8_t GT1151_Scan(uint8_t mode)
{
tp_dev.x[i] = ((uint16_t)buf[1] << 8) + buf[0];
tp_dev.y[i] = ((uint16_t)buf[3] << 8) + buf[2];
}else
}
else
{
tp_dev.x[i] = ((uint16_t)buf[1] << 8) + buf[0];
tp_dev.y[i] = ((uint16_t)buf[3] << 8) + buf[2];
@@ -356,14 +220,17 @@ uint8_t GT1151_Scan(uint8_t mode)
tp_dev.x[0] = tp_dev.x[1];
tp_dev.y[0] = tp_dev.y[1];
t = 0;
}else
}
else
{
tp_dev.x[0] = tp_dev.x[4];
tp_dev.y[0] = tp_dev.y[4];
mode = 0X80;
tp_dev.sta = tempsta;
}
}else t=0;
}
else
t = 0;
}
}
if ((mode & 0X8F) == 0X80)
@@ -371,13 +238,28 @@ uint8_t GT1151_Scan(uint8_t mode)
if (tp_dev.sta & TP_PRES_DOWN)
{
tp_dev.sta &= ~(1 << 7);
}else
}
else
{
tp_dev.x[0] = 0xffff;
tp_dev.y[0] = 0xffff;
tp_dev.sta &= 0XE0;
}
}
if(t>240)t=10;
if (t > 240)
t = 10;
return res;
}
extern "C"
{
void EXTI10_15_IRQHandler(void)
{
if (exti_flag_get(TOUCH_EXTI_LINE) == SET)
{
g_touch_irq_flag = 1;
exti_flag_clear(TOUCH_EXTI_LINE);
}
}
}
+41 -54
View File
@@ -21,77 +21,69 @@
#define SDA_OFF gpio_bit_reset(SDA_PORT,SDA_PIN)
#define SDA_TOGGLE gpio_bit_toggle(SDA_PORT,SDA_PIN)
//IO方向设置
#define CT_SDA_IN() gpio_mode_set(SCL_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,SDA_PIN);//{GPIOF->MODER&=~(3<<(2*11));GPIOF->MODER|=0<<2*11;} //PF11输入模式
#define CT_SDA_OUT() gpio_mode_set(SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP,SDA_PIN);//{GPIOF->MODER&=~(3<<(2*11));GPIOF->MODER|=1<<2*11;} //PF11输出模式
//IO操作函数
//IO方向设置
#define CT_SDA_IN() gpio_mode_set(SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, SDA_PIN)
#define CT_SDA_OUT() gpio_mode_set(SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SDA_PIN)
//IO操作函数
#define CT_IIC_SCL //PBout(0) //SCL
#define CT_IIC_SDA(val) ((val)==1?SDA_ON:SDA_OFF)//PFout(11) //SDA
#define CT_READ_SDA gpio_input_bit_get(SDA_PORT,SDA_PIN) //PFin(11) //输入SDA
#define CT_READ_SDA gpio_input_bit_get(SDA_PORT,SDA_PIN) //PFin(11) //输入SDA
#define RST_RCU RCU_GPIOD
#define RST_PORT GPIOD
#define RST_PIN GPIO_PIN_12
#define RST_ON gpio_bit_set(RST_PORT,RST_PIN);
#define RST_OFF gpio_bit_reset(RST_PORT,RST_PIN);
#define RST_TOGGLE gpio_bit_toggle(RST_PORT,RST_PIN);
#define RST_ON gpio_bit_set(RST_PORT,RST_PIN)
#define RST_OFF gpio_bit_reset(RST_PORT,RST_PIN)
#define RST_TOGGLE gpio_bit_toggle(RST_PORT,RST_PIN)
#define INT_RCU RCU_GPIOD
#define INT_PORT GPIOD
#define INT_PIN GPIO_PIN_11
#define INT_ON gpio_bit_set(INT_PORT,INT_PIN);
#define INT_OFF gpio_bit_reset(INT_PORT,INT_PIN);
#define INT_TOGGLE gpio_bit_toggle(INT_PORT,INT_PIN);
#define INT_ON gpio_bit_set(INT_PORT,INT_PIN)
#define INT_OFF gpio_bit_reset(INT_PORT,INT_PIN)
#define INT_TOGGLE gpio_bit_toggle(INT_PORT,INT_PIN)
//I2C读写命令
#define GT_CMD_WR 0X28 //写命令
#define GT_CMD_RD 0X29 //读命令
// EXTI 中断配置
#define TOUCH_EXTI_LINE EXTI_11
#define TOUCH_EXTI_IRQn EXTI10_15_IRQn
extern volatile uint8_t g_touch_irq_flag;
//GT1151 部分寄存器定义
#define GT_CTRL_REG 0X8040 //GT1151控制寄存器
#define GT_CFGS_REG 0X8050 //GT1151地址寄存器
#define GT_CHECK_REG 0X813C //GT1151验和寄存器
#define GT_PID_REG 0X8140 //GT1151产品ID寄存器
//I2C读写命令
#define GT_CMD_WR 0X28 //写命令
#define GT_CMD_RD 0X29 //读命令
#define GT_GSTID_REG 0X814E //GT1151前检测到的触摸情况
#define GT_TP1_REG 0X8150 //第一个触摸点数据地址
#define GT_TP2_REG 0X8158 //第二个触摸点数据地址
#define GT_TP3_REG 0X8160 //第三个触摸点数据地址
#define GT_TP4_REG 0X8168 //第四个触摸点数据地址
#define GT_TP5_REG 0X8170 //第五个触摸点数据地址
//GT1151 部分寄存器定义
#define GT_CTRL_REG 0X8040 //GT1151控制寄存器
#define GT_CFGS_REG 0X8050 //GT1151地址寄存器
#define GT_CHECK_REG 0X813C //GT1151验和寄存器
#define GT_PID_REG 0X8140 //GT1151产品ID寄存器
#define TP_PRES_DOWN 0x80 //触屏被按下
#define TP_CATH_PRES 0x40 //有按键按下了
#define CT_MAX_TOUCH 5 //电容屏支持的点数,固定为5点
//触摸屏控制器
#define GT_GSTID_REG 0X814E //GT1151前检测到的触摸情况
#define GT_TP1_REG 0X8150 //第一个触摸点数据地址
#define GT_TP2_REG 0X8158 //第二个触摸点数据地址
#define GT_TP3_REG 0X8160 //第三个触摸点数据地址
#define GT_TP4_REG 0X8168 //第四个触摸点数据地址
#define GT_TP5_REG 0X8170 //第五个触摸点数据地址
#define TP_PRES_DOWN 0x80 //触屏被按下
#define TP_CATH_PRES 0x40 //有按键按下了
#define CT_MAX_TOUCH 5 //电容屏支持的点数,固定为5点
//触摸屏控制器
typedef struct
{
// uint8_t (*init)(void); //初始化触摸屏控制器
// uint8_t (*scan)(uint8_t); //扫描触摸屏.0,屏幕扫描;1,物理坐标;
// void (*adjust)(void); //触摸屏校准
uint16_t x[CT_MAX_TOUCH]; //当前坐标
uint16_t y[CT_MAX_TOUCH]; //电容屏有最多5组坐标,电阻屏则用x[0],y[0]代表:此次扫描时,触屏的坐标,用
uint8_t sta; //笔的状态
// uint8_t (*init)(void); //初始化触摸屏控制器
// uint8_t (*scan)(uint8_t); //扫描触摸屏.0,屏幕扫描;1,物理坐标;
// void (*adjust)(void); //触摸屏校准
uint16_t x[CT_MAX_TOUCH]; //当前坐标
uint16_t y[CT_MAX_TOUCH]; //电容屏有最多5组坐标,电阻屏则用x[0],y[0]代表:此次扫描时,触屏的坐标,用
uint8_t sta; //笔的状态
float xfac;
float yfac;
short xoff;
short yoff;
uint8_t touchtype;
}_m_tp_dev;
extern _m_tp_dev tp_dev; //触屏控制器在touch.c里面定义
//IIC所有操作函数
void CT_IIC_Init(void); //初始化IIC的IO口
void CT_IIC_Start(void); //发送IIC开始信号
void CT_IIC_Stop(void); //发送IIC停止信号
void CT_IIC_Send_Byte(uint8_t txd); //IIC发送一个字节
uint8_t CT_IIC_Read_Byte(unsigned char ack); //IIC读取一个字节
uint8_t CT_IIC_Wait_Ack(void); //IIC等待ACK信号
void CT_IIC_Ack(void); //IIC发送ACK信号
void CT_IIC_NAck(void); //IIC不发送ACK信号
extern _m_tp_dev tp_dev; //触屏控制器在touch.c里面定义
uint8_t GT1151_Send_Cfg(uint8_t mode);
uint8_t GT1151_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len);
@@ -99,9 +91,4 @@ void GT1151_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len);
uint8_t GT1151_Init(void);
uint8_t GT1151_Scan(uint8_t mode);
#endif
+149 -40
View File
@@ -4,7 +4,8 @@
#define I2C_TIMEOUT 50000
struct i2c_hw_config_t {
struct i2c_hw_config_t
{
uint32_t i2c_periph;
rcu_periph_enum rcu_clock;
uint32_t gpio_port;
@@ -15,7 +16,7 @@ struct i2c_hw_config_t {
};
static constexpr i2c_hw_config_t i2c_hw_map[] = {
{I2C0, RCU_I2C0, GPIOB, GPIO_PIN_8, GPIO_PIN_9, GPIO_AF_4, RCU_GPIOB},
{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},
};
@@ -23,15 +24,18 @@ static constexpr i2c_hw_config_t i2c_hw_map[] = {
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) {
while (RESET == i2c_flag_get(i2c_periph, flag))
{
if (--timeout == 0)
{
return RET_ERROR;
}
}
return RET_OK;
}
extern "C" {
extern "C"
{
static I2cBus i2c_0(I2cPort::_0);
static I2cBus i2c_1(I2cPort::_1);
@@ -41,7 +45,8 @@ static uint8_t i2c_inited[3] = {0};
int i2c_init(uint8_t port, uint32_t speed_hz)
{
if (port >= 3) return -1;
if (port >= 3)
return -1;
I2cConfig cfg;
cfg.speed_hz = speed_hz;
RetCode ret = i2c_instances[port]->init(cfg);
@@ -51,21 +56,24 @@ int i2c_init(uint8_t port, uint32_t speed_hz)
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;
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;
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;
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;
}
@@ -89,7 +97,8 @@ I2cBus::I2cBus(I2cPort port)
I2cBus::~I2cBus()
{
if (initialized_) {
if (initialized_)
{
deinit();
}
}
@@ -97,12 +106,14 @@ I2cBus::~I2cBus()
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])) {
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) {
if (hw.i2c_periph == 0)
{
return RET_NOT_SUPPORTED;
}
@@ -118,7 +129,8 @@ RetCode I2cBus::init(const I2cConfig &config)
i2c_deinit(hw.i2c_periph);
uint32_t speed = config.speed_hz;
if (speed == 0) {
if (speed == 0)
{
speed = 100000;
}
i2c_clock_config(hw.i2c_periph, speed, I2C_DTCY_2);
@@ -133,7 +145,8 @@ RetCode I2cBus::init(const I2cConfig &config)
RetCode I2cBus::deinit()
{
uint8_t port_idx = static_cast<uint8_t>(port_);
if (port_idx >= sizeof(i2c_hw_map) / sizeof(i2c_hw_map[0])) {
if (port_idx >= sizeof(i2c_hw_map) / sizeof(i2c_hw_map[0]))
{
return RET_INVALID_PARAM;
}
@@ -149,19 +162,23 @@ RetCode I2cBus::deinit()
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) {
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) {
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) {
if (wait_flag(i2c_periph, I2C_FLAG_ADDSEND) != RET_OK)
{
return RET_TIMEOUT;
}
@@ -172,30 +189,36 @@ static RetCode i2c_master_start(uint32_t i2c_periph, uint16_t addr, uint32_t dir
RetCode I2cBus::master_write(I2cDevice &dev, const uint8_t *data, uint32_t len)
{
if (data == nullptr || len == 0) {
if (data == nullptr || len == 0)
{
return RET_INVALID_PARAM;
}
if (!initialized_) return RET_NOT_INITIALIZED;
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) {
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) {
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) {
if (wait_flag(i2c, I2C_FLAG_TBE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
@@ -206,34 +229,43 @@ RetCode I2cBus::master_write(I2cDevice &dev, const uint8_t *data, uint32_t len)
RetCode I2cBus::master_read(I2cDevice &dev, uint8_t *data, uint32_t len)
{
if (data == nullptr || len == 0) {
if (data == nullptr || len == 0)
{
return RET_INVALID_PARAM;
}
if (!initialized_) return RET_NOT_INITIALIZED;
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) {
if (len == 1)
{
i2c_ack_config(i2c, I2C_ACK_DISABLE);
} else {
}
else
{
i2c_ack_config(i2c, I2C_ACK_ENABLE);
}
RetCode ret = i2c_master_start(i2c, dev.dev_addr_, I2C_RECEIVER);
if (ret != RET_OK) {
if (ret != RET_OK)
{
i2c_stop_on_bus(i2c);
return ret;
}
for (uint32_t i = 0; i < len; i++) {
if (i == len - 1) {
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) {
if (wait_flag(i2c, I2C_FLAG_RBNE) != RET_OK)
{
i2c_stop_on_bus(i2c);
return RET_TIMEOUT;
}
@@ -245,18 +277,95 @@ RetCode I2cBus::master_read(I2cDevice &dev, uint8_t *data, uint32_t len)
RetCode I2cBus::master_write_read(I2cDevice &dev, const uint8_t *wdata, uint32_t wlen, uint8_t *rdata, uint32_t rlen)
{
if (wlen > 0) {
RetCode ret = master_write(dev, wdata, wlen);
if (ret != RET_OK) {
return ret;
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;
}
if (rlen > 0) {
RetCode ret = master_read(dev, rdata, rlen);
if (ret != RET_OK) {
return ret;
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;
+13
View File
@@ -46,4 +46,17 @@ private:
bool initialized_ = false;
};
#ifdef __cplusplus
extern "C" {
#endif
int i2c_init(uint8_t port, uint32_t speed_hz);
int i2c_master_write(uint8_t port, uint16_t dev_addr, const uint8_t *data, uint32_t len);
int i2c_master_read(uint8_t port, uint16_t dev_addr, uint8_t *data, uint32_t len);
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);
#ifdef __cplusplus
}
#endif
#endif
+2
View File
@@ -63,6 +63,8 @@ void DebugMon_Handler(void);
void PendSV_Handler(void);
/* this function handles SysTick exception */
void SysTick_Handler(void);
/* this function handles EXTI10-15 exception */
void EXTI10_15_IRQHandler(void);
#ifdef __cplusplus
}