基于STM32的感应开关垃圾桶

news2025/1/12 2:43:37

1.定时器介绍

1.1 工作原理

使用精准的时基,通过硬件的方式,实现定时功能。

1.2 定时器分类

  • 基本定时器(TIM6~TIM7)
  • 通用定时器(TIM2~TIM5)
  • 高级定时器(TIM1和TIM8)

1.3 通用定时器介绍

1) 16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)
2) 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。
3)4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
        A.输入捕获
        B.输出比较
        C.PWM 生成(边缘或中间对齐模式)
        D.单脉冲模式输出
4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
5)如下事件发生时产生中断/DMA:
        A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
        B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
        C.输入捕获
        D.输出比较
        E.支持针对定位的增量(正交)编码器和霍尔传感器电路
        F.触发输入作为外部时钟或者按周期的电流管理

1.4 定时器计数模式

1.5 定时器溢出时间计算公式

例如,要定时500ms,则:PSC=7199,ARR=4999,Tclk=72M(PSC和ARR的值没有规定 只需要预先想好溢出时间的值 通过公式能够整除得到即可)

1.6 定时器中断实验

需求:使用定时器中断方法,每500ms翻转一次LED1灯状态。
1. RCC配置
2. LED1灯配置
3. 时钟数配置
4. TIM2配置

5. 工程配置
6. 重写更新中断回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM2)
    {
        HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);//翻转电平
    }
}

7. 启动定时器
在main.c中,在定时器初始化命令之后加入以下代码:

HAL_TIM_Base_Start_IT(&htim2);

2.PWM介绍

2.1 STM32F103C8T6 PWM资源

高级定时器(TIM1):7路
通用定时器(TIM2~TIM4):各4路

2.2 PWM输出模式

  • PWM模式1:在向上计数时,一旦 CNT < CCRx 时输出为有效电平,否则为无效电平; 在向下计数时,一旦 CNT > CCRx 时输出为无效电平,否则为有效电平。
  • PWM模式2:在向上计数时,一旦 CNT < CCRx 时输出为无效电平,否则为有效电平; 在向下计数时,一旦 CNT > CCRx 时输出为有效电平,否则为无效电平。

2.3 PWM周期与频率

2.4 PWM占空比

由TIMx_CCRx寄存器决定。

2.5 PWM实验

需求:使用PWM点亮LED1实现呼吸灯效果。

2.5.1 LED灯为什么可以越来越亮,越来越暗?

这是由不同的占空比决定的。

2.5.2 如何计算周期/频率?

假如频率为 2kHz ,则:PSC=71,ARR=499

2.5.3 LED1连接到哪个定时器的哪一路?

学会看产品手册

2.6 PWM呼吸灯实验

1. 设置时钟
2. 设置定时器

3. 配置工程
4. 业务代码

// 定义变量
uint16_t pwmVal=0; //调整PWM占空比
uint8_t dir=1; //设置改变方向。1:占空比越来越大;0:占空比越来越小
// 使能 Timer4 第3通道 PWM 输出
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);
// while循环实现呼吸灯效果
while (1)
{
		HAL_Delay(1);
		if(dir)
		{
			pwmVal++;
			if(pwmVal >= 499)
			{
				dir = 0;
			}
		}
		else
		{
			pwmVal--;
			if(pwmVal == 0)
			{
			    dir = 1;
			}
		}
        //修改比较值,修改占空比
        __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwmVal);
}

3.项目需求

  • 检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

4.项目框图

5.sg90舵机介绍及实战

 PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右。

5.1 确定频率/周期

 如果周期为20ms,则 PSC=7199,ARR=199

5.2 角度控制

0.5ms-------------0度; 2.5% 对应函数中CCRx为5
1.0ms------------45度; 5.0% 对应函数中CCRx为10
1.5ms------------90度; 7.5% 对应函数中CCRx为15
2.0ms-----------135度; 10.0% 对应函数中CCRx为20
2.5ms-----------180度; 12.5% 对应函数中CCRx为25

5.3 CCRx计算

以0度为例:

 

这里的CCRx就是有效电平 上下图对比可知CCRx对应0.5ms ARR对应20ms 呈现比例关系 但在上面我们设置ARR=200 所以通过比例式得到:

5.4 编程实现

5.4.1 需求

每隔1s,转动一个角度:0度 --> 45度 --> 90度 --> 135度 --> 180度 --> 0度

5.4.2 硬件接线

5.4.3 代码

HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);
while (1)
{
    HAL_Delay(1000);
    __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);
    HAL_Delay(1000);
    __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 10);
    HAL_Delay(1000);
    __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15);
    HAL_Delay(1000);
    __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20);
    HAL_Delay(1000);
    __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 25);
}

