TIM输出比较

一、OC(Output Compare)输出比较

1、输出比较可以通过比较CNT(计数器)与CCR(捕获/比较寄存器)寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形

2、每个高级定时器和通用定时器都拥有4个输出比较通道

3、高级定时器的前3个通道额外拥有死区生成和互补输出的功能,用于驱动三相无刷电机

二、PWM(Pulse Width Modulation)脉冲宽度调制

1、在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域

2、PWM参数:

频率   =   1/Ts                 占空比  =   Ton/Ts                  分辨率   =  占空比变化步距

3、输出比较通道(通用)

4、PWM基本结构

参数计算

PWM频率:    Freq = CK_PSC / (PSC + 1) / (ARR + 1) = 计数器的更新频率

PWM占空比:    Duty = CCR / (ARR + 1)

PWM分辨率:    Reso = 1 / (ARR + 1)

5、输出比较通道(高级)

三、PWM驱动LED呼吸灯

1、按照以下接线方式连接,并将STLINK插到电脑上

2、PWM驱动函数模块

(1)输出比较库函数功能

输出比较的配置

小功能和运行时更改参数的函数

(2)PWM.c

#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
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
	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;
	TIM_OCStructInit(&TIM_OCInitStructure);	//给所有参数赋初始值
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;		//输出模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;	//输出比较极性
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse=0;	//设置CCR寄存器值
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);
	
	TIM_Cmd(TIM2,ENABLE);
}

void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2,Compare);
}

(3)PWM.h

#ifndef __PWM_H
#define __PWM_h

void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);

#endif

3、编写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();
	
	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);
		}
	}
}

4、实现效果

PWM驱动LED呼吸灯

5、引脚重映射和解除调试端口

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);		//打开AFIO时钟
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);	//AFIO的复用功能引脚重映射 PA15
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);	//解除JTAG的复用,保留SWD的复用 关闭调试端口PA15、PB3、PB4
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;    //引脚口改为PA15

SWJ就是SWD和JTAG这两种调试方式 

GPIO_Remap_SWJ_NoJTRST 解除JTRST引脚的复用(PB4变为正常的GPIO接口,PA13、PA14、PA15、PB3还是调试端口)

GPIO_Remap_SWJ_JTAGDisable 解除JTAG调试端口的复用(PA15、PB3、PB4三个端口变回GPIO,PA13、PA14任为SWD的调试端口)

GPIO_Remap_SWJ_Disable 把SWD和JTAG的调试端口全部解除(PA13、PA14、PA15、PB3、PB4全变为普通的GPIO,没有调试功能了)

引脚重映射

四、PWM驱动舵机

1、外部设备——舵机

(1)舵机是一种根据输入PWM信号占空比来控制输出角度的装置

(2)输入PWM信号要求:周期为20ms高电平宽度为0.5ms~2.5ms

频率=1/周期=50Hz 

(3)硬件电路

2、按照以下接线方式连接,并将STLINK插到电脑上

3、驱动函数模块

(1)舵机驱动函数模块

        Servo.c

#include "stm32f10x.h"                  // Device header
#include "PWM.h"

void Servo_Init(void)
{
	PWM_Init();
}

void Servo_SetAngle(float Angle)
{
	PWM_SetCompare2(Angle/180*2000+500);	//将角度转化为CCR 0~180到500~2500的映射
}

        Servo.h

#ifndef __SERVO_H
#define __SERVO_H

void Servo_Init(void);
void Servo_SetAngle(float Angle);	

#endif

(2)PWM驱动函数模块

        PWM.c

#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
	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 舵机要求的周期是20ms,频率为1/20ms=50HZ
	TIM_TimeBaseInitStructure.TIM_Prescaler=72 - 1;	//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);	//给所有参数赋初始值
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;		//输出模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;	//输出比较极性
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse=0;	//设置CCR寄存器值 占空比
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);//通道2初始化对应引脚PA1
	
	TIM_Cmd(TIM2,ENABLE);
}

void PWM_SetCompare2(uint16_t Compare)
{
	TIM_SetCompare2(TIM2,Compare);
}

       PWM.h

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);

#endif

4、编写main.c代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "button.h"

uint8_t KeyNum;
float Angle;

uint8_t i;

int main(void)
{
	OLED_Init();
	Servo_Init();
	Button_Init();
	
	OLED_ShowString(1,1,"Angle:");
	
	while(1)
	{
		KeyNum=Button_GetNum();
		if(KeyNum == 1)
		{
			Angle+=30;
			if(Angle>180)
			{
				Angle=0;
			}
		}
		Servo_SetAngle(Angle);
		OLED_ShowNum(1,7,Angle,3);
	}
}

5、实现效果

PWM驱动舵机

五、PWM驱动直流电机

1、外部设备——直流电机

(1)直流电机是一种将电能转换为机械能的装置,有两个电极,当电极正接时,电机正转,当电极反接时,电机反转

(2)直流电机属于大功率器件,GPIO口无法直接驱动,需要配合电机驱动电路来操作

(3)TB6612是一款双路H桥型直流电机驱动芯片,可以驱动两个直流电机并且控制其转速方向

(4)硬件电路

2、按照以下接线方式连接,并将STLINK插到电脑上

3、驱动函数模块

(1)电机驱动函数模块

        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_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4 | GPIO_Pin_5;
	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);	//函数输出应该是正数
	}
}

         Motor.h

#ifndef __MOTOR_H
#define __MOTOR_H

void Motor_Init(void);
void Motor_SetSpeed(int8_t Speed);


#endif

(2)PWM驱动函数模块

        PWM.c

#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
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;				//通道3
	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   人耳听到的声音频率范围是20HZ到20kHZ
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);	//给所有参数赋初始值
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;		//输出模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;	//输出比较极性
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;	//输出使能
	TIM_OCInitStructure.TIM_Pulse=0;	//设置CCR寄存器值
	TIM_OC3Init(TIM2,&TIM_OCInitStructure);		//通道3
	
	TIM_Cmd(TIM2,ENABLE);
}

void PWM_SetCompare3(uint16_t Compare)
{
	TIM_SetCompare3(TIM2,Compare);
}

        PWM.h

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_SetCompare3(uint16_t Compare);

#endif

4、编写main.c代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "button.h"

uint8_t KeyNum;
int8_t Speed;

int main(void)
{
	OLED_Init();
	Motor_Init();
	Button_Init();
	
	OLED_ShowString(1,1,"Speed:");
	
	while(1)
	{
		KeyNum=Button_GetNum();
		if(KeyNum == 1)
		{
			Speed += 20;
			if(Speed >100)
			{
				Speed=-100;
			}
			Motor_SetSpeed(Speed);
			OLED_ShowSignedNum(1,7,Speed,3);
		}
	}
}

5、实现效果

PWM驱动直流电机

  • 16
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值