STM32F103C8T6的学习(5-1)——PWM驱动呼吸灯

 :  本教程基于up主江科大自化协——“STM32入门教程”记录的个人学习笔记​​​​​​​

跳转链接:STM32入门教程-2022持续更新中_哔哩哔哩_bilibili

输出比较介绍

OC(Output Compare)输出比较

输出比较可以通过比较CNTCCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形

每个高级定时器和通用定时器都拥有4个输出比较通道

高级定时器的前3个通道额外拥有死区生成和互补输出的功能

PWM简介

PWM(Pulse Width Modulation)脉冲宽度调制

在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域

PWM参数:

     频率 = 1 / TS            占空比 = TON / TS           分辨率 = 占空比变化步距

 Ton表示高电平

Ts表示整个周期

输出比较模式

TIM_OCMode_Timing                 
TIM_OCMode_Active               
TIM_OCMode_Inactive      
TIM_OCMode_Toggle     
TIM_OCMode_PWM1       
TIM_OCMode_PWM2 

有效电平:高电平

无效电平:低电平

PWM基本结构

 参数计算

其中蓝色线是CNT的值,黄色线是ARR的值,红色线是CCR的值

PWM频率:  Freq = CK_PSC / (PSC + 1) / (ARR + 1)

PWM占空比:  Duty = CCR / (ARR + 1)

PWM分辨率:  Reso = 1 / (ARR + 1)                          Reso越小越好,越小越细腻

 硬件电路

舵机

直流电机及驱动简介

直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转

直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作

TB6612是一款双路H桥型的直流电机驱动芯片,可以驱动两个直流电机并且控制其转速和方向

 

 VM:与电机的额定电压保持一致

VCC:与控制电路的电压保持一致(一般与控制电路共用)

TIM库函数

用结构体初始化输出比较单元

TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

//不同的GPIO口对应不同的比较单元(引脚定义表)

TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);//给输出比较结构体赋一个默认值(防止有些参数没有配置,出现报错)

用来配置强制输出模式(暂停波形并强制高低电平)

TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

用来配置CCR寄存器的预装功能

TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

用来配置快速使能的

TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

外部事件清除REP信号

TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

//注:TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);仅高级定时器使用,在使用高级定时器输出PWM时,需要调用这个函数,使能主输出,否则PWM将不能正常输出

单独更改CCR寄存器值的函数

TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);

TIM1_SetCompare1设置 TIM1 捕获比较 1 寄存器值
TIM1_SetCompare2设置 TIM1 捕获比较 2 寄存器值
TIM1_SetCompare3设置 TIM1 捕获比较 3 寄存器值
TIM1_SetCompare4设置 TIM1 捕获比较 4 寄存器值

//TIM1_SetCompare1是用来控制CCR寄存器的值,但是占空比跟CCR与ARR都有关

配置流程

1,配置时钟,把TIM外设与GPIO外设时钟打开

2,配置时基单元

3,配置输出比较单元

4,配置GPIO PWM对应的GPIO配置为复用推挽输出

5,控制运行

配置时钟 

配置GPIO为复用推挽输出

//因为GPIO的推挽、开漏输出的引脚控制权是来自于输出数据寄存器,如果要用定时器控制引脚,就需要使用复用推挽或者复用开漏

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   //TIM外设
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //GPIO外设
	
	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_Period =100-1;     //ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler =720-1;   //PSC
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;
	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=50;     //Pulse是CCR的值

    TIM_OC1Init(TIM2,&TIM_OCInitStruct);
	
	TIM_Cmd(TIM2,ENABLE);   //TIM2-CH1-ETR服用了PA0引脚
TIM1_OCMode描述
TIM1_OCMode_TIM1ingTIM1 输出比较时间模式
TIM1_OCMode_ActiveTIM1 输出比较主动模式
TIM1_OCMode_InactiveTIM1 输出比较非主动模式
TIM1_OCMode_ToggleTIM1 输出比较触发模式
TIM1_OCMode_PWM1TIM1 脉冲宽度调制模式 1
TIM1_OCMode_PWM2TIM1 脉冲宽度调制模式 2
TIM1_OCPolarity描述
TIM1_OCPolarity_HighTIM1 输出比较极性高
TIM1_OCPolarity_LowTIM1 输出比较极性低
TIM1_OutputState描述
TIM1_OutputState_Disable失能输出比较状态
TIM1_OutputState_Enable使能输出比较状态

TIM1_Pulse
TIM1_Pulse 设置了待装入捕获比较寄存器CCR的脉冲值。它的取值必须在 0x0000 和 0xFFFF 之间。                                                          Pulse表示CCR的值
//由于TIM_OCStructureInit已经给赋予一个默认值了

AAR=100-1;PSC=720-1;CCR=50;

对应的:

分辨率为1%;占空比为50%;频率为100Hz

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_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_Period =100-1;     //ARR
	TIM_TimeBaseInitStruct.TIM_Prescaler =720-1;   //PSC
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;
	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=50;     //Pulse是CCR的值
	
	
}

void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2,Compare);
}

pwm.h

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);

#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++)
		{
			PWM_SetCompare1(i);
			Delay_ms(10);
		}
		for (i=0 ;i<= 100; i++)
		{
			PWM_SetCompare1(100-i);
			Delay_ms(10);
		}
	}
}

后面使用PWM驱动舵机,直流电机都是基于上述函数进行二次开发,稍微观看视频即可理解

一个定时器有多个输出比较通道(一般是4个),可以对不同的通道调节不同的占空比,但是他们的频率和周期是保持一致的,周期一致指的是起始和结束是一致的

  • 10
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值