当前位置:   article > 正文

STM32-TIM定时器输出比较_stm32定时器输出比较

stm32定时器输出比较

目录

一、输出比较简介

二、PWM简介

三、输出比较通道(通用)

四、输出比较通道(高级)

五、输出比较模式

六、PWM基本结构 

七、PWM参数计算

八、外设介绍

8.1 舵机

8.2 直流电机及驱动

九、开发步骤

十、输出比较库函数 

十一、实验

9.1 PWM驱动LED呼吸灯

9.2 PWM驱动舵机

9.3 PWM驱动直流电机


一、输出比较简介

>OC(Output Compare)输出比较
>输出比较可以通过比较CNT与CCR(捕获/比较寄存器)值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
>每个高级定时器和通用定时器都拥有4个输出比较通道
>高级定时器的前3个通道额外拥有死区生成和互补输出的功能

二、PWM简介

>PWM(Pulse Width Modulation)脉冲宽度调制
>在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域
>PWM参数:
  频率 = 1 / Ts           占空比 = Ton / Ts           分辨率 = 占空比变化步距

三、输出比较通道(通用)

四、输出比较通道(高级)

五、输出比较模式

六、PWM基本结构 

七、PWM参数计算

八、外设介绍

8.1 舵机

8.2 直流电机及驱动

九、开发步骤

①RCC打开时钟,TIM和GPIO外设的时钟打开

②配置时基单元,包括前面的时钟源选择

③结构体配置输出比较单元(CCR,输出比较模式,极性选择,输出使能)

④配置GPIO,PWM对应GPIO初始化为复用推挽输出

⑤运行控制,启动计数器

十、输出比较库函数 

注:标@的为重要,需掌握

@===================输出比较4模块配置函数==============================

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

参数:①定时器;②结构体

=====================================================================

void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

//输出比较结构体赋初值

=====================配置强制输出模式(了解即可)========================

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

=============配置CCR寄存器的预装功能(影子寄存器)(了解即可)=============

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

=======================配置快速使能(了解即可)==========================

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

=======================外部事件清除REF信号(了解即可)===================

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

=======================单独设置输出比较极性=============================

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

//N高级定时器互补通道的配置
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

=======================单独修改输出使能参数=============================

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);

=======================单独更改输出比较模式=============================

void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

@=====================单独更改CCR寄存器值=============================

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

==========================补充========================================

void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

//仅高级定时器使用,在使用高级定时器输出PWM时,需要调用这个函数,使能主输出,否则PWM将不能正常输出

十一、实验

9.1 PWM驱动LED呼吸灯

PWM.c

  1. #include "stm32f10x.h" // Device header
  2. /*PWM初始化*/
  3. void PWM_Init(void)
  4. {
  5. /*一、RCC开启时钟,TIM与GPIO时钟打开*/
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  8. // /*使用重映射(*_*)*/
  9. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
  10. // GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//PA0->PA15,部分重映射S
  11. // GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//解除JATG调试
  12. GPIO_InitTypeDef GPIO_InitStructure;
  13. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
  14. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//(*_*)GPIO_Pin_15
  15. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16. GPIO_Init(GPIOA,&GPIO_InitStructure);
  17. /*二、配置时基单元(时钟源选择和时基单元配置)*/
  18. TIM_InternalClockConfig(TIM2);//选择内部时钟
  19. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  20. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  21. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  22. TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR自动重装器值
  23. TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC预分频器值
  24. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器值
  25. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  26. /*三、配置输出比较单元(CCR的值(捕获/比较器),输出比较模式,极性选择,输出使能)*/
  27. TIM_OCInitTypeDef TIM_OCInitStructure;
  28. TIM_OCStructInit(&TIM_OCInitStructure);//给结构体所有成员赋初始值(有些用不到但是必须赋值)
  29. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式
  30. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较的极性
  31. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
  32. TIM_OCInitStructure.TIM_Pulse = 0;//设置CCR
  33. TIM_OC1Init(TIM2,&TIM_OCInitStructure);
  34. /*四、配置GPIO,复用推挽输出*/
  35. //一处已操作
  36. /*五、运行控制,启动计数器CNT*/
  37. TIM_Cmd(TIM2,ENABLE);
  38. }
  39. /*封装函数->更改CCR值来改变占空比*/
  40. void PWM_SetCompare1(uint16_t Compare)
  41. {
  42. TIM_SetCompare1(TIM2,Compare);
  43. }

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. //CCR增大,逐渐变亮
  13. for (i = 0; i <= 100; i++)
  14. {
  15. PWM_SetCompare1(i);
  16. Delay_ms(10);
  17. }
  18. //CCR减小,逐渐变暗
  19. for (i = 0; i <= 100; i++)
  20. {
  21. PWM_SetCompare1(100 - i);
  22. Delay_ms(10);
  23. }
  24. }
  25. }

