学习硬件测试04:触摸按键+PWM 驱动蜂鸣器+数码管(P62~P67、P71、P72)

news2024/12/28 5:59:41

一、触摸按键

1.1理论讲解

1.1.1实验现象

  1. 触摸按键 1 单击与长按,控制 LED1;
  2. 触摸按键 2 单击与长按,控制 LED2;
  3. 触摸按键 3 单击与长按,控制 LED3;
  4. 触摸按键 4 单击与长按,控制继电器;

1.1.2硬件电路

是原理图上触摸按键、继电器、LED 灯三部分电路。

注意;按键一般为高电平,按下后为低电平,在配置时就要注意是下降沿触发。

1.1.3外部中断

1.1.4HAL库函数

第一行:读管脚状态,要么低电平,要么高电平。

第二行:写管脚状态,写高或者写低。

第三行:选择一个管脚,状态取反。

第四行:锁定管脚,进行保护状态,不能写了。

第五行:中断处理函数,软件自动生成的,后续讲解。

第六行:外部中断的回调函数,其中的变量是指示具体管脚,是具体管脚的回调函数。(如PA~PA15共用一个外部中断,如上图,共用一个回调函数,通过变量去判断具体是哪一个管脚引起的中断)

1.2初始化

1.2.1继电器初始化

推挽输出,默认低电平,使其刚开始处于断开的模式。

1.2.2触摸按键初始化

一般为高电平,按下后为低电平,故配置成下降沿触发。

(如果配上升沿触发,单击按键松开才触发,长按不触发;如果配置成均触发,则单击触发两次,所以触发方式的配置和硬件紧密相连)

注意不是配置成输入模式,而是配置成中断模式,后面软件编写也是启动中断的功能。

注意当按键 1 配置成中断时,与其共使用一个外部中断的其他引脚配置成的中断就会自动消失 

1.2.3配置按键的中断

1.3编程

在 main.c 中代码都是一样的,但是代码调用的代码是不一样的,不论是软件自动生成的初始化代码,还是我们自己编写的代码。

MyInit.Peripheral_Set() 自定义初始化代码如下:

static void Peripheral_Set()
{
	printf("----此程序实现触摸按键单击与长按功能----\r\n");
	printf("Initialization completed, system startup!\r\n");
	printf("Software version is V%.1f\r\n\r\n",SoftWare_Version);
	
	printf("等待触摸按键:\r\n\r\n");
}

说明:

  1. 代码比较灵活,长按的时间可以自由设定。
  2. 单击的时间也可以自由设定,可以不是10ms检查一次,可以是5ms检查一次,用户就不用等待那么长的时间。
  3. 本测试中按键式中断,并且是不影响其他中断的运行或者被影响,当有别的中断并不会影响该中断检查是不是长按/ 单击的程序。
  4. 注意上面说的别的中断,以及在其他任何项目中的一般中断,都要遵循“中断快进快出”的原则,运行几十微秒~几百微秒,问题都不大。

1.4实验现象

单击翻转 LED 灯的状态,长按 ≥2S 翻转两次 LED 灯的状态,两次间隔 200ms。

触摸按键

二、PWM 驱动蜂鸣器

2.1理论讲解

2.1.1程序功能

上电后,无源蜂鸣器发出声音,通过触摸按键关闭或打开蜂鸣器。

2.1.2无源蜂鸣器

无源蜂鸣器没有振动源,驱动需要 PWM 波来驱动,通过改变 PWM 波的频率来改变蜂鸣器的声音。

2.1.3 PWM

英文全称 Pulse-Width Modulation,脉冲宽度调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,通过调占空比调节光的强度、声音、电机等。本次是通过通用定时器进行频率调节。

2.1.4通用定时器 TIMx

本次是通过通用定时器来调节 PWM 的频率,TIMx 器是一个通过可编程预分频器驱动的 16 位自动装载计数器构成。它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)。使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整,每个定时器都是完全独立的,没有互相共享任何资源,可以一起同步操作,包含:

  • 计数器寄存器(TIMx_CNT)
  • 预分频器寄存器 (TIMx_PSC)
  • 自动装载寄存器 (TIMx_ARR)

2.1.5计数模式

在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。这样的计数方式更加灵活,在计数中间时可以和另一个设定的值进行比较,进行其他需要的操作。

2.1.6 PWM模式

脉冲宽度调制模式可以产生一个由 TIMx_ARR 寄存器确定频率由TIMx_CCRx寄存器确定占空 比的信号

2.1.7HAL库函数

