1. stm32f103xx高级定时器/通用定时器、基本定时器比较:
2. IC: 输入捕获
OC: 输出比较
TIMx_CCRx: 捕获/比较寄存器
3. OC(output compare)输出比较
- 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作。用于输出一定频率和占空比的PWM波形
- 每个高级定时器和通用定时器都有4个输出比较通道
- 高级定时器的前3个通道额外拥有死区生成和互补输出的功能
4. CNT: 时基单元的计数器
时基单元包含:
● 计数器寄存器(TIMx_CNT)
● 预分频器寄存器 (TIMx_PSC)
● 自动装载寄存器 (TIMx_ARR)
● 重复次数寄存器 (TIMx_RCR)
模式 | 描述 |
冻结 | CNT=CCR时,REF保持为原状态 |
匹配时置有效电平 | CNT=CCR时,REF置有效电平 |
匹配时置无效电平 | CNT=CCR时,REF置无效电平 |
匹配时电平翻转 | CNT=CCR时,REF电平翻转 |
强制为无效电平 | CNT与CCR无效,REF强制为无效电平 |
强制为有效电平 | CNT与CCR无效,REF强制为有效电平 |
PWM1模式 |
向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平 向下计数: CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平 |
PWM2模式 |
向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置有效电平 向下计数: CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置无效电平 |
有效电平:高电平
冻结:暂停PWM
无效电平:低电平
5. PWM控制流程
- PWM频率:Freq = CK_PSC / (PSC+1)(ARR+1)
- PWM占空比: Duty = CCR / (ARR + 1)
- PEM分辨率: Reso = 1 / (ARR + 1)
例如:PWM: 1kHz, 占空比50, 分辨率1% => ARR = 100, CCR=50, PSC=720
- PWM频率:Freq = 72M / (PSC+1)(ARR+1) = 1000
- PWM占空比: Duty = CCR / (ARR + 1) = 50%
- PEM分辨率: Reso = 1 / (ARR + 1) = 1%
6. 舵机控制
- 利用PWM占空比控制角度
- 输入PWM信号: 周期20ms, 高电平宽度0.5ms~2.5ms
- 20ms = 50Hz
- 舵机驱动程序
-
void pwm_init() { GPIO_InitTypeDef GPIO_InitStructure; //声明初始化定时器GPIO的结构体变量 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//声明初始化定时器时基的结构体变量 TIM_OCInitTypeDef TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx //开启时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); // 配置GPIO的模式和IO口 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;// PC6 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出 GPIO_Init(GPIOC,&GPIO_InitStructure); //TIM3定时器初始化 TIM_TimeBaseInitStructure.TIM_Period = 199; //PWM 频率=72000/(199+1)=36Khz//设置自动重装载寄存器周期的值 TIM_TimeBaseInitStructure.TIM_Prescaler = 7199;//设置用来作为TIMx时钟频率预分频值 TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, & TIM_TimeBaseInitStructure); GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射 规则在F103参考手册里。 //PWM初始化 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; TIM_OC1Init(TIM3,&TIM_OCInitStructure); //配置TIM1时基单元 TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器 TIM_Cmd(TIM3,ENABLE);//使能或者使能TIMx外设 }
-
-
void PWM_SerCompare1(u16 Compare) { TIM_SetCompare1(TIM2, Compare); }
-
主函数不断更新RCC值
-
for (i=0; i<=100; i++) { PWM_SetCompare1(i); Delay_ms(10); } for (i=0; i<1=100; i++) { PWM_SetCompare1(100-i); Delay_ms(10); }
-
Delay_ms
-
//毫秒级的延时 void delay_ms(u16 time) { u16 i=0; while(time--) { i=12000; //自己定义 while(i--) ; } }
- 同时使用两个通道输出PWM, 频率必须是一样的,RCC占空比可以不一样;
- Freq=50Hz = 20ms = 72M / (72) / 20k
- ARR = 20k = 20ms = CCR / 20k
- CCR = 500 = 0.5ms
6. TB6612FNG电机驱动模块
-
-
电机驱动程序 bsp_AdvanceTim.c
#include "bsp_AdvanceTim.h" //TP6612 GPIO驱动函数代码 /*驱动6112 的AIN1 AIN2 AIN1 PB13 置高电平 AIN2 PB12 置低电平 */ void TB6612_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*使能PB端口时钟*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /*PB12 PB13端口配置*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13; /*推挽输出*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /*IO口速度设置为50MHz*/ GPIO_Init(GPIOB, &GPIO_InitStructure); /*根据设定参数初始化*/ //电机正转 GPIO_SetBits(GPIOB, GPIO_Pin_13); /*PB13输出高*/ GPIO_ResetBits(GPIOB, GPIO_Pin_12); /*PB12输出低*/ //电机反转 // GPIO_SetBits(GPIOB, GPIO_Pin_12); /*PB13输出高*/ // GPIO_ResetBits(GPIOB, GPIO_Pin_13); /*PB12输出低*/ //电机停止 // GPIO_SetBits(GPIOB, GPIO_Pin_12); /*PB13输出高*/ // GPIO_SetBits(GPIOB, GPIO_Pin_13); /*PB12输出低*/ } //TIM1 PWM部分初始化 /* PWM输出初始化 arr: 自动重装值 psc: 时钟预分频数 */ void TIM1_PWM_Init(u16 arr, u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; //使能对应定时器 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); /*使能定时器1时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); /*使能GPIO外设和AFIO复用功能模块*/ //配置对应引脚功能,设置该引脚为复用输出功能,输出TIM1, CH1, CH4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; /*复用推挽输出*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11; /*TIM_CH1 TIM_CH4*/ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /**/ GPIO_Init(GPIOA, &GPIO_InitStructure); /*初始化GPIO口*/ //初始化TIM1 // TIM_TimeBaseStructure.TIM_ClockDivision = 0; /*设置时钟分割:TDTS = TCK_TIM*/ TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; /*设置时钟分割:TDTS = TCK_TIM*/ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /*TIM向上计数模式*/ TIM_TimeBaseStructure.TIM_Period = arr; /*设置在下一个更新事件装入活动的自动重装载寄存器周期的值*/ TIM_TimeBaseStructure.TIM_Prescaler = psc; /*设置用来作为TIMx时钟频率除数的预分频值*/ //TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; /**/ TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); /*根据TIM_TimeBaseInitStructure中指定的参数初始化TIMx的时间基数单位*/ //初始化TIM1 Channel1 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; /*选择定时器模式:TIM脉冲宽度调制模式2*/ TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; /*输出极性:TIM输出比较极性高*/ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; /*比较输出使能*/ TIM_OC1Init(TIM1, &TIM_OCInitStructure); /*根据TIM_OCInitStructure指定的参数初始化外设TIM3*/ TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); /*使能TIM3在CCR2上的预装载寄存器*/ TIM_CtrlPWMOutputs(TIM1,ENABLE); /*MOE主输出使能,高级定时器必须开启这个*/ //初始化TIM1 Channel4 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC4Init(TIM1, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_Cmd(TIM1, ENABLE); /*使能TIM1*/ } void ADVANCE_TIM_Init(void) { TB6612_GPIO_Init(); //TIM1挂载APB2为72MHz,故72000000/(359+1)/(1999+1) = 100Hz; /*故设置频率为100Hz,自动重装载值1999*/ //TIM1_PWM_Init(1999, 359); TIM1_PWM_Init(120-1, 10-1); // TIM1_PWM_Init(110, 100); }
- bsp_AdvanceTim.h
#ifndef __bsp_AdvanceTim_h #define __bsp_AdvanceTim_h #include "stm32f10x.h" //配置高级定时器1(Timer1) #define ADVANCE_TIM TIM1 #define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd #define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1 //PWM信号的频率F = TIM_CLK/{(ARR+1) * (PSC+1)} #define ADVANCE_TIM_PERIOD (8-1) #define ADVANCE_TIM_PSC (9-1) #define ADVANCE_TIM_PULSE 4 ////中断相关宏定义 #define ADVANCE_TIM_IRQ TIM1_CC_IRQn #define ADVANCE_TIM_IRQHandler TIM1_CC_IRQHandler ////TIM1输出比较通道 #define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA #define ADVANCE_TIM_CH1_PORT GPIOA #define ADVANCE_TIM_CH1_PIN GPIO_Pin_8 //TIM1输出比较通道的互补通道 #define ADVANCE_TIM_CH1N_GPIO_CLK RCC_APB2Periph_GPIOB #define ADVANCE_TIM_CH1N_PORT GPIOB #define ADVANCE_TIM_CH1N_PIN GPIO_Pin_13 //TIM1输出比较通道的刹车通道 #define ADVANCE_TIM_BKIN_GPIO_CLK RCC_APB2Periph_GPIOB #define ADVANCE_TIM_BKIN_PORT GPIOB #define ADVANCE_TIM_BKIN_PIN GPIO_Pin_12 //#define ADVANCE_TIM_IC1PWM_CHANNEL TIM_Channel_1 //#define ADVANCE_TIM_IC2PWM_CHANNEL TIM_Channel_2 #define AIN1 GPIO_Pin_13 #define AIN2 GPIO_Pin12 //void TIM1_PWM_Init(u16 arr, u16 psc); void ADVANCE_TIM_Init(void); //void ADVANCE_TIM_Init(void); #endif /*__bsp_AdvanceTim_h*/
- 主函数main.c
#include "stm32f10x.h" //相当于51单片机中的 #include "bsp_AdvanceTim.h" int main() { while(1) { TIM_SetCompare1(TIM1, 30);//设置马达转速 } }