基于STM32的感应开关垃圾桶

2024-03-14 03:12
文章标签 stm32 开关 感应 垃圾桶

本文主要是介绍基于STM32的感应开关垃圾桶,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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);elseHAL_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 */

这篇关于基于STM32的感应开关垃圾桶的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/807034

相关文章

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

STM32内部闪存FLASH(内部ROM)、IAP

1 FLASH简介  1 利用程序存储器的剩余空间来保存掉电不丢失的用户数据 2 通过在程序中编程(IAP)实现程序的自我更新 (OTA) 3在线编程(ICP把整个程序都更新掉) 1 系统的Bootloader写死了,只能用串口下载到指定的位置,启动方式也不方便需要配置BOOT引脚触发启动  4 IAP(自己写的Bootloader,实现程序升级) 1 比如蓝牙转串口,

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

寻迹模块TCRT5000的应用原理和功能实现(基于STM32)

目录 概述 1 认识TCRT5000 1.1 模块介绍 1.2 电气特性 2 系统应用 2.1 系统架构 2.2 STM32Cube创建工程 3 功能实现 3.1 代码实现 3.2 源代码文件 4 功能测试 4.1 检测黑线状态 4.2 未检测黑线状态 概述 本文主要介绍TCRT5000模块的使用原理,包括该模块的硬件实现方式,电路实现原理,还使用STM32类

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

基于stm32的河流检测系统-单片机毕业设计

文章目录 前言资料获取设计介绍功能介绍具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机设计精品

STM32的使用方法一

注:我采用的是STM32F103RC芯片、相应的电路图和STM32CubeIDE软件这是在STM32CubeIDE软件定义芯片后,所给的必要的代码逻辑,加上了注释 #include "main.h"/* Private variables ---------------------------------------------------------*//* Private function

STM32 HAL CAN通讯 实操

1、简介 相比于串口通讯,对于刚接触CAN通讯的小白来说,CAN通讯相对复杂,看各种视频、帖子理论,总是一知半解。本次通过傻瓜式操作,先实现CAN通讯的交互,以提高小白的信心,也便于自己复习观看。本次以STM32CubeMX进行初始化配置,通过Keil 5软件进行软件设计,通过CAN盒实现进行数据的交互。该流程实际以STM32F0、F1、F3、F4、F7实测好用(理论上都适用),这三种型号单片机