3. 应用案例 点灯测试是每一款MCU的必经之路,这里采用呼吸灯作为演示。 3.1 GPIO初始化注意:
由于演示程序采用呼吸灯,即通过改变LED对应IO的PWM占空比控制小灯亮灭程度,所以需要初始化具有PWM输出功能的引脚。
void GPIO_init(PWMCH_enum pwmch, uint32 freq, uint32 duty) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; uint16 match_temp; //占空比值 uint16 period_temp; //周期值 uint16 freq_div = 0; //分频值
pwm_gpio_init(pwmch); //PWM引脚初始化
if((pwmch >> 8) == 0x00) RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //使能定时器1时钟 else if((pwmch >> 8) == 0x01) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能定时器2时钟 else if((pwmch >> 8) == 0x02) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟 else if((pwmch >> 8) == 0x03) RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能定时器4时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能AFIO复用功能模块时钟
//引脚重映射 if((pwmch >> 4) == 0x10) //PWM1的部分重映射 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM1, ENABLE); else if((pwmch >> 4) == 0x11) //PWM2的完全重映射 GPIO_PinRemapConfig(GPIO_FullRemap_TIM2, ENABLE); else if((pwmch >> 4) == 0x21) //PWM3的完全重映射 GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); else if((pwmch >> 4) == 0x22) //PWM3的部分重映射 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
//获取系统主频 sys_clk = 8000000 * (((RCC->CFGR0 >> 18)&0x0F) + 2);
freq_div = (uint16)((sys_clk / freq) >> 16); //多少分频 period_temp = (uint16)(sys_clk/(freq*(freq_div + 1))); //周期 match_temp = period_temp * duty / PWM_DUTY_MAX; //占空比
//初始化TIM1-4 TIM_TimeBaseStructure.TIM_Period = period_temp - 1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler = freq_div; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
//初始化TIM1-4 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_Pulse = match_temp; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高 TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性高 TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_TimeBaseInit(((TIM_TypeDef *) TIMERN[pwmch>>8]), &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
if((pwmch & 0x03) == 0x00) //通道选择 { TIM_OC1Init(((TIM_TypeDef *) TIMERN[pwmch>>8]), &TIM_OCInitStructure ); //定时器通道1初始化 TIM_OC1PreloadConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OCPreload_Enable); //定时器预装载配置 TIM_OC1FastConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OC1FE); //比较捕获通道快速使能 } else if((pwmch & 0x03) == 0x01) { TIM_OC2Init(((TIM_TypeDef *) TIMERN[pwmch>>8]), &TIM_OCInitStructure ); TIM_OC2PreloadConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OCPreload_Enable); TIM_OC2FastConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OC2FE); //比较捕获通道快速使能 } else if((pwmch & 0x03) == 0x02) { TIM_OC3Init(((TIM_TypeDef *) TIMERN[pwmch>>8]), &TIM_OCInitStructure ); TIM_OC3PreloadConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OCPreload_Enable); TIM_OC3FastConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OC3FE); //比较捕获通道快速使能 } else if((pwmch & 0x03) == 0x03) { TIM_OC4Init(((TIM_TypeDef *) TIMERN[pwmch>>8]), &TIM_OCInitStructure ); TIM_OC4PreloadConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OCPreload_Enable); TIM_OC4FastConfig(((TIM_TypeDef *) TIMERN[pwmch>>8]), TIM_OC4FE); //比较捕获通道快速使能 }
TIM_Cmd(((TIM_TypeDef *) TIMERN[pwmch>>8]), ENABLE); //定时器使能 TIM_CtrlPWMOutputs(((TIM_TypeDef *) TIMERN[pwmch>>8]), ENABLE ); //TIM_ARRPreloadConfig( TIM1, ENABLE ); }
|