当前位置:   article > 正文

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

stm32f103c8t6 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的推挽、开漏输出的引脚控制权是来自于输出数据寄存器,如果要用定时器控制引脚,就需要使用复用推挽或者复用开漏

  1. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //TIM外设
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //GPIO外设
  3. GPIO_InitTypeDef GPIO_InitStructure;
  4. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  5. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  6. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  7. GPIO_Init(GPIOA, &GPIO_InitStructure);
  8. TIM_InternalClockConfig(TIM2);

配置时基单元

  1. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  2. TIM_TimeBaseInitStruct.TIM_ClockDivision =TIM_CKD_DIV1;
  3. TIM_TimeBaseInitStruct.TIM_CounterMode =TIM_CounterMode_Up;
  4. TIM_TimeBaseInitStruct.TIM_Period =100-1; //ARR
  5. TIM_TimeBaseInitStruct.TIM_Prescaler =720-1; //PSC
  6. TIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;
  7. TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);

配置输出比较单元

  1. TIM_OCInitTypeDef TIM_OCInitStruct;
  2. TIM_OCStructInit(&TIM_OCInitStruct); //给结构体赋予一个默认值
  3. TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
  4. TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
  5. TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;
  6. TIM_OCInitStruct.TIM_Pulse=50; //Pulse是CCR的值
  7. TIM_OC1Init(TIM2,&TIM_OCInitStruct);
  8. 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代码

  1. #include "stm32f10x.h" // Device header
  2. void PWM_Init(void)
  3. {
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  6. GPIO_InitTypeDef GPIO_InitStructure;
  7. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  9. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10. GPIO_Init(GPIOA, &GPIO_InitStructure);
  11. TIM_InternalClockConfig(TIM2);
  12. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  13. TIM_TimeBaseInitStruct.TIM_ClockDivision =TIM_CKD_DIV1;
  14. TIM_TimeBaseInitStruct.TIM_CounterMode =TIM_CounterMode_Up;
  15. TIM_TimeBaseInitStruct.TIM_Period =100-1; //ARR
  16. TIM_TimeBaseInitStruct.TIM_Prescaler =720-1; //PSC
  17. TIM_TimeBaseInitStruct.TIM_RepetitionCounter =0;
  18. TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
  19. TIM_OCInitTypeDef TIM_OCInitStruct;
  20. TIM_OCStructInit(&TIM_OCInitStruct);
  21. TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_PWM1;
  22. TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
  23. TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;
  24. TIM_OCInitStruct.TIM_Pulse=50; //Pulse是CCR的值
  25. }
  26. void PWM_SetCompare1(uint16_t Compare)
  27. {
  28. TIM_SetCompare1(TIM2,Compare);
  29. }

pwm.h

  1. #ifndef __PWM_H
  2. #define __PWM_H
  3. void PWM_Init(void);
  4. void PWM_SetCompare1(uint16_t Compare);
  5. #endif

main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "PWM.h"
  5. uint8_t i; //定义变量
  6. int main (void)
  7. {
  8. OLED_Init();
  9. PWM_Init();
  10. while(1)
  11. {
  12. for (i=0;i <= 100; i++)
  13. {
  14. PWM_SetCompare1(i);
  15. Delay_ms(10);
  16. }
  17. for (i=0 ;i<= 100; i++)
  18. {
  19. PWM_SetCompare1(100-i);
  20. Delay_ms(10);
  21. }
  22. }
  23. }

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/57053
推荐阅读
相关标签
  

闽ICP备14008679号