网站建设开票是几个点,手机h5制作,游戏中心下载安装,天猫网站建设的意义四部分讲解内容#xff0c;本文是第二部分
输出比较主要用于PWM波形的控制电机#xff08;驱动电机的必要条件#xff09;
1、定时器基本定时#xff0c;定一个时间#xff0c;然后让定时器每隔一段时间产生一个中断#xff0c;来实现每隔一个固定时间执行一段程序的目…四部分讲解内容本文是第二部分
输出比较主要用于PWM波形的控制电机驱动电机的必要条件
1、定时器基本定时定一个时间然后让定时器每隔一段时间产生一个中断来实现每隔一个固定时间执行一段程序的目的比如要做一个时钟、秒表或者使用一些程序算法
2、定时器输出比较的功能输出比较这个模块最常见的用途是产生PWM波形用于驱动电机等设备使用stm32的PWM波形来驱动舵机和直流电机的例子
3、定时器输入捕获的功能学习使用输入捕获这个模块来测量方波频率的例子
4、定时器的编码器接口使用这个编码器接口能够更加方便地读取正交编码器的输出波形在编码电机测速中应用广泛。
TIM输出比较
CNT时基单元里面的计数器
CCR: 捕获/比较寄存器输入捕获和输出比较公用
输出比较的基本功能当CNT大于CCR、小于CCR或者等于CCR时输出就会对应的置1、置0。这样就可以输出一个电平不断跳变的PWM波形 PWM(Pulse Width Modulation 脉冲宽度调制)的秘诀时天下武功为快不破——惯性系统才可用
高低电平跳变的数字信号可以等效为中间虚线所表示的模拟量当上面电平时间长一点下面电平时间短一点的时候那么等效的模拟量就偏向于上面当下面电平时间长一点上面电平时间短一点的时候等效的模拟量就偏向于下面。 当我们调控这个点亮和熄灭的时间比例时就能让LED呈现出不同的亮度级别。
只有具有惯性的系统才能使用PWM
占空比它决定了PWM等效出来的模拟电压的大小。占空比越大那等效的模拟电压就越趋近于高电平占空比越小那等效的模拟电压就越趋近于低电平。线性关系
分辨率占空比变化的精细程度
使用PWM波形就可以在数字系统等效输出模拟量就能实现LED控制亮度 电机控速等功能。
输出比较通道通用定时器 模式控制的输入是CNT和CCR的大小关系输出是REF的高低电平。
冻结比如你正在输出PWM波突然想暂停一会输出就可以设置成这个模式一旦切换为冻结模式输出就暂停并且高低电平也维持为暂停时刻的状态保持不变。
PWM模式1和PWM模式2可以用于输出频率和占空比都可调的PWM波形。而PWM模式2实际上就是PWM模式1输出的取反。改变PWM模式1和PWM模式2就只是改变了REF电平的极性。 输出模式可设置极性最终输出之前也可以设置极性灵活 重点-PWM基本结构 左上角是时基单元和运行控制最左边是时钟源选择这里省略了这里更新中断申请不再需要输出PWM暂时不需要中断。
配置好时基单元CNT就可以开始不断自增运行。然后下面就是输出比较单元总共4路。输出比较单元的最开始是CCR捕获寄存器。CCR是我们设定的CNT不断自增运行同时它俩还在不断比较后面就是输出模式控制器。
上图是PWM1模式1的执行逻辑。
蓝色线: CNT的值
黄色线ARR的值
红色线CCR
蓝色线从0开始自增一直增到ARR也就是99之后清0继续自增在这个过程中再设置一条红色线这条红色线就是CCR比如我们设置CCR为30之后再执行以下这个逻辑。
绿色线就是输出
CNTCCR,置高电平
CNTCCR,置低电平
以上占空比是受到CCR值的调控的。
若CCR设置高则输出的占空比就变大。若CCR设置低一些输出的占空比就变小。
REF一个频率可调占空比也可调的PWM波形
最终经过极性选择输出使能最终通向GPIO完成PWM波形的输出 PWM参数计算
CNT从0一直加到ARR(99),总共计算了100个数再看高电平时间从0加到CCR30在等于30的瞬间就已经跳变为低电平所以CNT从0到29是高电平总共是30个数。
占空比30/99ARR130/10030%
CCR的值取决于ARR的范围。ARR越大CCR的范围就越大对应的分辨率就越大。
舵机直流电机硬件电路
执行逻辑:PWM输入到控制板给控制板一个指定的目标角度然后电位器检测输出轴的当前角度如果大于目标角度电机就会反转如果小于目标角度电机就会正转最终使输出轴固定在指定角度。 PWM驱动LED呼吸灯代码
第一步RCC开启时钟把我们要用的TIM外设和GPIO外设的始终打开
第二步配置时基单元包括前面的时钟源选择
第三步配置输出比较单元里面包括这个CCR的值、输出比较模式、极性选择、输出使能这些参数
第四步配置GPIO把PWM对应的GPIO口初始化为复用推挽输出的配置PWM和GPIO的对应关系是怎样的参考引脚定义表
第五步运行控制启动计数器就能输出PWM
PWM代码总体思路
初始化TIM2的通道1产生一个PWM波形输出引脚是PA0然后通过SetCompare1函数可以调节CCR1寄存器的值从而控制PWM的占空比。但是PWM的频率在初始化写定运行时调节不方便所以在最后加一个函数来便捷调节PWM频率 通用公式 PSC和ARR都可以调节频率但是占空比CCR/ARR1,如果通过调节ARR调节频率同时会影响到占空比。通过PSC调节频率不会影响占空比。因此固定ARR通过调节PSC改变PWM频率另外ARR为100-1CCR的数值直接就是占空比。
main.c
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include PWM.huint8_t i;int main(void)
{OLED_Init();PWM_Init();//在主循环里不断调用PWM_SetCompare1函数//更改CCR的值这样就能完成LED呼吸灯的效果while (1){//从0变到100for (i 0; i 100; i){PWM_SetCompare1(i);Delay_ms(10); //延时否则太快}//从100变到0for (i 0; i 100; i){PWM_SetCompare1(100 - i);Delay_ms(10);}}
}pwm.c:
#include stm32f10x.h // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE); //引脚重映射配置函数部分重映射可将PA0换到PA15
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //关闭调试端口的复用GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; //GPIO_Pin_15;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);//初始化时基单元TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period 100 - 1; //ARR周期TIM_TimeBaseInitStructure.TIM_Prescaler 720 - 1; //PSC预分频器TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStructure);//初始化输出比较单元即初始化通道TIM_OCInitTypeDef TIM_OCInitStructure;//给结构体赋初始值如果不想把所有成员都列一遍赋值可以先用structInit赋值再更改想要修改的值TIM_OCStructInit(TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; //输出比较模式PWM模式1TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; //设置输出比较的极性高极性就是极性不翻转REF波形直接输出TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; //设置输出使能TIM_OCInitStructure.TIM_Pulse 0; //设置CCR//在TIM2的OC1通道上就可以输出PWM波形了但最终这个波形需要借用GPIO口才能输出TIM_OC1Init(TIM2, TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}
//该函数单独设置通道1的CCR值。
void PWM_SetCompare1(uint16_t Compare)
{TIM_SetCompare1(TIM2, Compare);
}pwm.h
#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void); //PWM初始化
void PWM_SetCompare1(uint16_t Compare); //设置CCR改变占空比#endif
PWM舵机控制代码
驱动舵机的关键输出如下图的PWM波形: main.c:
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Servo.h
#include Key.huint8_t Angle;
uint8_t KeyNum;int main(void)
{OLED_Init();Servo_Init();Servo_SetAngle(90);OLED_ShowString(1,1,Angle:);while (1){KeyNum Key_GetNum();if(KeyNum 1){Angle 90;if(Angle 180){Angle 0;}}Servo_SetAngle(Angle);OLED_ShowNum(1,7,Angle,3); //1行7列显示Angle长度为3}
}
pwm.c:
#include stm32f10x.h // Device headervoid PWM_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//PA1 口的通道2GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);//初始化时基单元TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period 20000 - 1; //ARR周期TIM_TimeBaseInitStructure.TIM_Prescaler 72 - 1; //PSC预分频器TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStructure);//初始化输出比较单元即初始化通道TIM_OCInitTypeDef TIM_OCInitStructure;//给结构体赋初始值如果不想把所有成员都列一遍赋值可以先用structInit赋值再更改想要修改的值TIM_OCStructInit(TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; //输出比较模式PWM模式1TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; //设置输出比较的极性高极性就是极性不翻转REF波形直接输出TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; //设置输出使能TIM_OCInitStructure.TIM_Pulse 0; //设置CCR 500~2500对应0.5ms~2.5ms//在TIM2的OC1通道上就可以输出PWM波形了但最终这个波形需要借用GPIO口才能输出TIM_OC2Init(TIM2, TIM_OCInitStructure); //通道2TIM_Cmd(TIM2, ENABLE);
}
//该函数在运行过程中单独设置通道2的CCR值
void PWM_SetCompare2(uint16_t Compare)
{TIM_SetCompare2(TIM2, Compare);
}
pwm.h
#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);#endif
servo.c
#include stm32f10x.h
//舵机模块需要继承PWM文件的功能
#include PWM.h//舵机初始化函数
void Servo_Init(void)
{PWM_Init();
}/*
0 500
180 2500
*/
//线性映射
void Servo_SetAngle(float Angle)
{PWM_SetCompare2(Angle / 180 * 2000 500);
}
servo.h
#ifndef __SERVO_H
#define __SERVO_Hvoid Servo_Init(void);
void Servo_SetAngle(float Angle);#endifPWM驱动直流电机
main.c
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Motor.h
#include Key.h//通过按键控制电机转速(全局变量)
uint8_t KeyNum;
int8_t Speed;int main(void)
{OLED_Init();Motor_Init();Key_Init();Motor_SetSpeed(2);OLED_ShowString(1,1,Speed);while (1){//实现按键控制速度KeyNum Key_GetNum();if(KeyNum 1){Speed 20;if(Speed 100){Speed -100;}}if(KeyNum 2){Speed - 10;if(Speed -100){Speed 100;}}Motor_SetSpeed(Speed);OLED_ShowNum(1,7,Speed,3);}
}
pwm.c
#include stm32f10x.h // Device headervoid 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_2; //PWM电平输出的GPIO口控制速度GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);//初始化时基单元TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period 100 - 1; //ARR周期TIM_TimeBaseInitStructure.TIM_Prescaler 36 - 1; //PSC预分频器TIM_TimeBaseInitStructure.TIM_RepetitionCounter 0;TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStructure);//初始化输出比较单元即初始化通道TIM_OCInitTypeDef TIM_OCInitStructure;//给结构体赋初始值如果不想把所有成员都列一遍赋值可以先用structInit赋值再更改想要修改的值TIM_OCStructInit(TIM_OCInitStructure);TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; //输出比较模式PWM模式1TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; //设置输出比较的极性高极性就是极性不翻转REF波形直接输出TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; //设置输出使能TIM_OCInitStructure.TIM_Pulse 0; //设置CCR//在TIM2的OC3通道上就可以输出PWM波形了但最终这个波形需要借用GPIO口才能输出TIM_OC3Init(TIM2, TIM_OCInitStructure);TIM_Cmd(TIM2, ENABLE);
}
//该函数单独设置通道1的CCR值。
void PWM_SetCompare3(uint16_t Compare)
{TIM_SetCompare3(TIM2, Compare);
}
pwm.h
#ifndef __PWM_H
#define __PWM_Hvoid PWM_Init(void); //PWM初始化
void PWM_SetCompare3(uint16_t Compare); //设置CCR改变占空比#endif
motor.c
#include stm32f10x.h
//继承PWM
#include PWM.h//初始化电机
void Motor_Init(void)
{//电机模块里多了控制方向的两个引脚//额外初始化方向控制的两个引脚RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin GPIO_Pin_4 | GPIO_Pin_5; //初始化电机控制方向的两个GPIO口GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);PWM_Init();
}
//通过PWM_Setcompare来设置占空比来设置转速
//设置电机速度的函数参数需要给带符号的速度变量负数用来表示反转
void Motor_SetSpeed(int8_t Speed)
{if(Speed 0){GPIO_SetBits(GPIOA,GPIO_Pin_4); //PA41GPIO_ResetBits(GPIOA,GPIO_Pin_5); //PA5 0PWM_SetCompare3(Speed);}if(Speed 0){GPIO_SetBits(GPIOA,GPIO_Pin_5); //PA5 1GPIO_ResetBits(GPIOA,GPIO_Pin_4); //PA4 0PWM_SetCompare3(-Speed); //配置CCR的值}
}motor.h
#ifndef __MOTOR_H
#define __MOTOR_Hvoid Motor_Init(void);
void Motor_SetSpeed(int8_t Speed);#endif