项目:感应开关垃圾桶

项目介绍

项目需求:

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

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

项目框图:

硬件清单: 

超声波传感器(chsr04)震动传感器蜂鸣器舵机(sg90)
开发板杜邦线ST-LinkUSB转TTL

模块:Sg90舵机

        舵机,也叫伺服电机,在嵌入式开发中,舵机作为一种常见的运动控制组件,具有广泛的应用。其中,SG90 舵机以其高效、稳定的性能特点,成为了许多工程师和爱好者的首选,无论是航模、云台、机器人、智能小车中都有它的身影。       

型号介绍          

        市面上常见的舵机型号有 SG90、MG90S、MG995、MG996R 等等,主要是扭矩大小、工作电压大小、齿轮材质塑料或金属的不同。

分类:(按旋转角度)

180度360度
        可以控制旋转角度、有角度定位。上电后舵机自动复位到0度,通过一定参数的脉冲信号控制它的角度。

        360°舵机版本不可控制角度,只能控制顺时针旋转、逆时针旋转、停止和调节转速。

本章讲解的舵机是SG90,180度的:

工作原理

        舵机的控制信号是通过脉冲宽度调制(PWM)来实现的。PWM 信号的周期通常为20ms,而脉冲宽度则在 0.5ms 至 2.5ms 之间变化。这个脉冲宽度与舵盘的位置呈线性关系,范围从0度到180度。

        当给舵机提供特定宽度的脉冲信号时输出轴会保持在相应的角度上,不受外界转矩的影响,直到接收到不同宽度的脉冲信号才会改变输出角度,使舵盘移动到新的位置。舵机内部有一个基准电路产生周期为 20ms、宽度为 1.5ms 的基准信号。同时,还有一个比较器,用于将外部输入信号与基准信号进行比较,以确定转动方向和幅度,并生成驱动电机转动的信号

        控制电路板接收来自信号线的 PWM 控制信号,然后控制电机的转动。电机带动一系列齿轮组,在经过减速传动后,将力量传递到输出舵盘上。舵机的输出轴与位置反馈电位计相连,当舵盘旋转时,位置反馈电位计也会随之变化,向控制电路板输出电压信号进行反馈。控制电路板根据位置反馈信号判断当前位置,并决定电机的转动方向和速度,以实现目标停止。

        为了控制舵机,需要使用单片机来生成周期为 20ms 的脉冲信号,并通过控制脉冲的高电平时间 0.5ms 至 2.5ms 之间来控制舵机的角度。这样,我们可以通过调整 PWM 信号的脉冲宽度来精确控制舵机的位置和运动。

  • 控制关系:
脉冲高电平角度占空比
0.5ms2.5%
1.0ms45°5.0%
1.5ms90°7.5%
2.0ms135°10.0%
2.5ms180°12.5%

工作参数和引脚介绍 

  • 工作参数:

工作扭矩:1.6kg/cm

反应速度:0.12 - 0.13秒/60°

死区设定:5us

死区设定:5us

转动角度:常见0°、90°、180°、360°

齿轮材质:尼龙塑料齿

工作电压:3V - 6V

温度范围:-30° ~ +60°

-------
  • 引脚接线:
SG90STM32
PWM 信号线(橙色线)输出PWM的GPIO口
VCC(红线)3.3/5V
GND(棕色线)GND

小实验:驱动SG90舵机

  • 引脚接线:
SG90STM32
PWM 信号线(橙色线)TIM3 通道1 PA6
VCC(红线)3.3/5V
GND(棕色线)GND
  • 20ms周期计算:psc = 7200-1,arr = 200-1
  •  sg90.c文件代码:
#include "sg90.h"

