【STM32单片机_(HAL库)】4-5-3【定时器TIM】【感应开关盖垃圾桶项目】项目实现

embedded/2024/10/11 0:07:07/

1.项目需求

以下几个事件触发时,垃圾桶自动开盖,并伴随蜂鸣器短响一声,同时 LED 灯闪烁一下,2秒后自动关盖:

  • 检测到有人靠近
  • 检测到有震动
  • 按下按键 KEY1

2.硬件

  • STM32单片机最小系统
  • 震动传感器模块
  • 蜂鸣器模块(低电平触发)
  • HC-SR04超声波传感器模块
  • SG90舵机模块
  • LED灯模块

硬件接线

STM32震动传感器蜂鸣器超声波传感器舵机LED灯
PA4DO
PA6I/O
PB5I/O
PB6Trig
PB7Echo
PB8负极
3V3VCCVCC
5VVCCVCC
GNDGNDGNDGNDGND
  • 项目框图
    在这里插入图片描述

3.软件

  • led、exti、beep、key、sg90、hcsr04驱动文件添加
  • main.c程序
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "beep.h"
#include "exti.h"
#include "hcsr04.h"
#include "key.h"
#include "sg90.h"#define OPEN 1//宏定义
#define CLOSE 0uint8_t dustbin_status = CLOSE;//定义盖的状态void open_dustbin(void)//开盖函数
{if(dustbin_status == CLOSE)//判断盖的状态,防止手一直放在超声波导致蜂鸣器一直滴{                          //如果是盖关闭情况下才执行sg90_angle_set(30); beep_on();led1_on();delay_ms(100);beep_off();led1_off();dustbin_status = OPEN;//此时盖的状态为打开}
}void close_dustbin(void)//关盖函数
{sg90_angle_set(0);beep_off();led1_off();dustbin_status = CLOSE;
}int main(void)
{HAL_Init();                         /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */led_init();                         /* 初始化LED灯 */uart1_init(115200);beep_init();exti_init();hcsr04_init();key_init();sg90_init();printf("hello world!\r\n");uint8_t key_num = 0;while(1){ key_num = key_scan();//扫描按键if(key_num == 1 || vibrate_flag_get() == TRUE || hcsr04_get_length() < 10)//条件或,满足一个即可{open_dustbin();delay_ms(2000);vibrate_flag_set(FALSE);}elseclose_dustbin();delay_ms(10);//防止超声波传感器一直获取距离,而导致崩//        sg90_angle_set(0);
//        delay_ms(1000);
//        sg90_angle_set(20);
//        delay_ms(1000);
//        sg90_angle_set(40);
//        delay_ms(1000);
//        sg90_angle_set(90);
//        delay_ms(1000);
//        sg90_angle_set(180);
//        delay_ms(1000);//        key_num = key_scan();           /* 扫描按键获取按下按键的值 */
//        if(key_num == 1)                /* 检测到按键1按下 */
//            led1_toggle();              /* 翻转LED1 */
//        
//        if(key_num == 2)                /* 检测到按键2按下 */
//            led2_toggle();              /* 翻转LED2 *///        printf("dis: %.2f\r\n", hcsr04_get_length());
//        delay_ms(1000);//        if(vibrate_flag_get() == TRUE)
//        {
//            //那么就点亮LED1两秒,然后熄灭
//            led1_on();
//            delay_ms(2000);
//            led1_off();
//            vibrate_flag_set(FALSE);
//        }//        beep_on();
//        delay_ms(500);
//        beep_off();
//        delay_ms(500);//        led1_on();
//        led2_off();
//        delay_ms(500);
//        led1_off();
//        led2_on();
//        delay_ms(500);}
}
  • exti.c程序
#include "exti.h"
#include "sys.h"
#include "delay.h"
#include "led.h"uint8_t vibrate_flag = FALSE;                               // 检测到震动标志位void exti_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOA_CLK_ENABLE();                           // 使能GPIOA时钟//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_4;                       // 震动传感器对应的引脚gpio_initstruct.Mode = GPIO_MODE_IT_FALLING;            // 下降沿触发gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉HAL_GPIO_Init(GPIOA, &gpio_initstruct);HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);                 // 设置EXTI0中断线的优先级HAL_NVIC_EnableIRQ(EXTI4_IRQn);                         // 使能中断
}void EXTI4_IRQHandler(void)
{HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
}void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{//delay_ms(20);if (GPIO_Pin == GPIO_PIN_4){if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == GPIO_PIN_RESET)//led1_toggle();vibrate_flag = TRUE;}
}uint8_t vibrate_flag_get(void)
{uint8_t temp = vibrate_flag;vibrate_flag = FALSE;return temp;}void vibrate_flag_set(uint8_t value)
{vibrate_flag = value;
}
  • exti.h程序
