stm32标准库和HAL库的对比学习5.《学习pwm输出和驱动舵机》

本文介绍了STM32单片机使用定时器OC功能实现PWM的基本原理,包括CRR输入/捕获寄存器的作用,以及如何通过调整CNT和CRR设置PWM的频率和占空比。作者还提供了使用标准库和HAL库配置PWM输出的示例,以及如何驱动舵机以控制电机角度。
摘要由CSDN通过智能技术生成

本人是大一的学生,学习了一段时间的stm32,此系列博客为个人的学习笔记,方便个人复习,如有错误或问题,非常非常欢迎大家来大力指正。

本篇默认有51单片机基础,所以pwm原理就不再赘述

与51单片机不同,stm32实现pwm的方法是通过定时器的“输出比较output compare(简称oc,不是超频)”来实现的。通过CNT(计时单元)与CRR(输入/捕获寄存器)的比较实现电平的反转。

先说CRR输入/捕获寄存器,顾名思义,他是有输入和输出的功能,输出功能就是输出pwm,输入功能就是对输入的pwm进行识别。而想要驱动舵机,就要用pwm输出来控制。

先讲pwm输出

stm32实现pwm的方法是CNT计数,然后和CRR比较,当CNT=CCR时,对电平产生变化。然后当CNT=ARR时,触发计数器中断,CNT置0,恢复以前的电平,重新计数。这样就是现实电平在一个周期内的有规律变化,通过调整CRR,就可以调整pwm的占空比。

CNT=CRR的电平变化由模式所决定,下面程序说

PWM freq=ck psc(单片机频率)/(psc+1)/(ARR+1)
pwm占空比 duty=ccr/(arr+1)
pwm分辨率 reso=1/(arr+1)

②标准库的代码实现

pwm的基本结构如图,要用到上节定时器的功能,所以要开启RCC时钟,定义时基单元,配置CCR。前两部像上一节一样配就行,但是不用设定NVIC中断。而定义CCR首先要看TIM_OCInitTypeDef structure结构体中所要定义的东西。

有很多都是高级定时器要用的,我们只需要写出我们需要用的进行,看下面代码

输出极性可以理解为“是否要将电平信号反转”

下面4个都是输出极性的定义,死区生成是防止互补输出时两个电路一起导通产生损耗,延迟下一个端口导通的时间

TIM_ocmode中有几个模式,配置输出比较控制器,当CCR=CNT时输出不同形式的电平

第一个为保持原状态

有效电平和无效电平就可以看作高电平和低电平,电平反转可以输出一个固定平衡率的波形

强制电平和第一个差不多,就是暂停后输出特定的电平

pwm模式是可以输出频率可变的波形.

void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);高级寄存器要用这条使能。

第一步开启RCC,定义好TIM时基单元

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);		//开启GPIOA的时钟
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//因为一般的GPIO控制权是在寄存器上的,看原理图,OC1通道要接到引脚才能输出pwm,所以要用复用推挽,让引脚接入片上外设
	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_Prescaler=720-1;         //psc预分频器
    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式       

    TIM_TimeBaseInitStructure.TIM_Period=100-1;            //ARR自动重装器的初始值(周期)

    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;     //滤波分频

    TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;  //重复计数器
                                
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

第二步用结构体定义OC

	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//注意事项,初始值赋值,防止未定义的函数产生错误
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//配置OC的输出模式
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//比较极性
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出使能
	TIM_OCInitStructure.TIM_Pulse=50 ;//ccr的值
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);//注意OC后面是通道编号
	TIM_Cmd(TIM2, ENABLE);

PWM已经定义完毕。

实现pwm的占空比变化不能像51单片机这样写,要用到专门改变占空比的

 TIM_SetCompare1(TIM2, num);函数来改变CCR的值,从而改变占空比。

改变num的值,就是改变CCR,从而输出PWM。用上面的公式计算。

100hz:ARR:100-1.PSC:720-1

50hz(sg50):ARR:20000-1,PSC:72-1.接上对应接上通道的引脚,就可以输出pwm信号

③HAL库的实现:

我们可以按照标准库的定义开启选项

①开启RCC

②开启TIM,打开内部时钟,选择通道和输出模式,打开NVIC中断

③配置OC(跟着标准库数据配置就好)

然后生成代码

写上下面两条代码

HAL_TIM_Base_Init(&htim2);//初始化tim2

HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);//打开pwm输出

下面那条是比较输出的代码

	__HAL_TIM_SetCompare(&htim2,TIM_CHANNEL_1,CCR的值);
和TIM_SetCompare1(TIM2, num);一样

驱动舵机:

根据上面来输出合适的pwm使电机转动特定的角度,通过上面几条公式,进行计算即可。

        重映射复用端口的小知识:要看手册找到相应的复用端口,先开启RCC时钟(将gpio换为AFIO就可以)然后用gpio_pinremapconfig();来重映射引脚

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值