蓝桥杯嵌入式学习记录——PWM输出

目录

一、PWM原理介绍

二、学习目的

三、cubeMX的配置

四、PWM输出代码


一、PWM原理介绍

        PWM(Pulse Width Modulation,脉宽调制)是一种通过改变信号的脉冲宽度控制电平的技术。它通过调整脉冲信号的占空比(高电平时间与周期的比例)来实现对电压或电流的精确控制。

PWM的原理可以简单描述为以下几个步骤:

  1. 选择一个固定的周期:PWM信号由一系列周期性的脉冲组成,其中周期是固定的,表示脉冲信号的重复时间。

  2. 设置一个目标值:根据需要控制的设备或系统,设置一个目标值,例如期望的电压或电流。

  3. 比较目标值和当前值:将目标值与一个计数器进行比较,该计数器在每个周期内递增。如果目标值大于计数器的当前值,则输出高电平;如果目标值小于计数器的当前值,则输出低电平。

  4. 调整占空比:通过调整目标值与计数器的比较关系,可以改变脉冲信号的占空比。占空比越大,高电平时间越长,输出电平的平均值也就越高;占空比越小,高电平时间越短,输出电平的平均值也就越低。

  5. 输出PWM信号:根据比较结果,生成相应的脉冲信号。通常,高电平表示逻辑1或高电平电压,低电平表示逻辑0或低电平电压。

二、学习目的

        我们今天的学习目的是完成第十一届蓝桥杯嵌入式真题中的两路PWM输出部分,通过PA6、PA7两个引脚输出PWM脉冲,频率分别为100MHz、200MHz,并且通过两个按键来分别调节两路PWM输出的占空比,每次按下按键增加10%的占空比。

三、cubeMX的配置

我们需要通过定时器来完成PWM的输出,所以需要设置两个引脚为PWM输出引脚

1、打开cubeMX,选择PA6、PA7引脚并设置为定时器引脚

由上图可知,将PA6设置为TIM16_CH1,PA7设置为TIM17_CH1

这是因为我们需要选择通道1进行输出,而同为通道1的TIM3在上一节按键的使用中已经被用作按键的中断定时器,所以选择定时器16、17的通道1来进行PWM输出

2、点击Timers,选择TIM16、TIM17,勾选Activated打开使能,选择PWM Generation CH1

然后设置分频系数,预分频器值设置为8000-1数器重载值设置为100-1,此时脉冲频率为100MHz

同理,预分频器值设置为4000-1数器重载值设置为100-1,此时脉冲频率为200MHz

公式如下:

定时时间 = (预分频器值\times计数器重载值)/ 定时器时钟频率

脉冲频率 = 1 / 定时时间

3、设置脉冲数为20

四、PWM输出代码

        由于定时器的代码在cubeMX配置完成后就会自动生成,所以只需要在主函数中调用以下函数来启动定时器16、17:

HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);

再用以下函数设置占空比即可:

__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, pa6_duty);

__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, pa7_duty);

其中pa6_duty和pa7_duty是占空比,范围是10-90

与PWM输出相关的主函数代码如下:

main.c

// main.c

#include "main.h"
#include "tim.h"
#include "gpio.h"

#include "led.h"
#include "lcd.h"
#include "interrupt.h"
#include "stdio.h"

...  // 省略部分初始代码

extern struct keys key[];
uchar pa6_duty = 10;       // 定义占空比
uchar pa7_duty = 10;       // 定义占空比

char view = 0;             // 用于表示界面 0 or 1
char text[30];             // LCD显示的内容
void key_proc(void)        // 通过按键来切换界面、调节PWM占空比
{
	if(key[3].flag == 1)
	{
		view =! view;
	    key[3].flag = 0;
	}
	if(key[0].flag == 1)
	{
		pa6_duty += 10;
		if(pa6_duty >= 100) pa6_duty = 10;
		__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, pa6_duty);
		key[0].flag = 0;
	}
	if(key[1].flag == 1)
	{
		pa7_duty += 10;
		if(pa7_duty >= 100) pa7_duty = 10;
		__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, pa7_duty);
		key[1].flag = 0;
	}
}

void disp_proc(void)      // 界面的切换
{
	if(view == 0)
	{
		sprintf(text, "       Para");
		LCD_DisplayStringLine(Line0,(unsigned char *)text);
		LCD_DisplayStringLine(Line1,(unsigned char *)"                    ");
		LCD_DisplayStringLine(Line2,(unsigned char *)"                    ");
	}
	if(view == 1)
	{
		sprintf(text, "       DATA");		
	    LCD_DisplayStringLine(Line0,(unsigned char *)text);
	    sprintf(text, "    PA6:%d / 100     ", pa6_duty);
	 	LCD_DisplayStringLine(Line1,(unsigned char *)text);
		sprintf(text, "    PA7:%d / 100     ", pa7_duty);
		LCD_DisplayStringLine(Line2,(unsigned char *)text);		
	}
}

int main()
{
...// 省略部分初始代码
    LCD_Init();                // LCD的初始化
    LCD_Clear(Blue);
    LCD_SetBackColor(Blue);
    LCD_SetTextColor(White);

	HAL_TIM_Base_Start_IT(&htim3);              // 开启定时器3
	
	HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);  // 开启定时器16
	HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);  // 开启定时器17

while(1)
{
	disp_proc();
	key_proc();	
}
}

  • 24
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KAIs32

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值