STM32 PWM

OC(Output Compare)输出比较

输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。(CCR是我们给定的值,当CNT大于、小于/等于CCR时,进行翻转)

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

高级定时器的前3个通道额外拥有死区生成和互补输出的功能

PWM简介

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

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

PWM参数:

频率 = 1 / TS     占空比 = TON / TS  分辨率 = 占空比变化步距

分辨率是以占空比的变化值的变量名,例如从1%、2、3%等就是以1%的的步距跳变,分辨率就是1%

模式

描述

冻结

CNT=CCR时,REF保持为原状态

匹配时置有效电平

CNT=CCR时,REF置有效电平

匹配时置无效电平

CNT=CCR时,REF置无效电平

匹配时电平翻转

CNT=CCR时,REF电平翻转

强制为无效电平

CNT与CCR无效,REF强制为无效电平

强制为有效电平

CNT与CCR无效,REF强制为有效电平

PWM模式1

向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平

向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平

PWM模式2

向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平

向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平

 PSC是预分频器的时钟,CCR是设定的比较值,ARR是计数器最大溢出值

 舵机简介

上述的值代入PWM公式满足要求,20K对应20ms

有此对应关系:

20K=20ms         

         X=需要的高电平宽度     求出X,X就是CCR的值

也可推出输出指定角度的公式有:Angle/180*2000+500

PWM.c

#include "stm32f10x.h"                  // Device header


void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择TIM2定时器
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//需要复用推挽输出,因为此程序是CH1输出,是片上外设
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;//根据GPIO引脚定义,此程序用的是OC2通道,对应的是CH2,由引脚图可知选PA1
	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;     //预分频系数1
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitStructure.TIM_Prescaler=72-1;//             //PSC
    TIM_TimeBaseInitStructure.TIM_Period=20000-1;//                 //ARR
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的中的重复计数器的
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时机单元初始化函数
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
	
	TIM_Cmd(TIM2,ENABLE);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//避免给一些没用到的参数赋予初始值而导致混乱
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//模式选择,此时选择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);
	
	
	
	
}

void PWM_SetCompare2(uint16_t Compare)
{
	
	TIM_SetCompare2(TIM2,Compare);//外部设计CCR的值
}

角度.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);
	
}

PWM.h

#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare2(uint16_t Compare);
#endif

角度.h

#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void);
void Servo_SetAngle(float Angle);

#endif

main

#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:");

	while(1)
	{
		KeyNum=Key_GetNum();
		if(KeyNum==1)
		{
			Angle+=15;
			if(Angle>180)
			{
				Angle=0;
			}
		}
			Servo_SetAngle(Angle);
			OLED_ShowNum(1,7,Angle,3);
	}
}

直流电机及驱动简介

 驱动芯片.c

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

void Motor_Init()
{
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5| GPIO_Pin_6| GPIO_Pin_7;
 	GPIO_Init(GPIOA, &GPIO_InitStructure);
	PWM_Init();
	
	
}

void Motor_SetSpeed(int8_t Speed)
{
	
	if(Speed>=0)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
		GPIO_SetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_6);
		PWM_SetCompare3(Speed);
		PWM_SetCompare2(Speed);
	}
	else
		{
		GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_7);
		GPIO_ResetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_6);
		PWM_SetCompare3(-Speed);
		PWM_SetCompare2(-Speed);
		}
	}

PWM.c

#include "stm32f10x.h"                  // Device header


void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择TIM2定时器
	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|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;     //预分频系数1
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
	TIM_TimeBaseInitStructure.TIM_Prescaler=36-1;//
TIM_TimeBaseInitStructure.TIM_Period=100-1;//
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器的中的重复计数器的
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时机单元初始化函数
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
	
	TIM_Cmd(TIM2,ENABLE);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//避免给一些没用到的参数赋予初始值而导致混乱
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//模式选择,此时选择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);
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);
	
	
	
}

void PWM_SetCompare3(uint16_t Compare)
{
	
	TIM_SetCompare3(TIM2,Compare);//外部设计CCR的值
}
void PWM_SetCompare2(uint16_t Compare)
{
	
	TIM_SetCompare2(TIM2,Compare);//外部设计CCR的值
}

本文是跟着江科大学习的,是本人的学习笔记,如有侵权请联系本人删除!

猜你喜欢

转载自blog.csdn.net/m0_71827453/article/details/131872577