/******************************************************************** 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 ***************************/