- 寄存器版本
参考手册:
STM32F4xx中文参考手册.pdf
STM32F405xx,STM32F407xx.pdf - pwm.h
#ifndef __PWM_H
#define __PWM_H
#include "sys.h"
//模块使能宏
#define TIM1_NUM 1
#define TIM5_NUM 1
#define PWM1 TIM1->CCR1
#define PWM2 TIM1->CCR2
#define PWM3 TIM1->CCR3
#define PWM4 TIM1->CCR4
#define PWM5 TIM5->CCR1
#define PWM6 TIM5->CCR2
#define PWM7 TIM5->CCR3
#define PWM8 TIM5->CCR4
//输出通道初始化
void out_pwm_io_init(u16 arr,u16 psc);
//TIM PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3);
#endif
- pwm.c
#include"pwm.h"
void out_pwm_io_init(u16 arr,u16 psc)
{
#if TIM1_NUM==1
/******* TIM1 CH1_E9 CH2_E11 CH3_E13 CH4_E14 *******/
RCC->AHB1ENR|=1<<4;
RCC->APB2ENR|=1<<0;
GPIO_Set(GPIOE,PIN9|PIN11|PIN13|PIN14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_AF_Set(GPIOE,9|11|13|14,1);
TIM1->ARR=arr; //设定计数器自动重装值
TIM1->PSC=psc; //设定预分频系数
TIM1->CCMR1 |=6<<4; //CH1 PWM1 模式
TIM1->CCMR1 |=6<<12; //CH2 PWM1 模式
TIM1->CCMR2 |=6<<4; //CH3 PWM1
TIM1->CCMR2 |=6<<12;//CH4 PWM1
TIM1->CCMR1 |=1<<3; // ch1预装载使能
TIM1->CCMR1 |=1<<11; // ch2预装载使能
TIM1->CCMR2 |=1<<3;// ch3预装载使能
TIM1->CCMR2 |=1<<11;// ch4预装载使能
/****/
TIM1->EGR|=1<<0; //ug位置一 不知道加这一句有什么用 看手册需要加
TIM1->CCER |=1<<0; //oc1 输出使能
TIM1->CCER |=0<<1; //oc1 高电平有效
TIM1->CCER |=1<<4; //CH2输出使能
TIM1->CCER |=0<<5; //oc2 高电平有效
TIM1->CCER |=1<<8; //CH3输出使能
TIM1->CCER |=0<<9; //oc3 高电平有效
TIM1->CCER |=1<<12; //CH4输出使能
TIM1->CCER |=0<<13; //oc4 高电平有效
//TIM4->BDTR |= 1<<15; //TIM1必须要这句话才能输出PWM
TIM1->CR1|=1<<7; //arpe使能
TIM1->CR1|=1<<0; //使能定时器4
#endif
#if TIM5_NUM==1
// TIM5 CH1_A0 CH2_A1 CH3_A2 CH4_A3
RCC->AHB1ENR|=1<<0;
RCC->APB1ENR|=1<<3;
GPIO_Set(GPIOA,PIN0|PIN1|PIN2|PIN3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);
GPIO_AF_Set(GPIOA,0|1|2|3,2);
TIM5->ARR=arr; //设定计数器自动重装值
TIM5->PSC=psc; //设定预分频系数
TIM5->CCMR1 |=6<<4; //CH1 PWM1 模式
TIM5->CCMR1 |=6<<12; //CH2 PWM1 模式
TIM5->CCMR2 |=6<<4; //CH3 PWM1
TIM5->CCMR2 |=6<<12;//CH4 PWM1
TIM5->CCMR1 |=1<<3; // ch1预装载使能
TIM5->CCMR1 |=1<<11; // ch2预装载使能
TIM5->CCMR2 |=1<<3;// ch3预装载使能
TIM5->CCMR2 |=1<<11;// ch4预装载使能
/****/
TIM5->EGR|=1<<0; //ug位置一 不知道加这一句有什么用 看手册需要加
TIM5->CCER |=1<<0; //oc1 输出使能
TIM5->CCER |=0<<1; //oc1 高电平有效
TIM5->CCER |=1<<4; //CH2输出使能
TIM5->CCER |=0<<5; //oc2 高电平有效
TIM5->CCER |=1<<8; //CH3输出使能
TIM5->CCER |=0<<9; //oc3 高电平有效
TIM5->CCER |=1<<12; //CH4输出使能
TIM5->CCER |=0<<13; //oc4 高电平有效
//TIM4->BDTR |= 1<<15; //TIM1必须要这句话才能输出PWM
TIM5->CR1|=1<<7; //arpe使能
TIM5->CR1|=1<<0; //使能定时器4
#endif
}
//TIM PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3)
{
#if TIM1_NUM==1
TIM1->CCR1=num0; //修改比较值,修改占空比
TIM1->CCR2=num1; //修改比较值,修改占空比
TIM1->CCR3=num2; //修改比较值,修改占空比
TIM1->CCR4=num3; //修改比较值,修改占空比
#endif
#if TIM5_NUM==1
TIM5->CCR1=num0; //修改比较值,修改占空比
TIM5->CCR2=num1; //修改比较值,修改占空比
TIM5->CCR3=num2; //修改比较值,修改占空比
TIM5->CCR4=num3; //修改比较值,修改占空比
#endif
}
- 飞控板有8路pwm输出,分别对应
PE14 TIM1CH1 ESC_PWM_OUT1
PE13 TIM1CH2 ESC_PWM_OUT2
PE11 TIM1CH3 ESC_PWM_OUT3
PE9 TIM1CH4 ESC_PWM_OUT4
PA0 TIM5CH1 ESC_PWM_OUT5
PA1 TIM5CH2 ESC_PWM_OUT6
PA2 TIM5CH3 ESC_PWM_OUT7
PA3 TIM5CH4 ESC_PWM_OUT8
- pwm_out相关电路
-库函数版本
- PWM.C
#include "PWM.h"
//TIMx: TIM模块号
//arr:自动重装值
//psc:时钟预分频数
void TIMx_PWM_Init(uint32_t arr, uint32_t psc)
{
//此部分需手动修改IO口设置
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
#if TIM1_NUM==1
/******* TIM1 CH1_E9 CH2_E11 CH3_E13 CH4_E14 *******/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //TIM1时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE); //使能PORTE时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOE,&GPIO_InitStructure); //初始化PE口
GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1); //GPIOE9复用为定时器1
GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1); //GPIOE11复用为定时器1
GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1); //GPIOE13复用为定时器1
GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1); //GPIOE14复用为定时器1
TIM_TimeBaseStructure.TIM_Prescaler=psc*2; //定时器分频(此时定时器的时钟为APB2时钟)
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;//重复计数器寄存器(TIM1和TIM8中才设置)
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//初始化定时器1
//初始化TIM1 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = (arr+1)/2;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性低
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
//使能通道1
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器
//使能通道2
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器
//使能通道3
TIM_OC3Init(TIM1, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器
//使能通道4
TIM_OC4Init(TIM1, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); //使能TIM1在CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM1,ENABLE);//ARPE使能
TIM_Cmd(TIM1, ENABLE); //使能TIM1
TIM_CtrlPWMOutputs(TIM1,ENABLE);//启用TIM输出
#endif
#if TIM5_NUM==1
/******* TIM5 CH1_A0 CH2_A1 CH3_A2 CH4_A3 *******/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); //TIM5时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能PORTA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM5); //GPIOA0复用为定时器5
GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM5); //GPIOA1复用为定时器5
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM5); //GPIOA2复用为定时器5
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM5); //GPIOA3复用为定时器5
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA口
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载值
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);//初始化定时器5
//初始化TIM5 Channel1 PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
//使能通道1
TIM_OC1Init(TIM5, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC1PreloadConfig(TIM5, TIM_OCPreload_Enable); //使能TIM5在CCR1上的预装载寄存器
//使能通道2
TIM_OC2Init(TIM5, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC2PreloadConfig(TIM5, TIM_OCPreload_Enable); //使能TIM5在CCR1上的预装载寄存器
//使能通道3
TIM_OC3Init(TIM5, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM1 1OC1
TIM_OC3PreloadConfig(TIM5, TIM_OCPreload_Enable); //使能TIM5在CCR1上的预装载寄存器
//使能通道4
TIM_OC4Init(TIM5, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM4 1OC1
TIM_OC4PreloadConfig(TIM5, TIM_OCPreload_Enable); //使能TIM5在CCR1上的预装载寄存器
TIM_ARRPreloadConfig(TIM5,ENABLE);//ARPE使能
TIM_Cmd(TIM5, ENABLE); //使能TIM5
#endif
}
//TIM PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3)
{
#if TIM1_NUM==1
TIM_SetCompare1(TIM1,num0); //修改比较值,修改占空比
TIM_SetCompare2(TIM1,num1); //修改比较值,修改占空比
TIM_SetCompare3(TIM1,num2); //修改比较值,修改占空比
TIM_SetCompare4(TIM1,num3); //修改比较值,修改占空比
#endif
#if TIM5_NUM==1
TIM_SetCompare1(TIM5,num0); //修改比较值,修改占空比
TIM_SetCompare2(TIM5,num1); //修改比较值,修改占空比
TIM_SetCompare3(TIM5,num2); //修改比较值,修改占空比
TIM_SetCompare4(TIM5,num3); //修改比较值,修改占空比
#endif
}
- PWM.H
#ifndef _PWM_H_
#define _PWM_H_
#include "header.h"
//模块使能宏
#define TIM1_NUM 1
#define TIM5_NUM 1
//PWM输出初始化
void TIMx_PWM_Init(uint32_t arr, uint32_t psc);
//PWM输出
void setPwm(uint16_t num0,uint16_t num1,uint16_t num2,uint16_t num3);
#endif