蓝桥基础之硬件配置(四)——普通(通用)定时器的配置(②)

蓝桥基础之硬件配置(四)——普通(通用)定时器的配置(②)

~QQ:3020889729

~小蔡

简单说明一下:普通定时器部分将分为3个部分(①②③blog)——第一个部分(①blog)是通用初始化,仅仅是普通的定时中断;第二个部分(②blog)是PWM的一般输出配置;第三个部分(③blog)是输入捕获的配置。

PWM初始化配置

第一步·PWM输出通道初始化结构体参数的了解:

PWM作为定时器的输出功能。
它可以设置需要的频率和占空比来作为信号输出源。
下面就是对使用它之前的初始化参数进行简要说明
	GPIO_InitTypeDef GPIO_InitStructure;
	//输出PWM,需要有引脚作为输出通道,而定时器的引脚是固定(芯片手册有)的
	TIM_OCInitTypeDef TIM_OCInitStructure;//PWM输出通道,初始化参数结构体
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定时器基本参数初始化结构体

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能对应的输出通道的引脚
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器的时钟

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;//引脚1——对应TIME2通道2
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//输出模式——复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度一般选择50Mhz就好——个人觉得比赛和一般情况下不用换
	
	GPIO_Init(GPIOA, &GPIO_InitStructure);//IO口的初始化

	TIM_TimeBaseInitStructure.TIM_Period = 999;//1000的预装载值,一次完整的计数为1ms----即对应的PWM频率1000hz
	TIM_TimeBaseInitStructure.TIM_Prescaler = 71;//每记录一次1us/共1000000=即1Mhz
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;//时钟不分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;//计数模式——向上计数(0x0)
	
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//定时器基础配置初始化函数

	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//PWM模式1——PWM属于输出比较的特殊情况
	//常用的PWM模式还有:TIM_OCMode_PWM2
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//输出低极性——即有效电平为低电平
	//另外常用的模式:TIM_OCPolarity_High——输出高极性
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//通道输出打开
	//不想输出PWM时,可以将通道关闭——TIM_OutputState_Disable
	
	TIM_OCInitStructure.TIM_Pulse=(999)*duty_1/100;
	//比较值——在PWM模式下,它是占空比的有效值范围
	//eg:duty_1=50时,TIM_Pulse的值就代表了50%占空比——
	//999的预装载值下计算的,改变999为其它占空比都是一样的——比例由:duty_1/100控制
	
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);//通道2初始化函数
	
	TIM_SetCounter(TIM2,0);//设置定时器当时值——设置为0时,就是定时器新启

	TIM_Cmd(TIM2,ENABLE);//TIM2定时器打开

第二步·PWM输出初始化的配置:
其实,以后无论哪一个外设或者模块的初始化大都是一个大路线——时钟源(APB1/APB2),初始化参数(IO/BeseInit等),功能使能,除此之外可能有一些功能嵌套(比如定时器PWM之类的)需要在参数上做增添或者修改,但是大体都一样的。

#include "timer.h"

void PWM_Init(u8 duty_1)//函数功能,实现相同频率下不同占空比的PWM输出
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//参数结构体初始化——初始化参数

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//相应时钟使能——时钟源
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);//IO口初始化
	
	TIM_TimeBaseInitStructure.TIM_Period = 999;//1000的预装载值,一次完整的计数为1ms----即对应的PWM频率1000hz
	TIM_TimeBaseInitStructure.TIM_Prescaler = 71;//每记录一次1us/共1000000=即1Mhz
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;
	TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//定时器基础配置初始化

	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//输出:翻转
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//有效电平高电平
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse=(999)*duty_1/100;//占空比--计数值
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);//通道初始化2
	
	TIM_SetCounter(TIM2,0);//设置定时器值
	
	TIM_Cmd(TIM2,ENABLE);//定时器打开——功能使能

}

第三步·PWM占空比的初调试:
我这里是用初始化函数入口参数控制的占空比修改,还有一种是通过改变对应通道的比较值来实现占空比的修改的。我在末尾贴上代码。

#include "stm32f10x.h"
#include "lcd.h"
#include "timer.h"

u32 TimingDelay;//这个在滴答定时中断中被引用,实现定时

//Main Body
int main(void)
{
    u8 dutys=50;//占空比 
	SysTick_Config(SystemCoreClock/1000);
	PWM_Init(50);//初始化输出占空比为50%的波
	while(1)
	{
		Delay_Ms(500);//0.5s改变一次占空比
		dutys+=10;
		if(dutys==110)
			dutys=10;
		PWM_Init(dutys);//更改占空比输出
	}
}

void Delay_Ms(u32 nTime)//
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

PWM输出可能出现的问题

①输出时的频率的计算:
	在PWM模式下的PWM输出频率=时钟源(72Mhz)/(分频系数*预装载值)
	1)我个人认为,确定分频系数为71后,工作频率就等于1Mhz=1000000hz
	2)这样只需要确定自己要的频率(fre),用1000000/fre得到预装载值。
②占空比的计算:
	在PWM模式1下,占空比的有效值是Pulse值;
	在PWM模式2下,占空比的有效值是预装载值-Pulse值后余下的值。
③有效电平的选择:
	Low也就是有效电平为低电平,High就是有效电平为高电平。
	关于有效电平——我觉得可以这么理解,选Low,意味着输出的有效值内都是低电平,无效值部分就是高电平。

结束

这就是简单的PWM输出初始化配置(②),希望对大家有所帮助——对于比赛之后,如果还是有很大的兴趣,在使用其他开
发板时,配置方法都是大同小异的——一般都是,先去查看原理图以及函数参数,再开始配置。

代码补充:(代码如有纰漏,还望道友指出,一起进步,一起加油!)
(初始化部分)

#include "timer.h"

void PWM_Init(u32 per,u32 pre)
{
	
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_TimeBaseInitStructure.TIM_Period = per;//预装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler = pre;//工作频率=72Mhz/(pre+1)
	TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;
	TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//输出:翻转
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//有效电平高电平
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse=0;//占空比--计数值暂时置0
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);//通道初始化2
	 
	TIM_SetCounter(TIM2,0);//设置定时器起始值
	
	TIM_Cmd(TIM2,ENABLE);
}

(主函数部分)

#include "stm32f10x.h"
#include "lcd.h"
#include "timer.h"

u32 TimingDelay = 0;

//Main Body
int main(void)
{
	u8 dutys=50;//占空比 
	SysTick_Config(SystemCoreClock/1000);
	PWM_Init(1000,71);//1000hz
	while(1)
	{
		Delay_Ms(500);//0.5s改变一次占空比
		dutys+=10;
		if(dutys==110)
			dutys=10;//百分十之比
		TIM_SetCompare2(TIM2,1000*dutys/100);//公式和之前一样——设置新的比较值,来实现占空比的变化
	}
}

//
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}
发布了7 篇原创文章 · 获赞 7 · 访问量 4998

猜你喜欢

转载自blog.csdn.net/weixin_44604887/article/details/104007753