项目介绍
项目需求:
以下几个事件触发时,自动开盖,并伴随蜂鸣器短响一声,同时 LED 灯闪烁一下,2秒后自动关盖:
- 检测到有人靠近
- 检测到有震动
- 按下按键 KEY1
项目框图:
硬件清单:
超声波传感器(chsr04) | 震动传感器 | 蜂鸣器 | 舵机(sg90) |
开发板 | 杜邦线 | ST-Link | USB转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.5ms | 0° | 2.5% |
1.0ms | 45° | 5.0% |
1.5ms | 90° | 7.5% |
2.0ms | 135° | 10.0% |
2.5ms | 180° | 12.5% |
工作参数和引脚介绍
- 工作参数:
工作扭矩:1.6kg/cm | 反应速度:0.12 - 0.13秒/60° 死区设定:5us | 死区设定:5us | 转动角度:常见0°、90°、180°、360° |
齿轮材质:尼龙塑料齿 | 工作电压:3V - 6V | 温度范围:-30° ~ +60° | ------- |
- 引脚接线:
SG90 | STM32 |
PWM 信号线(橙色线) | 输出PWM的GPIO口 |
VCC(红线) | 3.3/5V |
GND(棕色线) | GND |
小实验:驱动SG90舵机
- 引脚接线:
SG90 | STM32 |
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,传播速度受到环境条件的影响,如温度、湿度和气压等。
正常测距的时序图:
介绍时序图的步骤:
- 单片机给超声波模块发送大于 10us 的高电平的触发信号;
- 超声波模块收到触发信号后 Trig 端发送 8个40kHz 的超声波脉冲;
- Echo 端由低电平转为高电平,同时开始发送超声波;
- 超声波模块检测到返回信号,Echo 端 由高电平转为低电平;
- 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-SR04 | STM32 | 备注 |
VCC | 3.3/5V | 外接直流电源 |
Trig | 任意一个GPIO口 | 输入端 |
Echo | 任意一个GPIO口 | 输出端 |
GND | GND | 接地 |
小实验:超声波测距
实验目的:利用超声波传感器实现超声波测距。
硬件清单:开发板、超声波传感器(chsr04)、USB转TTL、ST-Linkl V2
引脚接线:
HC-SR04 | STM32 | USB 转 TTL |
---|---|---|
VCC | 3.3/5V | |
Trig | B6 | |
Echo | B7 | |
GND | G | |
A10 | TX | |
A9 | RX | |
G | GND |
- 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 之间给舵机供电。
- 按键不灵敏:如下代码,下面代码再进行循环时会调用两次函数进行判断,容易导致异常;解决办法:用一个变量进行接收函数的返回值,在用变量进行条件判断。
- 在主函数中,给开盖函数中加上一个条件判断,(是否此时是关盖状态)。