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的值
}

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32中的PWM是通过定时器来生成的。在STM32F1系列中,并不是所有的定时器都支持PWM功能。支持PWM硬件输出技术的定时器有"通用定时器"和"高级控制定时器"这两种类型,而"基本定时器"则不支持PWM硬件输出技术。\[1\]\[2\]要使用PWM功能,需要配置定时器的基本设置,并设置一个比较计数值来确定一个周期内翻转电平的时机。此外,还需要使用GPIO的复用功能来输出方波。PWM波的高低电平顺序由极性、PWM模式和计数模式共同决定。需要注意的是,只有具有定时器复用功能的GPIO才能输出PWM信号。\[3\]所以,如果你想在STM32中使用PWM功能,需要根据具体的型号和定时器类型进行配置和编程。 #### 引用[.reference_title] - *1* *2* [STM32笔记之 PWM(脉宽调制)](https://blog.csdn.net/qq_42992084/article/details/108547321)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【STM32】详解PWM的概念和原理](https://blog.csdn.net/qq_43533553/article/details/128206887)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值