STM32——感应开关盖垃圾桶

2024-01-31 14:36
文章标签 stm32 开关 感应 垃圾桶

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

STM32——感应开关盖垃圾桶

1.定时器介绍

软件定时

缺点:不精确、占用CPU资源

void Delay500ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();i = 4;j = 129;k = 119;do{do{while (--k);} while (--j);} while (--i);
}

定时器工作原理

使用精准的时基,通过硬件的方式,实现定时功能。定时器核心就是计数器。

2.PWM介绍

STM32F103C8T6 PWM资源:

高级定时器(TIM1):7路

通用定时器(TIM2~TIM4):各4路

PWM输出模式:

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

PWM模式2:在向上计数时,一旦 CNT < CCRx 时输出为无效电平,否则为有效电平; 在向下计数时,一旦 CNT > CCRx 时输出为有效电平,否则为无效电平。
在这里插入图片描述

PWM周期与频率:
在这里插入图片描述

3.呼吸灯

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

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

代码实现

// 定义变量
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++;elsepwmVal--;if (pwmVal > 500)dir = 0;if (pwmVal == 0)dir =1;//修改比较值,修改占空比__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwmVal);
}

项目实现

项目需求

检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

项目框图
在这里插入图片描述

硬件清单

SG90舵机,超声波模块,震动传感器,蜂鸣器

舵机介绍

在这里插入图片描述

角度控制

  • 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

编程实现

需求

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

代码实现

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);
}

超声波传感器介绍

  • 怎么让它发送波

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

  • 怎么知道它开始发了

Echo信号,由低电平跳转到高电平,表示开始发送波

  • 怎么知道接收了返回波

Echo,由高电平跳转回低电平,表示波回来了

  • 怎么算时间

Echo引脚维持高电平的时间!

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

波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间

  • 怎么算距离

距离 = 速度 (340m/s)* 时间/2外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

编程实现

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

接线

Trig — PB6

Echo — PB7

LED1 — PB8外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

编写微秒级函数

//使用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);
}

主函数:

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

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

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

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

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

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

//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)

//每500毫秒测试一次距离

int cnt;
float distance;
while (1)
{//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. 计算出中间经过多少时间cnt = __HAL_TIM_GetCounter(&htim2);//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)distance = cnt*340/2*0.000001*100; //单位:cmif(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);
}        

封装成函数

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);
}double getDistance()
{int time=0;//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.2. echo由低电平跳转到高电平,表示开始发送波while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_RESET);//3.波发出去的那一下,开始启动定时器HAL_TIM_Base_Start(&htim2);__HAL_TIM_SetCounter(&htim2,0);//让定时器从0开始数数//4. 由高电平跳转回低电平,表示波回来了while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_SET);//5.波回来的那一下,我们开始停止定时器HAL_TIM_Base_Stop(&htim2);//6. 计算出中间经过多少时间time=__HAL_TIM_GetCounter(&htim2);//7.距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)return (340*time*0.000001/2*100);
}int main()
{double distance=0;while (1){distance=getDistance();if(distance<5)HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);elseHAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//8.每500毫秒测试一次距离HAL_Delay(500);}}

项目设计及实现

项目设计

超声波模块:

Trig – PB6

Echo – PB7

sg90****舵机:

PWM – PB9

按键:

KEY1 – PA0

LED****灯:

LED1 – PB8

震动传感器:

D0 – PB5

VCC – 5V

蜂鸣器:

IO – PB4

VCC – 3V3

测距开关盖

硬件:超声波模块,舵机

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);
}double getDistance()
{int time=0;//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.2. echo由低电平跳转到高电平,表示开始发送波while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_RESET);//3.波发出去的那一下,开始启动定时器HAL_TIM_Base_Start(&htim2);__HAL_TIM_SetCounter(&htim2,0);//让定时器从0开始数数//4. 由高电平跳转回低电平,表示波回来了while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_SET);//5.波回来的那一下,我们开始停止定时器HAL_TIM_Base_Stop(&htim2);//6. 计算出中间经过多少时间time=__HAL_TIM_GetCounter(&htim2);//7.距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)return (340*time*0.000001/2*100);
}void closeStatusLight()
{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}void initSg90_0()
{HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);
}void openDusBin()
{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15);HAL_Delay(2000);
}void closeDusBin()
{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);HAL_Delay(150);
}int main(void)
{double distance=0;initSg90_0();while (1){distance=getDistance();if(distance<5){openDusBin();openStatusLight();}	else{closeDusBin();closeStatusLight();}	}
}

在测距开光盖的基础上加上按键开盖和震动开盖

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);
}double getDistance()
{int time=0;//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.2. echo由低电平跳转到高电平,表示开始发送波while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_RESET);//3.波发出去的那一下,开始启动定时器HAL_TIM_Base_Start(&htim2);__HAL_TIM_SetCounter(&htim2,0);//让定时器从0开始数数//4. 由高电平跳转回低电平,表示波回来了while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_SET);//5.波回来的那一下,我们开始停止定时器HAL_TIM_Base_Stop(&htim2);//6. 计算出中间经过多少时间time=__HAL_TIM_GetCounter(&htim2);//7.距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)return (340*time*0.000001/2*100);
}void openStatusLight()
{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}void closeStatusLight()
{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}void initSg90_0()
{HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);
}void openDusBin()
{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15);HAL_Delay(2000);
}void closeDusBin()
{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);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();openDusBin();}	}			
}int main(void)
{double distance=0;HAL_NVIC_SetPriority(SysTick_IRQn,0,0);initSg90_0();while (1){distance=getDistance();if(distance<10){openDusBin();openStatusLight();}	else{closeDusBin();closeStatusLight();}	}
}

项目完结

#define  OPEN  1
#define  CLOSE 0char flag=0;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);
}double getDistance()
{int time=0;//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.2. echo由低电平跳转到高电平,表示开始发送波while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_RESET);//3.波发出去的那一下,开始启动定时器HAL_TIM_Base_Start(&htim2);__HAL_TIM_SetCounter(&htim2,0);//让定时器从0开始数数//4. 由高电平跳转回低电平,表示波回来了while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7)==GPIO_PIN_SET);//5.波回来的那一下,我们开始停止定时器HAL_TIM_Base_Stop(&htim2);//6. 计算出中间经过多少时间time=__HAL_TIM_GetCounter(&htim2);//7.距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)return (340*time*0.000001/2*100);
}void openStatusLight()
{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}void closeStatusLight()
{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}void initSg90_0()
{HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);
}void  beepDusBin()
{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET);HAL_Delay(100);HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET);
}void openDusBin()
{if(flag==CLOSE){		flag=OPEN;__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15);beepDusBin();}HAL_Delay(2000);
}void closeDusBin()
{__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 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();openDusBin();}	}			
}int main(void)
{double distance=0;HAL_NVIC_SetPriority(SysTick_IRQn,0,0);initSg90_0();while (1){distance=getDistance();if(distance<10){openDusBin();openStatusLight();}	else{closeDusBin();closeStatusLight();}	}
}

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



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

相关文章

【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实测好用(理论上都适用),这三种型号单片机