记录嵌入式学习心得1:智能垃圾桶项目
历时一个多月的学习,掌握了HAL库的GPIO,中断,定时器最基础的外设。也学习了一些模块的使用,振动传感器,超声波传感器,舵机等等。利用开源小项目检验所学知识,熟练运用。
项目要求:几个事件触发打开垃圾桶并闪灯并蜂鸣器响,打开2秒后关闭垃圾桶,事件一:按下按钮,事件二:检测到震动,事件三:有物体靠近

思路:各个模块分别调试,最后集中在主函数main里。
1.LED,使用GPIO,输出低电平点亮,输出高电平熄灭。运用GPIO端口输出。
2.蜂鸣器,类似LED,低电平响,高电平不向。
3.按键,运用GPIO端口输入,检测按下,置一标志位,代表按下。
4.震动传感器,需要运用中断,检测到震动则在中断里配置震动标志位,配置GPIO模式为IT_Falling,意思为检测到低电平则会进入中断。
5.超声波传感器,HCSR04,用定时器来计算超声波来回的时间,进而算出距离。
6.舵机SG90,定时器输出比较,输出PWM波,控制舵机转动。
在main函数中初始化各个模块,检测到对应的打开垃圾桶条件,那么控制舵机打开垃圾桶,灯亮蜂鸣器响,否则控制舵机关闭垃圾桶。
遇到的问题
1.舵机在单独的程序中可以有效运行,但是在项目中作为一个模块使用不能有效运行。检查各个模块代码发现,舵机的定时器和超声波传感器的定时器用的同一个,这样一来,在主函数初始化的时候,后初始化的模块的定时器参数会覆盖前一个初始化的模块,导致前一个模块的定时器错误。于是改变超声波传感器的定时器,解决了问题。注意:不能改变舵机的定时器,因为舵机接线对应的端口是PA6,对应了定时器3的第一通道,而超声波传感器只是需要一个定时功能。
2.运行一段时间后,程序卡死不动。可能原因是主函数while循环里一直在检测垃圾桶开启条件,可能出问题。通过在while里延时10ms,解决此问题。
3.在垃圾桶打开时,若继续给触发开启的条件,蜂鸣器则会再次响,灯会再亮,这是不想要的。解决方法,添加垃圾桶的状态标志位,每此开启垃圾桶的时候,判断垃圾桶状态是不是关闭,若是,则打开垃圾桶。
下例部分代码:
超声波传感器模块
#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;
}
舵机模块
#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);
}
主函数
#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);
}
}
更多推荐



所有评论(0)