#ifndef __EXTI_H__
#define __EXTI_H__#include "stdint.h"#define TRUE    1
#define FALSE   0void exti_init(void);
uint8_t vibrate_flag_get(void);
void vibrate_flag_set(uint8_t value);#endif
  • led.c
#include "led.h"
#include "sys.h"//初始化GPIO函数
void led_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOB_CLK_ENABLE();                           // 使能GPIOB时钟//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;          // 两个LED对应的引脚gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             // 推挽输出gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           // 高速HAL_GPIO_Init(GPIOB, &gpio_initstruct);//关闭LEDled1_off();led2_off();
} //点亮LED1的函数
void led1_on(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);   // 拉低LED1引脚,点亮LED1
}//熄灭LED1的函数
void led1_off(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);     // 拉高LED1引脚,熄灭LED1
}//翻转LED1状态的函数
void led1_toggle(void)
{HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_8);
}//点亮LED2的函数
void led2_on(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);   // 拉低LED2引脚,点亮LED2
}//熄灭LED2的函数
void led2_off(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);     // 拉高LED2引脚,熄灭LED2
}//翻转LED2状态的函数
void led2_toggle(void)
{HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_9);
}
  • led.h
#ifndef __LED_H__
#define __LED_H__void led_init(void);
void led1_on(void);
void led1_off(void);
void led1_toggle(void);
void led2_on(void);
void led2_off(void);
void led2_toggle(void);#endif
  • beep.c
#include "beep.h"
#include "sys.h"//初始化GPIO函数
void beep_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOB_CLK_ENABLE();                           // 使能GPIOB时钟//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_5;                       // 蜂鸣器对应的引脚PB5gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             // 推挽输出gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           // 高速HAL_GPIO_Init(GPIOB, &gpio_initstruct);//关闭蜂鸣器beep_off();
}//打开蜂鸣器的函数
void beep_on(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);   // 拉低蜂鸣器引脚,打开蜂鸣器
}//关闭蜂鸣器的函数
void beep_off(void)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);     // 拉高蜂鸣器引脚,关闭蜂鸣器
}
  • beep.h
#ifndef __BEEP_H__
#define __BEEP_H__void beep_init(void);
void beep_on(void);
void beep_off(void);#endif
  • hcsr04.c
