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芯片引脚:

电机驱动芯片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));
		}
	}	
}

 

posted on 2025-01-23 13:56  轩~邈  阅读(240)  评论(0)    收藏  举报