这些是定时器关于PWM的函数:

  1. 上面4个是:初始化函数,不用我们写
  2. 第4个:DMA功能,没用到
  3. 第3个:中断,没用到
  4. 第2个:启动、停止输出功能,后续就是通过触摸按键调用这两个函数打开或者关闭报警。

2.2软件初始化

2.2.1 框1

蜂鸣器的引脚为 PA8 ,在 Cubemx 中 PA8 只能设置成为定时器 1,定时器 1 是高级定时器,具有上面所讲的通用定时器的功能,我们也只使用通用定时器的功能,其他的功能不展开讲解和使用。

2.2.2 框2

Clock Source 时钟源:选择使用内部时钟

Channel1:输出 PWM 波

注意在这里设置完之后,引脚可能会自动跳变到默认引脚,这里是 PE9,还需要手动重新设置为我们蜂鸣器的 PA8。

2.2.3 框3

(1)预分频器

系统时钟 72M,AHB2 的时钟频率也是 72M ,故 PA8 的初始时钟也是 72M ,通过预分频器企图达到的目标评率为 1M 。

预分频器可以进行 0~65535 分频(因为零也算,所以后面要加一),计算预分频器具体分频数 X 的公式如下:

所以在软件配置的值为:72000000/1000000-1(目标频率是 1M )

(2)其他

Counter Mode 计数模式:向上

Counter Period 自动重装定时器:设置 PWM 波的频率

频率=预分频器频率/次数=1000000/1000=1000HZ

Internal Clock Division 内部时钟分频器:不需要

Repetition Counter 重复计数器:高级定时器功能,此处不需要

auto-reload preload 自动重新装载:必须使能,由于后续需要改变蜂鸣器的音色,就需要改变频率,该变频率就需要重装载。如果没有使能,后续即使改变 ARR 值夜不会重新装载进去。

2.2.4 框4

这里主要是设置占空比。

Mode 模式:PWM 模式 1

Pulse 脉冲(16 位值):500,这个值就是 CCR

可以这么理解,通过预分频器最后的时钟频率是1M,但是我还要自己更加灵活的控制PWM的频率,灵机一动想到了计数的方式。

所以才有了通过上面的设置让计数 1000 次(ARR),周期就变成了 1M×1000 =1ms 。

就这么利用一下这个计数,未免也太浪费资源了吧,既然它在向上计数,那就在中间设计一个比较值 CCR,利用 CCR 来调节占空比,小于 CCR 时 PWM 波输出高电平,大于 CCR 是 PWM 波输出低电平。)

Qutput compare preload 输出比较预加载:使能(可以改变占空比,而不是固定占空比)

极速模式:关闭

CH 极性:高(小于 CCR 的状态)

状态:重置

2.2.5达到的状态

每隔一毫秒中断一次,占空比为 50% 。

2.3编程

2.3.1文件结构

Buzzer.c:控制蜂鸣器的开启,并记录其状态。

Timer6.c:通过定时器 6 改变频率,发出不同的声音。

触摸按键:触发中断关闭或者打开蜂鸣器。

2.3.2文件内容

(1)运行函数

main.c → System.c 

运行函数中没有内容,因为这一次是通过按键中断来改变声音。

(2)蜂鸣器结构体

Buzzer.h

Buzzer.c

#include "MyApplication.h"


static void Buzzer_ON(void); 
static void Buzzer_OFF(void); 

//定义结构体
Buzzer_t Buzzer = 
{
	OFF_Status,//默认蜂鸣器初始状态是关闭
	
	Buzzer_ON,
	Buzzer_OFF
    //两个函数赋给函数指针,函数如下
};


static void Buzzer_ON(void)//打开蜂鸣器
{
	Buzzer.Status = ON_Status;//更新一下状态为打开状态
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);//通过这个HAL库函数打开定时器(定时器1,通道1)
}


static void Buzzer_OFF(void)//关闭蜂鸣器,理论同上
{
	Buzzer.Status = OFF_Status;
	HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_1);
}
(3)Myinit.c

上电初始化只是打开蜂鸣器

(4)改变频率来改变音色

也是在 CallBack.c 文件中,共有三个参数:

  1. f:频率 → 通过改变 ARR(1000:1ms;2000:2ms;500:0.5ms)
  2. cnt:在某一频率是重复的时间长度
#include "MyApplication.h"

