HL-PDJ-1/app/Src/timer.c
xiaozhengsheng 6df0f7d96e 初始版本
2025-08-19 09:49:41 +08:00

483 lines
14 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) 2021 Xiangyu Medical Co.Ltd. All rights reserved.
FileName : timer.c
Author : zhangdawei
Version : V1.0
Date :
Note :
History :
********************************************************************/
/* Includes ------------------------------------------------------*/
#include "nrf_drv_pwm.h"
#include "drv_uart.h"
#include "IoControl.h"
#include "timer.h"
#include "nrf_delay.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_gpiote.h"
/* Private define ------------------------------------------------*/
/* 定义APP定时器 */
APP_TIMER_DEF(detect_button_100ms);
#define DETECT_BUTTON APP_TIMER_TICKS(100)
/* Private typedef -----------------------------------------------*/
//定义名称为m_pwm_add的驱动程序实例
static nrfx_pwm_t m_pwm_dac = NRFX_PWM_INSTANCE(1);
static nrfx_pwm_t m_pwm0 = NRFX_PWM_INSTANCE(0);
static nrfx_pwm_t m_pwm2 = NRFX_PWM_INSTANCE(2);
/* Private constants ---------------------------------------------*/
/* Private variables ---------------------------------------------*/
/* 呼吸灯占空比 */
uint16_t m_step = 150;
/* 存放RunLED占空比的数组 */
static nrf_pwm_values_common_t seq3_values[M_STEP*2];
//定义PWM序列该序列必须位于RAM中因此要定义为static类型
static nrf_pwm_values_common_t dac_values[] = {CYCLE_CALUE}; //14
static nrf_pwm_values_wave_form_t seq0_current_values[] =
{
10000 - 600,
10000 - 400,
10000 - 200,
10000 //100Hz
};
static nrf_pwm_values_wave_form_t seq2_current_values[] =
{
800 - 125,
800,
800,
800 //20khz
};
E_WORK_STATE eRmsState = E_RMS_STOP;
/* Private function prototypes -----------------------------------*/
/* Public constants ----------------------------------------------*/
/* Public variables ----------------------------------------------*/
/********************************************************************
* name : void acquisition_start(void)
* description : 开始采集肌电
* Input : void
* Output : void
* Return :
********************************************************************/
void acquisition_start(void)
{
eRmsState = E_RMS_START;
// rms_saadc_init();
nrf_gpio_pin_set(SAMPLE_POWER_PIN);
open_acquisition_relay();
timer3_rms_start();
}
/********************************************************************
* name : void acquisition_stop(void)
* description : 停止肌电采集
* Input : void
* Output : void
* Return :
********************************************************************/
void acquisition_stop(void)
{
timer3_rms_stop();
eRmsState = E_RMS_STOP;
nrf_gpio_pin_clear(SAMPLE_POWER_PIN);
close_acquisition_relay();
}
/********************************************************************
* name : void stimulate_start(void)
* description : 开始刺激
* Input : void
* Output : void
* Return :
********************************************************************/
void stimulate_start(void)
{
acquisition_stop(); //先停止肌电采集
// stimulate_stop(); //停止刺激,重新开始刺激
eRmsState = E_STIM_START;
open_stimulate_relay();
pwm0_play();
pwm2_play();
}
/********************************************************************
* name : void stimulate_stop(void)
* description : 停止刺激
* Input : void
* Output : void
* Return :
********************************************************************/
void stimulate_stop(void)
{
eRmsState = E_STIM_STOP;
close_stimulate_relay();
}
/********************************************************************
* name : static void detect_button(void)
* description : 开关机按键检测处理
* Input : void
* Output : void
* Return :
********************************************************************/
static void detect_button(void)
{
static uint8_t CountValue=0;
if((Bit_RESET == nrf_gpio_pin_read(KEY_PWR_SWITICH))&&((ChargeState == Uncharged))) //检测按键是否按下
{
CountValue++;
if(CountValue == 10)
{
if(POWER_CLOSE == DeviceState) //开机
{
DeviceState = POWER_OPEN;
nrf_gpio_pin_set(KEY_POWER); //锁定电源键给MCU供电
NRF_LOG_INFO("Open!");
StartAdv();
}
else if(POWER_OPEN == DeviceState) //关机
{
DeviceState = POWER_CLOSE;
acquisition_stop();
NRF_LOG_INFO("Close!");
nrf_gpio_pin_clear(KEY_POWER); //断电
}
}
}
else
{
CountValue = 0;
}
static uint16_t runBlinkCount = 0;
if(runBlinkCount == 0 && DeviceState == POWER_OPEN)
nrf_gpio_pin_set(LED_YELLOW);
else if(runBlinkCount == 1)
nrf_gpio_pin_clear(LED_YELLOW);
if(runBlinkCount++ > 8) //1S闪烁一次
{
runBlinkCount = 0;
}
}
/********************************************************************
* name : static void detect_charging_status(void)
* description : 充电状态检测处理
* Input : void
* Output : void
* Return :
********************************************************************/
static void detect_charging_status(void)
{
static uint8_t CountValue=0;
if((Bit_RESET == nrf_gpio_pin_read(CHG_MANAGER_CHG))) //检测按键是否按下
{
ChargeState = Charging;
}
else
{
ChargeState = Uncharged;
}
}
/********************************************************************
* name : static void Hundredms_handler(void * p_context)
* description : 检测按键是否长按函数100ms中断一次累计计数
* Input : void *p_context
* Output : void
* Return :
********************************************************************/
static void Hundredms_handler(void * p_context)
{
//防止编译器警告同时清晰地的表明p_context未使用而不是应用程序忽略了。如果应用
//程序需要使用p_context则不需要这行代码
UNUSED_PARAMETER(p_context);
/* 开机按键检测处理 */
detect_button();
/* 电池电量检测 */
CalculateBatteryPower();
/* 充电状态检测 */
detect_charging_status();
static uint16_t delay_open = 0;
if(POWER_OPEN == DeviceState && delay_open != 70 && delay_open++ >60 )
{
//acquisition_start();
stimulate_start();
delay_open = 70;
}
}
/********************************************************************
* name : void AppTimersInit(void)
* description : 初始化APP定时器模块、创建APP定时器
* Input : void
* Output : void
* Return :
********************************************************************/
void AppTimersInit(void)
{
ret_code_t err_code = app_timer_init();//初始化APP定时器模块
APP_ERROR_CHECK(err_code);
err_code = app_timer_create(&detect_button_100ms,
APP_TIMER_MODE_REPEATED,
Hundredms_handler);
APP_ERROR_CHECK(err_code);
}
/********************************************************************
* name : void ApplicationTimersStart(void)
* description : 启动已经创建的的APP定时器
* Input : void
* Output : void
* Return :
********************************************************************/
void ApplicationTimersStart(void)
{
ret_code_t err_code;
err_code = app_timer_start(detect_button_100ms, DETECT_BUTTON, NULL);
APP_ERROR_CHECK(err_code);
}
/********************************************************************
* name : void PwmDACInit(void)
* description : 控制DAC的pwm初始化
* Input : void
* Output : void
* Return :
********************************************************************/
void PwmDACInit(void)
{
//定义PWM初始化配置结构体并初始化参数
nrfx_pwm_config_t const config0 =
{
.output_pins =
{
PWM_DAC_GPIO, //通道0映射到P WM_DAC_GPIO空闲状态输出低电平
NRFX_PWM_PIN_NOT_USED , //通道1不使用
NRFX_PWM_PIN_NOT_USED , //通道2不使用
NRFX_PWM_PIN_NOT_USED //通道3不使用
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
.base_clock = NRF_PWM_CLK_1MHz, //PWM时钟频率设置为1MHz
.count_mode = NRF_PWM_MODE_UP, //向上计数模式
.top_value = CYCLE_CALUE, //该值为周期值
.load_mode = NRF_PWM_LOAD_COMMON, //通用模式
.step_mode = NRF_PWM_STEP_AUTO //序列中的周期自动推进
};
APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm_dac, &config0, NULL));//初始化PWM
}
/********************************************************************
* name : void PwmDACPlay(void)
* description : 播放充能PWM
* Input : void
* Output : void
* Return :
********************************************************************/
void PwmDACPlay(void)
{
//定义PWM播放序列播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
nrf_pwm_sequence_t const seq =
{
.values.p_common = dac_values,//指向PWM序列
.length = NRF_PWM_VALUES_LENGTH(dac_values),//PWM序列中包含的周期个数
.repeats = 0, //序列中周期重复次数为0
.end_delay = 0 //序列后不插入延时
};
//启动PWM序列播放flags设置为NRFX_PWM_FLAG_LOOP序列播放完成后自动触发任务重新播放
(void)nrfx_pwm_simple_playback(&m_pwm_dac, &seq, 1, NRFX_PWM_FLAG_LOOP);
}
void SetPWMValues(uint16_t tempvalue)
{
*dac_values = CYCLE_CALUE - tempvalue;
}
/********************************************************************
* name : void PwmDACStop(void)
* description : 停止播放充能PWM
* Input : void
* Output : void
* Return :
********************************************************************/
void PwmDACStop(void)
{
nrfx_pwm_stop(&m_pwm_dac,1);
}
/********************************************************************
* name : void pwm0_common_init(void)
* description : 电流控制PWM初始化
* Input : void
* Output : void
* Return :
********************************************************************/
void pwm0_common_init(void)
{
//定义PWM初始化配置结构体并初始化参数
nrfx_pwm_config_t const config0 =
{
.output_pins =
{
BASE_WAVE_06_PIN,
BASE_WAVE_07_PIN,
BASE_WAVE_08_PIN,
NRFX_PWM_PIN_NOT_USED
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
.base_clock = NRF_PWM_CLK_1MHz, //PWM时钟频率设置为16MHz
.count_mode = NRF_PWM_MODE_UP, //向上计数模式
.top_value = 0, //使用波形装载模式时,该值被忽略
.load_mode = NRF_PWM_LOAD_WAVE_FORM, //独立装载模式
.step_mode = NRF_PWM_STEP_AUTO //序列中的周期自动推进
};
//初始化PWM
APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm0, &config0, NULL));
/////////////
//pwm0_play();
}
/********************************************************************
* name : void pwm0_play(void)
* description : 电流控制PWM开始播放
* Input : void
* Output : void
* Return :
********************************************************************/
void pwm0_play(void)
{
//定义PWM播放序列播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
nrf_pwm_sequence_t const seq0 =
{
.values.p_wave_form = seq0_current_values,//指向PWM序列
.length = NRF_PWM_VALUES_LENGTH(seq0_current_values),//PWM序列中包含的周期个数
.repeats = 0, //序列中周期重复次数为0
.end_delay = 0 //序列后不插入延时
};
//启动PWM序列播放flags设置为NRFX_PWM_FLAG_LOOP序列播放完成后自动触发任务重新播放
//如改为NRFX_PWM_FLAG_STOP则播放结束后PWM停止
(void)nrfx_pwm_simple_playback(&m_pwm0, &seq0, 1,
NRFX_PWM_FLAG_LOOP);
}
void pwm0_stop(void)
{
nrfx_pwm_stop(&m_pwm0, 1);
}
/********************************************************************
* name : void pwm2_common_init(void)
* description : 电流控制PWM初始化
* Input : void
* Output : void
* Return :
********************************************************************/
void pwm2common_init(void)
{
//定义PWM初始化配置结构体并初始化参数
nrfx_pwm_config_t const config0 =
{
.output_pins =
{
BOOST_VOLTAGE_CONTROL_PIN,
NRFX_PWM_PIN_NOT_USED,
NRFX_PWM_PIN_NOT_USED,
NRFX_PWM_PIN_NOT_USED
},
.irq_priority = APP_IRQ_PRIORITY_LOWEST,//中断优先级
.base_clock = NRF_PWM_CLK_16MHz, //PWM时钟频率设置为16MHz
.count_mode = NRF_PWM_MODE_UP, //向上计数模式
.top_value = 0, //使用波形装载模式时,该值被忽略
.load_mode = NRF_PWM_LOAD_WAVE_FORM, //独立装载模式
.step_mode = NRF_PWM_STEP_AUTO //序列中的周期自动推进
};
//初始化PWM
APP_ERROR_CHECK(nrfx_pwm_init(&m_pwm2, &config0, NULL));
/////////////
//pwm2_play();
}
/********************************************************************
* name : void pwm2_play(void)
* description : 电流控制PWM开始播放
* Input : void
* Output : void
* Return :
********************************************************************/
void pwm2_play(void)
{
//定义PWM播放序列播放序列包含了PWM序列的起始地址、大小和序列播放控制描述
nrf_pwm_sequence_t const seq2 =
{
.values.p_wave_form = seq2_current_values,//指向PWM序列
.length = NRF_PWM_VALUES_LENGTH(seq2_current_values),//PWM序列中包含的周期个数
.repeats = 0, //序列中周期重复次数为0
.end_delay = 0 //序列后不插入延时
};
//启动PWM序列播放flags设置为NRFX_PWM_FLAG_LOOP序列播放完成后自动触发任务重新播放
//如改为NRFX_PWM_FLAG_STOP则播放结束后PWM停止
(void)nrfx_pwm_simple_playback(&m_pwm2, &seq2, 1,
NRFX_PWM_FLAG_LOOP);
}
void pwm2_stop(void)
{
nrfx_pwm_stop(&m_pwm2, 1);
}
/********************************************************************
* name : void GpioteInit(void)
* description : 刺激的任务GPIOTE初始化
* Input : void
* Output : void
* Return :
********************************************************************/
void GpioteInit(void)
{
}
/********************************************************************
* name : void PPIPwmInit(void)
* description : 刺激PWM的PPI初始化
* Input : void
* Output : void
* Return :
********************************************************************/
void PPIPwmInit(void)
{
}
/*************************** END OF FILE ***************************/