TIM_HandleTypeDef tim3_handle = {0};
void tim3_init(void){
     
    tim3_handle.Instance = TIM3;
    tim3_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    tim3_handle.Init.Period = 200-1;       //周期20ms = 200 * 100us
    tim3_handle.Init.Prescaler = 7200-1;   //记一个数的时间是100us
    tim3_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    HAL_TIM_PWM_Init(&tim3_handle);
    
    //pwm模式和crr寄存器设置
    TIM_OC_InitTypeDef tim_oc_initstruct = {0};
    tim_oc_initstruct.OCMode = TIM_OCMODE_PWM1;          //pwm的模式
    tim_oc_initstruct.OCPolarity = TIM_OCPOLARITY_HIGH;   //高电平有效还是低电平;led灯是低电平点亮,故低电平有效
    tim_oc_initstruct.Pulse = 100;                     //占空比CCR的值,这里随便填,后面crr修改函数
    HAL_TIM_PWM_ConfigChannel(&tim3_handle,&tim_oc_initstruct,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){                          //判断这个函数是否被定时器4占用
      
        __HAL_RCC_TIM3_CLK_ENABLE();                      //打开定时器3的时钟
      __HAL_RCC_GPIOA_CLK_ENABLE();                       //打开GPIO口的时钟
      
      GPIO_InitTypeDef gpio_initstruct;
        gpio_initstruct.Mode = GPIO_MODE_AF_PP;            //复用推挽输出,看GPIO口定义表
        gpio_initstruct.Pin = GPIO_PIN_6;
        gpio_initstruct.Pull = GPIO_PULLUP;
        gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
      HAL_GPIO_Init(GPIOA,&gpio_initstruct);
    }
}
//初始化舵机的函数
void sg90_init(void){
    tim3_init();
}

//声明一个设置angle的函数
void angle_set(uint16_t angle){
    uint16_t CCR = (1.0 / 9.0) * angle + 5.0 ;
//    __HAL_TIM_SetCompare(&tim3_handle,TIM_CHANNEL_1,CCR);   //设置CCR寄存器值得函数
    __HAL_TIM_SET_COMPARE(&tim3_handle,TIM_CHANNEL_1,CCR);
}
  • sg90.h文件代码
#ifndef __SG90_H__
#define __SG90_H__
#include "stm32f1xx.h"

void sg90_init(void);
void angle_set(uint16_t angle);

#endif
  • main.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "sg90.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    led_init();                         /* LED初始化 */
    sg90_init();
    
    //在while函数中不停的修改CRR的值,来实现占空比不断改变
    while(1)
    { 
        angle_set(0);
        delay_ms(1000);
        angle_set(45);
        delay_ms(1000);
        angle_set(90);
        delay_ms(1000);
        angle_set(180);
        delay_ms(1000);
        angle_set(90);
        delay_ms(1000);
        
    }
}

遇到的问题和注意事项:

  • 输出pwm波的相关流程;
  • 对于RCC值和舵机转角之间的关系计算;
  • 关于记一个数的时间和舵机高电平持续时间的关系 = RCC的值都是多少。
  • 改变CCR值得函数。

模块:超声波传感器 

         我们都知道声音是由物体振动产生的,人能听到的频率在20Hz~20kHz。频率小于20Hz的叫次声波,频率大于20kHz的叫超声波。本次我们要讲的超声波传感器就是非接触测距,用于测量物体与传感器之间的距离,可用于车辆安全(倒车雷达),安防系统(检测到移动物体并触发警报),工业自动化(物体定位、检测和避障)等等。

 HC-SR04介绍

        超声波传感器有很多的信号:HC-SR04、UC-025、UC-026、UC-015、US-100等等,它们之间大同小异,无非是工作参数有点不一样,像是工作的电压或温度、探测距离或精度有点差别,引脚是一样的,都是4个引脚(US-100 多一个 GND 引脚),引脚顺序和功能也是一样的。

         现在市面上的 HC- SR04 有新版和旧版,我们介绍的是新版。新版性能比老版的精度更高,测距范围更远,可达6米(时间大概35ms),高于一般超声波测距模块。采用 CS-100A 超声波测距 SOC 芯片,高性能,工业级,宽电压,价格在4块钱左右。

 HC-SR04工作原理

超声波测距的工作原理:

        超声波测距的工作原理其实很简单,传感器发送超声波,超声波碰到障碍物反弹回来,被传感器接收到。实际距离 = 测量距离 / 2 = 速度 × 时间 / 2。超声波在空气中的传播速度大概是 343m/s,传播速度受到环境条件的影响,如温度、湿度和气压等。

 正常测距的时序图:

介绍时序图的步骤: 

  1. 单片机给超声波模块发送大于 10us 的高电平的触发信号;
  2. 超声波模块收到触发信号后 Trig 端发送 8个40kHz 的超声波脉冲
  3. Echo 端低电平转为高电平,同时开始发送超声波
  4. 超声波模块检测到返回信号Echo 端 由高电平转为低电平
  5. Echo 端高电平宽度即为超声波传播时间

