10、PWM

定義

PWM(Pulse Width Modulation),脉冲宽度调制。
脉冲:方波,频率(freq)
宽度:高电平的宽度,占空比(duty)

PWM的模式分为1和2
PWM1:TIMx_CNT<TIMx_CCR1,通道1便为有效状态,否则为无效状态
PWM2:TIMx_CNT<TIMx_CCR1,通道1便为无效状态,否则为有效状态
TIMx_CNT由TIM_TimeBaseStructure.TIM_Period决定
TIMx_CCR1由TIM_SetComparex(x:1、2、3、4)函数决定
有效状态由TIM_OCInitStructure.TIM_OCPolarity决定
其中频率值由计数值决定,占空比由比较值决定

#include "stm32f4xx.h"
#include "sys.h"

static GPIO_InitTypeDef GPIO_InitStructe;
static USART_InitTypeDef USART_InitStructe;
static NVIC_InitTypeDef NVIC_InitStructe;
static TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructe;
//串口初始化
void usart_init(uint32_t baud)
{
    //使端口A通电
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    
    //使串口1通电
    RCC_APB1PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
    
    //配置引脚9、10为复用功能
    GPIO_InitStructe.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
    GPIO_InitStructe.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructe.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructe.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructe.GPIO_PuPd = GPIO_PuPd_UP;//上拉电阻,串口空闲位为高电平
    GPIO_Init(GPIOA,&GPIO_InitStructe);
    
    //将引脚9、10链接到串口1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
    
    //串口参数初始化:设置波特率,字长,奇偶校验等参数 
    USART_InitStructe.USART_BaudRate = baud;//设置波特率
    USART_InitStructe.USART_WordLength = USART_WordLength_8b;//设置数据位
    USART_InitStructe.USART_StopBits = USART_StopBits_1;//设置停止位
    USART_InitStructe.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控制
    USART_InitStructe.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;//设置收发模式
    USART_Init(USART1,&USART_InitStructe);
    
    //设置串口的中断模式
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//开启中断,接受到数据时产生中断
    //设置串口1的优先级
    NVIC_InitStructe.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority =0;//抢占优先级
    NVIC_InitStructe.NVIC_IRQChannelSubPriority = 0;//响应优先级
    NVIC_InitStructe.NVIC_IRQChannelCmd = ENABLE;//使能串口1
    NVIC_Init(&NVIC_InitStructe);
    
    //使串口1工作
    USART_Cmd(USART1,ENABLE);
}

//定时器1初始化
void tim1_init(void)
{
    //使TIM1通电
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
    
    //【重点】设置定时器1的计数值,决定它的定时时间
    //定时器1的时钟频率=84MHz/8400=10000Hz
    //分频就是降低频率
    TIM_TimeBaseInitStructe.TIM_Period=(10000/100)-1;//定时为100ms
    TIM_TimeBaseInitStructe.TIM_Prescaler = 8400-1;//设置预分频值8400,第一次分频
    TIM_TimeBaseInitStructe.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructe);
    
    //设置TIM1的触发方式:时间更新中断
    TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
    
    //设置TIM1的优先级
    NVIC_InitStructe.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;//中断信号1
    NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructe.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructe.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructe);
    
    //使定时器1工作
    TIM_Cmd(TIM1,ENABLE);
}

//定时器2初始化
void tim2_init(void)
{
    //使TIM2通电
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    //【重点】设置定时器2的计数值,决定它的定时时间
    //定时器2的时钟频率=84MHz/8400=10000Hz
    //分频就是降低频率
    TIM_TimeBaseInitStructe.TIM_Period=(10000/50)-1;//定时为200ms
    TIM_TimeBaseInitStructe.TIM_Prescaler = 8400-1;//设置预分频值8400,第一次分频
    TIM_TimeBaseInitStructe.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructe);
    
    //设置TIM2的触发方式:时间更新中断
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    
    //设置TIM2的优先级
    NVIC_InitStructe.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructe.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructe.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructe);
    
    //使定时器2工作
    TIM_Cmd(TIM2,ENABLE);
}