6.超声波模块介绍及实战

6.1 超声波传感器介绍

6.2 编程实现

6.2.1 需求

使用超声波测距,当手离传感器距离小于5cm时,LED1点亮,否则保持不亮状态。

6.2.2 接线

Trig --- PB6
Echo --- PB7
LED1 --- PB8

6.2.3 定时器配置

6.2.4 编写微妙级函数
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//使用TIM2来做us级延时函数
void TIM2_Delay_us(uint16_t n_us)
{
	/* 使能定时器2计数 */
	__HAL_TIM_ENABLE(&htim2);
	__HAL_TIM_SetCounter(&htim2, 0);
	while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
	/* 关闭定时器2计数 */
	__HAL_TIM_DISABLE(&htim2);
}
 
/* USER CODE END 0 */
6.2.5 主函数

//1. Trig ,给Trig端口至少10us的高电平

//2. echo由低电平跳转到高电平,表示开始发送波

        //波发出去的那一下,开始启动定时器

//3. 由高电平跳转回低电平,表示波回来了

        //波回来的那一下,我们开始停止定时器

//4. 计算出中间经过多少时间

//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us) //每500毫秒测试一次距离

  /* USER CODE BEGIN 1 */
	int cnt=0;
	float distance=0;
	
  /* USER CODE END 1 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
		//1. Trig ,给Trig端口至少10us的高电平
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//拉高
		TIM2_Delay_us(20);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);//拉低
		
		//2. echo由低电平跳转到高电平,表示开始发送波
		//波发出去的那一下,开始启动定时器
		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_RESET);
		HAL_TIM_Base_Start(&htim2);
		__HAL_TIM_SetCounter(&htim2, 0);
		
		//3. 由高电平跳转回低电平,表示波回来了
		//波回来的那一下,我们开始停止定时器
		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_SET);
		HAL_TIM_Base_Stop(&htim2);
		
		//4. 计算出中间经过多少时间
		time_us = __HAL_TIM_GetCounter(&htim2);
		
		//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)
		distance = time_us * 340/2 * 0.000001 * 100; //单位:cm
		
		//距离小于10,点灯
		if(distance < 5)
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
		else
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
		
		//每500毫秒测试一次距离
		HAL_Delay(500);
		
  }
  /* USER CODE END 3 */

7.项目设计与实现

7.1 项目设计

超声波模块:
Trig -- PB6
Echo -- PB7


sg90舵机:

PWM -- PB9


按键:
KEY1 -- PA0


LED灯:
LED1 -- PB8


震动传感器:
D0 -- PB5
VCC -- 5V


蜂鸣器:
IO -- PB4
VCC -- 3V3

7.2 项目实现

/* Private variables ---------------------------------------------------------*/
 
/* USER CODE BEGIN PV */
float distance;
#define OPEN 1
#define CLOSE 0
/* USER CODE END PV */

/* USER CODE BEGIN PV */
char flag = CLOSE;
/* USER CODE END PV */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

//测距获取信息
float get_distance()
{
	//1. Trig ,给Trig端口至少10us的高电平
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);//拉高
	TIM2_Delay_us(20);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);//拉低
	
	//2. echo由低电平跳转到高电平,表示开始发送波
	//波发出去的那一下,开始启动定时器
	while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_RESET);
	HAL_TIM_Base_Start(&htim2);
	__HAL_TIM_SetCounter(&htim2, 0);
	
	//3. 由高电平跳转回低电平,表示波回来了
	//波回来的那一下,我们开始停止定时器
	while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_SET);
	HAL_TIM_Base_Stop(&htim2);
	
	//4. 计算出中间经过多少时间	
	//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)
	return __HAL_TIM_GetCounter(&htim2) * 340/2 * 0.000001 * 100; //单位:cm
}

void openStatusLight()
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);//打开LED1
}

void closeStatusLight()
{
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//熄灭LED1
}

void initSG90()
{
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);
	__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5);//将舵机设罿0度
}
 
//开盖,亮指示灯,蜂鸣器响
void openDubsin()
{
	if(flag == CLOSE)
	{
		__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 15);//打开垃圾盖 舵机设置90度
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);
		HAL_Delay(100);
		HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
		flag = OPEN;
	}
	HAL_Delay(2000);
}
 
//关盖,灭指示灯,每100ms检测一次
void closeDubsin()
{
	__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5);
	flag = CLOSE;
	HAL_Delay(150);
}
 
//按键、震动传感器中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_0 || GPIO_Pin == GPIO_PIN_5)
	{
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET ||
			HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_5) == GPIO_PIN_RESET)
		{
			openStatusLight();
			openDubsin();//这里只需要设置打弿的原因:按键或振动进入中断 打开垃圾盖后逿出中断 当执行到whlie时 超声波模块会不断进行测距 当大于10cm时 垃圾盖会自动关上
		}
	}	
	}
}
 