相关的问题:

  • 怎么让它发送波?

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

  • 怎么知道它开始发了波?

Echo引脚,由低电平跳转到高电平,表示开始发送波。

  • 怎么知道接收了返回波?

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

  • 怎么算时间?

Echo引脚维持高电平的时间;波发出去的那一下,开始启动定时器;

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

  • 怎么算距离?

距离 = 速度(343m/s * 时间 / 2。

工作参数和引脚介绍 

  • HC-SR04 工作参数

探测距离:2~600cm

探测精度:0.1cm±1%

感应角度:<15°

输出方式:GPIO

工作电压:DC 3~5.5V

工作电流:5.3mA

工作温度:-40~85℃

------
  • 引脚接线

HC-SR04STM32备注
VCC3.3/5V外接直流电源
Trig任意一个GPIO口输入端
Echo任意一个GPIO口输出端
GNDGND接地

小实验:超声波测距

 实验目的:利用超声波传感器实现超声波测距。

硬件清单:开发板、超声波传感器(chsr04)、USB转TTL、ST-Linkl V2

引脚接线: 

HC-SR04STM32USB 转 TTL
VCC3.3/5V
TrigB6
EchoB7
GNDG
A10TX
A9RX
GGND
  •  chsr04.c文件代码

思路: 

        当测量距离超过 HC-SR04 的测量范围时,Echo 任会输出高电平,宽度约为66ms,后转为低电平。

#include "chsr04.h"
#include "delay.h"
#include "stdio.h"

//函数原型
void tim2_base_init(void);
void gpio_init(void);

//将下面定时器和GPIO口初始化函数,封装到声明的初始化chsr04函数
void chsr04_init(void){
    tim2_base_init();
    gpio_init();
}

TIM_HandleTypeDef tim2_handle = {0};
void tim2_base_init(void){
    tim2_handle.Instance = TIM2;
    tim2_handle.Init.Prescaler = 72-1;    //1us记一个数
    tim2_handle.Init.Period = 65536-1;     //一个周期记65536个数    
    tim2_handle.Init.CounterMode =TIM_COUNTERMODE_UP;
    HAL_TIM_Base_Init(&tim2_handle);
}
//msp初始化msu相关的函数
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 get_tim2_counter(void){
    return __HAL_TIM_GetCounter(&tim2_handle);
}
//设置计数器的值
void set_tim2_counter(uint16_t value){
    __HAL_TIM_SetCounter(&tim2_handle,value);
}

//初始化GPIO口
void gpio_init(void){
    
    GPIO_InitTypeDef gpio_initstruct = {0};
     //打开Trig的GPIO时钟
    Trig_EClock;
     //打开Echo的GPIO时钟
    Echo_EClock;
    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;
    gpio_initstruct.Pull = GPIO_PULLUP;
    gpio_initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(Echo_port,&gpio_initstruct);
}

//测量超声波测得距离
float chsr04_instance(void){
    uint16_t tim2_cnt = 0;
    float chsr04_length = 0;
//单片机给超声波模块发送大于 10us 的高电平的触发信号;
    Trig_High;
    delay_us(15);
    Trig_Low;
//超声波模块收到触发信号后 Trig 端发送 8个40kHz 的超声波脉冲;
//Echo 端由低电平转为高电平,同时开始发送超声波;
    //计数器清零,定时器打开,开始计数
    while(Echo_read_pin == GPIO_PIN_RESET);
    tim2_start();
    set_tim2_counter(0);
//超声波模块检测到返回信号,Echo 端由高电平转为低电平;
    while(Echo_read_pin == GPIO_PIN_SET);
    tim2_stop();
   
    //Echo 端高电平宽度即为超声波传播时间。
    tim2_cnt = get_tim2_counter();
       
//计算超声波测得的距离
   //instance = (100 * 343(m/s)/1000000)(cm/us)* tim2_cnt(us)/2 = tim2_cnt(us) * 0.01715  (cm)
   chsr04_length = tim2_cnt * 0.01715;
   return chsr04_length;
    
}
  • chsr04.h文件代码 
#ifndef __CHSR04_H__
#define __CHSR04_H__
#include "stm32f1xx.h"

#define Trig_port            GPIOB
#define Trig_Pin             GPIO_PIN_6
#define Trig_EClock          __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_EClock          __HAL_RCC_GPIOB_CLK_ENABLE()
#define Echo_read_pin        HAL_GPIO_ReadPin(Echo_port,Echo_Pin)

void chsr04_init(void);
float chsr04_instance(void);

#endif

  • main.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "chsr04.h"

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    led_init();                         /* LED初始化 */
    uart1_init(115200);
    printf("hello,world");
    chsr04_init();
    
    while(1)
    { 
       printf("inst: %f \n",chsr04_instance());
       delay_ms(1000);
    }
}

