输出比较简介输出比较简介
- OC(Output Compare)输出比较。
- 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。
- 每个高级定时器和通用定时器都拥有4个输出比较通道。
- 高级定时器的前3个通道额外拥有死区生成和互补输出的功能。
PWM简介
- PWM(Pulse Width Modulation)脉冲宽度调制。
- 在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域。
- PWM参数: 频率= 1 /TS。 占空比= TON / TS 分辨率= 占空比变化步距
输出比较通道(高级)
输出比较通道(通用)
输出比较模式
模式 | 描述 |
---|---|
冻结 | CNT=CCR时,REF保持为原状态 |
匹配时置有效电平 | CNT=CCR时,REF置有效电平 |
匹配时置无效电平 | CNT=CCR时,REF置无效电平 |
匹配时电平翻转 | CNT=CCR时,REF电平翻转 |
强制为无效电平 | CNT与CCR无效,REF强制为无效电平 |
强制为有效电平 | CNT与CCR无效,REF强制为有效电平 |
PWM模式1 | 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平 向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平 |
PWM模式2 | 向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平 向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平 |
PWM基本结构
参数计算
PWM频率: Freq= CK_PSC / (PSC+ 1) / (ARR+1)
PWM占空比: Duty= CCR / (ARR+ 1)
PWM分辨率: Reso= 1 / (ARR+ 1)
舵机简介
- 舵机是一种根据输入PWM信号占空比来控制输出角度的装置
- 输入PWM信号要求:周期为20ms,高电平宽度为0.5ms~2.5ms
硬件电路

直流电机及驱动简介
- 直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转。
- 直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作。
- TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向。
硬件电路
PWM驱动呼吸灯
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++)
{
PWM_Set_Compare1(i);
Delay_ms(10);
}
for(i=0;i<=100;i++)
{
PWM_Set_Compare1(i);
Delay_ms(10);
}
}
}
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_Initstructre;
GPIO_Initstructre.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_Initstructre.GPIO_Pin = GPIO_Pin_0;
GPIO_Initstructre.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Initstructre);
TIM_InternalClockConfig(TIM2);
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; //配置输出比较结构体
TIM_OCStructInit(&TIM_OCInitStructure); //给结构体赋初始值
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //输出比较模式选择---PWM模式一
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出比较极性选择---极性不翻转
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable ; //输出状态使能
TIM_OCInitStructure.TIM_Pulse = 0; //设置CCR寄存器值
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
void PWM_Set_Compare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare); //设置CCR值
}
PWM.h
#ifndef __PWM_H
#define __PWM_H
void PWM_Init();
void PWM_Set_Compare1(uint16_t Compare);
#endif
PWM驱动舵机
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
OLED_Init();
PWM_Init();
Key_Init();
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);
}
}
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_Initstructre;
GPIO_Initstructre.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_Initstructre.GPIO_Pin = GPIO_Pin_1;
GPIO_Initstructre.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Initstructre);
TIM_InternalClockConfig(TIM2);
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; //输出比较模式选择---PWM模式一
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_Set_Compare2(uint16_t Compare)
{
TIM_SetCompare2(TIM2,Compare); //设置CCR值
}
Servo.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_init(void)
{
PWM_Init();
}
//0 500
//180 2500
void Servo_SetAngle(float Angle)
{
PWM_Set_Compare2(Angle / 180 * 2000+500);
}
PWM驱动直流电机
main.c
#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();
Key_Init();
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);
}
}
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_Initstructre;
GPIO_Initstructre.GPIO_Mode =GPIO_Mode_AF_PP;
GPIO_Initstructre.GPIO_Pin = GPIO_Pin_2;
GPIO_Initstructre.GPIO_Speed =GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_Initstructre);
TIM_InternalClockConfig(TIM2);
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
#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);
}
}