//使用TIM2来做us级延时函数
void TIM2_Delay_us(uint16_t n_us)
{
	/* 使能定时器2计数 */
	__HAL_TIM_ENABLE(&htim2);
	__HAL_TIM_SetCounter(&htim2, 0);
	while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
	/* 关闭定时器2计数 */
	__HAL_TIM_DISABLE(&htim2);
}
 
/* USER CODE END 0 */
//===================================================================
 /* USER CODE BEGIN SysInit */
	HAL_NVIC_SetPriority(SysTick_IRQn,0,0);//提高滴答定时器优先级
	
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
    initSG90();//舵机初始化 其函数内有使能开始输出PWM信号
    HAL_NVIC_SetPriority(SysTick_IRQn,0,0);//提高滴答定时器(Delay函数)的中断优先级(提升到0
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
		//距离检测开关盖
	distance = get_distance();//超声波测距
	if(distance < 10)//小于10cm 打开垃圾盖同时LED1开启
	{
		openStatusLight();
		openDubsin();
	}
	else//大于10cm 关闭垃圾盖同时LED1熄灭
	{
		closeStatusLight();
		closeDubsin();
	}
    
  }
	
  /* USER CODE END 3 */

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

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

相关文章

【C语言】Windows下的C语言线程编程详解

文章目录 1. 头文件1.1 windows.h1.2 process.h 2. 创建线程3. 线程同步3.1 线程同步方式3.1 互斥量&#xff08;Mutex&#xff09;3.2 事件&#xff08;Event&#xff09; 4. 线程的结束与资源管理5.线程池&#xff08;简要&#xff09; 在Windows平台下&#xff0c;C语言提供…

隧道技术和代理技术(三)

隧道技术 知识点 -隧道技术&#xff1a;解决不出网协议上线的问题&#xff08;利用出网协议进行封装出网&#xff09; -代理技术&#xff1a;解决网络通讯不通的问题&#xff08;利用跳板机建立节点后续操作&#xff09; 内环境示意图&#xff0c;方便理解 思路&#xff1a;…

【网络原理】UDP协议的详细解析

文章目录 &#x1f384;UDP协议概念&#x1f332;UDP协议端格式&#x1f384;UDP的特点&#x1f338;无连接&#x1f338;不可靠传输&#x1f338;面向数据报&#x1f338;缓冲区&#x1f338;全双工&#x1f338;大小受限 &#x1f340;基于UDP的应用层协议&#x1f38d;扩展问…

(BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等

看面试题可以是为了面试&#xff0c;也可以是对自己学到的东西的一种查漏补缺&#xff0c;更加深刻的去了解一些核心知识点 Spring面试高频问题 问题一&#xff1a;谈 需要zi料 绿色徽【vip1024b】 谈你对spring IOC 和 DI 的理解&#xff0c;它们有什么区别&#xff1f; **问题…

全球首个AI程序员Devin诞生,真的不再需要程序员了吗?

前言 今年到底是怎么回事&#xff1f;前有Sora(首个文生视频大模型)独领风骚&#xff0c;后有Mistral&#xff08;号称世界第二语言大模型&#xff09;横刀立马&#xff0c;甚至Claude3的热度都还没有过&#xff0c;今天一则更炸裂的消息就爆出&#xff0c;世界上第一个AI程序…

代码贴--链表--数据机构

本博客将记录链表代码(单链表)&#xff0c;后续其他链表和其他数据结构内容请看我的其他博客 头文件(SList.h) #pragma once #include<iostream> #include<bits/stdc.h> using namespace std;typedef int SLTDataType;struct SListNode {int data;struct SListNo…

windows系统玩游戏找不到d3dx9_43.dll缺失,无法启动此程序的解决方法

今日&#xff0c;我们要深入讨论d3dx9_43.dll文件的重要性及其缺失问题。最近&#xff0c;我也遇到了这个文件丢失的困扰&#xff0c;因此想借此机会与大家分享如何解决d3dx9_43.dll缺失的问题。 一.电脑d3dx9_43.dll丢失会提示什么&#xff1f; 关于电脑提示d3dx9_43.dll丢失…

【人力资源开发】某主题公园人力资源开发管理咨询项目纪实

虽然很多企业将“人事部”改为“人力资源部”&#xff0c;但是企业的人力资源管理水平却仍停留在“人事管理”的阶段。该主题公园也是如此。随着公园的不断发展&#xff0c;其人力资源管理问题逐渐显露&#xff0c;而管理者也不清楚问题的根源在哪里&#xff0c;只能采取“头疼…

AWS入门实践-AWS CLI工具的使用介绍

AWS CLI&#xff08;Amazon Web Services Command Line Interface&#xff09;是一个强大的工具&#xff0c;它允许您直接从命令行与AWS服务进行交互。这不仅可以加快许多任务的处理速度&#xff0c;而且还可以通过脚本自动化。 一、AWS CLI工具的安装 1、Windows 安装下载…

java-双列集合

什么是双列集合&#xff1f; 集合中每次存的数据是成对存入的 以及它的特点是什么&#xff1f; 特别注意&#xff1a;键不可重复&#xff0c;值可以 Map是双列集合的顶层接口 Map 它有哪些方法呢&#xff1f; Map的常用API 添加 添加操作的代码如下 我们要明白一些细节&…

【项目笔记】java微服务:黑马头条(day02)

文章目录 app端文章查看&#xff0c;静态化freemarker,分布式文件系统minIO1)文章列表加载1.1)需求分析1.2)表结构分析1.3)导入文章数据库1.3.1)导入数据库1.3.2)导入对应的实体类 1.4)实现思路1.5)接口定义1.6)功能实现1.6.1)&#xff1a;导入heima-leadnews-article微服务&am…

C++初阶:内存管理

目录 1. C/C中各种资源的内存分布1.1 C/C程序内存区域划分1.2 各资源的内存分布情况&#xff08;练习&#xff09; 2. C中的动态内存管理方式2.1 new/delete开辟内置类型空间2.2 new/delete开辟销毁自定义类型空间 3. operator new 与 operator delete函数4. new与delete的实现…

逆变器功率软起斜率要求

安规说明 在NB32004中&#xff0c;有明确要求&#xff0c;有功功率调整速率不得超过正负10%Pn/min&#xff0c;包括起停机。 控制对象 控制功率最终是通过调整D轴电流给定来达到限制功率的目的&#xff0c;所以我们只要让D轴的电流给定限幅值按照10%/min增加就好了。 具体实…

openAI key 与ChatGPTPlus的关系,如何升级ChatGPTPLus

一、前言 先详细介绍一下Plus会员和Open API之间的区别&#xff1a; 实际上&#xff0c;这两者是相互独立的。举例来说&#xff0c;虽然您开通了Plus会员&#xff0c;并不意味着您就可以使用4.0版本的API。尽管这两个账户可以是同一个&#xff0c;但它们是完全独立的平台。 …

ChatGPT提问技巧:可解释的软提示

ChatGPT提问技巧&#xff1a;可解释的软提示 可解释的软提示是一种既能控制模型生成的文本&#xff0c;又能为模型提供一定灵活性的技术。 具体做法是为模型提供一组受控输入和一些有关所需输出的附加信息。这种技术可以使生成的文本更具可解释性和可控性。 提示示例及其公式…

DAY by DAY 史上最全的Linux常用命令汇总----man

man是按照手册的章节号的顺序进行搜索的。 man设置了如下的功能键&#xff1a; 功能键 功能 空格键 显示手册页的下一屏 Enter键 一次滚动手册页的一行 b 回滚一屏 f 前滚一屏 q 退出man命令 h 列出所有功能键 /word 搜索word字符串 注意&#xff1a…

每日一题——LeetCode1678.设计Goal解析器

方法一 splice 将字符串转为数组&#xff0c;对数组进行遍历&#xff0c;碰到G保持不变&#xff0c;继续循环&#xff0c;碰到 ( 看他后一位&#xff0c;是 ) 则删除两个元素&#xff0c;添加一个 o &#xff0c;不是则删除四个元素&#xff0c;添加元素 al &#xff0c;最后将…

JS ATM练习案例(复习循环知识)

需求&#xff1a;用户可以选择存钱、取钱、查看余额和退出功能。 分析&#xff1a;1循环时反复出现提示框&#xff0c;所以提示框写到循环里面。 2.退出的条件是4&#xff0c;所以是4就会结束循环 3.提前准备一个金额预存储 4取钱为减法操作&#xff0c;存钱为加法操作&#xf…

【论文阅读】Vision Mamba:双向状态空间模型的的高效视觉表示学习

文章目录 Vision Mamba:双向状态空间模型的的高效视觉表示学习摘要介绍相关工作用于视觉应用的状态空间模型 方法准备视觉MambaVim块结构细节高效分析计算效率 实验图片分类语义分割目标检测和实例分割消融实验双向SSM分类设计 总结和未来工作 论文地址&#xff1a; Vision Mam…

【C语言】qsort函数的使用

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《C语言》 &#x1f389;道阻且长&#xff0c;行则将至 前言 这篇博客主要是介绍qsort函数的使用&#xff0c;以及利用冒泡排序的方式模拟实现qsort 一.初识qsort函数 我们可以在…