前言:最近学习了freertos的任务、队列、互斥量、任务标志位等理论知识,看着都会就怕一练就废,于是打算做些项目巩固一下,加深一下对freertos知识的理解。
一、项目介绍
项目简单需求:
检测靠近时,垃圾桶自动开盖,2秒后关盖
发生震动时,垃圾桶自动开盖,2秒后关盖
这里可加入蜂鸣器、按键等简单gpio口的运用,大家可以根据需求自行加入。
二、工程配置
时钟配置(我这里选择的72M时钟频率,如果选择其他频率可能会导致PWM波不一致,从而出不来效果)
1、在freertos创建任务
2、配置引脚
超声波引脚 Echo----PA4 Trig-----PA5
震动传感器 D0-------PA6
舵机数据线-------------PB8(定时器4第三通道PWM)可自行修改其他通道,支持PWM即可。
3、定时器的设置
定时器3(用做计数器,主要用于超声波测距的来回定时)
定时器4(主要用于舵机的PWM占空比的控制,PB8为定时器4的第三通道,具体可以查看stm32F103C8T6的数据手册)
PSC为分频系数,ARR为自动重装值。TCLK为时钟频率,上面设置为72M(注意,这里设置其他频率可能效果出现不了,本人在这里踩坑了。)
4、串口(主要用于调试)
三、代码实现
freertos.c
void StartHcsrTask(void const * argument)
{
/* USER CODE BEGIN StartHcsrTask */
int cnt;
float distance;//超声波距离
GPIO_PinState sw180State;//震动传感器状态
/* Infinite loop */
for(;;)
{
//初始化超声波模块
initHcsr();
//计算出中间经过多少时间
cnt = __HAL_TIM_GetCounter(&htim3);
// 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)
distance = cnt/58; //单位:cm
//振动传感器的引脚状态
sw180State = readVibrationSensor();
//串口打印测距距离
printf("%f",distance);
printf("cm\r\n");
//如何检测的距离低于5cm,或者发生震动,进行开盖,否则关盖。
if((distance < 8) || (sw180State == GPIO_PIN_RESET)){
openLid();//开盖
}else{
closeLid();//关盖
}
osDelay(100);
}
/* USER CODE END StartHcsrTask */
}
超声波
//使用TIM3来做us级延时函数
void TIM3_Delay_us(uint16_t n_us)
{
/* 使能定时器2计数 */
__HAL_TIM_ENABLE(&htim3);
__HAL_TIM_SetCounter(&htim3, 0);
while(__HAL_TIM_GetCounter(&htim3) < ((1 * n_us)-1) );
/* 关闭定时器2计数 */
__HAL_TIM_DISABLE(&htim3);
}
//初始化超声波模块
void initHcsr(void )
{
//1. Trig ,给Trig端口至少10us的高电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);//拉高
TIM3_Delay_us(20);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);//拉低
//2. echo由低电平跳转到高电平,表示开始发送波
//波发出去的那一下,开始启动定时器
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET);//等待输入电平拉高
HAL_TIM_Base_Start(&htim3);
__HAL_TIM_SetCounter(&htim3,0);
//3. 由高电平跳转回低电平,表示波回来了
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_SET);//等待输入电平变低
//波回来的那一下,我们开始停止定时器
HAL_TIM_Base_Stop(&htim3);
}
舵机部分
void openLid(void )//开盖
{
if(flag == CLOSE){
flag = OPEN;
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_3,15);//90度
osDelay(2000);
}
}
void closeLid(void )//关盖
{
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_3,5);//0度
flag = CLOSE;//标志位设置为关闭
osDelay(150);
}
震动传感器
//读取震动传感器的状态
GPIO_PinState readVibrationSensor() {
return HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6);
}