中断学习之timer_interrupt powerpc实现

本文详细解析了Linux内核中的时钟中断处理流程,包括如何响应时钟中断、更新时间戳、调度进程以及重新设置下次中断的时间等关键步骤。通过深入分析源代码,帮助读者理解Linux内核中时间管理和进程调度的核心机制。
#define DECREMENTER_EXCEPTION						      \
	START_EXCEPTION(Decrementer)					      \
	NORMAL_EXCEPTION_PROLOG;					      \
	lis     r0,TSR_DIS@h;           /* Setup the DEC interrupt mask */    \
	mtspr   SPRN_TSR,r0;		/* Clear the DEC interrupt */	      \
	addi    r3,r1,STACK_FRAME_OVERHEAD;				      \
	EXC_XFER_LITE(0x0900, timer_interrupt)

	
void timer_interrupt(struct pt_regs * regs)
	=>int cpu = smp_processor_id();
	=>if (atomic_read(&ppc_n_lost_interrupts) != 0)//如果还有未处理的外部中断处理函数,则处理
		do_IRQ(regs);
	=>old_regs = set_irq_regs(regs);//保存寄存器现场,注意old_regs是指针,指向现场全局寄存器的指针
		=>struct pt_regs *old_regs, **pp_regs = &__get_cpu_var(__irq_regs);//保存在__irq_regs全局变量里面,每个核一个
		old_regs = *pp_regs;
		*pp_regs = new_regs;
		return old_regs
	=>irq_enter();//中断计数加一,进入中断上下文
	=>while ((ticks = tb_ticks_since(per_cpu(last_jiffy, cpu))) >= tb_ticks_per_jiffy)
		per_cpu(last_jiffy, cpu) += tb_ticks_per_jiffy;
		account_process_time(regs);//#define account_process_time(regs)	update_process_times(user_mode(regs))
			=>scheduler_tick();//选择合适的进程,用于时钟中断返回继续调度
				=>curr->sched_class->task_tick(rq, curr);//.task_tick		= task_tick_fair
					=>struct sched_entity *se = &curr->se;
					=>for_each_sched_entity(se) {
						cfs_rq = cfs_rq_of(se);
						entity_tick(cfs_rq, se);
					}
		if (cpu != boot_cpuid)
			continue;
		tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
		if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
			tb_last_jiffy = tb_next_jiffy;
			do_timer(1);
			timer_recalc_offset(tb_last_jiffy);
			timer_check_rtc();
		}
	=>next_dec = tb_ticks_per_jiffy - ticks;
	=>set_dec(next_dec);//设置DEC寄存器,用于触发下一次的时钟中断
	=>irq_exit();
	=>set_irq_regs(old_regs);

 

如下两个人的博客都挺好的

 

时钟中断(1)
https://blog.youkuaiyun.com/wrx1721267632/article/details/50527595


把握linux内核设计思想(六):内核时钟中断
https://blog.youkuaiyun.com/shallnet/article/details/47132861

[收藏]时钟中断(Timer Interrupt)与 Linux内核调度
https://blog.youkuaiyun.com/don_chiang709/article/details/89181399

 