#include "hcsr04.h"
#include "delay.h"TIM_HandleTypeDef tim2_handle = {0};//定时器初始化函数
void tim2_init(void)
{tim2_handle.Instance = TIM2;tim2_handle.Init.Prescaler = 72 - 1;tim2_handle.Init.Period = 65536 - 1;tim2_handle.Init.CounterMode = TIM_COUNTERMODE_UP;tim2_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;HAL_TIM_Base_Init(&tim2_handle);
}//msp函数
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM2){__HAL_RCC_TIM2_CLK_ENABLE();}
}void tim2_start(void)
{HAL_TIM_Base_Start(&tim2_handle);
}void tim2_stop(void)
{HAL_TIM_Base_Stop(&tim2_handle);
}uint16_t tim2_get_cnt(void)
{return __HAL_TIM_GetCounter(&tim2_handle);
}void tim2_set_cnt(uint16_t val)
{__HAL_TIM_SetCounter(&tim2_handle, val);
}void hcsr04_gpio_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟TRIG_GPIO_CLK_ENABLE();ECHO_GPIO_CLK_ENABLE();//初始化Trig引脚gpio_initstruct.Pin = TRIG_PIN;gpio_initstruct.Mode = GPIO_MODE_OUTPUT_PP;             gpio_initstruct.Pull = GPIO_NOPULL;                     gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           HAL_GPIO_Init(TRIG_PORT, &gpio_initstruct);gpio_initstruct.Pin = ECHO_PIN;gpio_initstruct.Mode = GPIO_MODE_INPUT;             HAL_GPIO_Init(ECHO_PORT, &gpio_initstruct);
}void hcsr04_init(void)
{tim2_init();hcsr04_gpio_init();
}float hcsr04_get_length(void)
{uint16_t total_time = 0;float distance = 0;//1. Trig,给Trig端口至少10us的高电平TRIG_HIGH();delay_us(15);TRIG_LOW();//2. Echo引脚,由低电平跳转到高电平,表示开始发送波//波发出去的那一下,开始启动定时器while(ECHO_STATUS() == GPIO_PIN_RESET);tim2_start();tim2_set_cnt(0);//3. Echo,由高电平跳转回低电平,表示波回来了//波回来的那一下,我们开始停止定时器,计算出中间经过多少时间while(ECHO_STATUS() == GPIO_PIN_SET);tim2_stop();//4. 计算出中间经过多少时间total_time = tim2_get_cnt();//5. 距离 = 速度(343m/s) * 时间 / 2distance = total_time * 0.01715;return distance;
}
  • hcsr04.h
#ifndef __HCSR04_H__
#define __HCSR04_H__#include "sys.h"#define TRIG_PORT                   GPIOB
#define TRIG_PIN                    GPIO_PIN_6
#define TRIG_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE()
#define TRIG_HIGH()                 HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_SET)
#define TRIG_LOW()                  HAL_GPIO_WritePin(TRIG_PORT, TRIG_PIN, GPIO_PIN_RESET)#define ECHO_PORT                   GPIOB
#define ECHO_PIN                    GPIO_PIN_7
#define ECHO_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOB_CLK_ENABLE()
#define ECHO_STATUS()               HAL_GPIO_ReadPin(ECHO_PORT, ECHO_PIN)void hcsr04_init(void);
float hcsr04_get_length(void);#endif
  • key.c
#include "key.h"
#include "delay.h"//初始化GPIO
void key_init(void)
{GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOA_CLK_ENABLE();                           // 使能GPIOA时钟//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;          // 两个KEY对应的引脚gpio_initstruct.Mode = GPIO_MODE_INPUT;                 // 输入gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           // 高速HAL_GPIO_Init(GPIOA, &gpio_initstruct);
}//按键扫描函数
uint8_t key_scan(void)
{//检测按键是否按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){//消抖delay_ms(10);//再次判断按键是否按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET){//如果确实是按下的状态,等待按键松开while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET);//返回按键值return 1;}}//检测按键是否按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET){//消抖delay_ms(10);//再次判断按键是否按下if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET){//如果确实是按下的状态,等待按键松开while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == GPIO_PIN_RESET);//返回按键值return 2;}}//返回默认值return 0;
}
  • key.h
#ifndef __KEY_H__
#define __KEY_H__#include "sys.h"void key_init(void);
uint8_t key_scan(void);#endif
  • sg90.c
