STM32 PWM输出
PWM
脉冲宽度调制
由TIMx_ARR确定频率,由TIMx_CCRx确定占空比
两种PWM模式
- 1 TIMx_CNT<TIMx_CCRx 时为有效电平
- 2 TIMx_CNT>TIMx_CCRx 时为有效电平
PWM输出配置步骤
使能时钟(定时器时钟和相关IO口时钟)
RCC_APB1PeriphClockCmd();
RCC_APB2PeriphClockCmd();
IO口做为复用功能输出,初始化IO口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//选择对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PC端口
如果IO口要做重映射,还要使能AFIO时钟
//未做重映射
定时器初始化
TIM_TimeBaseStructure.TIM_Period=arr;
TIM_TimeBaseStructure.TIM_Prescaler=psc;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
初始化输出比较参数
TIM_OCInitTypeStructure.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitTypeStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitTypeStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC2Init(TIM3,&TIM_OCInitTypeStructure);
使能预装载寄存器
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
使能定时器
TIM_Cmd(TIM3,ENABLE);
在外部不断改变CCRx的值,调节占空比
TIM_SetCompare2(TIM3,led0pwmval);
配置示例
void TIM3_PWM(u16 arr,u16 psc)
{ TIM_OCInitTypeDef TIM_OCInitTypeStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOC和AFIO复用功能模块时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //选择对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PC端口
//GPIO_SetBits(GPIOC, GPIO_Pin_13 ); // 关闭所有LED
TIM_TimeBaseStructure.TIM_Period=arr;
TIM_TimeBaseStructure.TIM_Prescaler=psc;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_OCInitTypeStructure.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitTypeStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitTypeStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC2Init(TIM3,&TIM_OCInitTypeStructure);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_Cmd(TIM3,ENABLE);
}
总示例 使用TIM3,PA7接LED
#include "stm32f10x.h"
//#include "led.h"
void TIM3_PWM(u16 arr,u16 psc)
{TIM_OCInitTypeDef TIM_OCInitTypeStructure;
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//使能定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOC和AFIO复用功能模块时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //选择对应的引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PC端口
//GPIO_SetBits(GPIOC, GPIO_Pin_13 ); // 关闭所有LED
TIM_TimeBaseStructure.TIM_Period=arr;
TIM_TimeBaseStructure.TIM_Prescaler=psc;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_OCInitTypeStructure.TIM_OCMode=TIM_OCMode_PWM2;
TIM_OCInitTypeStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitTypeStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC2Init(TIM3,&TIM_OCInitTypeStructure);
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_Cmd(TIM3,ENABLE);
}
void Delay(__IO u32 nCount);
int main(void)
{
u16 led0pwmval=0;
u8 dir=1;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//SystemInit(); // 配置系统时钟为72M
//LED_GPIO_Config(); //LED 端口初始化
/*
while (1)
{
LED1( ON ); // 亮
Delay(0x200000);
LED1( OFF ); // 灭
Delay(0x200000);
LED2( ON );
Delay(0x200000);
LED2( OFF );
}*/
TIM3_PWM(899,0);
while(1){
Delay(1000);
if (dir)led0pwmval+=1;
else led0pwmval-=1;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
TIM_SetCompare2(TIM3,led0pwmval);
}
}
void Delay(__IO u32 nCount)
{
for(; nCount != 0; nCount--);
}
遇到的问题
STM32F103C8T6数据手册里没有找到重映射表,故没有做重映射。
而且STM32F103C8T6的重映射有点问题,虽然还没遇见,mark一下
另一个问题是,对定时器配置的函数写在另一个c文件里,在头文件h里声明函数,然后c和main.c都包含h,这样搞下来总有一个main.c(34): warning: #223-D: function "TIM3_PWM_Init" declared implicitly
故上面的示例里把配置函数和主函数写在了一起