遇到的问题和注意事项:

  • 在.h文件中while后面要加上“;”,不写不会报错,但结果出现问题。 
  • 最后测量的距离单位是cm。注意单位间的换算问题。

完结项目

硬件接线 

STM32
振动传感器
蜂鸣器
超声波传感器
舵机
PA4
DO
PA6
I/O
PB5
I/O
PB6
Trig
PB7
Echo
3V3
VCC
VCC
5V
VCC
VCC
GND
GND
GND
GND
GND

项目框图 

    //测试每个模块是否有问题
//    uint8_t key_number = 0;
    while(1)
    {   
//        key_number = key_scan();
        if(key_scan() == 1)
            led1_on();
        if(key_scan() == 2)
            led1_off();
    }
}

项目代码

舵机和超声波传感器的代码参考上面

  • 震动传感器:

vibrate.c文件代码:

#include "exti.h"
#include "stm32f1xx.h"
#include "delay.h"
#include "led.h"

#define vibrate_port GPIOA
#define vibrate_pin  GPIO_PIN_4

//定义一个标志位
uint8_t vibrate_flag = False;

void exti_init(void){
    //打开时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    //初始化GPIO口
    GPIO_InitTypeDef GPIO_Initstruct;
    
    GPIO_Initstruct.Mode =GPIO_MODE_IT_FALLING;
    GPIO_Initstruct.Pin = vibrate_pin;
    GPIO_Initstruct.Pull = GPIO_PULLUP;
    GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
    
    HAL_GPIO_Init(vibrate_port,&GPIO_Initstruct);
    
    //在HAL_Init()函数中进行优先级分组,默认第四种,实际用二种
    HAL_NVIC_SetPriority(EXTI4_IRQn,2,0);
    HAL_NVIC_EnableIRQ(EXTI4_IRQn);
    
}

//中断服务函数,
void EXTI4_IRQHandler(void){
    //调用GPIO的中断公共函数,不同外设不同
    HAL_GPIO_EXTI_IRQHandler(vibrate_pin);
    
}
//回调函数(GPIO口只有一个),业务代码:按键;消抖
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    //消抖,震动可忽略不计: 
    delay_ms(20);
    if(GPIO_Pin == vibrate_pin){  //判断EXTI0是否是GPIO_PIN0
        if(HAL_GPIO_ReadPin(vibrate_port,vibrate_pin) == GPIO_PIN_RESET){//判断GPIO口是否是低电平
//            led1_toggle();
           //设置中断标志位
            vibrate_flag = True;
        }
    }   
}
//让主函数识别中断标志位,定义一个获取中断标志位的函数
uint8_t vibrate_flag_get(void){
    uint8_t temp = vibrate_flag;  //第一次调用这个函数,返回:True;第二次调用,返回:False
    vibrate_flag = False;
    return temp;
}

//设置中断标志位的值
void vibrate_flag_set(uint8_t value){
    vibrate_flag = value;
}

vibrate.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
  •  按键代码

 key.c文件代码

#include "key.h"
#include "stm32f1xx.h"
#include "Delay.h"

//初始化GPIO口
void key_init(void){
    //打开时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();
    //调用GPIO初始化函数
    GPIO_InitTypeDef GPIO_Initstruct;
    GPIO_Initstruct.Mode = GPIO_MODE_INPUT;
    GPIO_Initstruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_Initstruct.Pull = GPIO_PULLUP;
    GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA,&GPIO_Initstruct);
}


