1、STM32的输出比较功能:PWD驱动呼吸灯、舵机和直流电机
OC(Output Compare)、CC (Capture Compare)、IC (Input Capture)
2、PWM(Pulse Width Modulation)
🧭调节高电平和低电平的比例,控制模拟量的大小,例如LED灯亮度、直流电机转速等惯性系统。
🎮 比较时基单元计数器CNT和输出比较CCR寄存器的值,对电平进行置1、0和翻转电平,以输出指定频率和占空比的PWM波形。
频率:频率越快,等效模拟的信号越平稳
占空比:高电平时间 / 周期,占空比可以调节模拟量大小
分辨率:占空比变化步距


输出模式控制器的8种模式:

PWM的基本结构:

PWM的频率 f = CK_PSC / (PSC+1)(ARR+1)
PWM的占空比 = CCR / ARR+1
PWM的分辨率 = 1 / ARR+1
舵机和直流电机的工作原理:
PWM控制舵机输出轴的角度(PWM作为通信协议):信号周期为20ms,高电平宽度为0.5至2.5ms,对应的输出轴角度为-90°至90度。
直流电机:正接时正转,反接时反转。
常见的电机驱动芯片:TB6612、DRV8833、L9110、L298N
TB6612是双路H桥型直流电机驱动芯片,可以控制正反转。

TB6612芯片引脚:


旋转编码器调节LED灯亮度实验

旋转编码器源文件:
EnCoder.c
#include "stm32f10x.h" // Device header
int16_t EnCoder_Cnt = 0;
void EnCoder_Init(void)
{
/* RCC开启GPIOB和AFIO时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* EXTI 和 NVIC 不需要开启时钟 */
/* 配置GPIO */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* 配置AFIO */
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
/* 配置EXTI */
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line1;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStruct);
/* 配置NVIC */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_Init(&NVIC_InitStruct);
}
int16_t EnCode_Get(void)
{
int16_t tmp_Cnt = 0;
tmp_Cnt = EnCoder_Cnt;
EnCoder_Cnt = 0;
return tmp_Cnt;
}
void EXTI0_IRQHandler(void)
{
if( EXTI_GetITStatus(EXTI_Line0) == SET )
{
if(0 == GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1))
{
EnCoder_Cnt --;
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void)
{
if( EXTI_GetITStatus(EXTI_Line1) == SET )
{
if(0 == GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0))
{
EnCoder_Cnt ++;
}
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
旋转编码器头文件EnCoder.h:
#ifndef __ENCODER_H__
#define __ENCODER_H__
void EnCoder_Init(void);
int16_t EnCode_Get(void);
#endif
PWM源文件PWM.c
#include "stm32f10x.h" // Device header
#define ARR (100-1)
#define PSC (720-1)
// 输出频率等于 72MHz/(PWM_TimPeriod * PWM_TimPrescaler)= 72000000/(10 * 7200) = 1000
/*
1、RCC开始时钟,打开TIM定时器和GPIO的时钟
2、时钟源选择内部72MHz系统时钟
3、配置时基单元
4、配置输出比较单元
5、配置GPIOA引脚PA0
6、使能运行控制
*/
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_RepetitionCounter = 0;
TIM_TimeBaseInitStruct.TIM_Period = ARR;
TIM_TimeBaseInitStruct.TIM_Prescaler = PSC;
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;
TIM_OC1Init(TIM2, &TIM_OCInitStruct);
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2, Compare);
}
PWM头文件PWM.h
#ifndef __PWM_H__
#define __PWM_H__
extern void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare1);
#endif
主函数文件main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "EnCoder.h"
#include "PWM.h"
int16_t Num = 1;
int16_t i = 1;
int main(void)
{
OLED_Init();
EnCoder_Init();
PWM_Init();
while(1)
{
Num += EnCode_Get();
OLED_ShowSignedNum(1,1,Num,5);
if(Num > 0)
{
PWM_SetCompare1(Num*2);
}
else
{
PWM_SetCompare1(Num * (-2));
}
}
}
PWM输出比较
浙公网安备 33010602011771号