这节课依然是利用之前学过的数码管显示结合定时器的使用,再做一下进阶的使用。利用数码管来显示数字,然后LED根据定时器输出可变的PWM呈现呼吸灯的效果。为后续的直流电机控制打下一个良好的基础。
一、Proteus仿真图
硬件电路图可以参考之前的静态数码管显示电路:
基于Proteus无实物STM32入门自学教程(三)--静态数码管_永远都是新手的博客-CSDN博客
在此基础上增加了如上的按键和LED灯,并且LED灯的输出的IO使用示波器观测其波形,验证软件是否可以输出可变的PWM波形。从两个仿真图和LED的亮暗程度可以看到达到了试验之处的目的。可以通过可变的PWM输出实现LED呼吸灯的效果。
二、MED代码
void TIM1_PWM_Init(u16 arr,u16 psc) //初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟使能
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度50Hz
GPIO_Init(GPIOA, &GPIO_InitStructure); //GPIO初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
TIM_ITConfig( TIM1, TIM_IT_Update , ENABLE ); //使能TIM3中断
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能
// TIM_CtrlPWMOutputs(TIM1,ENABLE);
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
void TIM1_UP_IRQHandler(void) //TIM1中断
{if(dir)led0pwmval++; //如果dir为1,占空比增加
else led0pwmval--; //如果为0,占空比减小
if(led0pwmval>300)dir=0; //占空比最大为75%(300/400)
if(led0pwmval==0)dir=1; //最小为0
TIM_SetCompare1(TIM1,led0pwmval); //调节CCRx(调节占空比)
TIM_ClearITPendingBit(TIM1, TIM_IT_Update ); //ARR重装载
}
从代码中可以看到,只要掌握了定时器的初始化函数,那么实际应用的时候我们只需要简单设计几行代码即可以满足使用要求。也就是我们自行创建一个自加函数,然后使得定时中断的装载值不断变化就可以实现可变的PWM了。其实思想很简单。大家仔细研读最后几行代码。其余的代码也就是之前的代码,这里就不多作介绍了。
三、仿真效果和源代码资源
基于Proteus无实物零基础STM32入门自学教程(九)数码管显示和按键呼吸灯_proteus8.13下载及安装-嵌入式文档类资源-CSDN下载