#include "ENS1_TIMER.h" #include "ENS_CURRENT_CALIBRATION.h" #include "ENS1_CLOCK.h" #include uint8_t ems_control_count = 0; // 电刺激控制计数器 uint8_t ems_state = 0; // 电刺激状态:0=关闭,1=开启 uint16_t time_count = 0; void TIMER0_Init(uint32_t Int_Period) //形参,输入中断触发周期 (单位ms) { PCLK_Enable(TIMER0_PCLK_EN); NVIC_DisableIRQ(TIMER0_IRQn); NVIC_ClearPendingIRQ(TIMER0_IRQn); CMSDK_timer_Init(CMSDK_TIMER0,(uint32_t)(APB_Clock_Freq / 1000 *Int_Period) , 1); // NVIC_EnableIRQ(TIMER0_IRQn); } void TIMER1_Init(uint32_t Int_Period) { PCLK_Enable(TIMER1_PCLK_EN); NVIC_DisableIRQ(TIMER1_IRQn); NVIC_ClearPendingIRQ(TIMER1_IRQn); CMSDK_timer_Init(CMSDK_TIMER1,(uint32_t)(APB_Clock_Freq / 1000 * Int_Period) , 1); // 1ms NVIC_EnableIRQ(TIMER1_IRQn); } /*使能定时器中断*/ void CMSDK_timer_EnableIRQ(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { CMSDK_TIMER->CTRL |= CMSDK_TIMER_CTRL_IRQEN_Msk; } /*禁止定时器中断*/ void CMSDK_timer_DisableIRQ(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { CMSDK_TIMER->CTRL &= ~CMSDK_TIMER_CTRL_IRQEN_Msk; } /*启动定时器*/ void CMSDK_timer_StartTimer(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { CMSDK_TIMER->CTRL |= CMSDK_TIMER_CTRL_EN_Msk; } /*停止定时器*/ void CMSDK_timer_StopTimer(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { CMSDK_TIMER->CTRL &= ~CMSDK_TIMER_CTRL_EN_Msk; } /*获取定时器当前值*/ uint32_t CMSDK_timer_GetValue(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { return CMSDK_TIMER->VALUE; } /*设置定时器当前值*/ void CMSDK_timer_SetValue(CMSDK_TIMER_TypeDef *CMSDK_TIMER, uint32_t value) { CMSDK_TIMER->VALUE = value; } /*获取定时器重装载值*/ uint32_t CMSDK_timer_GetReload(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { return CMSDK_TIMER->RELOAD; } /*设置定时器重装载值*/ void CMSDK_timer_SetReload(CMSDK_TIMER_TypeDef *CMSDK_TIMER, uint32_t value) { CMSDK_TIMER->RELOAD = value; } void CMSDK_timer_ClearIRQ(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { CMSDK_TIMER->INTCLEAR = CMSDK_TIMER_INTCLEAR_Msk; } /*获取定时器中断状态*/ uint32_t CMSDK_timer_StatusIRQ(CMSDK_TIMER_TypeDef *CMSDK_TIMER) { return CMSDK_TIMER->INTSTATUS; } /*初始化定时器*/ void CMSDK_timer_Init(CMSDK_TIMER_TypeDef *CMSDK_TIMER, uint32_t reload, uint8_t irq_en) { uint32_t new_ctrl = 0; CMSDK_TIMER->VALUE = reload; CMSDK_TIMER->RELOAD = reload; if (irq_en!=0) new_ctrl |= CMSDK_TIMER_CTRL_IRQEN_Msk; /* non zero - enable IRQ */ new_ctrl |= CMSDK_TIMER_CTRL_EN_Msk; /* enable timer */ CMSDK_TIMER->CTRL = new_ctrl; } /** * * @param *CMSDK_TIMER Timer Pointer * @param reload The value to which the timer is to be set after an underflow has occurred * @param irq_en Defines whether the timer IRQ is to be enabled * @return none * @brief Initialises the timer to use the external clock and specifies the timer reload value and whether IRQ is enabled or not. */ void CMSDK_timer_Init_ExtClock(CMSDK_TIMER_TypeDef *CMSDK_TIMER, uint32_t reload,uint32_t irq_en) { CMSDK_TIMER->CTRL = 0; CMSDK_TIMER->VALUE = reload; CMSDK_TIMER->RELOAD = reload; if (irq_en!=0) /* non zero - enable IRQ */ CMSDK_TIMER->CTRL = (CMSDK_TIMER_CTRL_IRQEN_Msk | CMSDK_TIMER_CTRL_SELEXTCLK_Msk |CMSDK_TIMER_CTRL_EN_Msk); else { /* zero - do not enable IRQ */ CMSDK_TIMER->CTRL = ( CMSDK_TIMER_CTRL_EN_Msk | CMSDK_TIMER_CTRL_SELEXTCLK_Msk); /* enable timer */ } } /** * * @brief Initialises the timer to use the internal clock but with an external enable. It also specifies the timer reload value and whether IRQ is enabled or not. * * @param *CMSDK_TIMER Timer Pointer * @param reload The value to which the timer is to be set after an underflow has occurred * @param irq_en Defines whether the timer IRQ is to be enabled * @return none * Timer 0 only * */ void CMSDK_timer_Init_ExtEnable(CMSDK_TIMER_TypeDef *CMSDK_TIMER, uint32_t reload,uint32_t irq_en) { CMSDK_TIMER->CTRL = 0; CMSDK_TIMER->VALUE = reload; CMSDK_TIMER->RELOAD = reload; if (irq_en!=0) /* non zero - enable IRQ */ CMSDK_TIMER->CTRL = (CMSDK_TIMER_CTRL_IRQEN_Msk | CMSDK_TIMER_CTRL_SELEXTEN_Msk | CMSDK_TIMER_CTRL_EN_Msk); else{ /* zero - do not enable IRQ */ CMSDK_TIMER->CTRL = ( CMSDK_TIMER_CTRL_EN_Msk | CMSDK_TIMER_CTRL_SELEXTEN_Msk); /* enable timer */ } } /*DUAL Timer driver functions*/ /** * * @param *CMSDK_DUALTIMER DUAL Timer Pointer * @return none * * @brief Start timer in dual timers. */ /* Start Timer */ void CMSDK_dualtimer_start(CMSDK_DUALTIMER_TypeDef *CMSDK_DUALTIMERx) { CMSDK_DUALTIMERx->TimerControl |= CMSDK_DUALTIMER_CTRL_EN_Msk; } /** * * @param *CMSDK_DUALTIMER DUAL Timer Pointer * @return none * * @brief Stop timer in dual timers. */ /* Stop Timer */ void CMSDK_dualtimer_stop(CMSDK_DUALTIMER_TypeDef *CMSDK_DUALTIMERx) { CMSDK_DUALTIMERx->TimerControl &= ~CMSDK_DUALTIMER_CTRL_EN_Msk; } /** * * @param *CMSDK_DUALTIMER DUAL Timer Pointer * @return none * * @brief Clear the interrupt request in dual timers. */ /* Clear the Interrupt */ void CMSDK_dualtimer_irq_clear(CMSDK_DUALTIMER_TypeDef *CMSDK_DUALTIMERx) { CMSDK_DUALTIMERx->TimerIntClr = 0; } /** * * @param *CMSDK_DUALTIMER DUAL Timer Pointer * @return none * * @brief Setup Free running mode in dual timers. */ /* Free running timer mode */ void CMSDK_dualtimer_setup_freerunning(CMSDK_DUALTIMER_TypeDef *CMSDK_DUALTIMERx, unsigned int cycle, unsigned int prescale, unsigned int interrupt, unsigned int size) { int ctrl_val; CMSDK_DUALTIMERx->TimerControl = 0; /* Disable during programming */ /* Previous timer activities might have trigger interrupt flag, so need to clear it */ CMSDK_dualtimer_irq_clear(CMSDK_DUALTIMERx); CMSDK_DUALTIMERx->TimerLoad = cycle; ctrl_val = (prescale & 0x3) << CMSDK_DUALTIMER_CTRL_PRESCALE_Pos | (interrupt & 0x1) << CMSDK_DUALTIMER_CTRL_INTEN_Pos | (size & 0x1) << CMSDK_DUALTIMER_CTRL_SIZE_Pos | CMSDK_DUALTIMER_CTRL_EN_Msk; CMSDK_DUALTIMERx->TimerControl = ctrl_val; } /** * * @param *CMSDK_DUALTIMER DUAL Timer Pointer * @return none * * @brief Setup Periodic mode in dual timers. */ /* Periodic timer mode */ void CMSDK_dualtimer_setup_periodic(CMSDK_DUALTIMER_TypeDef *CMSDK_DUALTIMERx, unsigned int cycle, unsigned int prescale, unsigned int interrupt, unsigned int size) { int ctrl_val; CMSDK_DUALTIMERx->TimerControl = 0; /* Disable during programming */ /* Previous timer activities might have trigger interrupt flag, so need to clear it */ CMSDK_dualtimer_irq_clear(CMSDK_DUALTIMERx); CMSDK_DUALTIMERx->TimerLoad = cycle; ctrl_val = (prescale & 0x3) << CMSDK_DUALTIMER_CTRL_PRESCALE_Pos | (interrupt & 0x1) << CMSDK_DUALTIMER_CTRL_INTEN_Pos | (size & 0x1) << CMSDK_DUALTIMER_CTRL_SIZE_Pos | CMSDK_DUALTIMER_CTRL_EN_Msk | CMSDK_DUALTIMER_CTRL_MODE_Msk; CMSDK_DUALTIMERx->TimerControl = ctrl_val; } /** * * @param *CMSDK_DUALTIMER DUAL Timer Pointer * @return none * * @brief Setup One shot mode in dual timers. */ /* One shot timer mode */ void CMSDK_dualtimer_setup_oneshot(CMSDK_DUALTIMER_TypeDef *CMSDK_DUALTIMERx, unsigned int cycle, unsigned int prescale, unsigned int interrupt, unsigned int size) { int ctrl_val; CMSDK_DUALTIMERx->TimerControl = 0; /* Disable during programming */ /* Previous timer activities might have trigger interrupt flag, so need to clear it */ CMSDK_dualtimer_irq_clear(CMSDK_DUALTIMERx); CMSDK_DUALTIMERx->TimerLoad = cycle; ctrl_val = (prescale & 0x3) << CMSDK_DUALTIMER_CTRL_PRESCALE_Pos | (interrupt & 0x1) << CMSDK_DUALTIMER_CTRL_INTEN_Pos | (size & 0x1) << CMSDK_DUALTIMER_CTRL_SIZE_Pos | CMSDK_DUALTIMER_CTRL_EN_Msk | CMSDK_DUALTIMER_CTRL_ONESHOT_Msk; CMSDK_DUALTIMERx->TimerControl = ctrl_val; } /*RTC driver functions*/ /** * * @param *CMSDK_RTC RTC Pointer * @return none * * @brief Initialize RTC Calender */ void CMSDK_RTC_Init_Calender(uint16_t prescaler, uint8_t data_mode, uint8_t hour_mode, uint32_t init_time, uint32_t init_date) { uint32_t new_reg_ctrl = 0; //wait for rtc prescaler sync ready while(!((CMSDK_RTC->SR & CMSDK_RTC_PRES_SYNC_READY_Msk) >> CMSDK_RTC_PRES_SYNC_READY_Pos)); //set prescaler CMSDK_RTC->PR = prescaler; //config data/hour mode if(data_mode != 0) new_reg_ctrl |= CMSDK_RTC_DATA_MODE_Msk; if(hour_mode != 0) new_reg_ctrl |= CMSDK_RTC_HOUR_MODE_Msk; CMSDK_RTC->CR = new_reg_ctrl; //wait for init sync ready while(!(CMSDK_RTC->SR & CMSDK_RTC_INIT_SYNC_READY_Msk)); //set INIT CMSDK_RTC->CR |= CMSDK_RTC_INIT_EN_Msk; //Set Initial Time & Date CMSDK_RTC->TR = init_time; CMSDK_RTC->DR = init_date; //Clear INIT bit CMSDK_RTC->CR &= ~CMSDK_RTC_INIT_EN_Msk; //wait for init sync ready while(!(CMSDK_RTC->SR & CMSDK_RTC_INIT_SYNC_READY_Msk)); return; } /** * * @param *CMSDK_RTC RTC Pointer * @return none * * @brief Config RTC Alarm */ void CMSDK_RTC_Config_Alarm(uint16_t prescaler, uint8_t data_mode, uint8_t hour_mode, uint32_t init_time, uint32_t init_date, uint32_t alarm_time, uint32_t alarm_date) { uint32_t new_reg_ctrl = 0; //wait for rtc prescaler sync ready while(!((CMSDK_RTC->SR & CMSDK_RTC_PRES_SYNC_READY_Msk) >> CMSDK_RTC_PRES_SYNC_READY_Pos)); //set prescaler CMSDK_RTC->PR = prescaler; //config data/hour mode if(data_mode != 0) new_reg_ctrl |= CMSDK_RTC_DATA_MODE_Msk; if(hour_mode != 0) new_reg_ctrl |= CMSDK_RTC_HOUR_MODE_Msk; CMSDK_RTC->CR = new_reg_ctrl; //wait for init sync ready while(!(CMSDK_RTC->SR & CMSDK_RTC_INIT_SYNC_READY_Msk)); //set INIT CMSDK_RTC->CR |= CMSDK_RTC_INIT_EN_Msk; //Set Initial Time & Date CMSDK_RTC->TR = init_time; CMSDK_RTC->DR = init_date; //Set Alarm Time & Date CMSDK_RTC->TAR = alarm_time; CMSDK_RTC->DAR = alarm_date; //Alarm enabled CMSDK_RTC->CR |= CMSDK_RTC_ALARM_EN_Msk; //Clear INIT bit CMSDK_RTC->CR &= ~CMSDK_RTC_INIT_EN_Msk; return; } /** * * @param *CMSDK_RTC RTC Pointer * @return none * * @brief Config Period Wakeup */ void CMSDK_RTC_Config_PeriodWake(uint8_t clock_sel, uint16_t prescaler, uint16_t period_time) { if(clock_sel) { CMSDK_RTC->CR |= CMSDK_RTC_WUT_CLK_EN_Msk; //wait for rtc prescaler sync ready while(!((CMSDK_RTC->SR & CMSDK_RTC_PRES_SYNC_READY_Msk) >> CMSDK_RTC_PRES_SYNC_READY_Pos)); //set prescaler CMSDK_RTC->PR = prescaler; } else { CMSDK_RTC->CR &= ~CMSDK_RTC_WUT_CLK_EN_Msk; //wait for wut prescaler sync ready while(!((CMSDK_RTC->SR & CMSDK_RTC_WUT_PRES_SYNC_READY_Msk) >> CMSDK_RTC_WUT_PRES_SYNC_READY_Pos)); //set prescaler CMSDK_RTC->WPR = prescaler; } //wait for wut value sync ready while(!((CMSDK_RTC->SR & CMSDK_RTC_WUT_VAL_SYNC_READY_Msk) >> CMSDK_RTC_WUT_VAL_SYNC_READY_Pos)); //set Wakeup time register CMSDK_RTC->WTR = period_time; //Config CR with Periodic Wakeup timer enabled CMSDK_RTC->CR |= CMSDK_RTC_WUT_EN_Msk; return; } void Fuse_result(void) { // 获取时间标志位 Time_Flag_TypeDef* time_flags = Time_Manager_GetFlags(); // 处理电刺激(在主循环中运行) // 注意:这里不再直接调用EMS_Process(),而是通过状态控制 if (time_flags->T_1ms) { // 1ms周期任务 - 高频控制任务 time_count++; EMS_Process(); time_flags->T_1ms = 0; // 清除标志位 } // 基于时间标志位执行不同周期的任务 if (time_flags->T_2ms) { // 2ms周期任务 - 高频控制任务 time_flags->T_2ms = 0; // 清除标志位 } if (time_flags->T_10ms) { // 10ms周期任务 - 中频控制任务 time_flags->T_10ms = 0; // 清除标志位 } if (time_flags->T_100ms) { // 100ms周期任务 - 低频控制任务 time_flags->T_100ms = 0; // 清除标志位 } if (time_flags->T_1s) { GPIO_Overturn(GPIO_19); // 1s周期任务 - 超低频任务 ems_control_count++; // 每秒递增计数器 // 间断性放电控制逻辑 if (ems_control_count <= 10) { // 前10秒:开启电刺激 if (ems_state == 0) { ems_state = 1; EMS_Start(); // 启动电刺激 } // 处理电刺激 } else if (ems_control_count <= 20) { // 后10秒:关闭电刺激 if (ems_state == 1) { ems_state = 0; EMS_Stop(); // 停止电刺激 } } else { // 重置计数器,开始新的周期 ems_control_count = 0; } time_flags->T_1s = 0; // 清除标志位 } // 定时器中断处理在 TIMER0_Handler() 中 } // --------------------------------------------------------------- // // 时间管理全局变量 // --------------------------------------------------------------- // static Time_Flag_TypeDef g_time_flags = {0}; static Time_Counter_TypeDef g_time_counters = {0}; // --------------------------------------------------------------- // // 时间管理函数实现 // --------------------------------------------------------------- // /** * @brief 初始化时间管理器 */ void Time_Manager_Init(void) { // 清零所有标志位和计数器 memset(&g_time_flags, 0, sizeof(Time_Flag_TypeDef)); memset(&g_time_counters, 0, sizeof(Time_Counter_TypeDef)); } /** * @brief 时间管理处理函数(在定时器中断中调用) * 基于1ms定时器中断,实现不同时间周期的任务调度 */ void Time_Manager_Process(void) { // 所有计数器递增 g_time_counters.t_1ms++; g_time_counters.t_2ms++; g_time_counters.t_6ms++; g_time_counters.t_10ms++; g_time_counters.t_20ms++; g_time_counters.t_100ms++; g_time_counters.t_1s++; // 2ms控制周期 if (g_time_counters.t_1ms >= 1) { g_time_counters.t_1ms = 0; g_time_flags.T_1ms = 1; /* code */ } if (g_time_counters.t_2ms >= 2) { g_time_counters.t_2ms = 0; g_time_flags.T_2ms = 1; } // 6ms控制周期 if (g_time_counters.t_6ms >= 6) { g_time_counters.t_6ms = 0; g_time_flags.T_6ms = 1; } // 10ms控制周期 if (g_time_counters.t_10ms >= 10) { g_time_counters.t_10ms = 0; g_time_flags.T_10ms = 1; } // 20ms控制周期 if (g_time_counters.t_20ms >= 20) { g_time_counters.t_20ms = 0; g_time_flags.T_20ms = 1; } // 100ms控制周期 if (g_time_counters.t_100ms >= 100) { g_time_counters.t_100ms = 0; g_time_flags.T_100ms = 1; } // 1s控制周期 if (g_time_counters.t_1s >= 1000) { g_time_counters.t_1s = 0; g_time_flags.T_1s = 1; } Fuse_result(); } /** * @brief 获取时间标志位 * @return 时间标志位结构体指针 */ Time_Flag_TypeDef* Time_Manager_GetFlags(void) { return &g_time_flags; } /** * @brief 清除所有时间标志位 */ void Time_Manager_ClearFlags(void) { memset(&g_time_flags, 0, sizeof(Time_Flag_TypeDef)); } /** * @brief 重置时间管理器 */ void Time_Manager_Reset(void) { Time_Manager_Init(); } // --------------------------------------------------------------- // // TIMER0_IRQ // --------------------------------------------------------------- // uint32_t timer0_irq_occurred=0; uint32_t time_flag =0; void TIMER0_Handler(void){ CMSDK_TIMER0->INTCLEAR = 1; timer0_irq_occurred++; // 调用时间管理处理函数 Time_Manager_Process(); // 注意:GPIO翻转现在通过时间管理系统在主循环中处理 // 这里不再直接翻转GPIO,避免重复操作 } // --------------------------------------------------------------- // // TIMER1_IRQ // --------------------------------------------------------------- // uint32_t timer1_irq_occurred=0; void TIMER1_Handler(void){ CMSDK_TIMER1->INTCLEAR = 1; timer1_irq_occurred++; }