9.2 PWM驱动舵机

实验现象:按下按键,舵机转动固定角度

PWM.c

  1. #include "stm32f10x.h" // Device header
  2. /*PWM初始化*/
  3. void PWM_Init(void)
  4. {
  5. /*一、RCC开启时钟,TIM与GPIO时钟打开*/
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  8. GPIO_InitTypeDef GPIO_InitStructure;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
  10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  11. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12. GPIO_Init(GPIOA,&GPIO_InitStructure);
  13. /*二、配置时基单元(时钟源选择和时基单元配置)*/
  14. TIM_InternalClockConfig(TIM2);//选择内部时钟
  15. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  16. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  17. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  18. TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1; //ARR自动重装器值
  19. TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC预分频器值
  20. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器值
  21. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  22. /*三、配置输出比较单元(CCR的值(捕获/比较器),输出比较模式,极性选择,输出使能)*/
  23. TIM_OCInitTypeDef TIM_OCInitStructure;
  24. TIM_OCStructInit(&TIM_OCInitStructure);//给结构体所有成员赋初始值(有些用不到但是必须赋值)
  25. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式
  26. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较的极性
  27. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
  28. TIM_OCInitStructure.TIM_Pulse = 0;//设置CCR(500~2500
  29. TIM_OC2Init(TIM2,&TIM_OCInitStructure);
  30. /*四、配置GPIO,复用推挽输出*/
  31. //一处已操作
  32. /*五、运行控制,启动计数器CNT*/
  33. TIM_Cmd(TIM2,ENABLE);
  34. }
  35. /*封装函数->更改CCR值来改变占空比*/
  36. void PWM_SetCompare2(uint16_t Compare)
  37. {
  38. TIM_SetCompare2(TIM2,Compare);
  39. }

PWM.h

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

Servo.c

  1. #include "stm32f10x.h" // Device header
  2. #include "PWM.h"
  3. //舵机初始化(PWM初始化)
  4. void Servo_Init(void)
  5. {
  6. PWM_Init();
  7. }
  8. /*
  9. 舵机设置角度
  10. 角度:0-180
  11. CCR:500-2500
  12. */
  13. void Servo_SetAngle(float Angle)
  14. {
  15. PWM_SetCompare2(Angle / 180 * 2000 + 500);
  16. }

Servo.h

  1. #ifndef __SERVO_H
  2. #define __SERVO_H
  3. void Servo_Init(void);
  4. void Servo_SetAngle(float Angle);
  5. #endif

Key.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. //===按键初始化===//
  4. void Key_Init(void)
  5. {
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
  7. GPIO_InitTypeDef GPIO_InitStructure;
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
  9. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOB,&GPIO_InitStructure);
  12. }
  13. //===获取按键返回码===//
  14. uint8_t Key_GetNum(void)
  15. {
  16. uint8_t KeyNum = 0;
  17. if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
  18. {
  19. Delay_ms(20);//消抖
  20. while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0);//如果不松手则卡着
  21. Delay_ms(20);
  22. KeyNum = 1;
  23. }
  24. if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0)
  25. {
  26. Delay_ms(20);//消抖
  27. while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) == 0);
  28. Delay_ms(20);
  29. KeyNum = 2;
  30. }
  31. return KeyNum;
  32. }