/** * @file main.c * @author Nations * @version v1.0.0 * * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. */ #define HSE_VALUE (40000000) #include <stdio.h> #include "main.h" #include "sys_var.h" #include "key.h" #include "n32g43x_gpio.h" int main(void) { /* System Clocks Configuration */ RCC_Configuration(); /* NVIC configuration */ NVIC_Configuration(); /* Configure the GPIO ports */ GPIO_Configuration(); /* USART configuration */ USART_Configuration(); /* TIM Configuration */ TIM_Configuration(); DelayMs(200);//待上电稳定 ADC_Initial(); //检测上电类型 if(1) { /* Check if the system has resumed from solft reset */ if (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_SFTRSTF) != RESET) { /* solft reset flag set */ printf("\n\rsystem solft reset\n\r\n\r"); /* Clear reset flags */ RCC_ClrFlag(); } else { /* WWDGRST flag is not set */ printf("\n\rnormal power on\n\r\n\r"); } } PrintSystemClock(); gpio_func_init(); printf("\n\r seat 8 io project\n\rbuild datetime : %s %s\n\r",__DATE__,__TIME__); //printf("\n\rwhile\n\r"); strength_Led_state = 0; while (1) { /* running led*/ { if(IsTimeOut(&LedTimer)) { TimeOutSet(&LedTimer,1000); GpioToggle(LED); } } #ifdef FY_1KEY_3LED /* mode led */ set_led_mode(mode_state); /* key led */ GpioSetOut(LED5,1); // if(!GpioGet(KEY6)) // { // GpioSetOut(LED5,1); // } // else // { // GpioSetOut(LED5,0); // } #endif /* key func */ //if (IsTimeOut(&KeyScanTimer)) { keyScan(); if( key_mode == KEY_MODE_ADC) { AdcKeyFunc(); //TimeOutSet(&KeyScanTimer,50); } if( key_mode == KEY_MODE_GPIO) { GpioKeyFunc(); //TimeOutSet(&KeyScanTimer,80); } } } } /** * @} */ /** * @} */ #include "app.h" #include "key.h" #include "sys_var.h" #ifdef FY_1KEY_3LED void set_led_mode(uint8_t mode) { if(mode == 0x1) { GpioSetOut(LED4,1); GpioSetOut(LED3,0); GpioSetOut(LED2,0); } else if(mode == 0x2) { GpioSetOut(LED4,1); GpioSetOut(LED3,1); GpioSetOut(LED2,0); } else if(mode == 0x3) { GpioSetOut(LED4,1); GpioSetOut(LED3,1); GpioSetOut(LED2,1); } else { GpioSetOut(LED4,0); GpioSetOut(LED3,0); GpioSetOut(LED2,0); } } #endif void air_bag_init(void) { GpioInitOut( SW1 ); GpioInitOut( SW2 ); GpioInitOut( SW3 ); GpioInitOut( SW4 ); GpioInitOut( SW5 ); GpioInitOut( SW6 ); GpioInitOut( SW7 ); GpioInitOut( SW8 ); GpioInitOut( SW9 ); GpioInitOut( SW10 ); //GpioInitOut( SW11 ); //GpioInitOut( SW12 ); GpioInitOut( POWER_FB ); GpioInitOut( POWER_EN ); GpioInitOut( MOTOR_PWM); GpioSetOut( SW1 ,0); GpioSetOut( SW2 ,0); GpioSetOut( SW3 ,0); GpioSetOut( SW4 ,0); GpioSetOut( SW5 ,0); GpioSetOut( SW6 ,0); GpioSetOut( SW7 ,0); GpioSetOut( SW8 ,0); GpioSetOut( SW9 ,0); GpioSetOut( SW10 ,0); //GpioSetOut( SW11 ,0); //GpioSetOut( SW12 ,0); GpioSetOut( POWER_FB ,1); GpioSetOut( POWER_EN ,0); GpioSetOut( MOTOR_PWM,0); } void air_bag_idle(void) { POWER_OFF; MOTOR_OFF; GpioSetOut( SW1 ,0); GpioSetOut( SW2 ,0); GpioSetOut( SW3 ,0); GpioSetOut( SW4 ,0); GpioSetOut( SW5 ,0); GpioSetOut( SW6 ,0); GpioSetOut( SW7 ,0); GpioSetOut( SW8 ,0); GpioSetOut( SW9 ,0); GpioSetOut( SW10 ,0); //GpioSetOut( SW11 ,0); //GpioSetOut( SW12 ,0); } void air_bag_out(void) { GpioSetOut( SW1 ,0); GpioSetOut( SW2 ,0); GpioSetOut( SW3 ,0); GpioSetOut( SW4 ,0); GpioSetOut( SW5 ,0); GpioSetOut( SW6 ,0); GpioSetOut( SW7 ,0); GpioSetOut( SW8 ,0); GpioSetOut( SW9 ,0); GpioSetOut( SW10 ,0); } void gpio_func_init(void) { #ifdef FY_1KEY_3LED GpioInitIn(KEY6); #elif defined(FY_1KEY_NOLED) GpioInitIn(KEY4); #endif #ifdef FY_1KEY_3LED GpioInitOut(LED); GpioSetOut(LED,0); GpioInitOut(LED2); GpioSetOut(LED2,0); GpioInitOut(LED3); GpioSetOut(LED3,0); GpioInitOut(LED4); GpioSetOut(LED4,0); GpioInitOut(LED5); GpioSetOut(LED5,0); #endif air_bag_init(); } void AdcKeyFunc(void) { static unsigned char last_adckey_code = 0; static unsigned char last_adckey_type = 0; if(( last_adckey_code != key.KeyEventCode || last_adckey_type != key.KeyEventType) ) { if(key.KeyEventCode > 0 && key.KeyEventType > 0 ) printf("\n\rADC key KeyEventCode : %d KeyEventType : %d \n\r",key.KeyEventCode , key.KeyEventType); if( key.KeyEventCode == ADC_KEY_CODE_UP && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //上充下放 POWER_ON; MOTOR_ON; #ifdef FY_SEAT_10 WAIST_1_IN; WAIST_2_OUT; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_DOWN && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //下充上放 POWER_ON; MOTOR_ON; #ifdef FY_SEAT_10 WAIST_2_IN; WAIST_1_OUT; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_LEFT && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //全充 POWER_ON; MOTOR_ON; #ifdef FY_SEAT_10 WAIST_1_IN; WAIST_2_IN; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_RIGHT && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //全放 POWER_ON; MOTOR_OFF; #ifdef FY_SEAT_10 WAIST_1_OUT; WAIST_2_OUT; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_OK) { if( key.KeyEventType == KEYTYPE_HOLD) { printf("\n\rkey hold\n\r"); TimeOutSet(&ModeSwitch_Timer,1000); if(mode_state) { mode_state = 0; } else { mode_state = 1; } air_bag_ctrl.current_mode = mode_state; air_bag_ctrl.schedule_table_pntr = air_bag_schedule_table[air_bag_ctrl.current_mode]; air_bag_ctrl.current_schedule_index = 0; air_bag_ctrl.last_schedule_index = 0; air_bag_ctrl.current_schedule_duration = 0; TimeOutSet(&StopWork_Timer,work_mode_total_duration[mode_state]); statck_init(); air_bag_idle(); statck_push(&air_bag_ctrl.schedule_table_pntr[0]); printf(" air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } else if( key.KeyEventType == KEYTYPE_SINGLE) { //printf("\n\radc key down \n\r"); TimeOutSet(&ModeSwitch_Timer,1000); if(mode_state) { mode_state = (mode_state + 1) % SEAT_FUNC_MODE_AMOUNT ; if(mode_state == 0) mode_state = 1; } air_bag_ctrl.current_mode = mode_state; air_bag_ctrl.schedule_table_pntr = air_bag_schedule_table[air_bag_ctrl.current_mode]; air_bag_ctrl.current_schedule_index = 0; air_bag_ctrl.last_schedule_index = 0; air_bag_ctrl.current_schedule_duration = 0; TimeOutSet(&StopWork_Timer,work_mode_total_duration[mode_state]); statck_init(); air_bag_init(); statck_push(&air_bag_ctrl.schedule_table_pntr[0]); printf(" air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } #ifdef FY_SEAT_10 WAIST_1_IDLE; WAIST_2_IDLE; #endif } else { //无按键动作 if(!IsTimeOut(&Out_15S_Before_Stop_Timer)) { { //放气15S POWER_ON; MOTOR_OFF; air_bag_idle(); } } else if(mode_state == 0) { //闭气 air_bag_idle(); POWER_OFF; MOTOR_OFF; #ifdef FY_SEAT_10 WAIST_1_IDLE; WAIST_2_IDLE; #endif } } last_adckey_code = key.KeyEventCode; last_adckey_type = key.KeyEventType; } // else if(mode_state) //循环工作中 // { // if( key.KeyEventCode == ADC_KEY_CODE_OK && key.KeyEventType == KEYTYPE_LONGPRES) // { // //退出循环工作 // air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; // air_bag_ctrl.autoWorkFlag = 0; // TimeOutSet(&Out_15S_Before_Stop_Timer,SECOND_15); // } // } } void GpioKeyFunc(void) { static unsigned char last_key_code = 0; static unsigned char last_key_type = 0; /* LED KEY */ if(last_key_code != key.KeyEventCode || last_key_type != key.KeyEventType) { if(key.KeyEventCode > 0 && key.KeyEventType > 0 ) printf("\n\rGPIO key KeyEventCode : %d KeyEventType : %d \n\r",key.KeyEventCode , key.KeyEventType); if( key.KeyEventCode == GPIO_KEY_CODE_K6 && key.KeyEventType == KEYTYPE_SINGLE) { //printf("\n\rgpio key down \n\r"); TimeOutSet(&ModeSwitch_Timer,1000); //if(mode_state) { mode_state = (mode_state + 1) % 4 ; } air_bag_ctrl.current_mode = mode_state; air_bag_ctrl.schedule_table_pntr = air_bag_schedule_table[air_bag_ctrl.current_mode]; air_bag_ctrl.current_schedule_index = 0; air_bag_ctrl.last_schedule_index = 0; air_bag_ctrl.current_schedule_duration = 0; TimeOutSet(&StopWork_Timer,work_mode_total_duration[mode_state]); statck_init(); air_bag_init(); statck_push(&air_bag_ctrl.schedule_table_pntr[0]); // printf(" air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } last_key_code = key.KeyEventCode; last_key_type = key.KeyEventType; } } /** * @file n32g43x_it.c * @author Nations * @version v1.0.0 * * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved. */ #include <stdio.h> #include "n32g43x_it.h" #include "bsp.h" #include "sys_var.h" #include "util.h" extern uint8_t mode_state; /** @addtogroup N32G43X_StdPeriph_Template * @{ */ /******************************************************************************/ /* Cortex-M4 Processor Exceptions Handlers */ /******************************************************************************/ /** * @brief This function handles NMI exception. */ void NMI_Handler(void) { } /** * @brief This function handles Hard Fault exception. */ void HardFault_Handler(void) { /* Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** * @brief This function handles Memory Manage exception. */ void MemManage_Handler(void) { /* Go to infinite loop when Memory Manage exception occurs */ while (1) { } } /** * @brief This function handles Bus Fault exception. */ void BusFault_Handler(void) { /* Go to infinite loop when Bus Fault exception occurs */ while (1) { } } /** * @brief This function handles Usage Fault exception. */ void UsageFault_Handler(void) { /* Go to infinite loop when Usage Fault exception occurs */ while (1) { } } /** * @brief This function handles SVCall exception. */ void SVC_Handler(void) { } /** * @brief This function handles Debug Monitor exception. */ void DebugMon_Handler(void) { } /** * @brief This function handles SysTick Handler. */ void SysTick_Handler(void) { } /** * @brief This function handles TIM2 update interrupt request. */ void TIM2_IRQHandler(void) { if (TIM_GetIntStatus(TIM2, TIM_INT_UPDATE) != RESET) //1ms 定时中断 { TIM_ClrIntPendingBit(TIM2, TIM_INT_UPDATE);//重置定时器 //软定时器滴答 TimerTickHandler(); if( (air_bag_ctrl.current_mode != SEAT_FUNC_MODE_IDLE && !IsTimeOut(&StopWork_Timer) && IsTimeOut(&ModeSwitch_Timer) )) { int stack_idx; for(stack_idx = 0;stack_idx < STACK_SIZE;stack_idx++) { if (schedule_stack[stack_idx].IsUsed) { if (schedule_stack[stack_idx].InDuration > 0) { //充气 POWER_ON; air_bag_set_in(schedule_stack[stack_idx].OpAirBagGroup); schedule_stack[stack_idx].InDuration --; } else { if (schedule_stack[stack_idx].OutDuration > 0) { //放气 POWER_ON; air_bag_set_out(schedule_stack[stack_idx].OpAirBagGroup); schedule_stack[stack_idx].OutDuration --; if (schedule_stack[stack_idx].OutDuration == 0) { //停止放气 //放气完毕,出栈 //printf("out end idx %d\r\n",schedule_stack[stack_idx].sch_idx); statck_pop(stack_idx); if(0) { int i; for (i = 0; i < STACK_SIZE; i++) { //printf(" st_idx : %d is_used : %d sch_idx : %d InD :%d OutD :%d NexD : %d \r\n",i,schedule_stack[i].IsUsed,schedule_stack[i].sch_idx,schedule_stack[i].InDuration,schedule_stack[i].OutDuration,schedule_stack[i].NextOpDuration); } } } } } if (schedule_stack[stack_idx].NextOpDuration > 0) { schedule_stack[stack_idx].NextOpDuration --; //下一动作入栈 if (schedule_stack[stack_idx].NextOpDuration == 0) { if(schedule_stack[stack_idx].sch_idx + 1 <= schedule_stack[stack_idx].sch_idx_max) { statck_push(&air_bag_ctrl.schedule_table_pntr[schedule_stack[stack_idx].sch_idx+1]); //printf("next op idx %d\r\n",schedule_stack[stack_idx].sch_idx + 1); { int i; for (i = 0; i < STACK_SIZE; i++) { //printf(" st_idx : %d is_used : %d sch_idx : %d InD :%d OutD :%d NexD : %d \r\n",i,schedule_stack[i].IsUsed,schedule_stack[i].sch_idx,schedule_stack[i].InDuration,schedule_stack[i].OutDuration,schedule_stack[i].NextOpDuration); } } } else { statck_push(&air_bag_ctrl.schedule_table_pntr[0]); //printf("cycle end return 0 idx %d\r\n",schedule_stack[stack_idx].sch_idx); { int i; for (i = 0; i < STACK_SIZE; i++) { //printf(" st_idx : %d is_used : %d sch_idx : %d InD :%d OutD :%d NexD : %d \r\n",i,schedule_stack[i].IsUsed,schedule_stack[i].sch_idx,schedule_stack[i].InDuration,schedule_stack[i].OutDuration,schedule_stack[i].NextOpDuration); } } } } } if(schedule_stack[stack_idx].InDuration == 0 && schedule_stack[stack_idx].OutDuration == 0 && schedule_stack[stack_idx].NextOpDuration == 0) { statck_pop(stack_idx); } } } } else if( (air_bag_ctrl.current_mode != SEAT_FUNC_MODE_IDLE && IsTimeOut(&StopWork_Timer))) { statck_init(); air_bag_idle(); mode_state = 0; air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; printf(" timeout air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } } } /** * @brief This function handles lin usart interrupt request. */ void USART_LIN_S_IRQHandler(void) { } void EXTI15_10_IRQHandler(void) { #ifdef CFG_LOW_POWER_MODE if (EXTI_GetITStatus(LPM_WAKEUP_LINE) != RESET) { /* Clear the Key Button EXTI line pending bit */ EXTI_ClrITPendBit(LPM_WAKEUP_LINE); } #endif } /** * @} */ /***************************************************************************** * Copyright (c) 2022, Nations Technologies Inc. * * All rights reserved. * ****************************************************************************/ /** * @file bsp.c * @author Nations * @version V1.2.2 */ #include <stdio.h> #include "bsp.h" USART_InitType USART_InitStructure; TIM_TimeBaseInitType TIM_TimeBaseStructure; /** * @brief Configures GPIO. * @param GPIOx x can be A to G to select the GPIO port. * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. */ void GpioInitOut(GPIO_Module* GPIOx, uint16_t Pin) { GPIO_InitType GPIO_InitStructure; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); /* Enable the GPIO Clock */ if (GPIOx == GPIOA) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); } else if (GPIOx == GPIOB) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); } else if (GPIOx == GPIOC) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); } else if (GPIOx == GPIOD) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); } /* Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Current = GPIO_DC_12mA; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } } /** * @brief Configures GPIO. * @param GPIOx x can be A to G to select the GPIO port. * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. */ void GpioInitIn(GPIO_Module* GPIOx, uint16_t Pin) { GPIO_InitType GPIO_InitStructure; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); /* Enable the GPIO Clock */ if (GPIOx == GPIOA) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); } else if (GPIOx == GPIOB) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); } else if (GPIOx == GPIOC) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); } else if (GPIOx == GPIOD) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); } /* Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } } /** * @brief Turns selected gpio as output low/hight level. * @param GPIOx x can be A to G to select the GPIO port. * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. * @param value This parameter can be 0/1. */ void GpioSetOut(GPIO_Module* GPIOx, uint16_t Pin,uint8_t value) { GPIO_InitType GPIO_InitStructure; if(value) { /* Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Current = GPIO_DC_12mA; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } GPIOx->PBSC = Pin; } else { /* Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA; GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } GPIOx->PBC = Pin; } } /** * @brief Toggles the selected gpio. * @param GPIOx x can be A to G to select the GPIO port. * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. */ uint8_t GpioGet(GPIO_Module* GPIOx, uint16_t Pin) { return GPIO_ReadInputDataBit(GPIOx, Pin); } /** * @brief Toggles the selected gpio. * @param GPIOx x can be A to G to select the GPIO port. * @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. */ void GpioToggle(GPIO_Module* GPIOx, uint16_t Pin) { GPIOx->POD ^= Pin; } /** * @brief Configures tim2 clocks. */ void TIM_Configuration(void) { /* 公式1:频率Fpwm = 1/T周期 = TIMER_CLK/[(Period+1)*(Prescaler+1)] ①、TIMER_CLK是TIMEx挂在系统时钟APB1总线上的时钟频率; ②、Period是设置在下一个更新事件装入活动的自动重装载寄存器周期的值(计数值); ③、Prescaler是预分频值; ④、频率单位:hz,周期单位:s; */ /* Time base configuration */ TIM_InitTimBaseStruct(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.Period = 5; TIM_TimeBaseStructure.Prescaler = 8999; TIM_TimeBaseStructure.ClkDiv = 0; TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP; TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure); /* TIM2 enable update irq */ TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE); /* TIM2 enable counter */ TIM_Enable(TIM2, ENABLE); } /** * @brief Configures the different system clocks. */ void RCC_Configuration(void) { /* PCLK1 = HCLK/4 */ RCC_ConfigPclk2(RCC_HCLK_DIV1); /* TIM2 clock enable */ RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE); #ifdef _UART_DEBUG_ /* Enable GPIO clock */ UART_DEBUG_GPIO_APBxClkCmd(UART_DEBUG_GPIO_CLK, ENABLE); /* Enable UART_DEBUG_CLK Clock */ UART_DEBUG_APBxClkCmd(UART_DEBUG_CLK, ENABLE); #endif } /** * @brief Configures the different GPIO ports. */ void GPIO_Configuration(void) { GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); #ifdef _UART_DEBUG_ /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); /* Configure LPUART Tx as alternate function push-pull */ GPIO_InitStructure.Pin = UART_DEBUG_TxPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /******重要 *******/ GPIO_InitStructure.GPIO_Alternate = UART_DEBUG_Tx_GPIO_AF; GPIO_InitPeripheral(UART_DEBUG_GPIO, &GPIO_InitStructure); /* Configure LPAURT Rx as alternate function push-pull and pull-up */ GPIO_InitStructure.Pin = UART_DEBUG_RxPin; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; /******重要 *******/ GPIO_InitStructure.GPIO_Alternate = UART_DEBUG_Rx_GPIO_AF; GPIO_InitPeripheral(UART_DEBUG_GPIO, &GPIO_InitStructure); #endif } /** * @brief Configures the nested vectored interrupt controller. */ void NVIC_Configuration(void) { NVIC_InitType NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the TIM2 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #ifdef _UART_DEBUG_ /* Enable the LPUART Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif } /* USART configuration ------------------------------------------------------*/ void USART_Configuration(void) { USART_InitType USART_InitStructure; USART_StructInit(&USART_InitStructure); #ifdef _UART_DEBUG_ USART_StructInit(&USART_InitStructure); /* UART_DEBUG configuration ------------------------------------------------------*/ USART_InitStructure.BaudRate = 19200; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; USART_Init(UART_DEBUG, &USART_InitStructure); /* Enable USARTz Receive and Transmit interrupts */ //USART_ConfigInt(UART_DEBUG, USART_INT_RXDNE, ENABLE); //USART_ConfigInt(UART_DEBUG, USART_INT_TXDE, ENABLE); /* Enable the UART_DEBUG */ USART_Enable(UART_DEBUG, ENABLE); #endif } void ADC_Initial(void) { /* Enable GPIOB clocks */ RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); /* Enable ADC clocks */ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE); /* RCC_ADCHCLK_DIV16*/ ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16); RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8); //selsect HSE as RCC ADC1M CLK Source //GPIO_Configuration { GPIO_InitType GPIO_InitStructure; GPIO_InitStruct(&GPIO_InitStructure); /* Configure PC0 PC1 as analog input -------------------------*/ GPIO_InitStructure.Pin = ADC_KEY_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog; GPIO_InitPeripheral(ADC_KEY_PORT, &GPIO_InitStructure); } // ADC Initial { ADC_InitType ADC_InitStructure; /* ADC configuration ------------------------------------------------------*/ ADC_InitStructure.MultiChEn = DISABLE; ADC_InitStructure.ContinueConvEn = DISABLE; ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; ADC_InitStructure.ChsNumber = 1; ADC_Init(ADC, &ADC_InitStructure); /* Enable ADC */ ADC_Enable(ADC, ENABLE); /* Check ADC Ready */ while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_RDY) == RESET) ; /* Start ADC1 calibration */ ADC_StartCalibration(ADC); /* Check the end of ADC1 calibration */ while (ADC_GetCalibrationStatus(ADC)) ; } } uint16_t ADC_GetData(uint8_t ADC_Channel) { uint16_t dat; ADC_ConfigRegularChannel(ADC, ADC_Channel, 1, ADC_SAMP_TIME_55CYCLES5); /* Start ADC Software Conversion */ ADC_EnableSoftwareStartConv(ADC,ENABLE); while(ADC_GetFlagStatus(ADC,ADC_FLAG_ENDC)==0){ } ADC_ClearFlag(ADC,ADC_FLAG_ENDC); ADC_ClearFlag(ADC,ADC_FLAG_STR); dat=ADC_GetDat(ADC); return dat; } /** * @brief 配置低功耗模式 * @param * @param */ void LowPowrModeInit(void) { #ifdef CFG_LOW_POWER_MODE printf("Low Power Mode Configuration\n"); /* Enable PWR and BKP clock */ RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE); /* Enable WKUP pin */ PWR_WakeUpPinEnable(LPM_WAKEUP_NO, ENABLE); #endif } /** * @brief 打印系统时钟信息 * @param * @param */ void PrintSystemClock(void) { RCC_ClocksType RCC_Clocks; RCC_GetClocksFreqValue(&RCC_Clocks); printf("SysclkFreq : %d\n", RCC_Clocks.SysclkFreq); printf("HclkFreq : %d\n", RCC_Clocks.HclkFreq); printf("Pclk1Freq : %d\n", RCC_Clocks.Pclk1Freq); printf("Pclk2Freq : %d\n", RCC_Clocks.Pclk2Freq); printf("AdcPllClkFreq : %d\n", RCC_Clocks.AdcPllClkFreq); printf("AdcHclkFreq : %d\n", RCC_Clocks.AdcHclkFreq); } /** * @brief Configures system clock after wake-up from low power mode: enable HSE, PLL * and select PLL as system clock source. * @param freq: PLL clock eg 108000000 * @param src * This parameter can be one of the following values: * @arg SYSCLK_PLLSRC_HSI, * @arg SYSCLK_PLLSRC_HSIDIV2, * @arg SYSCLK_PLLSRC_HSI_PLLDIV2, * @arg SYSCLK_PLLSRC_HSIDIV2_PLLDIV2, * @arg SYSCLK_PLLSRC_HSE, * @arg SYSCLK_PLLSRC_HSEDIV2, * @arg SYSCLK_PLLSRC_HSE_PLLDIV2, * @arg SYSCLK_PLLSRC_HSEDIV2_PLLDIV2, */ void SetSysClockToPLL(uint32_t freq, uint32_t RCC_SYSCLKSource) { uint32_t pllsrcclk; uint32_t pllsrc; uint32_t pllmul; uint32_t plldiv = RCC_PLLDIVCLK_DISABLE; uint32_t latency; uint32_t pclk1div, pclk2div; uint32_t msi_ready_flag = RESET; uint8_t src = SYSCLK_PLLSRC_HSE; ErrorStatus HSEStartUpStatus; ErrorStatus HSIStartUpStatus; if (HSE_VALUE != 8000000) { /* HSE_VALUE == 8000000 is needed in this project! */ while (1); } /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration */ if ((src == SYSCLK_PLLSRC_HSI) || (src == SYSCLK_PLLSRC_HSIDIV2) || (src == SYSCLK_PLLSRC_HSI_PLLDIV2) || (src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2)) { /* Enable HSI */ RCC_ConfigHsi(RCC_HSI_ENABLE); /* Wait till HSI is ready */ HSIStartUpStatus = RCC_WaitHsiStable(); if (HSIStartUpStatus != SUCCESS) { /* If HSI fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error Go to infinite loop */ while (1); } if ((src == SYSCLK_PLLSRC_HSIDIV2) || (src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2)) { pllsrc = RCC_PLL_HSI_PRE_DIV2; pllsrcclk = HSI_VALUE/2; if(src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSI_VALUE/4; } } else if ((src == SYSCLK_PLLSRC_HSI) || (src == SYSCLK_PLLSRC_HSI_PLLDIV2)) { pllsrc = RCC_PLL_HSI_PRE_DIV1; pllsrcclk = HSI_VALUE; if(src == SYSCLK_PLLSRC_HSI_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSI_VALUE/2; } } } else if ((src == SYSCLK_PLLSRC_HSE) || (src == SYSCLK_PLLSRC_HSEDIV2) || (src == SYSCLK_PLLSRC_HSE_PLLDIV2) || (src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2)) { /* Enable HSE */ RCC_ConfigHse(RCC_HSE_ENABLE); /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitHseStable(); if (HSEStartUpStatus != SUCCESS) { /* If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error Go to infinite loop */ while (1); } if ((src == SYSCLK_PLLSRC_HSEDIV2) || (src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2)) { pllsrc = RCC_PLL_SRC_HSE_DIV2; pllsrcclk = HSE_VALUE/2; if(src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSE_VALUE/4; } } else if ((src == SYSCLK_PLLSRC_HSE) || (src == SYSCLK_PLLSRC_HSE_PLLDIV2)) { pllsrc = RCC_PLL_SRC_HSE_DIV1; pllsrcclk = HSE_VALUE; if(src == SYSCLK_PLLSRC_HSE_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSE_VALUE/2; } } } latency = (freq/32000000); if(freq > 54000000) { pclk1div = RCC_HCLK_DIV4; pclk2div = RCC_HCLK_DIV2; } else { if(freq > 27000000) { pclk1div = RCC_HCLK_DIV2; pclk2div = RCC_HCLK_DIV1; } else { pclk1div = RCC_HCLK_DIV1; pclk2div = RCC_HCLK_DIV1; } } if(((freq % pllsrcclk) == 0) && ((freq / pllsrcclk) >= 2) && ((freq / pllsrcclk) <= 32)) { pllmul = (freq / pllsrcclk); if(pllmul <= 16) { pllmul = ((pllmul - 2) << 18); } else { pllmul = (((pllmul - 17) << 18) | (1 << 27)); } } else { while(1); } /* Cheak if MSI is Ready */ if(RESET == RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_MSIRD)) { /* Enable MSI and Config Clock */ RCC_ConfigMsi(RCC_MSI_ENABLE, RCC_MSI_RANGE_4M); /* Waits for MSI start-up */ while(SUCCESS != RCC_WaitMsiStable()); msi_ready_flag = SET; } /* Select MSI as system clock source */ RCC_ConfigSysclk(RCC_SYSCLK_SRC_MSI); FLASH_SetLatency(latency); /* HCLK = SYSCLK */ RCC_ConfigHclk(RCC_SYSCLKSource);//RCC_SYSCLK_DIV1 /* PCLK2 = HCLK */ RCC_ConfigPclk2(pclk2div); /* PCLK1 = HCLK */ RCC_ConfigPclk1(pclk1div); /* Disable PLL */ RCC_EnablePll(DISABLE); RCC_ConfigPll(pllsrc, pllmul, plldiv); /* Enable PLL */ RCC_EnablePll(ENABLE); /* Wait till PLL is ready */ while (RCC_GetFlagStatus(RCC_CTRL_FLAG_PLLRDF) == RESET); /* Select PLL as system clock source */ RCC_ConfigSysclk(RCC_SYSCLK_SRC_PLLCLK); /* Wait till PLL is used as system clock source */ while (RCC_GetSysclkSrc() != 0x0C); if(msi_ready_flag == SET) { /* MSI oscillator OFF */ RCC_ConfigMsi(RCC_MSI_DISABLE, RCC_MSI_RANGE_4M); } } void LPM_WakeupExtiInit(GPIO_Module* GPIOx, uint16_t Pin) { } void AllGpioDeInit(void) { #ifdef _LPUART_DEBUG_ GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_TxPin); GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_RxPin); #endif #ifdef _UART_DEBUG_ GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_TxPin); GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_RxPin); #endif GpioInitIn(LED); } #ifdef _UART_DEBUG_ /* retarget the C library printf function to the LPUART */ int fputc(int ch, FILE* f) { USART_SendData(UART_DEBUG, (uint8_t)ch); while (USART_GetFlagStatus(UART_DEBUG, USART_FLAG_TXDE) == RESET) ; return (ch); } #endif #if !defined(_LPUART_DEBUG_) && !defined(_UART_DEBUG_) int fputc(int ch, FILE* f) { return (ch); } #endif #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file pointer to the source file name * @param line assert_param error line source number */ void assert_failed(const uint8_t* expr, const uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ //while (1) { } } #endif /** * @} */ /** * @} */ /** * @file util.c * @author Nations * @version V1.0 * @description 实用工具 * * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved. */ #include "util.h" /*********************** 定时器定义 START ***********************/ #if 0<TIMER_AMOUNT TIMER Timer_0; #endif #if 1<TIMER_AMOUNT TIMER Timer_1; #endif #if 2<TIMER_AMOUNT TIMER Timer_2; #endif #if 3<TIMER_AMOUNT volatile TIMER Timer_3; #endif #if 4<TIMER_AMOUNT volatile TIMER Timer_4; #endif #if 5<TIMER_AMOUNT volatile TIMER Timer_5; #endif #if 6<TIMER_AMOUNT TIMER Timer_6; #endif #if 7<TIMER_AMOUNT TIMER Timer_7; #endif #if 8<TIMER_AMOUNT volatile TIMER Timer_8; #endif #if 9<TIMER_AMOUNT volatile TIMER Timer_9; #endif #if 10<TIMER_AMOUNT volatile TIMER Timer_10; #endif #if 11<TIMER_AMOUNT TIMER Timer_11; #endif #if 12<TIMER_AMOUNT TIMER Timer_12; #endif #if 13<TIMER_AMOUNT TIMER Timer_13; #endif #if 14<TIMER_AMOUNT TIMER Timer_14; #endif /*********************** 定时器定义 END ***********************/ //返回从计时开始经过的时间 uint32_t GetPastTime(TIMER* timer) { return (timer->TimeOutVal - timer->TickValCache); } //返回设定的定时时间 uint32_t GetTimeOutValue(TIMER* timer) { return (timer->TimeOutVal); } //重置定时器并开始计时 void TimeOutSet(TIMER* timer, uint32_t timeout) { if (timeout > 0) { timer->TimeOutVal = timeout; timer->TickValCache = timeout; } else { timer->TimeOutVal = 0; timer->TickValCache = 0; } } //判断定时器是否超时 bool IsTimeOut(TIMER* timer) { return (timer->TickValCache>0 ? false : true); } //定时器滴答函数,在中断函数中执行 void TimerTickHandler(void) { #if 0<TIMER_AMOUNT if(Timer_0.TickValCache>0) Timer_0.TickValCache--; #endif #if 1<TIMER_AMOUNT if(Timer_1.TickValCache>0) Timer_1.TickValCache--; #endif #if 2<TIMER_AMOUNT if(Timer_2.TickValCache>0) Timer_2.TickValCache--; #endif #if 3<TIMER_AMOUNT if(Timer_3.TickValCache>0) Timer_3.TickValCache--; #endif #if 4<TIMER_AMOUNT if(Timer_4.TickValCache>0) Timer_4.TickValCache--; #endif #if 5<TIMER_AMOUNT if(Timer_5.TickValCache>0) Timer_5.TickValCache--; #endif #if 6<TIMER_AMOUNT if(Timer_6.TickValCache>0) Timer_6.TickValCache--; #endif #if 7<TIMER_AMOUNT if(Timer_7.TickValCache>0) Timer_7.TickValCache--; #endif #if 8<TIMER_AMOUNT if(Timer_8.TickValCache>0) Timer_8.TickValCache--; #endif #if 9<TIMER_AMOUNT if(Timer_9.TickValCache>0) Timer_9.TickValCache--; #endif #if 10<TIMER_AMOUNT if(Timer_10.TickValCache>0) Timer_10.TickValCache--; #endif #if 11<TIMER_AMOUNT if(Timer_11.TickValCache>0) Timer_11.TickValCache--; #endif #if 12<TIMER_AMOUNT if(Timer_12.TickValCache>0) Timer_12.TickValCache--; #endif #if 13<TIMER_AMOUNT if(Timer_13.TickValCache>0) Timer_13.TickValCache--; #endif #if 14<TIMER_AMOUNT if(Timer_14.TickValCache>0) Timer_14.TickValCache--; #endif #if 15<TIMER_AMOUNT if(Timer_15.TickValCache>0) Timer_15.TickValCache--; #endif #if 16<TIMER_AMOUNT if(Timer_16.TickValCache>0) Timer_16.TickValCache--; #endif } /** * @brief delay ms time. * @param ms specifies the delay time length. */ void DelayMs( uint32_t ms) { uint32_t m,n; /* Decrement nCount value */ for (; ms > 0; ms--) { for (m=4; m > 0; m--) { for (n=6725; n > 0; n--) { ; } } } } /** * 获取2的幂 指数 */ int getPowersOfTwo(int32_t num) { int power = 0; switch (num) { case 0: case 1: power = 0; break; case 2: power = 1; break; case 4: power = 2; break; case 8: power = 3; break; case 16: power = 4; break; case 32: power = 5; break; case 64: power = 6; break; case 128: power = 7; break; case 256: power = 8; break; case 512: power = 9; break; case 1024: power = 10; break; default: break; } return power; }
10-23
/** @file main.c @author Nations @version v1.0.0 @copyright Copyright © 2019, Nations Technologies Inc. All rights reserved. */ #define HSE_VALUE (40000000) #include <stdio.h> #include “main.h” #include “sys_var.h” #include “key.h” #include “n32g43x_gpio.h” int main(void) { /* System Clocks Configuration */ RCC_Configuration(); /* NVIC configuration */ NVIC_Configuration(); /* Configure the GPIO ports */ GPIO_Configuration(); /* USART configuration */ USART_Configuration(); /* TIM Configuration */ TIM_Configuration(); DelayMs(200);//待上电稳定 ADC_Initial(); //检测上电类型 if(1) { /* Check if the system has resumed from solft reset */ if (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_SFTRSTF) != RESET) { /* solft reset flag set */ printf("\n\rsystem solft reset\n\r\n\r"); /* Clear reset flags */ RCC_ClrFlag(); } else { /* WWDGRST flag is not set */ printf("\n\rnormal power on\n\r\n\r"); } } PrintSystemClock(); gpio_func_init(); printf("\n\r seat 8 io project\n\rbuild datetime : %s %s\n\r",__DATE__,__TIME__); //printf("\n\rwhile\n\r"); strength_Led_state = 0; while (1) { /* running led*/ { if(IsTimeOut(&LedTimer)) { TimeOutSet(&LedTimer,1000); GpioToggle(LED); } } #ifdef FY_1KEY_3LED /* mode led */ set_led_mode(mode_state); /* key led */ GpioSetOut(LED5,1); // if(!GpioGet(KEY6)) // { // GpioSetOut(LED5,1); // } // else // { // GpioSetOut(LED5,0); // } #endif /* key func */ //if (IsTimeOut(&KeyScanTimer)) { keyScan(); if( key_mode == KEY_MODE_ADC) { AdcKeyFunc(); //TimeOutSet(&KeyScanTimer,50); } if( key_mode == KEY_MODE_GPIO) { GpioKeyFunc(); //TimeOutSet(&KeyScanTimer,80); } } } } /** @} */ /** @} */ #include “app.h” #include “key.h” #include “sys_var.h” #ifdef FY_1KEY_3LED void set_led_mode(uint8_t mode) { if(mode == 0x1) { GpioSetOut(LED4,1); GpioSetOut(LED3,0); GpioSetOut(LED2,0); } else if(mode == 0x2) { GpioSetOut(LED4,1); GpioSetOut(LED3,1); GpioSetOut(LED2,0); } else if(mode == 0x3) { GpioSetOut(LED4,1); GpioSetOut(LED3,1); GpioSetOut(LED2,1); } else { GpioSetOut(LED4,0); GpioSetOut(LED3,0); GpioSetOut(LED2,0); } } #endif void air_bag_init(void) { GpioInitOut( SW1 ); GpioInitOut( SW2 ); GpioInitOut( SW3 ); GpioInitOut( SW4 ); GpioInitOut( SW5 ); GpioInitOut( SW6 ); GpioInitOut( SW7 ); GpioInitOut( SW8 ); GpioInitOut( SW9 ); GpioInitOut( SW10 ); //GpioInitOut( SW11 ); //GpioInitOut( SW12 ); GpioInitOut( POWER_FB ); GpioInitOut( POWER_EN ); GpioInitOut( MOTOR_PWM); GpioSetOut( SW1 ,0); GpioSetOut( SW2 ,0); GpioSetOut( SW3 ,0); GpioSetOut( SW4 ,0); GpioSetOut( SW5 ,0); GpioSetOut( SW6 ,0); GpioSetOut( SW7 ,0); GpioSetOut( SW8 ,0); GpioSetOut( SW9 ,0); GpioSetOut( SW10 ,0); //GpioSetOut( SW11 ,0); //GpioSetOut( SW12 ,0); GpioSetOut( POWER_FB ,1); GpioSetOut( POWER_EN ,0); GpioSetOut( MOTOR_PWM,0); } void air_bag_idle(void) { POWER_OFF; MOTOR_OFF; GpioSetOut( SW1 ,0); GpioSetOut( SW2 ,0); GpioSetOut( SW3 ,0); GpioSetOut( SW4 ,0); GpioSetOut( SW5 ,0); GpioSetOut( SW6 ,0); GpioSetOut( SW7 ,0); GpioSetOut( SW8 ,0); GpioSetOut( SW9 ,0); GpioSetOut( SW10 ,0); //GpioSetOut( SW11 ,0); //GpioSetOut( SW12 ,0); } void air_bag_out(void) { GpioSetOut( SW1 ,0); GpioSetOut( SW2 ,0); GpioSetOut( SW3 ,0); GpioSetOut( SW4 ,0); GpioSetOut( SW5 ,0); GpioSetOut( SW6 ,0); GpioSetOut( SW7 ,0); GpioSetOut( SW8 ,0); GpioSetOut( SW9 ,0); GpioSetOut( SW10 ,0); } void gpio_func_init(void) { #ifdef FY_1KEY_3LED GpioInitIn(KEY6); #elif defined(FY_1KEY_NOLED) GpioInitIn(KEY4); #endif #ifdef FY_1KEY_3LED GpioInitOut(LED); GpioSetOut(LED,0); GpioInitOut(LED2); GpioSetOut(LED2,0); GpioInitOut(LED3); GpioSetOut(LED3,0); GpioInitOut(LED4); GpioSetOut(LED4,0); GpioInitOut(LED5); GpioSetOut(LED5,0); #endif air_bag_init(); } void AdcKeyFunc(void) { static unsigned char last_adckey_code = 0; static unsigned char last_adckey_type = 0; if(( last_adckey_code != key.KeyEventCode || last_adckey_type != key.KeyEventType) ) { if(key.KeyEventCode > 0 && key.KeyEventType > 0 ) printf("\n\rADC key KeyEventCode : %d KeyEventType : %d \n\r",key.KeyEventCode , key.KeyEventType); if( key.KeyEventCode == ADC_KEY_CODE_UP && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //上充下放 POWER_ON; MOTOR_ON; #ifdef FY_SEAT_10 WAIST_1_IN; WAIST_2_OUT; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_DOWN && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //下充上放 POWER_ON; MOTOR_ON; #ifdef FY_SEAT_10 WAIST_2_IN; WAIST_1_OUT; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_LEFT && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //全充 POWER_ON; MOTOR_ON; #ifdef FY_SEAT_10 WAIST_1_IN; WAIST_2_IN; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_RIGHT && key.KeyScanState >= KEYSCANSTATE_HOLD) { { //全放 POWER_ON; MOTOR_OFF; #ifdef FY_SEAT_10 WAIST_1_OUT; WAIST_2_OUT; #endif air_bag_out(); } air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; TimeOutSet(&Out_15S_Before_Stop_Timer,0); mode_state = 0; } else if( key.KeyEventCode == ADC_KEY_CODE_OK) { if( key.KeyEventType == KEYTYPE_HOLD) { printf("\n\rkey hold\n\r"); TimeOutSet(&ModeSwitch_Timer,1000); if(mode_state) { mode_state = 0; } else { mode_state = 1; } air_bag_ctrl.current_mode = mode_state; air_bag_ctrl.schedule_table_pntr = air_bag_schedule_table[air_bag_ctrl.current_mode]; air_bag_ctrl.current_schedule_index = 0; air_bag_ctrl.last_schedule_index = 0; air_bag_ctrl.current_schedule_duration = 0; TimeOutSet(&StopWork_Timer,work_mode_total_duration[mode_state]); statck_init(); air_bag_idle(); statck_push(&air_bag_ctrl.schedule_table_pntr[0]); printf(" air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } else if( key.KeyEventType == KEYTYPE_SINGLE) { //printf("\n\radc key down \n\r"); TimeOutSet(&ModeSwitch_Timer,1000); if(mode_state) { mode_state = (mode_state + 1) % SEAT_FUNC_MODE_AMOUNT ; if(mode_state == 0) mode_state = 1; } air_bag_ctrl.current_mode = mode_state; air_bag_ctrl.schedule_table_pntr = air_bag_schedule_table[air_bag_ctrl.current_mode]; air_bag_ctrl.current_schedule_index = 0; air_bag_ctrl.last_schedule_index = 0; air_bag_ctrl.current_schedule_duration = 0; TimeOutSet(&StopWork_Timer,work_mode_total_duration[mode_state]); statck_init(); air_bag_init(); statck_push(&air_bag_ctrl.schedule_table_pntr[0]); printf(" air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } #ifdef FY_SEAT_10 WAIST_1_IDLE; WAIST_2_IDLE; #endif } else { //无按键动作 if(!IsTimeOut(&Out_15S_Before_Stop_Timer)) { { //放气15S POWER_ON; MOTOR_OFF; air_bag_idle(); } } else if(mode_state == 0) { //闭气 air_bag_idle(); POWER_OFF; MOTOR_OFF; #ifdef FY_SEAT_10 WAIST_1_IDLE; WAIST_2_IDLE; #endif } } last_adckey_code = key.KeyEventCode; last_adckey_type = key.KeyEventType; } // else if(mode_state) //循环工作中 // { // if( key.KeyEventCode == ADC_KEY_CODE_OK && key.KeyEventType == KEYTYPE_LONGPRES) // { // //退出循环工作 // air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; // air_bag_ctrl.autoWorkFlag = 0; // TimeOutSet(&Out_15S_Before_Stop_Timer,SECOND_15); // } // } } void GpioKeyFunc(void) { static unsigned char last_key_code = 0; static unsigned char last_key_type = 0; /* LED KEY */ if(last_key_code != key.KeyEventCode || last_key_type != key.KeyEventType) { if(key.KeyEventCode > 0 && key.KeyEventType > 0 ) printf("\n\rGPIO key KeyEventCode : %d KeyEventType : %d \n\r",key.KeyEventCode , key.KeyEventType); if( key.KeyEventCode == GPIO_KEY_CODE_K6 && key.KeyEventType == KEYTYPE_SINGLE) { //printf("\n\rgpio key down \n\r"); TimeOutSet(&ModeSwitch_Timer,1000); //if(mode_state) { mode_state = (mode_state + 1) % 4 ; } air_bag_ctrl.current_mode = mode_state; air_bag_ctrl.schedule_table_pntr = air_bag_schedule_table[air_bag_ctrl.current_mode]; air_bag_ctrl.current_schedule_index = 0; air_bag_ctrl.last_schedule_index = 0; air_bag_ctrl.current_schedule_duration = 0; TimeOutSet(&StopWork_Timer,work_mode_total_duration[mode_state]); statck_init(); air_bag_init(); statck_push(&air_bag_ctrl.schedule_table_pntr[0]); // printf(" air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } last_key_code = key.KeyEventCode; last_key_type = key.KeyEventType; } } /** @file n32g43x_it.c @author Nations @version v1.0.0 @copyright Copyright © 2019, Nations Technologies Inc. All rights reserved. */ #include <stdio.h> #include “n32g43x_it.h” #include “bsp.h” #include “sys_var.h” #include “util.h” extern uint8_t mode_state; /** @addtogroup N32G43X_StdPeriph_Template @{ */ // / Cortex-M4 Processor Exceptions Handlers / // /** @brief This function handles NMI exception. */ void NMI_Handler(void) { } /** @brief This function handles Hard Fault exception. / void HardFault_Handler(void) { / Go to infinite loop when Hard Fault exception occurs */ while (1) { } } /** @brief This function handles Memory Manage exception. / void MemManage_Handler(void) { / Go to infinite loop when Memory Manage exception occurs */ while (1) { } } /** @brief This function handles Bus Fault exception. / void BusFault_Handler(void) { / Go to infinite loop when Bus Fault exception occurs */ while (1) { } } /** @brief This function handles Usage Fault exception. / void UsageFault_Handler(void) { / Go to infinite loop when Usage Fault exception occurs */ while (1) { } } /** @brief This function handles SVCall exception. */ void SVC_Handler(void) { } /** @brief This function handles Debug Monitor exception. */ void DebugMon_Handler(void) { } /** @brief This function handles SysTick Handler. */ void SysTick_Handler(void) { } /** @brief This function handles TIM2 update interrupt request. */ void TIM2_IRQHandler(void) { if (TIM_GetIntStatus(TIM2, TIM_INT_UPDATE) != RESET) //1ms 定时中断 { TIM_ClrIntPendingBit(TIM2, TIM_INT_UPDATE);//重置定时器 //软定时器滴答 TimerTickHandler(); if( (air_bag_ctrl.current_mode != SEAT_FUNC_MODE_IDLE && !IsTimeOut(&StopWork_Timer) && IsTimeOut(&ModeSwitch_Timer) )) { int stack_idx; for(stack_idx = 0;stack_idx < STACK_SIZE;stack_idx++) { if (schedule_stack[stack_idx].IsUsed) { if (schedule_stack[stack_idx].InDuration > 0) { //充气 POWER_ON; air_bag_set_in(schedule_stack[stack_idx].OpAirBagGroup); schedule_stack[stack_idx].InDuration --; } else { if (schedule_stack[stack_idx].OutDuration > 0) { //放气 POWER_ON; air_bag_set_out(schedule_stack[stack_idx].OpAirBagGroup); schedule_stack[stack_idx].OutDuration --; if (schedule_stack[stack_idx].OutDuration == 0) { //停止放气 //放气完毕,出栈 //printf("out end idx %d\r\n",schedule_stack[stack_idx].sch_idx); statck_pop(stack_idx); if(0) { int i; for (i = 0; i < STACK_SIZE; i++) { //printf(" st_idx : %d is_used : %d sch_idx : %d InD :%d OutD :%d NexD : %d \r\n",i,schedule_stack[i].IsUsed,schedule_stack[i].sch_idx,schedule_stack[i].InDuration,schedule_stack[i].OutDuration,schedule_stack[i].NextOpDuration); } } } } } if (schedule_stack[stack_idx].NextOpDuration > 0) { schedule_stack[stack_idx].NextOpDuration --; //下一动作入栈 if (schedule_stack[stack_idx].NextOpDuration == 0) { if(schedule_stack[stack_idx].sch_idx + 1 <= schedule_stack[stack_idx].sch_idx_max) { statck_push(&air_bag_ctrl.schedule_table_pntr[schedule_stack[stack_idx].sch_idx+1]); //printf("next op idx %d\r\n",schedule_stack[stack_idx].sch_idx + 1); { int i; for (i = 0; i < STACK_SIZE; i++) { //printf(" st_idx : %d is_used : %d sch_idx : %d InD :%d OutD :%d NexD : %d \r\n",i,schedule_stack[i].IsUsed,schedule_stack[i].sch_idx,schedule_stack[i].InDuration,schedule_stack[i].OutDuration,schedule_stack[i].NextOpDuration); } } } else { statck_push(&air_bag_ctrl.schedule_table_pntr[0]); //printf("cycle end return 0 idx %d\r\n",schedule_stack[stack_idx].sch_idx); { int i; for (i = 0; i < STACK_SIZE; i++) { //printf(" st_idx : %d is_used : %d sch_idx : %d InD :%d OutD :%d NexD : %d \r\n",i,schedule_stack[i].IsUsed,schedule_stack[i].sch_idx,schedule_stack[i].InDuration,schedule_stack[i].OutDuration,schedule_stack[i].NextOpDuration); } } } } } if(schedule_stack[stack_idx].InDuration == 0 && schedule_stack[stack_idx].OutDuration == 0 && schedule_stack[stack_idx].NextOpDuration == 0) { statck_pop(stack_idx); } } } } else if( (air_bag_ctrl.current_mode != SEAT_FUNC_MODE_IDLE && IsTimeOut(&StopWork_Timer))) { statck_init(); air_bag_idle(); mode_state = 0; air_bag_ctrl.current_mode = SEAT_FUNC_MODE_IDLE; printf(" timeout air_bag_ctrl.current_mode : %d\r\n",air_bag_ctrl.current_mode); } } } /** @brief This function handles lin usart interrupt request. */ void USART_LIN_S_IRQHandler(void) { } void EXTI15_10_IRQHandler(void) { #ifdef CFG_LOW_POWER_MODE if (EXTI_GetITStatus(LPM_WAKEUP_LINE) != RESET) { /* Clear the Key Button EXTI line pending bit */ EXTI_ClrITPendBit(LPM_WAKEUP_LINE); } #endif } /** @} / /**************************************************************************** Copyright © 2022, Nations Technologies Inc. All rights reserved. ****************************************************************************/ /** @file bsp.c @author Nations @version V1.2.2 */ #include <stdio.h> #include “bsp.h” USART_InitType USART_InitStructure; TIM_TimeBaseInitType TIM_TimeBaseStructure; /** @brief Configures GPIO. @param GPIOx x can be A to G to select the GPIO port. @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. / void GpioInitOut(GPIO_Module GPIOx, uint16_t Pin) { GPIO_InitType GPIO_InitStructure; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); /* Enable the GPIO Clock */ if (GPIOx == GPIOA) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); } else if (GPIOx == GPIOB) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); } else if (GPIOx == GPIOC) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); } else if (GPIOx == GPIOD) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); } /* Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Current = GPIO_DC_12mA; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } } /** @brief Configures GPIO. @param GPIOx x can be A to G to select the GPIO port. @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. / void GpioInitIn(GPIO_Module GPIOx, uint16_t Pin) { GPIO_InitType GPIO_InitStructure; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); /* Enable the GPIO Clock */ if (GPIOx == GPIOA) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE); } else if (GPIOx == GPIOB) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); } else if (GPIOx == GPIOC) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE); } else if (GPIOx == GPIOD) { RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOD, ENABLE); } /* Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } } /** @brief Turns selected gpio as output low/hight level. @param GPIOx x can be A to G to select the GPIO port. @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. @param value This parameter can be 0/1. / void GpioSetOut(GPIO_Module GPIOx, uint16_t Pin,uint8_t value) { GPIO_InitType GPIO_InitStructure; if(value) { /* Configure the GPIO pin / if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Current = GPIO_DC_12mA; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } GPIOx->PBSC = Pin; } else { / Configure the GPIO pin */ if (Pin <= GPIO_PIN_ALL) { GPIO_InitStruct(&GPIO_InitStructure); GPIO_InitStructure.Pin = Pin; GPIO_InitStructure.GPIO_Current = GPIO_DC_4mA; GPIO_InitStructure.GPIO_Pull = GPIO_No_Pull; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure); } GPIOx->PBC = Pin; } } /** @brief Toggles the selected gpio. @param GPIOx x can be A to G to select the GPIO port. @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. / uint8_t GpioGet(GPIO_Module GPIOx, uint16_t Pin) { return GPIO_ReadInputDataBit(GPIOx, Pin); } /** @brief Toggles the selected gpio. @param GPIOx x can be A to G to select the GPIO port. @param Pin This parameter can be GPIO_PIN_0~GPIO_PIN_15. / void GpioToggle(GPIO_Module GPIOx, uint16_t Pin) { GPIOx->POD ^= Pin; } /** @brief Configures tim2 clocks. / void TIM_Configuration(void) { / 公式1:频率Fpwm = 1/T周期 = TIMER_CLK/[(Period+1)*(Prescaler+1)] ①、TIMER_CLK是TIMEx挂在系统时钟APB1总线上的时钟频率; ②、Period是设置在下一个更新事件装入活动的自动重装载寄存器周期的值(计数值); ③、Prescaler是预分频值; ④、频率单位:hz,周期单位:s; */ /* Time base configuration */ TIM_InitTimBaseStruct(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.Period = 5; TIM_TimeBaseStructure.Prescaler = 8999; TIM_TimeBaseStructure.ClkDiv = 0; TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP; TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure); /* TIM2 enable update irq */ TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE); /* TIM2 enable counter */ TIM_Enable(TIM2, ENABLE); } /** @brief Configures the different system clocks. / void RCC_Configuration(void) { / PCLK1 = HCLK/4 */ RCC_ConfigPclk2(RCC_HCLK_DIV1); /* TIM2 clock enable */ RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE); #ifdef UART_DEBUG /* Enable GPIO clock / UART_DEBUG_GPIO_APBxClkCmd(UART_DEBUG_GPIO_CLK, ENABLE); / Enable UART_DEBUG_CLK Clock */ UART_DEBUG_APBxClkCmd(UART_DEBUG_CLK, ENABLE); #endif } /** @brief Configures the different GPIO ports. */ void GPIO_Configuration(void) { GPIO_InitType GPIO_InitStructure; /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); #ifdef UART_DEBUG /* Initialize GPIO_InitStructure */ GPIO_InitStruct(&GPIO_InitStructure); /* Configure LPUART Tx as alternate function push-pull */ GPIO_InitStructure.Pin = UART_DEBUG_TxPin; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /******重要 *******/ GPIO_InitStructure.GPIO_Alternate = UART_DEBUG_Tx_GPIO_AF; GPIO_InitPeripheral(UART_DEBUG_GPIO, &GPIO_InitStructure); /* Configure LPAURT Rx as alternate function push-pull and pull-up */ GPIO_InitStructure.Pin = UART_DEBUG_RxPin; GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up; /******重要 *******/ GPIO_InitStructure.GPIO_Alternate = UART_DEBUG_Rx_GPIO_AF; GPIO_InitPeripheral(UART_DEBUG_GPIO, &GPIO_InitStructure); #endif } /** @brief Configures the nested vectored interrupt controller. */ void NVIC_Configuration(void) { NVIC_InitType NVIC_InitStructure; /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the TIM2 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #ifdef UART_DEBUG /* Enable the LPUART Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); #endif } /* USART configuration ------------------------------------------------------*/ void USART_Configuration(void) { USART_InitType USART_InitStructure; USART_StructInit(&USART_InitStructure); #ifdef UART_DEBUG USART_StructInit(&USART_InitStructure); /* UART_DEBUG configuration ------------------------------------------------------*/ USART_InitStructure.BaudRate = 19200; USART_InitStructure.WordLength = USART_WL_8B; USART_InitStructure.StopBits = USART_STPB_1; USART_InitStructure.Parity = USART_PE_NO; USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE; USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX; USART_Init(UART_DEBUG, &USART_InitStructure); /* Enable USARTz Receive and Transmit interrupts */ //USART_ConfigInt(UART_DEBUG, USART_INT_RXDNE, ENABLE); //USART_ConfigInt(UART_DEBUG, USART_INT_TXDE, ENABLE); /* Enable the UART_DEBUG */ USART_Enable(UART_DEBUG, ENABLE); #endif } void ADC_Initial(void) { /* Enable GPIOB clocks / RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE); / Enable ADC clocks */ RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE); /* RCC_ADCHCLK_DIV16*/ ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16); RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSE, RCC_ADC1MCLK_DIV8); //selsect HSE as RCC ADC1M CLK Source //GPIO_Configuration { GPIO_InitType GPIO_InitStructure; GPIO_InitStruct(&GPIO_InitStructure); /* Configure PC0 PC1 as analog input -------------------------*/ GPIO_InitStructure.Pin = ADC_KEY_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Analog; GPIO_InitPeripheral(ADC_KEY_PORT, &GPIO_InitStructure); } // ADC Initial { ADC_InitType ADC_InitStructure; /* ADC configuration ------------------------------------------------------*/ ADC_InitStructure.MultiChEn = DISABLE; ADC_InitStructure.ContinueConvEn = DISABLE; ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; ADC_InitStructure.ChsNumber = 1; ADC_Init(ADC, &ADC_InitStructure); /* Enable ADC */ ADC_Enable(ADC, ENABLE); /* Check ADC Ready */ while(ADC_GetFlagStatusNew(ADC,ADC_FLAG_RDY) == RESET) ; /* Start ADC1 calibration */ ADC_StartCalibration(ADC); /* Check the end of ADC1 calibration */ while (ADC_GetCalibrationStatus(ADC)) ; } } uint16_t ADC_GetData(uint8_t ADC_Channel) { uint16_t dat; ADC_ConfigRegularChannel(ADC, ADC_Channel, 1, ADC_SAMP_TIME_55CYCLES5); /* Start ADC Software Conversion */ ADC_EnableSoftwareStartConv(ADC,ENABLE); while(ADC_GetFlagStatus(ADC,ADC_FLAG_ENDC)==0){ } ADC_ClearFlag(ADC,ADC_FLAG_ENDC); ADC_ClearFlag(ADC,ADC_FLAG_STR); dat=ADC_GetDat(ADC); return dat; } /** @brief 配置低功耗模式 @param @param / void LowPowrModeInit(void) { #ifdef CFG_LOW_POWER_MODE printf(“Low Power Mode Configuration\n”); / Enable PWR and BKP clock / RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE); / Enable WKUP pin */ PWR_WakeUpPinEnable(LPM_WAKEUP_NO, ENABLE); #endif } /** @brief 打印系统时钟信息 @param @param */ void PrintSystemClock(void) { RCC_ClocksType RCC_Clocks; RCC_GetClocksFreqValue(&RCC_Clocks); printf(“SysclkFreq : %d\n”, RCC_Clocks.SysclkFreq); printf(“HclkFreq : %d\n”, RCC_Clocks.HclkFreq); printf(“Pclk1Freq : %d\n”, RCC_Clocks.Pclk1Freq); printf(“Pclk2Freq : %d\n”, RCC_Clocks.Pclk2Freq); printf(“AdcPllClkFreq : %d\n”, RCC_Clocks.AdcPllClkFreq); printf(“AdcHclkFreq : %d\n”, RCC_Clocks.AdcHclkFreq); } /** @brief Configures system clock after wake-up from low power mode: enable HSE, PLL and select PLL as system clock source. @param freq: PLL clock eg 108000000 @param src This parameter can be one of the following values: @arg SYSCLK_PLLSRC_HSI, @arg SYSCLK_PLLSRC_HSIDIV2, @arg SYSCLK_PLLSRC_HSI_PLLDIV2, @arg SYSCLK_PLLSRC_HSIDIV2_PLLDIV2, @arg SYSCLK_PLLSRC_HSE, @arg SYSCLK_PLLSRC_HSEDIV2, @arg SYSCLK_PLLSRC_HSE_PLLDIV2, @arg SYSCLK_PLLSRC_HSEDIV2_PLLDIV2, / void SetSysClockToPLL(uint32_t freq, uint32_t RCC_SYSCLKSource) { uint32_t pllsrcclk; uint32_t pllsrc; uint32_t pllmul; uint32_t plldiv = RCC_PLLDIVCLK_DISABLE; uint32_t latency; uint32_t pclk1div, pclk2div; uint32_t msi_ready_flag = RESET; uint8_t src = SYSCLK_PLLSRC_HSE; ErrorStatus HSEStartUpStatus; ErrorStatus HSIStartUpStatus; if (HSE_VALUE != 8000000) { / HSE_VALUE == 8000000 is needed in this project! / while (1); } / SYSCLK, HCLK, PCLK2 and PCLK1 configuration / if ((src == SYSCLK_PLLSRC_HSI) || (src == SYSCLK_PLLSRC_HSIDIV2) || (src == SYSCLK_PLLSRC_HSI_PLLDIV2) || (src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2)) { / Enable HSI / RCC_ConfigHsi(RCC_HSI_ENABLE); / Wait till HSI is ready / HSIStartUpStatus = RCC_WaitHsiStable(); if (HSIStartUpStatus != SUCCESS) { / If HSI fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error Go to infinite loop / while (1); } if ((src == SYSCLK_PLLSRC_HSIDIV2) || (src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2)) { pllsrc = RCC_PLL_HSI_PRE_DIV2; pllsrcclk = HSI_VALUE/2; if(src == SYSCLK_PLLSRC_HSIDIV2_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSI_VALUE/4; } } else if ((src == SYSCLK_PLLSRC_HSI) || (src == SYSCLK_PLLSRC_HSI_PLLDIV2)) { pllsrc = RCC_PLL_HSI_PRE_DIV1; pllsrcclk = HSI_VALUE; if(src == SYSCLK_PLLSRC_HSI_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSI_VALUE/2; } } } else if ((src == SYSCLK_PLLSRC_HSE) || (src == SYSCLK_PLLSRC_HSEDIV2) || (src == SYSCLK_PLLSRC_HSE_PLLDIV2) || (src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2)) { / Enable HSE / RCC_ConfigHse(RCC_HSE_ENABLE); / Wait till HSE is ready / HSEStartUpStatus = RCC_WaitHseStable(); if (HSEStartUpStatus != SUCCESS) { / If HSE fails to start-up, the application will have wrong clock configuration. User can add here some code to deal with this error Go to infinite loop / while (1); } if ((src == SYSCLK_PLLSRC_HSEDIV2) || (src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2)) { pllsrc = RCC_PLL_SRC_HSE_DIV2; pllsrcclk = HSE_VALUE/2; if(src == SYSCLK_PLLSRC_HSEDIV2_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSE_VALUE/4; } } else if ((src == SYSCLK_PLLSRC_HSE) || (src == SYSCLK_PLLSRC_HSE_PLLDIV2)) { pllsrc = RCC_PLL_SRC_HSE_DIV1; pllsrcclk = HSE_VALUE; if(src == SYSCLK_PLLSRC_HSE_PLLDIV2) { plldiv = RCC_PLLDIVCLK_ENABLE; pllsrcclk = HSE_VALUE/2; } } } latency = (freq/32000000); if(freq > 54000000) { pclk1div = RCC_HCLK_DIV4; pclk2div = RCC_HCLK_DIV2; } else { if(freq > 27000000) { pclk1div = RCC_HCLK_DIV2; pclk2div = RCC_HCLK_DIV1; } else { pclk1div = RCC_HCLK_DIV1; pclk2div = RCC_HCLK_DIV1; } } if(((freq % pllsrcclk) == 0) && ((freq / pllsrcclk) >= 2) && ((freq / pllsrcclk) <= 32)) { pllmul = (freq / pllsrcclk); if(pllmul <= 16) { pllmul = ((pllmul - 2) << 18); } else { pllmul = (((pllmul - 17) << 18) | (1 << 27)); } } else { while(1); } / Cheak if MSI is Ready / if(RESET == RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_MSIRD)) { / Enable MSI and Config Clock / RCC_ConfigMsi(RCC_MSI_ENABLE, RCC_MSI_RANGE_4M); / Waits for MSI start-up / while(SUCCESS != RCC_WaitMsiStable()); msi_ready_flag = SET; } / Select MSI as system clock source / RCC_ConfigSysclk(RCC_SYSCLK_SRC_MSI); FLASH_SetLatency(latency); / HCLK = SYSCLK / RCC_ConfigHclk(RCC_SYSCLKSource);//RCC_SYSCLK_DIV1 / PCLK2 = HCLK / RCC_ConfigPclk2(pclk2div); / PCLK1 = HCLK / RCC_ConfigPclk1(pclk1div); / Disable PLL / RCC_EnablePll(DISABLE); RCC_ConfigPll(pllsrc, pllmul, plldiv); / Enable PLL / RCC_EnablePll(ENABLE); / Wait till PLL is ready / while (RCC_GetFlagStatus(RCC_CTRL_FLAG_PLLRDF) == RESET); / Select PLL as system clock source / RCC_ConfigSysclk(RCC_SYSCLK_SRC_PLLCLK); / Wait till PLL is used as system clock source / while (RCC_GetSysclkSrc() != 0x0C); if(msi_ready_flag == SET) { / MSI oscillator OFF */ RCC_ConfigMsi(RCC_MSI_DISABLE, RCC_MSI_RANGE_4M); } } void LPM_WakeupExtiInit(GPIO_Module* GPIOx, uint16_t Pin) { } void AllGpioDeInit(void) { #ifdef LPUART_DEBUG GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_TxPin); GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_RxPin); #endif #ifdef _UART_DEBUG_ GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_TxPin); GpioInitIn(UART_DEBUG_GPIO,UART_DEBUG_RxPin); #endif GpioInitIn(LED); } #ifdef UART_DEBUG /* retarget the C library printf function to the LPUART / int fputc(int ch, FILE f) { USART_SendData(UART_DEBUG, (uint8_t)ch); while (USART_GetFlagStatus(UART_DEBUG, USART_FLAG_TXDE) == RESET) ; return (ch); } #endif #if !defined(LPUART_DEBUG) && !defined(UART_DEBUG) int fputc(int ch, FILE* f) { return (ch); } #endif #ifdef USE_FULL_ASSERT /** @brief Reports the name of the source file and the source line number where the assert_param error has occurred. @param file pointer to the source file name @param line assert_param error line source number / void assert_failed(const uint8_t expr, const uint8_t* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) */ /* Infinite loop */ //while (1) { } } #endif /** @} */ /** @} / /* @file util.c @author Nations @version V1.0 @description 实用工具 @copyright Copyright © 2022, Nations Technologies Inc. All rights reserved. */ #include “util.h” /*********************** 定时器定义 START ***********************/ #if 0<TIMER_AMOUNT TIMER Timer_0; #endif #if 1<TIMER_AMOUNT TIMER Timer_1; #endif #if 2<TIMER_AMOUNT TIMER Timer_2; #endif #if 3<TIMER_AMOUNT volatile TIMER Timer_3; #endif #if 4<TIMER_AMOUNT volatile TIMER Timer_4; #endif #if 5<TIMER_AMOUNT volatile TIMER Timer_5; #endif #if 6<TIMER_AMOUNT TIMER Timer_6; #endif #if 7<TIMER_AMOUNT TIMER Timer_7; #endif #if 8<TIMER_AMOUNT volatile TIMER Timer_8; #endif #if 9<TIMER_AMOUNT volatile TIMER Timer_9; #endif #if 10<TIMER_AMOUNT volatile TIMER Timer_10; #endif #if 11<TIMER_AMOUNT TIMER Timer_11; #endif #if 12<TIMER_AMOUNT TIMER Timer_12; #endif #if 13<TIMER_AMOUNT TIMER Timer_13; #endif #if 14<TIMER_AMOUNT TIMER Timer_14; #endif /*********************** 定时器定义 END ***********************/ //返回从计时开始经过的时间 uint32_t GetPastTime(TIMER* timer) { return (timer->TimeOutVal - timer->TickValCache); } //返回设定的定时时间 uint32_t GetTimeOutValue(TIMER* timer) { return (timer->TimeOutVal); } //重置定时器并开始计时 void TimeOutSet(TIMER* timer, uint32_t timeout) { if (timeout > 0) { timer->TimeOutVal = timeout; timer->TickValCache = timeout; } else { timer->TimeOutVal = 0; timer->TickValCache = 0; } } //判断定时器是否超时 bool IsTimeOut(TIMER* timer) { return (timer->TickValCache>0 ? false : true); } //定时器滴答函数,在中断函数中执行 void TimerTickHandler(void) { #if 0<TIMER_AMOUNT if(Timer_0.TickValCache>0) Timer_0.TickValCache–; #endif #if 1<TIMER_AMOUNT if(Timer_1.TickValCache>0) Timer_1.TickValCache--; #endif #if 2<TIMER_AMOUNT if(Timer_2.TickValCache>0) Timer_2.TickValCache--; #endif #if 3<TIMER_AMOUNT if(Timer_3.TickValCache>0) Timer_3.TickValCache--; #endif #if 4<TIMER_AMOUNT if(Timer_4.TickValCache>0) Timer_4.TickValCache--; #endif #if 5<TIMER_AMOUNT if(Timer_5.TickValCache>0) Timer_5.TickValCache--; #endif #if 6<TIMER_AMOUNT if(Timer_6.TickValCache>0) Timer_6.TickValCache--; #endif #if 7<TIMER_AMOUNT if(Timer_7.TickValCache>0) Timer_7.TickValCache--; #endif #if 8<TIMER_AMOUNT if(Timer_8.TickValCache>0) Timer_8.TickValCache--; #endif #if 9<TIMER_AMOUNT if(Timer_9.TickValCache>0) Timer_9.TickValCache--; #endif #if 10<TIMER_AMOUNT if(Timer_10.TickValCache>0) Timer_10.TickValCache--; #endif #if 11<TIMER_AMOUNT if(Timer_11.TickValCache>0) Timer_11.TickValCache–; #endif #if 12<TIMER_AMOUNT if(Timer_12.TickValCache>0) Timer_12.TickValCache–; #endif #if 13<TIMER_AMOUNT if(Timer_13.TickValCache>0) Timer_13.TickValCache–; #endif #if 14<TIMER_AMOUNT if(Timer_14.TickValCache>0) Timer_14.TickValCache–; #endif #if 15<TIMER_AMOUNT if(Timer_15.TickValCache>0) Timer_15.TickValCache–; #endif #if 16<TIMER_AMOUNT if(Timer_16.TickValCache>0) Timer_16.TickValCache–; #endif } /** @brief delay ms time. @param ms specifies the delay time length. / void DelayMs( uint32_t ms) { uint32_t m,n; / Decrement nCount value */ for (; ms > 0; ms–) { for (m=4; m > 0; m–) { for (n=6725; n > 0; n–) { ; } } } } /** 获取2的幂 指数 */ int getPowersOfTwo(int32_t num) { int power = 0; switch (num) { case 0: case 1: power = 0; break; case 2: power = 1; break; case 4: power = 2; break; case 8: power = 3; break; case 16: power = 4; break; case 32: power = 5; break; case 64: power = 6; break; case 128: power = 7; break; case 256: power = 8; break; case 512: power = 9; break; case 1024: power = 10; break; default: break; } return power; } #include “key.h” uint8_t key_mode = KEY_MODE_NULL; //按键模式 uint8_t KeyScanState = KEYSCANSTATE_IDLE; uint8_t KeyLstCode; uint8_t Keycode; uint8_t KeyEventCode; Key key; uint8_t gpio_key_value = GPIO_KEY_CODE_NULL; void keyScan(void) { key.keycode = get_gpio_key(); if(key.keycode == GPIO_KEY_CODE_NULL) { // key.keycode = get_adc_key(); } if (key.keycode != key.KeyCurCode) { key.KeyCurCode = key.keycode; //return; } if (GPIO_KEY_CODE_NULL) { /* code */ } switch (key.KeyScanState) { case KEYSCANSTATE_IDLE: if (key.keycode != ADC_KEY_CODE_NULL) { key.KeyLstCode = key.keycode; key.KeyScanState = KEYSCANSTATE_HAVE; TimeOutSet(&ADCKeyJitterTimer,40); } else { key.KeyScanState = KEYSCANSTATE_IDLE; key.KeyEventCode = ADC_KEY_CODE_NULL; key.KeyEventType = KEYTYPE_NULL; } break; case KEYSCANSTATE_HAVE: if (key.keycode == key.KeyLstCode) { if (IsTimeOut(&ADCKeyJitterTimer)) { key.KeyScanState = KEYSCANSTATE_HOLD; TimeOutSet(&ADCKeyJitterTimer,1000); key.KeyEventCode = key.KeyLstCode; } } else { if (IsTimeOut(&ADCKeyJitterTimer)) { key.KeyScanState = KEYSCANSTATE_IDLE; key.KeyEventCode = key.KeyLstCode; key.KeyEventType = KEYTYPE_SINGLE; } else { key.KeyScanState = KEYSCANSTATE_IDLE; key.KeyEventCode = key.KeyLstCode; key.KeyEventType = KEYTYPE_NULL; } } break; case KEYSCANSTATE_HOLD: if (key.keycode == key.KeyLstCode) { if (IsTimeOut(&ADCKeyJitterTimer)) { key.KeyScanState = KEYSCANSTATE_LONG; TimeOutSet(&ADCKeyJitterTimer,1000); key.KeyEventCode = key.KeyLstCode; key.KeyEventType = KEYTYPE_HOLD; } } else { key.KeyScanState = KEYSCANSTATE_IDLE; key.KeyEventCode = key.KeyLstCode; key.KeyEventType = KEYTYPE_SINGLE; } break; case KEYSCANSTATE_LONG: if (key.keycode == key.KeyLstCode) { } else { key.KeyScanState = KEYSCANSTATE_IDLE; key.KeyEventCode = key.KeyLstCode; key.KeyEventType = KEYTYPE_NULL; } break; } } uint8_t get_gpio_key(void) { #ifdef FY_1KEY_3LED if(!GpioGet(KEY6)) { gpio_key_value = GPIO_KEY_CODE_K6; key_mode = KEY_MODE_GPIO; } else { gpio_key_value = GPIO_KEY_CODE_NULL; } #elif defined(FY_1KEY_NOLED) if(!GpioGet(KEY4)) { gpio_key_value = GPIO_KEY_CODE_K6; key_mode = KEY_MODE_GPIO; } else { gpio_key_value = GPIO_KEY_CODE_NULL; } #endif return gpio_key_value; } uint16_t adc_value = 0; uint16_t adc_key_value = 0; uint8_t get_adc_key(void) { adc_value = ADC_GetData(ADC_CH_2_PA1); // if(adc_value < 0x0EFF) // { // key_mode = KEY_MODE_ADC; // } if (adc_value < 0x05FF) // OK 03B5 { adc_key_value = ADC_KEY_CODE_OK; } else if (adc_value > 0x05FF && adc_value < 0x08FF) // UP 074d { adc_key_value = ADC_KEY_CODE_UP; } else if (adc_value > 0x08FF && adc_value < 0x0BFF) // DOWN 0Ab8 { adc_key_value = ADC_KEY_CODE_DOWN; } else if (adc_value > 0x0BFF && adc_value < 0x0D5F) // RIGHT 0C90 { adc_key_value = ADC_KEY_CODE_RIGHT; } else if (adc_value > 0x0D5F && adc_value < 0x0EFF) // LEFT 0E5d { adc_key_value = ADC_KEY_CODE_LEFT; } else { adc_key_value = ADC_KEY_CODE_NULL; } if(adc_key_value != ADC_KEY_CODE_NULL) { key_mode = KEY_MODE_ADC; } return adc_key_value; }LED
10-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值