#include "sg90.h"TIM_HandleTypeDef tim3_handle = {0};
// init函数
void tim3_init(void)
{TIM_OC_InitTypeDef pwm_config = {0};tim3_handle.Instance = TIM3;tim3_handle.Init.Prescaler = 7200 - 1;tim3_handle.Init.Period = 200 - 1;tim3_handle.Init.CounterMode = TIM_COUNTERMODE_UP;HAL_TIM_PWM_Init(&tim3_handle);pwm_config.OCMode = TIM_OCMODE_PWM1;pwm_config.Pulse = 100;pwm_config.OCPolarity = TIM_OCPOLARITY_HIGH;HAL_TIM_PWM_ConfigChannel(&tim3_handle, &pwm_config, TIM_CHANNEL_1);HAL_TIM_PWM_Start(&tim3_handle, TIM_CHANNEL_1);
}//msp函数
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{if(htim->Instance == TIM3){GPIO_InitTypeDef gpio_initstruct;//打开时钟__HAL_RCC_GPIOA_CLK_ENABLE();                           // 使能GPIOB时钟__HAL_RCC_TIM3_CLK_ENABLE();//调用GPIO初始化函数gpio_initstruct.Pin = GPIO_PIN_6;                    // 两个LED对应的引脚gpio_initstruct.Mode = GPIO_MODE_AF_PP;             // 推挽输出gpio_initstruct.Pull = GPIO_PULLUP;                     // 上拉gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;           // 高速HAL_GPIO_Init(GPIOA, &gpio_initstruct);}
}//修改CCR值的函数
void tim3_compare_set(uint16_t val)
{__HAL_TIM_SET_COMPARE(&tim3_handle, TIM_CHANNEL_1, val);
}void sg90_init(void)
{tim3_init();
}void sg90_angle_set(uint16_t angle)
{uint16_t CCRx = (1.0 / 9.0) * angle + 5.0;tim3_compare_set(CCRx);
}
  • sg90.h
#ifndef __SG90_H__
#define __SG90_H__#include "sys.h"void sg90_init(void);
void sg90_angle_set(uint16_t angle);#endif

4.实物效果

ST-Link下载方式

感应开关盖垃圾桶项目keil源文件


http://www.ppmy.cn/embedded/125615.html

相关文章

Jensen-Shannon散度(JS散度)

Jensen-Shannon散度&#xff08;Jensen-Shannon Divergence, JS散度&#xff09;是概率分布之间的一种相似性度量。它是基于Kullback-Leibler散度&#xff08;KL散度&#xff09;的对称版本&#xff0c;并且具有一些更好的性质&#xff0c;例如它总是非负的&#xff0c;并且是有…

Luminar财务造假风波:激光雷达龙头的困境与挑战

近日,美国激光雷达上市公司Luminar被爆出财务造假嫌疑,这一消息震惊了整个行业。Luminar,这家曾风光无限的激光雷达公司,最高市值一度达到120亿美元,其年轻的创始人也因此坐拥豪宅豪车无数。然而,如今在市值仅剩5亿美元左右的时候,却被爆出如此丑闻,令人不禁唏嘘。 带…

软考《信息系统运行管理员》- 4.4 信息系统软件运维系统与专用工具

4.4 信息系统软件运维系统与专用工具 文章目录 4.4 信息系统软件运维系统与专用工具信息系统软件运维系统的功能信息系统软件信息采集信息系统软件监控信息系统软件分发功能 信息系统软件运维专用工具 信息系统软件运维系统的功能 信息系统软件信息采集 可以快速查询网络内各…

软件测试面试题大全

什么是软件测试&#xff1f; 答案&#xff1a;软件测试是一系列活动&#xff0c;旨在评估软件产品的质量&#xff0c;并验证它是否满足规定的需求。它包括执行程序或系统以识别任何缺陷、问题或错误&#xff0c;并确保软件产品符合用户期望。 软件测试的目的是什么&#xff1f…

SQL自学:使用函数处理数据

一、使用函数 1、文本处理函数 文本处理函数如同强大的文字操控工具&#xff0c;能够实现对文本数据的多样化操作。它可以进行字符串的转换、截取、拼接等处理&#xff0c;满足不同场景下对文本信息的处理需求。 例如&#xff0c;通过特定的文本处理函数&#xff0c;可以将文…

设计模式(2)工厂模式

让一个工厂类去生产出对象 &#xff08;new &#xff09;来。 我们想要一个 形状&#xff0c;我们用工厂去生产出&#xff0c;圆形&#xff0c;方形。 package com.example.factory2;public interface Shape {void draw(); }public class Square implements Shape {Overridep…

大数据-159 Apache Kylin 构建Cube 准备和测试数据

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

【大数据】Flink CDC 实时同步mysql数据

目录 一、前言 二、Flink CDC介绍 2.1 什么是Flink CDC 2.2 Flink CDC 特点 2.3 Flink CDC 核心工作原理 2.4 Flink CDC 使用场景 三、常用的数据同步方案对比 3.1 数据同步概述 3.1.1 数据同步来源 3.2 常用的数据同步方案汇总 3.3 为什么推荐Flink CDC 3.4 Flink …