key.h

  1. #ifndef __KEY_H
  2. #define __KEY_H
  3. void Key_Init(void);
  4. uint8_t Key_GetNum(void);
  5. #endif

main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "key.h"
  5. #include "Servo.h"
  6. uint8_t KeyNum;
  7. float Angle;
  8. int main(void)
  9. {
  10. OLED_Init();
  11. Key_Init();
  12. Servo_Init();
  13. OLED_ShowString(1,1,"Angle:");
  14. while (1)
  15. {
  16. KeyNum = Key_GetNum();
  17. if(KeyNum == 1)
  18. {
  19. Angle += 30;
  20. if(Angle >180)
  21. {
  22. Angle = 0;
  23. }
  24. }
  25. Servo_SetAngle(Angle);
  26. OLED_ShowNum(1,7,Angle,3);
  27. }
  28. }

*OLED显示屏代码请参考本专栏文章STM32-OLED显示屏

9.3 PWM驱动直流电机

实验现象: 按键按下,电机加速,达到最大转速时,再按一下,最大速度反转,按下按键,电机减速

PWM.c

  1. #include "stm32f10x.h" // Device header
  2. /*PWM初始化*/
  3. void PWM_Init(void)
  4. {
  5. /*一、RCC开启时钟,TIM与GPIO时钟打开*/
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  8. GPIO_InitTypeDef GPIO_InitStructure;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
  10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  11. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12. GPIO_Init(GPIOA,&GPIO_InitStructure);
  13. /*二、配置时基单元(时钟源选择和时基单元配置)*/
  14. TIM_InternalClockConfig(TIM2);//选择内部时钟
  15. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  16. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  17. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  18. TIM_TimeBaseInitStructure.TIM_Period = 100 - 1; //ARR自动重装器值
  19. TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1; //PSC预分频器值
  20. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器值
  21. TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  22. /*三、配置输出比较单元(CCR的值(捕获/比较器),输出比较模式,极性选择,输出使能)*/
  23. TIM_OCInitTypeDef TIM_OCInitStructure;
  24. TIM_OCStructInit(&TIM_OCInitStructure);//给结构体所有成员赋初始值(有些用不到但是必须赋值)
  25. TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式
  26. TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较的极性
  27. TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能
  28. TIM_OCInitStructure.TIM_Pulse = 0;//设置CCR
  29. TIM_OC3Init(TIM2,&TIM_OCInitStructure);
  30. /*四、配置GPIO,复用推挽输出*/
  31. //一处已操作
  32. /*五、运行控制,启动计数器CNT*/
  33. TIM_Cmd(TIM2,ENABLE);
  34. }
  35. /*封装函数->更改CCR值来改变占空比*/
  36. void PWM_SetCompare3(uint16_t Compare)
  37. {
  38. TIM_SetCompare3(TIM2,Compare);
  39. }

PWM.h

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

Motor.c

  1. #include "stm32f10x.h" // Device header
  2. #include "PWM.h"
  3. void Motor_Init(void)
  4. {
  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  6. GPIO_InitTypeDef GPIO_InitStructure;
  7. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
  9. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10. GPIO_Init(GPIOA,&GPIO_InitStructure);
  11. PWM_Init();
  12. }
  13. /*设置电机速度(-100~100*/
  14. void Motor_SetSpeed(int8_t Speed)
  15. {
  16. if(Speed >= 0)
  17. {
  18. GPIO_SetBits(GPIOA,GPIO_Pin_4);
  19. GPIO_ResetBits(GPIOA,GPIO_Pin_5);
  20. PWM_SetCompare3(Speed);
  21. }
  22. else
  23. {
  24. GPIO_SetBits(GPIOA,GPIO_Pin_5);
  25. GPIO_ResetBits(GPIOA,GPIO_Pin_4);
  26. PWM_SetCompare3(-Speed);
  27. }
  28. }

Motor.h

  1. #ifndef __PWM_H
  2. #define __PWM_H
  3. void Motor_Init(void);
  4. void Motor_SetSpeed(int8_t Speed);
  5. #endif

*按键与OLED显示屏的代码参考之前实验代码

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

闽ICP备14008679号