STM32-PWM实验

PWM(Pulse Width Modulation)脉冲宽度调制

在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域。

PWM参数:      频率 = 1 / TS            占空比 = TON / TS           分辨率 = 占空比变化步距

PWM的初始化与定时器的初始化有着相同的基础,不过PWM在定时器初始化中加入了有关PWM的内容,就是如图中的输入/捕获寄存器。

从其运行流程上看

 

这是上一组定时器中断的实验,PWM实验则是在其中去除中断,通过输出比较寄存器CCR来控制输出的电平,如下图:

其输出比较通道的电路图如下图:

当计数器的值没有超过CCR寄存器的值的时候其输出的值与超过后的不同,如上图一路直通OC1 。其中输出模式控制器的模式可以更改,其模式如下图:

本次实验选择PWM模式1, 接下来在程序中将PWM的通路打通。

实验程序PWM.c文件:

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 100 - 1;
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720 -1;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCStructInit(&TIM_OCInitStruct);
	
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse = 0;  // CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStruct);
	
	TIM_Cmd(TIM2, ENABLE);

}

void PWM_change(uint16_t compare)
{
	TIM_SetCompare1(TIM2, compare);  // change CCR value

}

与定时中断实验程序的区别不大,去除中断程序配置,结构化OC输出比较单元,其中先将OC模块初始化配置使用TIM_OCStructInit(),因为其中还包含了一部分为用到的配值,但为了其不影响实验的运行,将其初始化配置后,自行更改需要的配置。其中包含了模式的选择,高低电平的选择,使能输出,然后是CCR的值,此实验中CCR的值又下面的函数更改。

PWM.h文件:

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_change(uint16_t compare);

#endif

至此完成了PWM的模块化初始配置。

接下来做第一个实验,PWM驱动的呼吸灯。

上面的程序中PWM波由PA0口输出,在此加上LED灯珠。

主函数main.c文件如下:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"

uint16_t i;

int main(void)
{
	OLED_Init();
	PWM_Init();
	OLED_ShowString(2, 5, "Flying!");

	
	while (1)
	{
		for(i = 0; i <= 100; i++)
		{
			PWM_change(i);
			Delay_ms(10);
		}
		for(i = 0; i <= 100; i++)
		{
			PWM_change(100 - i);
			Delay_ms(10);
		
		}
	}
}

其中循环中加入了一定的延时,至此才能够看到灯珠的呼吸态,这是由于PWM调制波的频率过高。

第二个实验是PWM驱动舵机,选用的舵机是SG90,其具体要求如下:

那么就要按照这个信号要求来输出PWM信号, PWM的参数计算如下:

知晓了其周期,以及其占空比就可以来推算出合适的参数来输出控制舵机的PWM波。

本次实验的ARR取2000-1,PSC取720,这样他的周期就是20ms,至于其占空比,可用角度angle/180 *200 +50,由此来确定其CCR的值。具体看如下程序。其中PWM文件不更改,新建sensor文件。

sensor.c文件如下:

#include "stm32f10x.h"                  // Device header
#include "PWM.h"

void sensor_Init(void)
{
	PWM_Init();
	
}

void sensor_angle(float angle)
{
	PWM_change(angle / 180 * 200 +50);

}

 就是加了一个按照要求更改占空比的函数。

sensor.h文件:

#ifndef __SENSOR_H
#define __SENSOR_H

void sensor_Init(void);
void sensor_angle(float angle);

#endif

本程序还用到了按键读取,具体程序看附件完整工程。

主函数main.c如下:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "sensor.h"
#include "Key.h"

uint16_t key_num;
float angle;

int main(void)
{
	OLED_Init();
	sensor_Init();
	Key_Init();
	OLED_ShowString(1, 1, "Angle:");

	
	while (1)
	{
		key_num = Key_GetNum();
		if(key_num == 1)
		{
			angle += 30;
			if(angle > 180)
			{
				angle = 0;
			}
		
		}
		sensor_angle(angle);
		OLED_ShowNum(1, 7, angle, 3);
		
	}
}

至此完成PWM驱动舵机的实验。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值