/*
	* @name   HAL_TIM_PeriodElapsedCallback
	* @brief  定时器中断回调函数
	* @param  *htim -> 处理定时器的结构体指针
	* @retval None      
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint8_t Fre_Cnt = 0;
	
	if(htim->Instance == htim6.Instance)
	{
		//程序支持运行,指示灯间隔1s闪烁
		if(++Timer6.usMCU_Run_Timer >= TIMER0_1S)
		{
			Timer6.usMCU_Run_Timer = 0;
			
			LED.LED_Flip(LED1);
		}
		
		//控制PWM的频率长度与大小
		if(Fre_Cnt++ >= 2)
		{
			Fre_Cnt = 0;
			
			//定时器时钟 = 1MHz
			PWM频率 = 1/((1/1000000)*ARR) = 1000000/ARR  
			//ARR = 250, PWM频率为4KHz
			//ARR = 500, PWM频率为2KHz
			//ARR = 1000,PWM频率为1KHz
			//ARR = 2000,PWM频率为0.5KHZ
			TIM1->ARR -= 10;
			if(TIM1->ARR <= 500)
				TIM1->ARR = 2000;
			
			//设置占空比为50%
			TIM1->CCR1 = TIM1->ARR / 2;
		}
	}
}
(5)CallBack.c

只控制蜂鸣器打开或者关闭,按下按键就翻转蜂鸣器的状态。

#include "MyApplication.h"

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == KEY1_Pin)
	{
		LED.LED_Flip(LED2);
		
		//控制蜂鸣器开关
		if(Buzzer.Status == ON_Status)
		{
			Buzzer.OFF();
		}
		else
		{
			Buzzer.ON();
		}
	}
}

2.3.3整体框架

等我明天(8.3)画出来,等我!

2.3.4实验现象

PWM波驱动蜂鸣器

三、数码管

3.1数码管驱动 IC 手册阅读

3.2编程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1973385.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3+element-plus实现table表格整列的拖拽

参考文章&#xff1a;https://blog.csdn.net/candy0521/article/details/136470284 一、为防止原文章不见了将参考文章代码拷过来了&#xff08;不好意思&#xff09;&#xff1a;这是参考文章的代码 可直接复制粘贴运行 <template><div class"draggable-table&…

uniapp 多渠道打包实现方案

首先一个基础分包方案&#xff1a; 包不用区分渠道&#xff0c;只是通过文件名进行区分&#xff0c;公共代码逻辑可以通过mixins进行混入。 这样分包后就需要在打包时只针对编译的渠道包文件进行替换打包&#xff0c;其他渠道包的文件不打包进去&#xff0c;通过工具类实现…

商业策划案怎么写?附商场230个策划案例

商业策划案的撰写是一个系统性工程&#xff0c;旨在详细阐述项目的背景、目标、实施策略、财务预测及风险评估等内容&#xff0c;以吸引投资者或合作伙伴的关注。 以下是一个详细的撰写步骤和要点&#xff0c;码字不易&#xff0c;如果回答对你有所帮助&#xff0c;请不吝给一…

GraphRAG如何使用ollama提供的llm model 和Embedding model服务构建本地知识库

使用GraphRAG踩坑无数 在GraphRAG的使用过程中将需要踩的坑都踩了一遍&#xff08;不得不吐槽下&#xff0c;官方代码有很多遗留问题&#xff0c;他们自己也承认工作重心在算法的优化而不是各种模型和框架的兼容性适配性上&#xff09;&#xff0c;经过了大量的查阅各种资料以…

【目标和】python刷题记录

R3-dp篇. 目录 思路&#xff1a; 增加记忆化搜索&#xff1a; 优化空间复杂度&#xff1a; 思路&#xff1a; class Solution:def findTargetSumWays(self, nums: List[int], target: int) -> int:#设正数之和为p,总元素之和为s&#xff0c;带符号总元素之和为t&…

AWS开发人工智能:如何基于云进行开发人工智能AI

随着人工智能技术的飞速发展&#xff0c;企业对高效、易用的AI服务需求日益增长。Amazon Bedrock是AWS推出的一项创新服务&#xff0c;旨在为企业提供一个简单、安全的平台&#xff0c;以访问和集成先进的基础模型。本文中九河云将详细介绍Amazon Bedrock的功能特点以及其收费方…

安卓常用控件(上)

文章目录 TextViewButtonEditText TextView textview主要用于在界面上显示一段文本信息。 属性名描述id给当前控件定义一个唯一的标识符。layout_width给控件指定一个宽度。match_parent&#xff1a;控件大小与父布局一样&#xff1b;wrap_content&#xff1a;控件大小刚好够包…

WinUI vs WPF vs WinForms: 三大Windows UI框架对比

1.前言 在Windows平台上开发桌面应用程序时&#xff0c;WinUI、WPF和WinForms是三种主要的用户界面框架。每种框架都有其独特的特点和适用场景。本文将通过示例代码&#xff0c;详细介绍这些框架的优缺点及其适用场景&#xff0c;帮助dotnet桌面开发者更好地选择适合自己项目的…

【Spring】SSM框架整合Spring和SpringMVC

目录 1.项目结构 2.项目的pom.xml文件 3.spring.xml和springMVC配置文件 4.database.properties和mybatis.xml配置文件 5. 代码编写 6.测试整合结果 1.项目结构 首先创建一个名为ssm_pro的Mavew项目&#xff0c;然后再在主目录和资源目录下&#xff0c;创建如下所示的结…

5.2-软件工程基础知识-软件过程模型

软件过程模型 瀑布模型瀑布模型变种-V模型演化模型-原型模型增量模型演化模型-螺旋模型喷泉模型基于构件的开发模型形式化方法模型统一过程模型敏捷方法极限编程其他方法 软件过程模型概述练习题 瀑布模型 瀑布模型(SDLC):瀑布模型是一个经典的生命周期模型&#xff0c;一般将软…

SpringBoot中如何正确使用Redis(详细介绍,原理讲解,企业版)

1.引入Redis依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2.配置Redis的连接信息(application.yml) 实际开发中有两个一个是开发环境applicati…

VBA字典与数组第十七讲:工作表数组大小的扩展及意义

《VBA数组与字典方案》教程&#xff08;10144533&#xff09;是我推出的第三套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;字典是VBA的精华&#xff0c;我要求学员必学。7.1.3.9教程和手册掌握后&#xff0c;可以解决大多数工作中遇到的实际问题。…

JAVA(IO流)7.31

ok了家人们今天还是学习IO流&#xff0c; 一.打印流【了解】 1.1 打印流的概述 我们平时使用的System语句就是调用了print()方法和println()方法。 这两个方法都来自于 java.io.PrintStream 类。 作用&#xff1a; 该类能够方便地打印各种数据类型的值&#xff0c;写入数据后…

谷粒商城实战笔记-115-全文检索-ElasticSearch-进阶-bool复合查询

文章目录 1&#xff0c;must2&#xff0c;must not3&#xff0c;should 1&#xff0c;must {"query": {"bool": {"must": [{"match": {"gender": "M"}},{"match": {"address": "mill&q…

java代码审计-SQL的注入

0x01 前言 Java里面常见的数据库连接方式有三种&#xff0c;分别是JDBC&#xff0c;Mybatis&#xff0c;和Hibernate。 0x02 JDBC注入场景 很早之前的Javaweb都是用JDBC的方式连接数据库然后去实现dao接口再调service业务层去实现功能代码JDBC连接代码 WebServlet("/d…

科技云报道:大模型引领技术浪潮,AI安全治理面临“大考”

科技云报道原创。 从文生文到文生图&#xff0c;再到文生视频&#xff0c;近年来&#xff0c;以ChatGPT、Sora等为代表的大模型引领了全球人工智能技术与产业的新一轮浪潮。2024年更是被业内称为大模型应用爆发元年。 年初&#xff0c;Sora横空出世验证了Scalling Law在视频生…

计算机的错误计算(五十)

摘要 扩展了计算机的错误计算&#xff08;四十九&#xff09;中的代码。同时发现&#xff0c;误差也“扩展”了。 下面是代码&#xff1a; import torch# 设置随机种子 torch.manual_seed(0)# 创建张量并移动到GPU W1 torch.randn(5, 3) * 10 W1 W1.to(cuda) X1 torch.ran…

高级宏定义

平时常说的 C 语言三大预处理功能是什么&#xff1f;&#xff08;吹牛谈资&#xff0c;不能不知&#xff09; 答&#xff1a;宏定义&#xff1b;文件包含&#xff1b;条件编译。 说到底&#xff0c;宏定义的实质是什么&#xff1f; 答&#xff1a;替换。 关于宏定义有一点…

CSS技巧专栏:一日一例 18 -纯CSS实现背景浮光掠影的按钮特效

CSS技巧专栏:一日一例 18 -纯CSS实现背景浮光掠影的按钮特效 先发图,再说话: 案例图片 案例分析 按钮是好几种颜色的背景色组成的,使用css的话,应该会有几个不同颜色的层,在按钮后面移动。每个层互相叠加,大概还会用到图片混合模式产生了更多的叠加的颜色,然后边缘过…