//按键检测函数
uint8_t key_scan(void){
    //检测按键1是否按下,消除抖动
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){
        delay_ms(15);//消除抖动
        //再次判断按键是否按下
        if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET){
            //如果按键按下,等待按键松开
            while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET);
            //返回按键的值
            return 1;
        }
    }
        
        //检测按键2是否按下,消除抖动
    if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET){
        delay_ms(15);//消除抖动
        //再次判断按键是否按下
        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 "stdint.h"

void key_init(void);
uint8_t key_scan(void);

#endif
  •  蜂鸣器代码

beep.c文件代码

#include "stm32f1xx.h"
#include "beep.h"

#define beep_port GPIOB
#define beep_pin  GPIO_PIN_5

//初始化GPIO口
void beep_init(void){
    //打开时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();
    //打开GPIO口
    GPIO_InitTypeDef GPIO_Initstruct;
    GPIO_Initstruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Initstruct.Pin = beep_pin ;
    GPIO_Initstruct.Pull = GPIO_NOPULL;
    GPIO_Initstruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(beep_port,&GPIO_Initstruct);
    //关闭蜂鸣器
    beep_off();
}
//打开蜂鸣器函数
void beep_on(void){
    HAL_GPIO_WritePin(beep_port,beep_pin ,GPIO_PIN_RESET);
}
//关闭蜂鸣器
void beep_off(void){
    HAL_GPIO_WritePin(beep_port,beep_pin ,GPIO_PIN_SET);
}
//反转蜂鸣器
void beep_toggle(void){
    HAL_GPIO_TogglePin(beep_port,beep_pin );  
}

beep.h文件代码

#ifndef __BEEP_H__
#define __BEEP_H__
void beep_init(void);
void beep_on(void);
void beep_off(void);
void beep_toggle(void);
#endif
  •  led灯代码:

led.c文件代码

#include "led.h"
#include "sys.h"                  // 外设的驱动函数


//初始化GPIO口

void led_init(void){
    
    //打开时钟
    __HAL_RCC_GPIOB_CLK_ENABLE();
    //调用GPIO的初始化函数
    GPIO_InitTypeDef GPIO_Initstruct;
    GPIO_Initstruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    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);
    //关闭LED
    led1_off();
    led2_off();
    
}
//点亮LED1的函数
void led1_on(void){   
    
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);   
}

//反转LED1状态的函数
void led1_toggle(void){
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
}

//熄灭LED1状态的函数
void led1_off(void){
    
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
    
}

//点亮LED2的函数
void led2_on(void){   
    
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET);   
}

//反转LED2状态的函数
void led2_toggle(void){
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);
}

//熄灭LED1状态的函数
void led2_off(void){
    
    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET);
    
}

led.h文件代码

#ifndef __LED_H__
#define __LED_H__

void led_init(void);
void led1_on(void);
void led1_toggle(void);
void led1_off(void);

void led_init(void);
void led2_on(void);
void led2_toggle(void);
void led2_off(void);
#endif
  •  main.c文件代码
#include "sys.h"
#include "led.h"
#include "delay.h"
#include "uart1.h"
#include "chsr04.h"
#include "exti.h"
#include "beep.h"
#include "sg90.h"
#include "key.h"

#define open  1
#define close  0

uint8_t dustbin_status = close;

//开盖的函数
void open_dustbin(void){
    if(dustbin_status == close){    设置条件:这个要注意!!!
        angle_set(90);
        beep_on();
        led1_on();
        delay_ms(100);
        beep_off();
        led1_off();
        dustbin_status = open;
    }
}
//关盖的函数
void close_dustbin(void){
    angle_set(0);
    beep_off();
    led1_off();
    dustbin_status = close;
}

int main(void)
{
    HAL_Init();                         /* 初始化HAL库 */
    stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */
    uart1_init(115200);
    printf("hello,world");
    
    led_init();                         /* LED初始化 */
    key_init();
    beep_init();
    chsr04_init();
    sg90_init();
    exti_init();
    
    //测试每个模块是否有问题
    uint8_t key_number = 0;
    while(1)
    {   
      key_number = key_scan();
      if(key_number == 1 || vibrate_flag_get() == True || chsr04_instance() < 10){
          open_dustbin();
          delay_s(2);
          vibrate_flag_set(False);
      }    
      else
          close_dustbin();
     delay_ms(10);    //要进行延时,,一定要注意
    }
}


遇到的问题和注意事项:

  •  当硬件接线接上震动传感器时,舵机转到一定角度后无法回到原位置。解决:利用ST-Link v2 之间给舵机供电。
  • 按键不灵敏:如下代码,下面代码再进行循环时会调用两次函数进行判断,容易导致异常;解决办法:用一个变量进行接收函数的返回值,在用变量进行条件判断。

  • 在主函数中,给开盖函数中加上一个条件判断,(是否此时是关盖状态)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值