08_TIM输出比较
TIM输出比较
输出比较简介
CNT:计数器
CCR:捕获/比较寄存器
PWM简介
输出比较通道(高级)
输出比较通道(通用)
输出比较模式
PWM基本结构
参数计算
舵机简介
舵机硬件电路
直流电机及驱动简介
硬件电路
PWM驱动LED呼吸灯
接线图
参数计算
产生一个频率为1KHz,占空比为50%,分辨率为1%的PWM波形
代入公式:
ARR+1=100
CCR=50
PSC+1=720
不使用重定义功能
代码
PWM.c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
//产生一个频率为1KHz,占空比为50%,分辨率为1%的PWM波形
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//直接使用PA0接口对应TIM2_CH1_ETR
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
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); //TIM2的OC1通道初始化
TIM_Cmd(TIM2,ENABLE); //启动定时器
}
/**
* @brief 设置CCR的值(占空比)
* @param Compare: uint16_t
* @retval void
*/
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare);
}
PWM.h
#ifndef __PWM_H__
#define __PWM_H__
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
uint8_t i;
int main(void)
{
OLED_Init();
PWM_Init();
OLED_ShowString(1,1,"HelloWorld!");
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);
}
}
}
使用重定义功能
代码
xxxxxxxxxx #include "stm32f10x.h" // Device header#include "Delay.h"#include "OLED.h"#include "Timer.h"uint16_t Num;int main(void){ OLED_Init(); Timer_Init(); OLED_ShowString(1,1,"Num:"); OLED_ShowString(2,1,"CNT:"); while(1) { OLED_ShowNum(1,5,Num,5); OLED_ShowNum(2,5,Timer_GetCounter(),5); }}void TIM2_IRQHandler(void){ if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET) { Num++; TIM_ClearITPendingBit(TIM2,TIM_IT_Update); }}c
#include "stm32f10x.h" // Device header
void PWM_Init(void)
{
//产生一个频率为1KHz,占空比为50%,分辨率为1%的PWM波形
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//直接使用PA0接口对应TIM2_CH1_ETR
// GPIO_InitTypeDef GPIO_InitStruct;
// GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
// GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
// GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
// GPIO_Init(GPIOA,&GPIO_InitStruct);
//使用重定义功能将PA15映射给TIM2_CH1_ETR
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE); //引脚重映射配置 PA0->PA15
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //JTAG-DP Disabled and SW-DP Enabled,让PA15解除JTDI,变为正常的GPIO口
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_15; //PA0->PA15
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
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); //TIM2的OC1通道初始化
TIM_Cmd(TIM2,ENABLE); //启动定时器
}
/**
* @brief 设置CCR的值(占空比)
* @param Compare: uint16_t
* @retval void
*/
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2,Compare);
}
PWM驱动舵机
接线图
参数计算
周期=20ms
频率=50Hz
PSC+1=72
ARR+1=20K
占空比=0.5/20=0.025
CCR/20K=0.025,CCR=500
代码
Servo.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void)
{
PWM_Init();
}
/**
* @brief 设置舵机角度,范围(0°~180°)
* @param Angle:角度值
* @retval 无
*/
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2(Angle*2000/180+500);
}
Servo.h
#ifndef __SERVO_H__
#define __SERVO_H__
void Servo_Init(void);
void Servo_SetAngle(float Angle);
#endif
main.c
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main(void)
{
OLED_Init();
Servo_Init();
Key_Init();
OLED_ShowString(1,1,"Angle:");
Servo_SetAngle(Angle);
while(1)
{
KeyNum=Key_GetNum();
if(KeyNum==1)
{
Angle+=30;
if(Angle>180)
{
Angle=0;
}
}
Servo_SetAngle(Angle);
OLED_ShowNum(1,7,Angle,3);
}
}
PWM驱动直流电机
接线图
代码
Motor.c
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Motor_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
PWM_Init();
}
/**
* @brief 设置电机速度
* @param Speed >0 正转 <0 反转
* @retval 无
*/
void Motor_SetSpeed(int8_t Speed)
{
if(Speed>=0)
{
GPIO_SetBits(GPIOA,GPIO_Pin_5);
GPIO_ResetBits(GPIOA,GPIO_Pin_4);
PWM_SetCompare3(Speed);
}
else
{
GPIO_SetBits(GPIOA,GPIO_Pin_4);
GPIO_ResetBits(GPIOA,GPIO_Pin_5);
PWM_SetCompare3(-Speed);
}
}
Motor.h
#ifndef __MOTOR_H__
#define __MOTOR_H__
void Motor_Init(void);
void Motor_SetSpeed(int8_t Speed);
#endif
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();
OLED_Init();
OLED_ShowString(1,1,"Speed:");
Motor_SetSpeed(Speed);
while(1)
{
KeyNum = Key_GetNum();
if(KeyNum == 1)
{
Speed+=20;
if(Speed>100)
{
Speed=-100;
}
}
Motor_SetSpeed(Speed);
OLED_ShowSignedNum(1,7,Speed,3);
}
}