当前位置:   article > 正文

江科大STM32学习笔记——TIM输出比较_stm32中tim2从哪个口输出

stm32中tim2从哪个口输出

输出比较(Output Compare)

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

 

 PWM波形

 

例:以一个很快的频率让电机通、断、通、断电,那么电机就能都呈现出一个中等速度。

  • 占空比决定了PWM等效出的模拟电压的大小,占空比越高,模拟电压越接近高电压输出。
  • 分辨率就是占空比变化的精细程度

输出比较通道

当CNT计数器和CCR1第一路的捕获/比较寄存器进行比较,当CNT>/=CCR1时,输出模式控制器收到信号,然后改变输出oc1ref信号的高低电平。

然后这个信号一路到主模式控制器去(可以映射到TRGO输出上)

一路通过极性选择电路经过输出使能电路,最后输出到OC1引脚。

可以通过TIMx_CCER寄存器的值来决定是否将oc1ref输出的信号翻转。

输出比较模式

1. 冻结可以用于要暂停一段时间的输出情况

2.匹配时置有/无效电平:可以理解为高/低电平,用于一次性输出,不适合连续波形。

3.输出占空比50%的PWM波形

4.强制:可以用于暂停期间需要保持高/低电平

5.PWM模式1/2主要是极性的区别。可以就选模式1。

参数计算

外接设备(舵机和电机)

给个PWM,输出轴就会固定在一个角度。

上面红色三个引脚控制下面AO的电机,PWMA接PWM输出,而IN引脚可以接GPIO输出,给一个低功率控制信号就能控制电机转动。

输入与输出状态对应关系如右下角所示。

如当IN1置低,IN2置高,PWM为高电平则电机翻转,低电平则电机不转。

代码

1. PWM驱动呼吸灯

OLED部分与之前一样接,灯正极接PA0,负极接GND。

首先初始化PWM,即把输出比较模块打通。

  1. //配置输出比较单元的函数
  2. void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
  3. void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
  4. void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
  5. void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
  6. //给结构体赋默认值
  7. void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
  8. //配置强制输出模式
  9. void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
  10. void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
  11. void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
  12. void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
  13. //单独数值输出比歼的极性(单独修改输出极性)
  14. void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
  15. void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
  16. void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
  17. void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
  18. void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
  19. void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
  20. void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
  21. //单独修改输出使能
  22. void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
  23. void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);
  24. //单独更改输出使能
  25. void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);
  26. //单独更改CCR寄存器的值(运行时改变占空比)
  27. void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
  28. void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
  29. void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
  30. void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
  31. //以下不常用
  32. //配置CCR寄存器预装功能(影子寄存器)
  33. void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
  34. void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
  35. void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
  36. void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
  37. //配置快速使能
  38. void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
  39. void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
  40. void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
  41. void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
  42. //外部事件时清除REF
  43. void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
  44. void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
  45. void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
  46. void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
  47. //在使用高级定时器时,需调用使能主输出,否则PWM不能正常输出
  48. void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

1. RCC开启时钟,把要用的TIM外设和GPIO口的时钟打开

2. 配置时基单元,包括时钟源选择。

3. 配置输出比较单元,包括输出比较模式、极性选择、输出使能

4. 配置GPIO,把PWM输出对应的GPIO口初始化为复用推挽输出

查看引脚定义,TIM2的通道1和ETR复用在了PA0端口上。

5. 运行控制,启动计数器输出PWM

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.c

  1. #include "stm32f10x.h" // Device header
  2. void PWM_Init(void)
  3. {
  4. //打开时钟
  5. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  7. GPIO_InitTypeDef GPIO_InitStructure;
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽,将引脚控制权交与片上外设
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOA,&GPIO_InitStructure);
  12. //配置TIM,时基单元
  13. TIM_InternalClockConfig(TIM2);
  14. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  15. TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  16. TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  17. TIM_TimeBaseInitStruct.TIM_Period = 100-1; //ARR的值
  18. TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1; //PSC的值
  19. TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
  20. TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
  21. //初始化输出比较
  22. TIM_OCInitTypeDef TIM_OCInitStruct;
  23. TIM_OCStructInit(&TIM_OCInitStruct);
  24. TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//输出模式PWM1
  25. TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//高极性
  26. TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//
  27. TIM_OCInitStruct.TIM_Pulse = 0; //CCR的值
  28. TIM_OC1Init(TIM2,&TIM_OCInitStruct);
  29. TIM_Cmd(TIM2,ENABLE);//启动定时器
  30. }
  31. void PWM_SetCompare1(uint16_t Compare)
  32. {
  33. TIM_SetCompare1(TIM2,Compare);
  34. }

