Stimulate/工作交接文档_ECG十二导联信号生成系统.md

389 lines
11 KiB
Markdown
Raw Normal View History

2025-10-09 10:39:54 +08:00
# ECG十二导联信号生成系统 - 工作交接文档
## 项目概述
本项目是一个基于ESP32-S3的ECG心电图十二导联信号生成系统能够同时生成并输出I、II、III导联以及V1-V6胸导联的ECG信号通过DAC芯片输出到8个独立通道。
### 主要功能
- **十二导联ECG信号生成**I、II、III、V1-V6导联
- **多通道DAC输出**8个独立通道同时输出
- **高精度波形生成**20kHz采样率支持10,000点查找表
- **内存优化**PSRAM存储防止DRAM溢出
- **实时信号处理**50μs定时器中断
---
## 系统架构
### 硬件平台
- **主控芯片**ESP32-S3
- **DAC芯片**AD5328BRUZ8通道12位DAC
- **通信接口**SPI2DAC控制、I2C0触摸屏
- **显示**ST7789 LCD + FT5x06触摸屏
### 软件架构
```
main/
├── main.c # 主程序入口
├── esp32_s3_szp.c # 硬件驱动SPI、I2C、LCD
├── esp32_s3_szp.h # 硬件定义
└── app_ui.c # UI界面
components/signal_generators/
├── include/
│ ├── ecg_generator.h # ECG生成器接口
│ └── sine_generator.h # 正弦波生成器接口
└── src/
├── ecg_generator.c # ECG生成器实现
└── sine_generator.c # 正弦波生成器实现
```
---
## 核心代码功能详解
### 1. ECG信号生成器 (`ecg_generator.c`)
#### 1.1 导联类型定义
```c
typedef enum {
ECG_LEAD_I = 0, // I导联右手到左手
ECG_LEAD_II = 1, // II导联右手到左腿
ECG_LEAD_III = 2, // III导联左手到左腿
ECG_LEAD_V1 = 3, // V1导联胸骨右缘第四肋间
ECG_LEAD_V2 = 4, // V2导联
ECG_LEAD_V3 = 5, // V3导联过渡区
ECG_LEAD_V4 = 6, // V4导联高R波
ECG_LEAD_V5 = 7, // V5导联
ECG_LEAD_V6 = 8 // V6导联
} ecg_lead_t;
```
#### 1.2 ECG生成器结构体
```c
typedef struct {
// 用户参数
float heart_rate; // 心率 (次/分)
float amplitude; // 幅值 (V)
ecg_lead_t lead; // 当前导联
// 内部状态
uint32_t sample_count; // 样本计数器
float sample_rate; // 采样率 (Hz)
bool is_running; // 运行状态
// 导联特定参数
float p_amp_ratio; // P波幅度比例
float q_amp_ratio; // Q波幅度比例
float r_amp_ratio; // R波幅度比例
float s_amp_ratio; // S波幅度比例
float t_amp_ratio; // T波幅度比例
bool p_bidirectional; // P波是否双向V1导联特有
// 查找表相关
float* ecg_lookup_table; // ECG查找表
uint32_t table_size; // 查找表大小
uint32_t table_index; // 当前索引
// 按比例重复采样(防止相位失真)
uint32_t ideal_table_size; // 理想表大小
uint32_t samples_per_point; // 每个表点对应的样本数
uint32_t sample_counter; // 当前表点的样本计数器
} ecg_generator_t;
```
#### 1.3 关键算法:按比例重复采样
**问题**当理想表大小超过10,000点时需要限制表大小防止内存溢出但会导致相位失真。
**解决方案**:按比例重复采样
```c
// 计算理想表大小和实际表大小
generator->ideal_table_size = (uint32_t)(generator->sample_rate / generator->frequency);
const uint32_t MAX_TABLE_SIZE = 10000;
generator->table_size = generator->ideal_table_size;
if (generator->table_size > MAX_TABLE_SIZE) {
generator->table_size = MAX_TABLE_SIZE;
}
// 计算每个表点需要重复的样本数
generator->samples_per_point = generator->ideal_table_size / generator->table_size;
// 在get_next_sample中实现重复采样
if (generator->sample_counter >= generator->samples_per_point) {
generator->sample_counter = 0;
generator->table_index = (generator->table_index + 1) % generator->table_size;
}
```
#### 1.4 导联特定参数设置
每个导联都有独特的波形特征:
```c
void ecg_generator_set_lead_parameters(ecg_generator_t *generator, ecg_lead_t lead) {
switch (lead) {
case ECG_LEAD_I:
generator->p_amp_ratio = 0.12; // P波较小
generator->q_amp_ratio = 0.25;
generator->r_amp_ratio = 0.7; // R波中等
generator->s_amp_ratio = 0.3;
generator->t_amp_ratio = 0.3;
generator->p_bidirectional = false;
break;
case ECG_LEAD_V1:
generator->p_amp_ratio = 0.08; // P波双向
generator->q_amp_ratio = 0.0; // 无Q波
generator->r_amp_ratio = 0.25; // 小r波
generator->s_amp_ratio = 1.0; // 深S波
generator->t_amp_ratio = -0.15; // T波倒置
generator->p_bidirectional = true; // 双向P波
break;
// ... 其他导联
}
}
```
#### 1.5 双向P波实现V1导联特有
```c
// 在波形计算中
if (generator->p_bidirectional) {
// 双向P波先正后负
float p_positive = p_amp * expf(-(t_norm - p_time_ratio) * (t_norm - p_time_ratio) /
(2.0f * p_width_ratio * p_width_ratio));
float p_negative = -p_amp * 0.6f * expf(-(t_norm - (p_time_ratio + 0.02f)) *
(t_norm - (p_time_ratio + 0.02f)) /
(2.0f * p_width_ratio * p_width_ratio));
p = p_positive + p_negative;
} else {
// 单向P波
p = p_amp * expf(-(t_norm - p_time_ratio) * (t_norm - p_time_ratio) /
(2.0f * p_width_ratio * p_width_ratio));
}
```
### 2. 十二导联系统封装
#### 2.1 系统初始化函数
```c
int ecg_generator_init_twelve_leads_system(float sample_rate, float amplitude, float heart_rate) {
// 初始化所有9个导联生成器
ecg_generator_init(&g_ecg_gen_i, sample_rate, ECG_LEAD_I);
ecg_param_set(&g_ecg_gen_i, amplitude, heart_rate);
ecg_generator_generate_lookup_table(&g_ecg_gen_i);
ecg_generator_start(&g_ecg_gen_i);
// ... 重复其他8个导联
return 0; // 成功
}
```
#### 2.2 多通道输出函数
```c
void ecg_generator_output_twelve_leads(void (*set_channel_voltage)(uint8_t channel, float voltage)) {
float voltage;
// 通道映射0通道输出I导联1通道输出II导联2-7通道输出V1-V6导联
voltage = ecg_generator_get_next_sample(&g_ecg_gen_i);
set_channel_voltage(0, voltage); // 通道0I导联
voltage = ecg_generator_get_next_sample(&g_ecg_gen_ii);
set_channel_voltage(1, voltage); // 通道1II导联
voltage = ecg_generator_get_next_sample(&g_ecg_gen_v1);
set_channel_voltage(2, voltage); // 通道2V1导联
// ... 其他通道
}
```
### 3. 硬件驱动 (`esp32_s3_szp.c`)
#### 3.1 SPI初始化
```c
// SPI总线配置
spi_bus_config_t bus_config = {
.miso_io_num = GPIO_NUM_NC, // 不使用MISO
.mosi_io_num = PIN_MOSI, // GPIO12
.sclk_io_num = PIN_SCK, // GPIO13
.quadhd_io_num = GPIO_NUM_NC,
.quadwp_io_num = GPIO_NUM_NC,
};
// SPI设备配置
spi_device_interface_config_t dev_config = {
.clock_speed_hz = 1000000, // 1 MHz
.mode = 0, // SPI模式0
.spics_io_num = PIN_CS, // GPIO10
.queue_size = 1,
.flags = SPI_DEVICE_HALFDUPLEX, // 半双工
};
```
#### 3.2 DAC数据发送
```c
void set_channel_voltage(uint8_t channel, float voltage) {
// 电压转数字值12位
uint16_t dac_value = (uint16_t)((voltage / V_REF) * 4095);
// 组装SPI数据包16位
uint8_t tx_data[2] = {
((channel & 0x07) << 4) | ((dac_value >> 8) & 0x0F), // 高字节
(dac_value & 0xFF) // 低字节
};
// SPI事务
spi_transaction_t t = {
.length = 16,
.tx_buffer = tx_data,
.rx_buffer = NULL
};
esp_err_t ret = spi_device_transmit(handle, &t);
}
```
### 4. 主程序 (`main.c`)
#### 4.1 系统初始化流程
```c
void app_main(void) {
int led_count = 0;
// 1. 硬件初始化
init_hardware(); // I2C、LED、DAC初始化
// 2. ECG系统初始化
init_ecg_system(); // 初始化十二导联系统
// 3. 主循环
while (true) {
// LED状态指示
gpio_set_level(LED_PIN, 1);
vTaskDelay(pdMS_TO_TICKS(1000));
gpio_set_level(LED_PIN, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
// 内存监控
if (++led_count % 10 == 0) {
displayMemoryUsage();
}
}
}
```
#### 4.2 定时器中断处理
```c
static void signal_timer_callback(void* arg) {
// ECG十二导联模式使用十二导联输出函数
ecg_generator_output_twelve_leads(set_channel_voltage);
signal_sample_count++;
}
```
---
## 系统运行机制
### 1. 启动流程
1. **硬件初始化**I2C、SPI、GPIO配置
2. **DAC初始化**SPI总线、设备、控制引脚
3. **ECG系统初始化**9个导联生成器、查找表生成
4. **定时器启动**50μs周期20kHz
5. **主循环**LED指示、内存监控
### 2. 实时信号生成
1. **定时器中断**每50μs触发一次
2. **信号生成**:各导联生成器产生下一个样本
3. **DAC输出**8个通道同时更新电压
4. **相位同步**:所有导联保持同步
### 3. 内存管理
- **查找表存储**PSRAMheap_caps_malloc with MALLOC_CAP_SPIRAM
- **表大小限制**最大10,000点防止DRAM溢出
- **按比例采样**:保持波形形状和相位连续性
### 4. 通道映射
```
DAC通道 → ECG导联
通道0 → I导联
通道1 → II导联
通道2 → V1导联
通道3 → V2导联
通道4 → V3导联
通道5 → V4导联
通道6 → V5导联
通道7 → V6导联
```
---
## 技术参数
### 性能指标
- **采样率**20kHz
- **心率范围**30-200 BPM
- **电压范围**0-2.048V12位分辨率
- **查找表大小**最大10,000点
- **内存使用**PSRAM存储避免DRAM溢出
### 硬件接口
- **SPI2**DAC控制MOSI:GPIO12, SCK:GPIO13, CS:GPIO10
- **GPIO控制**LDAC(GPIO11), DAC_EN(GPIO17)
- **I2C0**触摸屏通信SDA:GPIO1, SCL:GPIO2
### 波形特征
- **I导联**R波中等P波较小
- **II导联**R波最大P波明显
- **III导联**波形介于I和II之间
- **V1导联**双向P波深S波T波倒置
- **V2-V6导联**过渡区到高R波区域
---
## 维护和调试
### 1. 常见问题排查
- **内存不足**检查PSRAM配置调整查找表大小
- **SPI通信失败**:检查引脚配置和时钟频率
- **波形失真**:验证按比例采样算法
- **相位不同步**:检查定时器配置
### 2. 性能优化
- **内存优化**使用PSRAM存储大查找表
- **实时性**50μs定时器确保20kHz输出
- **精度优化**12位DAC提供高精度输出
### 3. 扩展功能
- **参数调节**:心率、幅度、导联类型
- **波形存储**支持不同ECG模式
- **多设备支持**可扩展更多DAC通道
---
## 开发环境
### 编译环境
- **ESP-IDF**v5.0+
- **编译器**GCC for RISC-V
- **调试工具**ESP-IDF Monitor
### 依赖组件
- **esp_lcd_port**LCD显示
- **lvgl**:图形界面
- **esp_lcd_touch_ft5x06**:触摸屏
### 构建命令
```bash
idf.py build
idf.py flash monitor
---
**交接完成日期**2025年10月9日
**系统版本**v1.0