目录
题目要求(真题):
使用第十一届第二场真题,练习PWM波部分的代码,实现可以通过按键进行页面切换,加减PWM波占空比,并显示在LCD屏幕上
cubeMX配置:
配置pa6,pa7为pwm输出引脚
启用定时器为pwm输出,占空比可以先随便设置一下,这里为20
配置pwm频率,计算公式为:
根据题目,PA6输出100hz,PA7输出200hz:
PA6:
PA7:
小试牛刀:
Keil代码:
注意:首先要开启PWM输出通道
HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);
user.c
#include "user.h" // 包含用户定义的头文件 user.h
u8 ui=1; // 定义全局变量 ui,用于控制 LCD 显示
u8 pa6_duty=10; // 定义全局变量 pa6_duty,用于控制 PA6 引脚的 PWM 占空比
u8 pa7_duty=10; // 定义全局变量 pa7_duty,用于控制 PA7 引脚的 PWM 占空比
void KEY_proc() // 定义按键处理函数 KEY_proc
{
// 对四个按键进行单击、长按、双击的处理
if(single_key_flag[0]==1) // 如果按键1单次按下
{
ui+=1; // 控制 LCD 显示界面切换
if(ui>=3) ui=1; // 如果 ui 大于等于3,重置为1
single_key_flag[0]=0; // 用完标记清零
}
if(single_key_flag[1]==1) // 如果按键2单次按下
{
pa6_duty+=10; // 增加 PA6 引脚的 PWM 占空比
if(pa6_duty>=100) pa6_duty=10; // 如果占空比大于等于100,重置为10
__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, pa6_duty); // 设置 TIM16 的通道1 PWM 占空比
single_key_flag[1]=0; // 用完标记清零
}
if(single_key_flag[2]==1) // 如果按键3单次按下
{
pa7_duty+=10; // 增加 PA7 引脚的 PWM 占空比
if(pa7_duty>=100) pa7_duty=10; // 如果占空比大于等于100,重置为10
__HAL_TIM_SetCompare(&htim17, TIM_CHANNEL_1, pa7_duty); // 设置 TIM17 的通道1 PWM 占空比
single_key_flag[2]=0; // 用完标记清零
}
}
u32 lcd_tick=0; // 定义 LCD 刷新计时变量 lcd_tick
void Disp_proc () // 定义 LCD 显示处理函数 Disp_proc
{
if(uwTick-lcd_tick<100) // 如果当前时间与上次刷新时间间隔小于100ms,返回
return;
lcd_tick=uwTick; // 更新 LCD 刷新时间
if(ui==1) // 如果显示界面为1
{
u8 text[50]; // 定义存放文本的数组 text
sprintf(text, " DATE "); // 设置第一行显示文本为 " DATE "
LCD_DisplayStringLine(Line1, (unsigned char *)text); // 在第一行显示文本
sprintf(text, " V: "); // 设置第三行显示文本为 " V: "
LCD_DisplayStringLine(Line3, (unsigned char *)text); // 在第三行显示文本
sprintf(text, " Mode: "); // 设置第五行显示文本为 " Mode: "
LCD_DisplayStringLine(Line5, (unsigned char *)text); // 在第五行显示文本
}
if(ui==2) // 如果显示界面为2
{
u8 text[50]; // 定义存放文本的数组 text
sprintf(text, " Para "); // 设置第一行显示文本为 " Para "
LCD_DisplayStringLine(Line1, (unsigned char *)text); // 在第一行显示文本
sprintf(text, " PA6:%d ",pa6_duty); // 根据 PA6 占空比设置第三行显示文本
LCD_DisplayStringLine(Line3, (unsigned char *)text); // 在第三行显示文本
sprintf(text, " PA7:%d ",pa7_duty); // 根据 PA7 占空比设置第五行显示文本
LCD_DisplayStringLine(Line5, (unsigned char *)text); // 在第五行显示文本
}
}
在 KEY_proc 中,根据按键的单击事件更新全局变量 ui(控制 LCD 显示界面切换)和两个 PWM 占空比参数 pa6_duty 和 pa7_duty;在 Disp_proc 中,根据 ui 的值选择显示不同的界面,其中界面1显示固定文本,界面2显示带有动态参数的文本。
注意:
__HAL_TIM_SetCompare(&htim16, TIM_CHANNEL_1, pa6_duty); // 设置 TIM16 的通道1
一定要有这句代码,是它将pa6_duty这个参数的值更新到了PWM的输出中。
user.h
#ifndef __USER_H // 如果未定义过 __USER_H 宏
#define __USER_H // 定义 __USER_H 宏,防止头文件重复包含
#include "main.h" // 包含主头文件 main.h
#include "lcd.h" // 包含 LCD 相关头文件 lcd.h
#include "key.h" // 包含按键相关头文件 key.h
#include "led.h" // 包含 LED 相关头文件 led.h
#include "tim.h" // 包含定时器相关头文件 tim.h
void KEY_proc(void); // 声明按键处理函数 KEY_proc
void Disp_proc(void); // 声明显示处理函数 Disp_proc
#endif // 结束条件编译指令
main.c
int main(void)
{
/* USER CODE BEGIN 1 */ // 在这里插入用户自定义的代码段1
/* USER CODE END 1 */ // 用户自定义的代码段1结束
/* MCU Configuration--------------------------------------------------------*/ // MCU 配置
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */ // 复位所有外设,初始化 Flash 接口和 SysTick 定时器
HAL_Init(); // HAL 库初始化
/* USER CODE BEGIN Init */ // 用户自定义的代码段2开始
/* USER CODE END Init */ // 用户自定义的代码段2结束
/* Configure the system clock */ // 配置系统时钟
SystemClock_Config(); // 调用系统时钟配置函数
/* USER CODE BEGIN SysInit */ // 用户自定义的代码段3开始
/* USER CODE END SysInit */ // 用户自定义的代码段3结束
/* Initialize all configured peripherals */ // 初始化所有配置的外设
MX_GPIO_Init(); // 初始化 GPIO 外设
MX_TIM3_Init(); // 初始化定时器 TIM3
MX_TIM16_Init(); // 初始化定时器 TIM16
MX_TIM17_Init(); // 初始化定时器 TIM17
/* USER CODE BEGIN 2 */ // 用户自定义的代码段4开始
LED_disp (0); // 调用 LED 显示函数,将 LED 初始状态设置为关闭
HAL_TIM_Base_Start_IT(&htim3); // 启动 TIM3 定时器的基本定时器模式并启用定时器中断
LCD_Init(); // LCD 初始化
HAL_TIM_PWM_Start(&htim16, TIM_CHANNEL_1); // 启动 TIM16 定时器的 PWM 模式,并启用通道1
HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1); // 启动 TIM17 定时器的 PWM 模式,并启用通道1
/* USER CODE END 2 */ // 用户自定义的代码段4结束
/* Infinite loop */ // 无限循环
/* USER CODE BEGIN WHILE */ // 用户自定义的代码段5开始
LCD_Clear(Black); // 清屏,将背景色设置为黑色
LCD_SetBackColor(Black); // 设置背景色为黑色
LCD_SetTextColor(White); // 设置文本颜色为白色
while (1) // 进入无限循环
{
/* USER CODE END WHILE */ // 用户自定义的代码段5结束
/* USER CODE BEGIN 3 */ // 用户自定义的代码段6开始
KEY_proc(); // 处理按键事件
Disp_proc (); // 控制 LCD 显示内容
}
/* USER CODE END 3 */ // 用户自定义的代码段6结束
}
效果演示:
蓝桥杯嵌入式PWM输出效果演示