赞
踩
例:以一个很快的频率让电机通、断、通、断电,那么电机就能都呈现出一个中等速度。
当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为高电平则电机翻转,低电平则电机不转。
OLED部分与之前一样接,灯正极接PA0,负极接GND。
首先初始化PWM,即把输出比较模块打通。
- //配置输出比较单元的函数
- 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);
-
- //单独数值输出比歼的极性(单独修改输出极性)
- void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
- void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
- 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);
-
- //以下不常用
- //配置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);
-
- //在使用高级定时器时,需调用使能主输出,否则PWM不能正常输出
- void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
查看引脚定义,TIM2的通道1和ETR复用在了PA0端口上。
- #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);
- }
- }
-
- }
-
- #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_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽,将引脚控制权交与片上外设
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStructure);
-
- //配置TIM,时基单元
- 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;//输出模式PWM1
- TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//高极性
- TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//
- TIM_OCInitStruct.TIM_Pulse = 0; //CCR的值
- TIM_OC1Init(TIM2,&TIM_OCInitStruct);
-
- TIM_Cmd(TIM2,ENABLE);//启动定时器
-
- }
-
- void PWM_SetCompare1(uint16_t Compare)
- {
- TIM_SetCompare1(TIM2,Compare);
- }
根据舵机所需高电平时间及相应公式计算出各个寄存器的值。
- TIM_TimeBaseInitStruct.TIM_Period = 2000-1; //ARR的值
- TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1; //PSC的值
-
- TIM_OCInitStruct.TIM_Pulse = 0; //CCR的值
CCR:500->0°,2500->180°,根据线性关系可计算。
- //main.c
-
- #include "stm32f10x.h"// Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "Servo.h"
-
- uint8_t i;
- float Angle;
-
- int main(void)
- {
- OLED_Init();
- Servo_Init();
-
- Servo_SetAngle(90);
- OLED_ShowString(1,1,"Angle:");
- while(1)
- {
-
- Angle += 30;
- if(Angle > 180)
- Angle = 0;
- Delay_s(5);
- Servo_SetAngle(Angle);
- OLED_ShowNum(2,1,Angle,7);
- }
-
- }
-
- #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_Pin = GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽,将引脚控制权交与片上外设
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStructure);
-
- //配置TIM,时基单元
- 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 = 2000-1; //ARR的值
- TIM_TimeBaseInitStruct.TIM_Prescaler = 72-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;//输出模式PWM1
- TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//高极性
- TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//
- TIM_OCInitStruct.TIM_Pulse = 0; //CCR的值
- TIM_OC2Init(TIM2,&TIM_OCInitStruct);
-
- TIM_Cmd(TIM2,ENABLE);//启动定时器
-
- }
-
- void PWM_SetCompare2(uint16_t Compare)
- {
- TIM_SetCompare2(TIM2,Compare);
- }
-
TB6612硬件电路如下,根据引脚定义接线。
Motor.c
- #include "stm32f10x.h" // Device header
- #include "PWM.h"
-
- void Motor_Init(void)
- {
- //初始化控制方向的引脚
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStructure);
-
- PWM_Init();
-
- }
-
- //设置速度函数
- void Motor_SetSpeed(int8_t Speed) //带符号的,负号表示反转
- {
- if(Speed > 0)
- {
- GPIO_SetBits(GPIOA,GPIO_Pin_4);
- GPIO_ResetBits(GPIOA,GPIO_Pin_5);
- PWM_SetCompare3(Speed);
- }
- else
- {
- GPIO_ResetBits(GPIOA,GPIO_Pin_4);
- GPIO_SetBits(GPIOA,GPIO_Pin_5);
- PWM_SetCompare3(-Speed);
- }
-
- }
-
main.c
- #include "stm32f10x.h"// Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "Motor.h"
-
- uint8_t i;
- float Angle;
-
- int main(void)
- {
- OLED_Init();
- Motor_Init();
-
- Motor_SetSpeed(-50);
- while(1)
- {
-
- }
-
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。