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

389 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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