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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】整数和浮点数在内存中的存储

前言 我们都知道&#xff0c;在创建一个变量的时候&#xff0c;编译器会自动开辟一块内存空间用于存放它&#xff0c;但是对于不同的数据类型&#xff0c;它们的存储形式也会有所不同。今天就让我们一起来学习整数和浮点数在内存中的存储 1. 整数在内存中的存储 我们都知道&…

leetcode刷题(剑指offer) 10.正则表达式匹配

10.正则表达式匹配 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s的&#xff0c;而不是部分字符串。 示例 1&#xff1a;…

Linus Torvalds的20个事实

Linus Torvalds 是 Linux 操作系统的创造者&#xff0c;至今还在维护内核。本文是他的自传《Just for fun》的简短摘录&#xff0c;关于他个人的20个事实&#xff0c;比如他的老婆是他的学生。 Brief: Some known, some lesser known – here are 20 facts about the Linus Tor…

外汇天眼:Cryptodfmeta与Aden Markets──网恋对象热心带投资,鼓吹加码冻账拒出金

随着整个人类社会进入数字时代&#xff0c;我们愈来愈仰赖网络科技的便利性&#xff0c;由于远端工作逐渐成为趋势&#xff0c;就连社交与人际互动也开始云端化。 与此同时&#xff0c;诈骗集团也在各大社交平台申请假账号并寻找下手目标&#xff0c;并且诱骗人使用虚假的投资平…

JSON概述以及使用

1&#xff0c;JSON 1.1 概述 概念&#xff1a;JavaScript Object Notation。JavaScript 对象表示法. 如下是 JavaScript 对象的定义格式&#xff1a; {name:"zhangsan",age:23,city:"北京" } 接下来我们再看看 JSON 的格式&#xff1a; {"name&…

C++文件操作(1)

C文件操作 1.文本的写入及读取文本文件写入文本文件读取 2.二进制文件的写入及读取二进制文件写入二进制文件读取 3.小结 C也有处理文件的能力&#xff0c;其功能实现依赖文件流。文件流是C中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件…

uni-app小程序自定义导航栏

最近在开发一个uni-app小程序&#xff0c;用到了自定义导航栏&#xff0c;在这里记录一下实现过程&#xff1a; page.json 在对应页面路由的style中设置入"navigationStyle": "custom"取消原生导航栏&#xff0c;自定义导航栏 {"path": "…

【ARM Trace32(劳特巴赫) 使用介绍 6.1 -- 外设寄存器查看与修改】

请阅读【Trace32 ARM 专栏导读】 文章目录 外设寄存器查看与修改寄存器值修改外设寄存器查看与修改 外设寄存器的查看与修改,离不开TRACE32的外设文件(*.per),per文件一般存在于TRACE32的安装根目录下。 一般情况下,在调试时,TRACE32会根据当前选择的芯片名自动选择合适的…

正则表达式(RE)

什么是正则表达式 正则表达式&#xff0c;又称规则表达式&#xff08;Regular Expression&#xff09;。正则表达式通常被用来检索、替换那些符合某个规则的文本 正则表达式的作用 验证数据的有效性替换文本内容从字符串中提取子字符串 匹配单个字符 字符功能.匹配任意1个…

P1596 [USACO10OCT] Lake Counting S Flood Fill算法(洪水填充算法)

文章目录 题目链接题目描述解题思路算法原理实现方法复杂度分析 代码实现总结 题目链接 链接: P1596 [USACO10OCT] Lake Counting S 题目描述 解题思路 本题我在acwing和洛谷上都看到了 做这道题首先要了解一下Flood Fill 算法&#xff08;洪水填充算法&#xff09; 作为一个…

数据库MySQL查询设计||给定四个关联表,其定义和数据加载如下:-- 学生表 Student-- 选课表 SC

SQL查询设计 给定四个关联表&#xff0c;其定义和数据加载如下&#xff1a; -- 学生表 Student create table Student(Sno varchar(6), Sname varchar(10), Sdate datetime, Ssex varchar(10)); insert into Student values(01 , 赵雷 , 1999-01-01 , 男); insert into St…

重发布

一&#xff1a;作用 在两种路由协议之间&#xff0c;或者一个协议的不同进程之间&#xff0c;借助ASBR &#xff08;同时工作在两种协议或 者协 议的不同进程中&#xff09;学习到两个网络的路由信息&#xff0c;并且通过重发布进行路由共享&#xff0c;最终实现全网可 达。…