2. PWM驱动舵机

根据舵机所需高电平时间及相应公式计算出各个寄存器的值。

  1. TIM_TimeBaseInitStruct.TIM_Period = 2000-1; //ARR的值
  2. TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1; //PSC的值
  3. TIM_OCInitStruct.TIM_Pulse = 0; //CCR的值

CCR:500->0°,2500->180°,根据线性关系可计算。

  1. //main.c
  2. #include "stm32f10x.h"// Device header
  3. #include "Delay.h"
  4. #include "OLED.h"
  5. #include "Servo.h"
  6. uint8_t i;
  7. float Angle;
  8. int main(void)
  9. {
  10. OLED_Init();
  11. Servo_Init();
  12. Servo_SetAngle(90);
  13. OLED_ShowString(1,1,"Angle:");
  14. while(1)
  15. {
  16. Angle += 30;
  17. if(Angle > 180)
  18. Angle = 0;
  19. Delay_s(5);
  20. Servo_SetAngle(Angle);
  21. OLED_ShowNum(2,1,Angle,7);
  22. }
  23. }
  1. #include "stm32f10x.h" // Device header
  2. void PWM_Init(void)
  3. {
  4. //打开时钟
  5. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  7. GPIO_InitTypeDef GPIO_InitStructure;
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽,将引脚控制权交与片上外设
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOA,&GPIO_InitStructure);
  12. //配置TIM,时基单元
  13. TIM_InternalClockConfig(TIM2);
  14. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
  15. TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
  16. TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
  17. TIM_TimeBaseInitStruct.TIM_Period = 2000-1; //ARR的值
  18. TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1; //PSC的值
  19. TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
  20. TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
  21. //初始化输出比较
  22. TIM_OCInitTypeDef TIM_OCInitStruct;
  23. TIM_OCStructInit(&TIM_OCInitStruct);
  24. TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//输出模式PWM1
  25. TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//高极性
  26. TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//
  27. TIM_OCInitStruct.TIM_Pulse = 0; //CCR的值
  28. TIM_OC2Init(TIM2,&TIM_OCInitStruct);
  29. TIM_Cmd(TIM2,ENABLE);//启动定时器
  30. }
  31. void PWM_SetCompare2(uint16_t Compare)
  32. {
  33. TIM_SetCompare2(TIM2,Compare);
  34. }

3.  PWM驱动电机

TB6612硬件电路如下,根据引脚定义接线。

 Motor.c

  1. #include "stm32f10x.h" // Device header
  2. #include "PWM.h"
  3. void Motor_Init(void)
  4. {
  5. //初始化控制方向的引脚
  6. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  7. GPIO_InitTypeDef GPIO_InitStructure;
  8. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  10. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. GPIO_Init(GPIOA,&GPIO_InitStructure);
  12. PWM_Init();
  13. }
  14. //设置速度函数
  15. void Motor_SetSpeed(int8_t Speed) //带符号的,负号表示反转
  16. {
  17. if(Speed > 0)
  18. {
  19. GPIO_SetBits(GPIOA,GPIO_Pin_4);
  20. GPIO_ResetBits(GPIOA,GPIO_Pin_5);
  21. PWM_SetCompare3(Speed);
  22. }
  23. else
  24. {
  25. GPIO_ResetBits(GPIOA,GPIO_Pin_4);
  26. GPIO_SetBits(GPIOA,GPIO_Pin_5);
  27. PWM_SetCompare3(-Speed);
  28. }
  29. }

 main.c

  1. #include "stm32f10x.h"// Device header
  2. #include "Delay.h"
  3. #include "OLED.h"
  4. #include "Motor.h"
  5. uint8_t i;
  6. float Angle;
  7. int main(void)
  8. {
  9. OLED_Init();
  10. Motor_Init();
  11. Motor_SetSpeed(-50);
  12. while(1)
  13. {
  14. }
  15. }

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

闽ICP备14008679号