蓝桥杯嵌入式开发经验分享(10.输出比较PWM)

作者:马一飞                                                         QQ:791729359       

在学习过程中有什么问题可以联系

(原本资料是以网盘的方式公开提供给任何蓝桥杯爱好者进行下载的,但是最近临近蓝桥杯考试,遇到了很多伸手党,我无偿给爱好者们解答学习上的问题,回复得比较慢居然还有同学来说我这样那样,所以决定不再随意提供自己写的源码和资料。博主已经开始参加工作了,也不是闲着没事干盯着电脑手机为你们服务。记住,不要成为伸手党,要自己多动手实现。)

 

        之前我们讲解了通用定时器使用PWM模式产生PWM波,但是到最后我们总结出了一个缺点:PWM模式同一定时器中,不同的通道下,输出的频率固定,占空比可变。也就是说在初始化时频率设置成多少,那么在这个定时器下的各个通道产生个PWM波频率也是相同的。

        那么如果想各个通道产生的PWM频率不同,占空比也不同,那我们就需要借助一个通用定时器的输出比较模式了。

        首先我们先理解一下什么叫输出比较,我给大家简单画一个简图。

蓝桥杯嵌入式开发经验分享(10.输出比较PWM)_第1张图片

我们知道,stm32f1的通用定时器位数的16位的,那么就代表计数值最大可以达到0xFFFF如果到了0xFFFF再继续往下计数的话就会清0重新向上技术。那么我们可以利用定时器的这个特点,来产生一个PWM波。

        我们把计数值设置成0xFFFF,那么定时器就会一直向上计数,pulse就相当于我们设定的周期值,也就是我们所说的频率。那么,在一个周期内,占空比是多少?就是Duty所决定的,在一个pulse内,小于Duty为高电平,大于Duty为低电平,直到进入下一个pulse。这就是输出比较模式的特点。为什么把它称作为输出比较模式呢?就是因为定时器的计数值一直向上计数的同时,他要不断的跟我们设定的pulse和Duty做比较。

        我们把这个概念理解好了之后,就可以开始编写代码了。为了更好的让大家学习PWM波,上一次用的是TIM3,这次我就用TIM2来产生PWM

同样的方法,首先我们先查看有哪些引脚是复用为TIM2的

蓝桥杯嵌入式开发经验分享(10.输出比较PWM)_第2张图片

我们可以看到PA1,PA2,PA3都可以复用为TIM2,这次我们就用了PA1,PA2做双通道比较输出吧。如果大家想再开启PA3也是相同的方法。

        我们使用输出比较PWM的话是要用到定时器中断的,但是这个中断又不等同于定时中断。既然用到中断的话就一定要吧misc.c这个库函数添加进工程目录里。

 

1. 首先当然得使能PA口和TIM2时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

2.初始化PA1,PA2设置复用推挽输出模式

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);

3.配置TIM2中断

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

4. 配置定时器2基础设置,我们把计数值设置到最大,也就是0xffff,并且71分频。

TIM_TimeBaseInitStructure.TIM_Period = 0xffff;
TIM_TimeBaseInitStructure.TIM_Prescaler = 71;
TIM_TimeBaseInitStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseInitStructure.TIM_CounterMode = 0x0;
TIM_TimeBaseInit( TIM2, &TIM_TimeBaseInitStructure);

5. 通过输入的频率值,算出pulse的值,也就是周期值

CH2_Val = 1000000 / ch2_fre;
CH3_Val = 1000000 / ch3_fre;
CH2_Duty = CH2_Val * ch2_duty / 100;
CH3_Duty = CH3_Val * ch3_duty / 100;

        因为是71分频,所以pulse的值就等于1000000 除 输入的频率值。

        同时还得通过设定的占空比数,算出Duty的位置。

6. 设定输出模式为触发模式,并且极性为低极性,使能输出,把算出来的周期指赋给Pulse。

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CH2_Val;
TIM_OC2Init(TIM2,&TIM_OCInitStructure);
		
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CH3_Val;
TIM_OC3Init(TIM2,&TIM_OCInitStructure);

7. 把定时器计数值清0,并且把通道2,通道3的比较值也设置为0,在接下来只要一启动定时器就直接开始比较了。

TIM_SetCounter(TIM2,0x0);
TIM_SetCompare2(TIM2,0x0);
TIM_SetCompare3(TIM2,0x0);

8.启动定时器,并使能通道2、通道3比较中断。

TIM_Cmd( TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_CC2 | TIM_IT_CC3, ENABLE);

这个时候我们就把输入比较初始化完成了。

那么我们就要开始编写中断处理函数,手动的让定时器按照我们的要求,去产生指定占空比的PWM波形。

我们先定义两个标志位。用来确定我们当前比较的状态。

然后就开始编写中断服务函数了,

u16 capture;
if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == 1)
{
	TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
	capture = TIM_GetCapture2(TIM2);
	if(channel_2_flag)
	{
		TIM_SetCompare2(TIM2,capture + CH2_Duty);
	}else
	{
		TIM_SetCompare2(TIM2,capture + CH2_Val - CH2_Duty);
	}
	channel_2_flag ^= 1;
}

我们要写定义一个16位的变量,用处是来获取我们通道当前的比较值。在每次进入比较中断时,我们都把通道当前的比较值获取到capture里,当我们channel_2_flag为真的时候,代表将进入Duty以下的位置,channel_2_flag为假则代表将进入Duty以上的位置。当我们每次得到一个中断,引脚都会自动的把电平翻转,我们再中断处理函数中只需要设定好比较值就ok了。

TIM_SetCompare2(TIM2,capture + CH2_Duty);

代表在当前的比较值,加上一个高电平时间作为通道2的比较值。而

TIM_SetCompare2(TIM2,capture + CH2_Val - CH2_Duty);

        则是在当前的比较值加上一个低电平时间作为通道2的比较值。那么当我们初始化完成之后,比较通道的值就会不断的与计数值进行比较,假如计数值到达我们比较值,那么就会产生一个中断请求,并且引脚的电平会翻转。

同理,通道3的设置也是相同的。

if(TIM_GetITStatus(TIM2, TIM_IT_CC3) == 1)
{
	TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
	capture = TIM_GetCapture3(TIM2);
	if(channel_3_flag)
	{
		TIM_SetCompare3(TIM2,capture + CH3_Duty);
	}else
	{
		TIM_SetCompare3(TIM2,capture + CH3_Val - CH3_Duty);
	}
	channel_3_flag ^= 1;
}

那么我们写好之后就可以烧录这个程序到开发板上看看效果。

TIM2_PWM_OUTPUT(1000,40,5000,80);

我们把通道2的频率设置为1000HZ,占空比为40%,通道3的频率设置为5000HZ,占空比为80%。

我们用逻辑分析仪看看PA1,PA2引脚上产生的波形。

先看PA1的波形

蓝桥杯嵌入式开发经验分享(10.输出比较PWM)_第3张图片

PA2的波形

蓝桥杯嵌入式开发经验分享(10.输出比较PWM)_第4张图片

我们能够看到,完全达到我们的要求,且产生的波形频率和占空比,非常准确无误差。

我们能够发现,比较通道的优点是:同一定时器下,不同通道能够产生频率不同,占空比不同,甚至相位也不同的方波

至于相位不同怎么设置,也很简单,这个任务就交给你们思考啦。

 

                                                                                                                                                    (以上仅属于个人观点)

你可能感兴趣的:(蓝桥杯)