void tim3_init(void)
{
    //使TIM3通电
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    //【重点】设置定时器3的计数值,决定它的定时时间
    //定时器3的时钟频率=84MHz/8400=10000Hz
    //分频就是降低频率
    TIM_TimeBaseInitStructe.TIM_Period=(10000/2)-1;//定时为500ms
    TIM_TimeBaseInitStructe.TIM_Prescaler = 8400-1;//设置预分频值8400,第一次分频
    TIM_TimeBaseInitStructe.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructe);
    
    //设置TIM3的触发方式:时间更新中断
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
    
    //设置TIM3的优先级
    NVIC_InitStructe.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructe.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructe.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructe);
    
    //使定时器3工作
    TIM_Cmd(TIM3,ENABLE);
}

//定时器8初始化
void tim8_init(void)
{
    //使TIM8通电
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);
    
    //【重点】设置定时器8的计数值,决定它的定时时间
    //定时器8的时钟频率=84MHz/8400=10000Hz
    //分频就是降低频率
    TIM_TimeBaseInitStructe.TIM_Period=(10000*2)-1;//设置计数值为9999,定时为2s
    TIM_TimeBaseInitStructe.TIM_Prescaler = 8400-1;//设置预分频值8400,第一次分频
    TIM_TimeBaseInitStructe.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
    TIM_TimeBaseInit(TIM8,&TIM_TimeBaseInitStructe);
    
    //设置TIM8的触发方式:时间更新中断
    TIM_ITConfig(TIM8,TIM_IT_Update,ENABLE);
    
    //设置TIM8的优先级
    NVIC_InitStructe.NVIC_IRQChannel = TIM8_UP_TIM13_IRQn;//中断信号1
    NVIC_InitStructe.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructe.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructe.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructe);
    
    //使定时器1工作
    TIM_Cmd(TIM8,ENABLE);
}

int main(void)
{
    
    RCC_AHB1PeriphClockCmd(  RCC_AHB1Periph_GPIOF
                            |RCC_AHB1Periph_GPIOE
                            ,ENABLE);
    
    GPIO_InitStructe.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructe.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructe.GPIO_OType =GPIO_OType_PP;
    GPIO_InitStructe.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructe.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOF,&GPIO_InitStructe);
    
    GPIO_InitStructe.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
    GPIO_Init(GPIOE,&GPIO_InitStructe);
    
    GPIO_SetBits(GPIOF,GPIO_Pin_9|GPIO_Pin_10);
    GPIO_SetBits(GPIOE,GPIO_Pin_13|GPIO_Pin_14);
    
    //串口1工作波特率为115200bps
    usart_init(115200);
    
    //初始化定时器1
    tim1_init();
    
    //初始化定时器2
    tim2_init();
    
    //初始化定时器3
    tim3_init();
    
    //初始化定时器3
    tim8_init();
    
    while(1)
    {
        
    }
}

void  TIM1_UP_TIM10_IRQHandler(void)
{
    if((TIM_GetITStatus(TIM1,TIM_IT_Update)) ==SET)
    {
        PFout(9) ^=1;
        //清空标志位
        TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
    }
}

void  TIM2_IRQHandler(void)
{
    if((TIM_GetITStatus(TIM2,TIM_IT_Update)) ==SET)
    {
        PFout(10) ^=1;
        //清空标志位
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
    }
        
}

void  TIM3_IRQHandler(void)
{
    if((TIM_GetITStatus(TIM3,TIM_IT_Update)) ==SET)
    {
        PEout(13) ^=1;
        //清空标志位
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    }
        
}

void  TIM8_UP_TIM13_IRQHandler(void)
{
    if((TIM_GetITStatus(TIM8,TIM_IT_Update)) ==SET)
    {
        PEout(14) ^=1;
        //清空标志位
        TIM_ClearITPendingBit(TIM8,TIM_IT_Update);
    }
}

おすすめ

転載: www.cnblogs.com/lp06/p/12002759.html
おすすめ