2025-08-20 11:03:53 +08:00
|
|
|
|
/*
|
|
|
|
|
|
*Copyright (C),2023 , NANOCHAP
|
2025-08-29 11:30:52 +08:00
|
|
|
|
*File name: ENS1_WAVEGEN.C
|
|
|
|
|
|
*Author:
|
|
|
|
|
|
*Version: V1.0
|
|
|
|
|
|
*Date: 2023-11-
|
2025-08-20 11:03:53 +08:00
|
|
|
|
*Description: 波形生成器电刺激功能实现
|
2025-08-29 11:30:52 +08:00
|
|
|
|
*Function List:
|
2025-08-20 11:03:53 +08:00
|
|
|
|
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);
|
2025-08-29 11:30:52 +08:00
|
|
|
|
History:
|
2025-08-20 11:03:53 +08:00
|
|
|
|
1.V1.0
|
2025-08-29 11:30:52 +08:00
|
|
|
|
Date:
|
|
|
|
|
|
Author:
|
2025-08-20 11:03:53 +08:00
|
|
|
|
Modification: 初版
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include "ENS1_WAVEGEN.h"
|
|
|
|
|
|
#include "ENS1_CLOCK.h"
|
|
|
|
|
|
#include "ENS1_BOOST.h"
|
2025-09-10 18:07:54 +08:00
|
|
|
|
EMS_Config_TypeDef ems_config = {
|
|
|
|
|
|
.frequency = 100, // 100Hz
|
|
|
|
|
|
.duration = 1000, // 1000ms
|
|
|
|
|
|
.intensity = 128, // 中等强度
|
|
|
|
|
|
.rest_time = 100, // 100ms休息时间
|
|
|
|
|
|
.silent_time = 50, // 50ms静默时间
|
|
|
|
|
|
|
|
|
|
|
|
// 缓进缓出控制参数
|
|
|
|
|
|
.ramp_up_time = 2, // 缓进时间:2秒
|
|
|
|
|
|
.hold_time = 6, // 保持时间:6秒
|
|
|
|
|
|
.ramp_down_time = 2, // 缓出时间:2秒·
|
|
|
|
|
|
.enable_ramp = 1 // 启用渐进控制
|
|
|
|
|
|
};
|
2025-08-20 11:03:53 +08:00
|
|
|
|
// 全局变量
|
2025-09-10 18:07:54 +08:00
|
|
|
|
EMS_Config_TypeDef g_ems_config = {0};
|
2025-08-20 11:03:53 +08:00
|
|
|
|
static volatile uint8_t g_ems_running = 0;
|
|
|
|
|
|
static volatile uint32_t g_ems_count = 0;
|
2025-09-10 18:07:54 +08:00
|
|
|
|
float waves_per_step = 0;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
// 缓进缓出控制变量
|
2025-09-10 18:07:54 +08:00
|
|
|
|
static volatile float g_current_intensity = 0; // 当前强度
|
2025-08-29 11:30:52 +08:00
|
|
|
|
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; // 缓进步进计数器
|
|
|
|
|
|
|
2025-08-20 11:03:53 +08:00
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
|
/* 波形生成器驱动器A正弦波测试 */
|
|
|
|
|
|
/* --------------------------------------------------------------- */
|
|
|
|
|
|
int wavegen_driverA_sine_test(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA, uint16_t incount)
|
|
|
|
|
|
{
|
|
|
|
|
|
int return_val = 0;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
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)
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
2025-08-29 11:30:52 +08:00
|
|
|
|
|
|
|
|
|
|
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; // 使能驱动器
|
2025-08-20 11:03:53 +08:00
|
|
|
|
|
|
|
|
|
|
/* 生成返回值 */
|
2025-08-29 11:30:52 +08:00
|
|
|
|
if (err_code != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
printf("\n错误 : 驱动器A测试失败\n");
|
|
|
|
|
|
return_val = 1;
|
|
|
|
|
|
err_code = 0;
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-29 11:30:52 +08:00
|
|
|
|
return (return_val);
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void wavegen_Stop(CMSDK_WAVE_GEN_TypeDef *CMSDK_WAVEGEN_DRVA)
|
|
|
|
|
|
{
|
2025-08-29 11:30:52 +08:00
|
|
|
|
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
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化波形生成器
|
|
|
|
|
|
void wavegen_Init(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 设置MTP等待周期
|
|
|
|
|
|
CMSDK_MTPREG->MTP_CR = 0x00000002;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
|
2025-08-20 11:03:53 +08:00
|
|
|
|
// 注意:时钟配置已在ClockInit()中完成,这里不再重复配置
|
|
|
|
|
|
// 使用HSI作为主频 32MHz
|
|
|
|
|
|
// CMSDK_SYSCON->HSI_CTRL = (CMSDK_SYSCON->HSI_CTRL & ~CMSDK_SYSCON_HSI_FREQ_Msk) | (0x3 << CMSDK_SYSCON_HSI_FREQ_Pos); //HSI=32MHz
|
2025-08-29 11:30:52 +08:00
|
|
|
|
|
2025-08-20 11:03:53 +08:00
|
|
|
|
// 使能UART和WAVE_GEN外设时钟(不覆盖TIMER0时钟)
|
2025-08-29 11:30:52 +08:00
|
|
|
|
CMSDK_SYSCON->APB_CLKEN |= 0x1003 | 0x4000; // 使用|=而不是=,避免覆盖其他时钟使能
|
|
|
|
|
|
|
2025-08-20 11:03:53 +08:00
|
|
|
|
// 升压电压选择
|
2025-08-29 11:30:52 +08:00
|
|
|
|
//boost_voltage_select_11V();
|
|
|
|
|
|
//boost_voltage_select_15V();
|
|
|
|
|
|
//boost_voltage_select_26V();
|
|
|
|
|
|
//boost_voltage_select_45V();
|
|
|
|
|
|
boost_voltage_select_55V();
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 启动波形生成器
|
|
|
|
|
|
void wavegen_Start(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_ems_running = 1;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
|
|
|
|
|
|
// 初始化缓进缓出控制
|
|
|
|
|
|
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; // 直接使用设定强度
|
|
|
|
|
|
}
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 电刺激参数配置
|
|
|
|
|
|
void EMS_Configure(EMS_Config_TypeDef *config)
|
|
|
|
|
|
{
|
2025-08-29 11:30:52 +08:00
|
|
|
|
if (config != NULL)
|
|
|
|
|
|
{
|
2025-08-20 11:03:53 +08:00
|
|
|
|
g_ems_config = *config;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 启动电刺激
|
|
|
|
|
|
void EMS_Start(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
wavegen_Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 停止电刺激
|
|
|
|
|
|
void EMS_Stop(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_ems_running = 0;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
g_current_intensity = 0; // 重置强度
|
|
|
|
|
|
g_ramp_phase = 0; // 重置渐进阶段
|
|
|
|
|
|
g_wave_counter = 0; // 重置方波计数器
|
|
|
|
|
|
g_ramp_step_counter = 0; // 重置步进计数器
|
2025-08-20 11:03:53 +08:00
|
|
|
|
wavegen_Stop(WAVE_GEN_DRVA_BLK0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新电刺激强度
|
|
|
|
|
|
void EMS_UpdateIntensity(uint16_t intensity)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_ems_config.intensity = intensity;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-29 11:30:52 +08:00
|
|
|
|
// 缓进缓出处理函数(在电刺激处理中调用)
|
|
|
|
|
|
void EMS_Process_Ramp(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
2025-09-10 18:07:54 +08:00
|
|
|
|
if(ems_state)
|
|
|
|
|
|
{
|
|
|
|
|
|
float up_period = ems_config.ramp_up_time;
|
|
|
|
|
|
float down_period = ems_config.ramp_down_time;
|
|
|
|
|
|
if (!g_ems_config.enable_ramp || !g_ems_running)
|
|
|
|
|
|
{
|
|
|
|
|
|
return; // 如果未启用缓进缓出或未运行,直接返回
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-29 11:30:52 +08:00
|
|
|
|
|
2025-09-10 18:07:54 +08:00
|
|
|
|
switch (g_ramp_phase)
|
2025-08-29 11:30:52 +08:00
|
|
|
|
{
|
2025-09-10 18:07:54 +08:00
|
|
|
|
case 0: // 缓进阶段
|
2025-08-29 11:30:52 +08:00
|
|
|
|
{
|
2025-09-10 18:07:54 +08:00
|
|
|
|
if ( time_count <= ems_config.ramp_up_time*1000 )
|
2025-08-29 11:30:52 +08:00
|
|
|
|
{
|
2025-09-10 18:07:54 +08:00
|
|
|
|
if (g_current_intensity < g_ems_config.intensity)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_current_intensity += waves_per_step;
|
|
|
|
|
|
}
|
2025-08-29 11:30:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 18:07:54 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 缓进完成,进入保持阶段
|
|
|
|
|
|
g_ramp_phase = 1;
|
|
|
|
|
|
g_current_intensity = g_ems_config.intensity; // 确保达到最大强度
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
}
|
2025-09-10 18:07:54 +08:00
|
|
|
|
case 1:
|
2025-08-29 11:30:52 +08:00
|
|
|
|
{
|
2025-09-10 18:07:54 +08:00
|
|
|
|
if(time_count <= (ems_config.ramp_up_time+ems_config.hold_time)*1000)
|
2025-08-29 11:30:52 +08:00
|
|
|
|
{
|
2025-09-10 18:07:54 +08:00
|
|
|
|
|
|
|
|
|
|
g_current_intensity = g_ems_config.intensity;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
}
|
2025-09-10 18:07:54 +08:00
|
|
|
|
else g_ramp_phase = 2;
|
|
|
|
|
|
break;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-10 18:07:54 +08:00
|
|
|
|
case 2:
|
|
|
|
|
|
{
|
|
|
|
|
|
if(time_count <= (ems_config.ramp_up_time+ems_config.hold_time+ems_config.ramp_down_time)*1000)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (g_current_intensity > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
g_current_intensity -= waves_per_step;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
g_ramp_phase = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-08-29 11:30:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-10 18:07:54 +08:00
|
|
|
|
else time_count = 0;
|
2025-08-29 11:30:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 11:03:53 +08:00
|
|
|
|
// 电刺激主循环处理函数(在主循环中调用)
|
|
|
|
|
|
void EMS_Process(void)
|
|
|
|
|
|
{
|
2025-08-29 11:30:52 +08:00
|
|
|
|
if (g_ems_running)
|
|
|
|
|
|
{
|
|
|
|
|
|
EMS_Process_Ramp();
|
|
|
|
|
|
// 使用当前缓进缓出的强度
|
|
|
|
|
|
uint16_t current_intensity = g_current_intensity;
|
2025-09-10 18:07:54 +08:00
|
|
|
|
wavegen_driverA_sine_test(WAVE_GEN_DRVA_BLK0, current_intensity);
|
2025-08-20 11:03:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|