/* *Copyright (C),2023 , NANOCHAP *File name: ENS1_WAVEGEN.C *Author: *Version: V1.0 *Date: 2023-11- *Description: 波形生成器电刺激功能实现 *Function List: 1 int wavegen_driverA_sine_test(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA, uint16_t incount); 2 void wavegen_Stop(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA); 3 void wavegen_Init(void); 4 void wavegen_Start(void); History: 1.V1.0 Date: Author: Modification: 初版 */ #include #include "ENS1_WAVEGEN.h" #include "ENS1_CLOCK.h" #include "ENS1_BOOST.h" // 全局变量 static EMS_Config_TypeDef g_ems_config = {0}; static volatile uint8_t g_ems_running = 0; static volatile uint32_t g_ems_count = 0; // 缓进缓出控制变量 static volatile uint16_t g_current_intensity = 0; // 当前强度 static volatile uint8_t g_ramp_phase = 0; // 渐进阶段:0=缓进, 1=保持, 2=缓出 static volatile uint32_t g_wave_counter = 0; // 方波周期计数器 static volatile uint32_t g_ramp_step_counter = 0; // 缓进步进计数器 /* --------------------------------------------------------------- */ /* 波形生成器驱动器A正弦波测试 */ /* --------------------------------------------------------------- */ int wavegen_driverA_sine_test(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA, uint16_t incount) { int return_val = 0; int err_code = 0; printf("\n驱动器A正弦波测试\n"); CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_REST_T_REG = 100; // 死区时间10ms //交替模式下,死区时间失效,即使CONFIG_REG使能了死区时间也无效 // CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_SILENT_T_REG = 200; //静默时间20ms CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CLK_FREQ_REG = 0x00000020; // 32MHz ==PCLK CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CLK_FREQ_REG = 32; // 32MHz ==PCLK //MHz为单位 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_HLF_WAVE_PRD_REG = 100; // 正半周期脉宽10ms,有交替方波 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_NEG_HLF_WAVE_PRD_REG = 100; // 负半周期脉宽10ms,无交替方波 #if 1 // 无需静默时间 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CONFIG_REG = 0x00000050; // bit 0:rest enable , 正半周期和负半周期中间的休息时间 // 1:negative enable , 负半周期发生使能,如果不使能,则没有负半周期的波形(注意交替模式只会对正半周期起作用) // 2: silent enable , 负半周期结束后的静默时间 // 3: source B enable ,负脉宽方向使能位,1负脉宽在负半周期,0负脉宽在正半周期 // 4: alternating the positive side ,正极交替产生包络 // 5: continue mode ,连续模式 // 6: multi-electrode ,多电极模式 #else // 需要静默时间 /*交替模式下config寄存器说明: 正脉宽交替,无负脉宽,无死区时间,无静默时间:0x50 或 0x51 或 0x58 或 0x59 正脉宽交替,无死区时间,无负脉宽,有静默时间:0x54 或 0x55 或 0x5C 或 0x5D 正脉宽交替,无死区时间,负脉宽不交替但有波形,无静默时间 :0x5A 或 0x5B 正脉宽交替,无死区时间,负脉宽不交替但有波形且波形在正脉宽上(因为源B失能了),无静默时间 :0x52 或 0x53 正脉宽交替,无死区时间,负脉宽不交替但有波形且波形在正脉宽上(因为源B失能了),有静默时间 :0x56 或 0x57 正脉宽交替,无死区时间,负脉宽不交替但有波形,有静默时间 : 0x5E 或 0x5F */ // CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CONFIG_REG = 0x5F; //bit 0:rest enable , 正半周期和负半周期中间的死区时间 // 1:negative enable , 负半周期发生使能,如果不使能,则没有负半周期的波形 // 2: silent enable , 负半周期结束后的静默时间 // 3: source B enable // 4: alternating the positive side ,正极交替产生包络 // 5: continue mode ,连续模式 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CONFIG_REG = 0x34; // 静默时间、交替模式和多电极使能 //6: multi-electrode ,多电极模式 #endif CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ISEL_REG = 0x04; // 总电流 = 单元电流ISEL * WAVE_GEN_DRV_IN_WAVE_REG for (int i = 0; i < 64; i++) { CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_ADDR_REG = i; // CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = sine_data[i]; //正弦波数据数组,根据数组中的点描绘正半周期的波形 // CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = saw_data[i]; //三角波数据 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = incount; // 方波数据(固定值0x80) } CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ALT_LIM_REG = 3200; // 3200 需要设置一个正半周期下需要再生成多少个周期波形。设置10kHz=0.1ms=100us,100us=A*(1/32us),所以A=3200。 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ALT_SILENT_LIM_REG = 0; // 交替后静默的时钟数(无死区时间设置)。在这种情况下,驱动器B连续交替。//包络下波形的静默时间 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_DELAY_LIM_REG = 0x00000000; // 延迟时钟数 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_NEG_SCALE_REG = 0x00000001; // 负半周期幅值倍乘系数,如超过255,则从0开始增长 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_NEG_OFFSET_REG = 0x00000000; // 负半周期幅值偏移量,如超过255,则从0开始增长, // 如正半周期幅值为250,此处设置为10,则负半周期幅值为5 !!! CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_INT_REG = 0x0; // 中断寄存器设置为0 CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_CTRL_REG = 0x00000001; // 使能驱动器 /* 生成返回值 */ if (err_code != 0) { printf("\n错误 : 驱动器A测试失败\n"); return_val = 1; err_code = 0; } return (return_val); } void wavegen_Stop(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA) { CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_ISEL_REG = 0; // 范围 0x00 - 0x07 for (int i = 0; i < 64; i++) { CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_ADDR_REG = i; CMSDK_WAVEGEN_DRVA->WAVE_GEN_DRV_IN_WAVE_REG = 0; // 最大值0xff } } // 初始化波形生成器 void wavegen_Init(void) { // 设置MTP等待周期 CMSDK_MTPREG->MTP_CR = 0x00000002; // 注意:时钟配置已在ClockInit()中完成,这里不再重复配置 // 使用HSI作为主频 32MHz // CMSDK_SYSCON->HSI_CTRL = (CMSDK_SYSCON->HSI_CTRL & ~CMSDK_SYSCON_HSI_FREQ_Msk) | (0x3 << CMSDK_SYSCON_HSI_FREQ_Pos); //HSI=32MHz // 使能UART和WAVE_GEN外设时钟(不覆盖TIMER0时钟) CMSDK_SYSCON->APB_CLKEN |= 0x1003 | 0x4000; // 使用|=而不是=,避免覆盖其他时钟使能 // 升压电压选择 //boost_voltage_select_11V(); //boost_voltage_select_15V(); //boost_voltage_select_26V(); //boost_voltage_select_45V(); boost_voltage_select_55V(); } // 启动波形生成器 void wavegen_Start(void) { g_ems_running = 1; g_ems_count = 0; // 初始化缓进缓出控制 if (g_ems_config.enable_ramp) { g_current_intensity = 0; // 从0开始 g_ramp_phase = 0; // 缓进阶段 g_wave_counter = 0; // 重置方波计数器 g_ramp_step_counter = 0; // 重置步进计数器 } else { g_current_intensity = g_ems_config.intensity; // 直接使用设定强度 } } // 电刺激参数配置 void EMS_Configure(EMS_Config_TypeDef *config) { if (config != NULL) { g_ems_config = *config; } } // 启动电刺激 void EMS_Start(void) { wavegen_Start(); } // 停止电刺激 void EMS_Stop(void) { g_ems_running = 0; g_ems_count = 0; // 重置计数器 g_current_intensity = 0; // 重置强度 g_ramp_phase = 0; // 重置渐进阶段 g_wave_counter = 0; // 重置方波计数器 g_ramp_step_counter = 0; // 重置步进计数器 wavegen_Stop(WAVE_GEN_DRVA_BLK0); } // 更新电刺激强度 void EMS_UpdateIntensity(uint16_t intensity) { g_ems_config.intensity = intensity; } // 缓进缓出处理函数(在电刺激处理中调用) void EMS_Process_Ramp(void) { if (!g_ems_config.enable_ramp || !g_ems_running) { return; // 如果未启用缓进缓出或未运行,直接返回 } // 计算每个强度步进需要的方波周期数 // 2秒 = 2000000微秒,每个方波周期100微秒,所以2秒内有20000个方波周期 // 需要从0增加到128,所以每156.25个方波周期增加1个强度单位 uint32_t waves_per_step = 0; uint32_t total_waves_ramp_up = g_ems_config.ramp_up_time * 5; // 缓进阶段总方波周期数 uint32_t total_waves_ramp_down = g_ems_config.ramp_down_time * 1; // 缓出阶段总方波周期数 uint32_t total_waves_hold = g_ems_config.hold_time * 5; // 保持阶段总方波周期数 if (g_ems_config.intensity > 0) { waves_per_step = total_waves_ramp_up / g_ems_config.intensity; // 每个强度步进需要的方波周期数 } g_wave_counter++; // 每次调用增加一个方波周期计数 switch (g_ramp_phase) { case 0: // 缓进阶段 if (g_ramp_step_counter < total_waves_ramp_up) { // 检查是否需要增加强度 if (g_wave_counter >= waves_per_step) { g_wave_counter = 0; // 重置方波计数器 if (g_current_intensity < g_ems_config.intensity) { g_current_intensity++; } } g_ramp_step_counter++; } else { // 缓进完成,进入保持阶段 g_ramp_phase = 1; g_ramp_step_counter = 0; g_current_intensity = g_ems_config.intensity; // 确保达到最大强度 } break; case 1: // 保持阶段 if (g_ramp_step_counter < total_waves_hold) { // 保持最大强度 g_current_intensity = g_ems_config.intensity; g_ramp_step_counter++; } else { // 保持完成,进入缓出阶段 g_ramp_phase = 2; g_ramp_step_counter = 0; g_wave_counter = 0; // 重置方波计数器 } break; case 2: // 缓出阶段 if (g_ramp_step_counter < total_waves_ramp_down) { // 检查是否需要减少强度 if (g_wave_counter >= waves_per_step) { g_wave_counter = 0; // 重置方波计数器 if (g_current_intensity > 0) { g_current_intensity--; } } g_ramp_step_counter++; } else { // 缓出完成,停止电刺激 g_current_intensity = 0; // 这里不直接停止,让主循环控制停止 } break; } } // 电刺激主循环处理函数(在主循环中调用) void EMS_Process(void) { if (g_ems_running) { g_ems_count++; // 处理缓进缓出控制 EMS_Process_Ramp(); // 使用当前缓进缓出的强度 uint16_t current_intensity = g_current_intensity; // 根据配置生成不同强度的方波 if (g_ems_count < 1280) { wavegen_driverA_sine_test(WAVE_GEN_DRVA_BLK0, current_intensity); } else if (g_ems_count < 1280 * 256) { // 休息时间 } else if (g_ems_count < 1280 * 2) { wavegen_driverA_sine_test(WAVE_GEN_DRVA_BLK0, current_intensity); } else { // 重置计数器,开始新的周期 g_ems_count = 0; } } }