前言:记录个人学习使用STMCubeMx软件,通过freeRTOS队列功能进行超声波与舵机两个线程任务之间的数据传输,并实现相应的功能。
一、超声波模块配置
1、配置定时器(TIM4)
2、配置GPIO口
二、舵机配置
1、配置定时器(TIM3通道2)
需要20ms定时器周期
2、配置GPIO 配置定时器后自动生成为PA7
三、创建线程(任务)
1、创建可复写__weak超声波线程
2、创建舵机操作线程
四、创建队列(float类型)
五、参考代码
1、main.c
(1)添加stdio头文件(测试板子复位后往串口发送数据,PC端是否成功接收)
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "cmsis_os.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_FREERTOS_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
(2)复位上电:测试串口发送功能
初始化定时器TIM3产生PWM信号的占空比
启动定时器TIM3通道2输出PWM信号
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM3_Init();
MX_TIM4_Init();
/* USER CODE BEGIN 2 */
/*复位上电:测试串口发送功能*/
printf("successful!\r\n");
/*初始化定时器TIM3产生PWM信号的占空比*/
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, (1.0 / 9.0) * 30 + 5.0);
/*启动定时器TIM3通道2输出PWM信号*/
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
/* USER CODE END 2 */
/* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
2、HCSR04.c
(1)手动创建文件夹存放超声波.c文件并加载到项目中
(2)HCSR04.c代码
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include "HCSR04.h"
#include "tim.h"
#include "stdio.h"
//调用外部freertos.c定义的队列句柄
extern osMessageQId Queue_DistanceHandle;
/*GPIO口宏定义*/
#define Write_Trig_High() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET)
#define Write_Trig_Low() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET)
#define Read_Echo() HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7)
/*定时器延迟20us函数*/
void Timer4_delay_us(uint16_t n_us)
{
__HAL_TIM_ENABLE(&htim4);
__HAL_TIM_SetCounter(&htim4, 0);
while(__HAL_TIM_GetCounter(&htim4) < ((1*n_us)-1));
__HAL_TIM_DISABLE(&htim4);
}
//超声波模块运行
float HcSr04_Runing(void)
{
//存放定时间4计时计数
uint32_t cnt = 0;
//存放获取超声波的距离
float distance = 0;
/*超声波Trig口输出20us高电平,驱动超声波模块发射超声波*/
Write_Trig_High();
Timer4_delay_us(20);
Write_Trig_Low();
//等待超声波模块发射成功超声波,Echo引脚会输出高电平
while(Read_Echo() == GPIO_PIN_RESET);
/*启动定时器TIM4并重置计数器,开始计时*/
HAL_TIM_Base_Start(&htim4);
__HAL_TIM_SetCounter(&htim4, 0);
//等待超声波模块接收返回的超声波,Echo引脚会输出低电平
while(Read_Echo() == GPIO_PIN_SET);
/*关闭定时器TIM4并获取定时器计数值*/
HAL_TIM_Base_Stop(&htim4);
cnt = __HAL_TIM_GetCounter(&htim4);
/*计算并返回距离值*/
distance = (float)cnt/58.00;
printf("receive %f\r\n", distance);
return distance;
}
//重写freertos.c文件里面的超声波线程
void StartTaskHCSR04(void const * argument)
{
/* USER CODE BEGIN StartTaskOperation */
//存放超声波返回的测距值
float val = 0;
//存放队列状态标志
BaseType_t send_status;
/* Infinite loop */
for(;;)
{
//获取超声波测距值
val = HcSr04_Runing();
/*往队列发送数据(阻塞等待)*/
send_status = xQueueSend(Queue_DistanceHandle, &val, portMAX_DELAY) ;
if(send_status == pdFALSE)
{
printf("Queue Send fail\r\n");
}
osDelay(100);
}
/* USER CODE END StartTaskOperation */
}
3、freertos.c
(1)添加左侧项目栏tim.c的头文件tim.h,和stdio头文件
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "tim.h"
#include "stdio.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
(2)cubeMx自动生成了三个线程(默认线程、可复写超声波线程、舵机操作线程)
(3)舵机线程对应的代码
/* USER CODE BEGIN Header_StartTaskSteering */
/**
* @brief Function implementing the TaskSteering thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskSteering */
void StartTaskSteering(void const * argument)
{
/* USER CODE BEGIN StartTaskSteering */
//存放队列接收的数值
float val = 0;
//存放队列状态标志
BaseType_t receive_status;
/* Infinite loop */
for(;;)
{
//获取队列接收数值(阻塞等待)
receive_status = xQueueReceive(Queue_DistanceHandle,&val, portMAX_DELAY);
/*判断队列是否成功接收信息(否:之间break退出此次循环)*/
if(receive_status == pdFALSE)
{
printf("Queue Receive fail\r\n");
break;
}
/*队列接收数值对应的舵机操作功能*/
if(val < 10.0)
{
//设置定时器TIM3通道2的PWM输出占空比(实现开盖功能)
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, (1.0 / 9.0) * 0 + 5.0);
//判断超声波模块通过队列传输后接收的测距值是否在判断条件中,若是进行阻塞直到不在判断条件
while(val < 10.0)
{
/*不断获取队列接收数值(阻塞等待)*/
receive_status = xQueueReceive(Queue_DistanceHandle,&val, portMAX_DELAY);
osDelay(1);
}
//使用阻塞功能实现舵机开盖后有500ms的状态停留功能
osDelay(500);
}
else
{
//设置定时器TIM3通道2的PWM输出占空比(实现关盖功能)
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_2, (1.0 / 9.0) * 30 + 5.0);
}
osDelay(1);
}
/* USER CODE END StartTaskSteering */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */
/* USER CODE END Application */