11、stm32单片机基于hal库的感应开关盖垃圾桶

1、项目需求

以下几个事件触发时,自动开盖,并伴随蜂鸣器短响一声,同时 LED 灯闪烁一下, 2 秒后自动关盖:
检测到有人靠近
检测到有震动
按下按键 KEY1

2、硬件清单

超声波传感器
震动传感器
蜂鸣器
舵机
杜邦线
上官二号
ST-Link
USB TTL
3、硬件接线

4、项目框图

 5.sg90舵机实现代码

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

 6、hscr04超声波模块实现代码

hscr04.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) * 时间 / 2
    distance = total_time * 0.01715;
    return distance;
}

hscr04.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

7、蜂鸣器实现模块

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;                       // 蜂鸣器对应的引脚
    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);
    //关闭蜂鸣器
    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

8、震动传感器实现代码

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   0

void exti_init(void);
uint8_t vibrate_flag_get(void);
void vibrate_flag_set(uint8_t value);

#endif

9、按键代码

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

10、main函数代码

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 0

uint8_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);
        }
        else
            close_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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值