一、知识点补充
1.PWM波输出与GPIO的引脚对应关系图
a. TIM2的引脚复用子啊PA0引脚上,所以TIM2、CH1、PA0三者是捆绑在一起的,即在PA0引脚上通过TIM2通道1CH1输出PWM
b. TIM2、CH1、PA0三者一般是捆绑在一起,但可以通过重映射改变
c. TIM2、CH2、PA1同理
2.重映射简介
改为PA15,选择重映射方式1或完全重映射
在时钟开启后写入
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //PA15为调试端口,需要解除调试端
若想要让PA15、PB3、PB4这三个引脚当作普通GPIO来使用,则加第一、三句,打开AFIO时钟,让AFIO时钟将JTAG复用解除掉
如果想要重映射定时器或者其他外设的复用引脚,加第一句和第二句,就要先打开AFIO时钟,再用AFIO重映射外设复用的引脚,
若重映射的引脚正好是调试端口,则三句全加上
3.计数器的计算
PWM频率=计数器更新频率
比如要产生一个频率为1KHz,占空比为50%,分辨率为1%的PWM波形
72M/(PSC+1)/ (ARR+1)=1000
CCR/(ARR+1)=0.5
1/(ARR+1)=0.01
计算得:ARR=99,CCR=50, PSC=720-1;
4.基本步骤
第一步:RCC开启时钟,打开TIM外设和GPIO外设的时钟
第二步:配置时基单元,包括时基单元和时基单元前的时钟源选择(不选择则默认内部时钟)
第三步:配置输出比较单元,里面包括CCR的值、输出比较模式、极性选择、输出使能(结构体配置)
第四步:配置GPIO口,初始化为复用推挽输出的配置
第五步:运行控制,启动计数器,就能输出PWM波
5.输出比较模式简介
常用模式为 PWM1模式1
二、实例
1.PWM驱动LED灯
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //第一步,开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure; //第四步,配置GPIO
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //第二步,配置时基单元
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure; //第三步,配置输出比较单元(CCR)
TIM_OCStructInit(&TIM_OCInitStructure); //初始化所以结构体(结构体中有带N的变量,是高级配置输出比较单元才有的,本次实例不需要用到,初始化后让他不影响别的模块)
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 = 0; //CCR(0-0xff)
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2,ENABLE);//第五步,运行控制启动
}
void PWM_SetCompare1(uint16_t Compare) //由main.c设置占空比
{
TIM_SetCompare1(TIM2,Compare);
}
PWM.h
#ifndef __PWM_H__
#define __PWM_H__
void PWM_SetCompare1(uint16_t Compare);
void PWM_Init(void);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
uint8_t i;
int main(void)
{
OLED_Init();
PWM_Init();
while(1)
{
for(i=0;i<=100;i++) 更改CCR值
{
PWM_SetCompare1(i);
Delay_ms(10);
}
for(i=0;i<=100;i++)
{
PWM_SetCompare1(100-i);
Delay_ms(10);
}
}
}
2.PWM驱动舵机
参数计算
舵机要求频率 :50Hz(周期为20ms)
舵机角度控制(占空比):0.5-2.5ms(时长)
(3个变量,2个方程)解不是唯一的
为方便计算
取PSC+1=72,ARR+1=20k
当CCR=500时,高电平时长为0.5ms
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_1; //GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
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 = 0; //CCR
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2,ENABLE);
}
void PWM_SetCompare2(uint16_t Compare) //变为通道2
{
TIM_SetCompare2(TIM2,Compare);
}
Servo.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void)
{
PWM_Init();
}
void Servo_SetAngle(float Angle) //参数为浮点型,方便写入
{
PWM_SetCompare2(Angle / 180 * 2000 + 500);
}
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
OLED_Init();
Servo_Init();
Init_KEY();
OLED_ShowString(1, 1, "Angle:");
while (1)
{
KeyNum = Key_Getnum();
if (KeyNum == 1)
{
Angle += 30;
if (Angle > 180)
{
Angle = 0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(1, 7, Angle, 3);
}
}
3.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_2; //GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
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 = 0; //CCR
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_Cmd(TIM2,ENABLE);
}
void PWM_SetCompare3(uint16_t Compare)
{
TIM_SetCompare3(TIM2,Compare);
}
Motor.c文章来源:https://www.toymoban.com/news/detail-765471.html
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Motor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
PWM_Init();
}
void Motor_SetSpeed(int8_t Speed)
{
if (Speed >= 0)//正转
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(Speed);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4);//反转
GPIO_SetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(-Speed);
}
}
main.c文章来源地址https://www.toymoban.com/news/detail-765471.html
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "Key.h"
uint8_t KeyNum;
int8_t Speed;
int main(void)
{
OLED_Init();
Motor_Init();
Init_KEY();
OLED_ShowString(1, 1, "Speed:");
while (1)
{
KeyNum = Key_Getnum();
if (KeyNum == 1)
{
Speed += 20;
if (Speed > 100)
{
Speed = -100;
}
}
Motor_SetSpeed(Speed);
OLED_ShowSignedNum(1, 7, Speed, 3);
}
}
到了这里,关于stm32——pwm驱动LED灯、舵机、直流电机的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!