一、知識點補(bǔ)充
1.PWM波輸出與GPIO的引腳對應(yīng)關(guān)系圖
a. TIM2的引腳復(fù)用子啊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為調(diào)試端口,需要解除調(diào)試端
若想要讓PA15、PB3、PB4這三個引腳當(dāng)作普通GPIO來使用,則加第一、三句,打開AFIO時鐘,讓AFIO時鐘將JTAG復(fù)用解除掉
如果想要重映射定時器或者其他外設(shè)的復(fù)用引腳,加第一句和第二句,就要先打開AFIO時鐘,再用AFIO重映射外設(shè)復(fù)用的引腳,
若重映射的引腳正好是調(diào)試端口,則三句全加上
3.計數(shù)器的計算
PWM頻率=計數(shù)器更新頻率
比如要產(chǎn)生一個頻率為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外設(shè)和GPIO外設(shè)的時鐘
第二步:配置時基單元,包括時基單元和時基單元前的時鐘源選擇(不選擇則默認(rèn)內(nèi)部時鐘)
第三步:配置輸出比較單元,里面包括CCR的值、輸出比較模式、極性選擇、輸出使能(結(jié)構(gòu)體配置)
第四步:配置GPIO口,初始化為復(fù)用推挽輸出的配置
第五步:運行控制,啟動計數(shù)器,就能輸出PWM波
5.輸出比較模式簡介
常用模式為 PWM1模式1
二、實例
1.PWM驅(qū)動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); //初始化所以結(jié)構(gòu)體(結(jié)構(gòu)體中有帶N的變量,是高級配置輸出比較單元才有的,本次實例不需要用到,初始化后讓他不影響別的模塊)
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //設(shè)置比較輸出模式
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //設(shè)置極性
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //設(shè)置輸出使能
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設(shè)置占空比
{
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驅(qū)動舵機(jī)
參數(shù)計算
舵機(jī)要求頻率 :50Hz(周期為20ms)
舵機(jī)角度控制(占空比):0.5-2.5ms(時長)
(3個變量,2個方程)解不是唯一的
為方便計算
取PSC+1=72,ARR+1=20k
當(dāng)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) //變?yōu)橥ǖ?
{
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) //參數(shù)為浮點型,方便寫入
{
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驅(qū)動直流電機(jī)
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文章來源:http://www.zghlxwxcb.cn/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)//正轉(zhuǎn)
{
GPIO_SetBits(GPIOA, GPIO_Pin_4);
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(Speed);
}
else
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4);//反轉(zhuǎn)
GPIO_SetBits(GPIOA, GPIO_Pin_5);
PWM_SetCompare3(-Speed);
}
}
main.c文章來源地址http://www.zghlxwxcb.cn/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);
}
}
到了這里,關(guān)于stm32——pwm驅(qū)動LED燈、舵機(jī)、直流電機(jī)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!