美文网首页
抛弃原理不看文档我只想实现PWM输出控制LED

抛弃原理不看文档我只想实现PWM输出控制LED

作者: 八斗东流 | 来源:发表于2019-05-01 15:37 被阅读0次

刚刚实现PWM控制LED亮度,急急忙忙总结一下.
还望斧正.

第一步-了解什么是PWM脉冲宽度调制

什么是脉冲宽度调制

通过TIM快速开关电源改变占空比.

通过改变占空比改变平均电压.

1556684804542.png

就是通过一个值改变一个周期内高低电平所占的宽度.

这个值存放在CCR中,也就是捕获寄存器中.

我们可以控制某个引脚输出高电平点亮LED灯,但是也只是点亮LED灯.

通过PWM我们便可以来控制灯的亮度,高电平在一个周期内所占的越大,灯便越亮,反之高电平越小灯便越暗.

开发板资源

1556684883785.png

我使用的是STM32F407ZGT6野火的霸天虎开发板.

在这里我选择了PB15通道2(CH2).

第二步-输出捕获代码

初始化GPIO引脚复用

    /*定义一个GPIO_InitTypeDef类型的结构体*/
    GPIO_InitTypeDef GPIO_InitStructure;
    /*开启相关的GPIO外设时钟*/
    RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOB, ENABLE);
    /* 定时器通道引脚复用 */
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_TIM12);
    /* 定时器通道引脚配置 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

这一部分代码写的是将PB15引脚复用,推挽输出,不上拉也不下拉.

初始化中断优先级

    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    // 设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel =TIM8_BRK_TIM12_IRQn;
    // 设置抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    // 设置子优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

这一部分主要是设置中断来源,抢占优先级和子优先级.

初始化TIM定时器基础

clip_image001.png
void TIM_Base_Config(unsigned int psc,unsigned int arr)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    // 开启TIMx_CLK,x[2,3,4,5,12,13,14]
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12, ENABLE);
    /* 累计 TIM_Period个后产生一个更新或者中断*/
    //当定时器从0计数到8399,即为8400次,为一个定时周期
    TIM_TimeBaseStructure.TIM_Period = arr-1;
    // 通用控制定时器时钟源TIMxCLK = HCLK/2=84MHz
    // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=100KHz
    TIM_TimeBaseStructure.TIM_Prescaler =psc-1;
    // 采样时钟分频
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    // 计数方式
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    // 初始化定时器TIMx, x[2,3,4,5,12,13,14]
    TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure);
}

这一部分为配置TIM12的基础部分.

两个参数分别为

计数

TIM_TimeBaseStructure.TIM_Period = arr-1;

分频

TIM_TimeBaseStructure.TIM_Prescaler =psc-1;

初始化PWM模式

clip_image001-1556695815462.png
void TIM_PWM_Config(void)
    {
    /*PWM模式配置*/
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    /* PWM1 Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//配置为PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 2800-1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//当定时器计数值小于CCR1_Val时为高电平
    TIM_OC2Init(TIM12, &TIM_OCInitStructure);    //使能通道2
    /*使能通道2重载*/
    TIM_OC2PreloadConfig(TIM12, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(TIM12, ENABLE);            //使能TIM重载寄存器ARR
    // 开启计数器中断
    TIM_ITConfig(TIM12,TIM_IT_Update,ENABLE);
    // 使能定时器
    TIM_Cmd(TIM12, ENABLE);
}

这里要注意几个地方,一个是使能通道2初始化,一个是使能通道2重载.

如果说使用的是CH1(通道1),那么只需要将函数修改为通道1即可.

例:

    TIM_OC1Init(TIM12, &TIM_OCInitStructure);    //使能通道2
    /*使能通道2重载*/
    TIM_OC1PreloadConfig(TIM12, TIM_OCPreload_Enable);

中断服务函数

void TIM8_BRK_TIM12_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM12,TIM_IT_Update))
    {
            TIM12->CCR2=100;
            TIM_ClearITPendingBit(TIM12,TIM_IT_Update);
    }   
}

CCR2就是(CH2)通道2的捕获寄存器,通过修改CCR2的值.

注意:如果说引脚持续输出高电平,

没有低电平的切换的话大多是因为CCR的值高出了周期,

修改下计数分频或者修改CCR的值都可.

相关文章

网友评论

      本文标题:抛弃原理不看文档我只想实现PWM输出控制LED

      本文链接:https://www.haomeiwen.com/subject/asqwnqtx.html