在STM32标准库编译中查看相关函数的方法(以PWM为例):
打开对应的头文件,比如PWM使用的库函数是tim库,打开tim.h结尾的文件,查找到1055行左右,如下图:
其中1056/1057/1058/1059行为输出比较函数,第一个参数为选择定时器,第二个为输出比较的结构体;
用以给TIM_OCInitTypeDef* TIM_OCInitStruct结构体付初始值。
此外,还有以下函数:
用以更改CCR寄存器值的,可用以修改PWM中的占空比。
用以配置强制输出模式,作用是运行中暂停输出波形并强制输出高电平或低电平。
作用为配置CCR寄存器的预装功能(影子寄存器,写入的值在更新事件后生效)
还有其他函数就不列举了
配置RCC时钟
打开TIM与GPIO外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
配置时基单元
按配置定时器的方法配置:
打开时钟
使用函数RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
选择内部时钟
TIM_InternalClockconfig(TIM2);
初始化时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义结构体
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//1分频
TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=100-1;
TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter =0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//使用结构体参数
启动定时器
TIM_Cmd(TIM2,ENABLE);
配置输出比较单元
按一开始找到的函数配置,初始化哪个通道(TIM对应的GPIO),就调用哪个函数:
如TIM1口:
对应GPIOA的8,9,10,11,12.则调用TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);函数,
参数1为TIM1,参数2为结构体:
TIM_OCInitTypeDef TIM_OCInitStructure;//定义结构体变量
TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始默认值,使用该函数,没赋值的参数就初始化为默认值,而非任意值
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //输出比较模式
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High ;//输出比较的极性,为高极性:有效电平为高电平
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出使能
TIM_OCInitStructure.TIM_Pulse= 50; //CCR,与定时器中的ARR与PSC决定了占空比与分辨率
TIM_OC1Init(TIM1,&TIM_OCInitStructure);
配置GPIO
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出模式,是控制权归定时器
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
配置占空比与频率:
公式:
频率:F=CK_PSC/(PSC+1)/(ARR+1)
占空比:D=CCR/(ARR+1)
分辨率:R=1/(ARR+1)
其中,ARR/PSC为定时器处配置,ARR为输出比较函数的结构体参数处配置。
那么,要得到频率为1khz,占空比为50%的波,可将ARR调为100-1,PSC为720-1,CRR=50;
完整代码
一个1khz,占空比50%的完整代码为:
#include "stm32f10x.h" // Device header
int main(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=100-1;
TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter =0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=50;
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_Cmd(TIM2,ENABLE);
while(1)
{
}
}
易犯错误:
在Keil中,代码靠边写容易报错,所以要每行空2格,若出现error: #268: declaration may not appear after executable statement in block错误,原因为C语言标准问题,在魔术棒的C/C++界面勾选使用C99标准即可: