Electricity/FWLIB/source/ENS1_WAVEGEN.c

321 lines
12 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.

/*
*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 <stdio.h>
#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=100us100us=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;
}
}
}