Stimulate/main/main.c

221 lines
6.9 KiB
C
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.

#include <stdio.h>
#include "esp32_s3_szp.h"
#include "app_ui.h"
#include <esp_system.h>
#include <math.h>
#include "ecg_generator.h"
#include "sine_generator.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
EventGroupHandle_t my_event_group;
// 按键定义
#define BUTTON_PIN GPIO_NUM_0 // 使用GPIO0作为按键输入
#define BUTTON_DEBOUNCE_MS 200 // 防抖时间
static const char *TAG = "MAIN";
// 信号生成器相关
static ecg_generator_t g_ecg_gen;
static sine_generator_t g_sine_gen;
static esp_timer_handle_t signal_timer = NULL;
static uint32_t signal_sample_count = 0;
static uint32_t signal_last_log_time = 0;
static bool use_sine_wave = true; // true=正弦波, false=ECG
// 信号生成器定时器回调函数
static void signal_timer_callback(void* arg) {
float signal_voltage = 0.0f;
if (use_sine_wave) {
// 生成正弦波样本
signal_voltage = sine_generator_get_next_sample(&g_sine_gen);
} else {
// 生成ECG样本
signal_voltage = ecg_generator_get_next_sample(&g_ecg_gen);
}
// 输出到DAC通道2
set_channel_voltage(2, signal_voltage);
signal_sample_count++;
// 减少日志输出频率,避免影响高频中断性能
// 每20000个样本输出一次统计信息约1秒
if (signal_sample_count >= 20000) {
ESP_LOGI(TAG, "Generated %u samples at 20kHz (%s)",
signal_sample_count, use_sine_wave ? "Sine Wave" : "ECG");
signal_sample_count = 0;
signal_last_log_time = esp_timer_get_time() / 1000;
}
}
// 函数声明
void displayMemoryUsage(void);
void test_signal_generation(void);
void switch_to_ecg_mode(void);
void switch_to_sine_mode(void);
// 信号生成器测试函数
void test_signal_generation(void) {
ESP_LOGI(TAG, "=== Signal Generation Test ===");
// 初始化ECG生成器
ecg_generator_init(&g_ecg_gen, 20000.0f); // 20kHz生成率
ecg_param_set(&g_ecg_gen, 5.0f, 75.0f);
// 初始化正弦波生成器
sine_generator_init(&g_sine_gen, 20000.0f); // 20kHz生成率
sine_generator_set_frequency(&g_sine_gen, 10.0f); // 100Hz正弦波
sine_generator_set_amplitude(&g_sine_gen, 5.0f); // 5mV
// 创建定时器配置
const esp_timer_create_args_t timer_args = {
.callback = &signal_timer_callback,
.name = "signal_timer"
};
// 创建定时器
esp_err_t ret = esp_timer_create(&timer_args, &signal_timer);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to create signal timer: %s", esp_err_to_name(ret));
return;
}
// 启动信号生成器
if (use_sine_wave) {
sine_generator_start(&g_sine_gen);
ESP_LOGI(TAG, "Started sine wave generator: 100Hz, 5mV");
} else {
ecg_generator_start(&g_ecg_gen);
ESP_LOGI(TAG, "Started ECG generator: 75 BPM, 5mV");
}
// 启动定时器 (50us = 20kHz)
ret = esp_timer_start_periodic(signal_timer, 50); // 50微秒 = 20kHz
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to start signal timer: %s", esp_err_to_name(ret));
esp_timer_delete(signal_timer);
return;
}
ESP_LOGI(TAG, "Signal timer started at 20kHz (50us period)");
}
// 切换到ECG模式
void switch_to_ecg_mode(void) {
if (use_sine_wave) {
sine_generator_stop(&g_sine_gen);
ecg_generator_start(&g_ecg_gen);
use_sine_wave = false;
ESP_LOGI(TAG, "Switched to ECG mode");
}
}
// 切换到正弦波模式
void switch_to_sine_mode(void) {
if (!use_sine_wave) {
ecg_generator_stop(&g_ecg_gen);
sine_generator_start(&g_sine_gen);
use_sine_wave = true;
ESP_LOGI(TAG, "Switched to sine wave mode");
}
}
// 按键初始化
void button_init(void) {
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << BUTTON_PIN);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 1; // 启用上拉电阻
gpio_config(&io_conf);
ESP_LOGI(TAG, "Button initialized on GPIO %d", BUTTON_PIN);
}
// 检测按键按下
bool button_pressed(void) {
static uint32_t last_press_time = 0;
uint32_t current_time = esp_timer_get_time() / 1000; // 转换为毫秒
// 检测按键按下(低电平)
if (gpio_get_level(BUTTON_PIN) == 0) {
// 防抖处理
if (current_time - last_press_time > BUTTON_DEBOUNCE_MS) {
last_press_time = current_time;
return true;
}
}
return false;
}
// 打印内存使用情况
void displayMemoryUsage() {
size_t totalDRAM = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
size_t freeDRAM = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
size_t usedDRAM = totalDRAM - freeDRAM;
size_t totalPSRAM = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
size_t freePSRAM = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
size_t usedPSRAM = totalPSRAM - freePSRAM;
size_t DRAM_largest_block = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
size_t PSRAM_largest_block = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
float dramUsagePercentage = (float)usedDRAM / totalDRAM * 100;
float psramUsagePercentage = (float)usedPSRAM / totalPSRAM * 100;
ESP_LOGI(TAG, "DRAM Total: %zu bytes, Used: %zu bytes, Free: %zu bytes, DRAM_Largest_block: %zu bytes", totalDRAM, usedDRAM, freeDRAM, DRAM_largest_block);
ESP_LOGI(TAG, "DRAM Used: %.2f%%", dramUsagePercentage);
ESP_LOGI(TAG, "PSRAM Total: %zu bytes, Used: %zu bytes, Free: %zu bytes, PSRAM_Largest_block: %zu bytes", totalPSRAM, usedPSRAM, freePSRAM, PSRAM_largest_block);
ESP_LOGI(TAG, "PSRAM Used: %.2f%%", psramUsagePercentage);
}
// 主函数
void app_main(void)
{
ESP_LOGI(TAG, "Starting ECG application...");
// 硬件初始化
bsp_i2c_init(); // I2C初始化
LED_init(); // LED初始化
init_ad5328(); // DAC初始化
button_init(); // 按键初始化
my_event_group = xEventGroupCreate();
ESP_LOGI(TAG, "Hardware initialization completed.");
// 启动信号生成
test_signal_generation();
// LED状态指示
ESP_LOGI(TAG, "Starting LED status indicator...");
int led_count = 0;
while (true) {
// 检测按键按下
if (button_pressed()) {
if (use_sine_wave) {
switch_to_ecg_mode();
} else {
switch_to_sine_mode();
}
}
// LED闪烁指示系统运行
gpio_set_level(LED_PIN, 1); // LED亮
vTaskDelay(pdMS_TO_TICKS(1000));
gpio_set_level(LED_PIN, 0); // LED灭
vTaskDelay(pdMS_TO_TICKS(1000));
// 每10次循环显示一次内存使用情况
if (++led_count % 10 == 0) {
displayMemoryUsage();
}
}
}