22.2-任务的创建(有代码示例) FreeRTOS 项目 FreeRTOS学习笔记 FreeRTOS移植 FreeRTOS开源项目 FreeRTOS面试题汇总FreeRTOS项目实战F103

这个是全网最详细的STM32项目教学视频。
第一篇在这里:
视频在这里

STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随


**V3:HAL库开发、手把手教学下面功能:PID速度控制、PID循迹、PID跟随、遥控、避障、PID角度控制、openmv视觉控制、电磁循迹、FreeRTOS、K210视觉智能车(更新中)、K230视觉智能车(更新中)、MSPM0G3507视觉智能车(更新中)**

在这里插入图片描述

22.2-任务的创建(有代码示例)

任务创建生成的代码

上一个章节我们创建了LED的任务这节我们分析一下相关代码,然后再创建一个OLED刷新也就是模式零的任务

可以看到STM32cubemx软件生成RTOS代码调用的CMSIS-RTOS的函数(以os开通的函数都是CMSIS-RTOS的函数)

在这里插入图片描述
我们很容易就找到函数原型其实是
在这里插入图片描述
在这里插入图片描述
函数原型:在这里插入图片描述
函数描述:

函数 xTaskCreate 用于实现 FreeRTOS 操作系统的任务创建,并且还可以自定义任务栈的大小。

  1. 第 一 个参数填创建任务的函数名
  2. 第 二 个参数是任务名,这个参数主要用于调试的时候方便看是哪个任务
  3. 第 三 个参数是任务栈大小,单位 word,也就是 4 字节
  4. 第 四 个参数是创建的任务函数的形参
  5. 第 五 个参数是定义任务优先级
  6. 第 六 个参数是任务句柄,用于区分不同的任务

然后我们看一下,我们生成的代码都有那些

生成的的代码里面会定义任务的句柄
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

动手再创建一个任务

我们复制上一节21-2_LED_FreeRTOS文件 命名为22-2_LED_FreeRTOS

然后点击LED.ioc

我们这里再新建一个任务用于OLED刷新,也就是我们之前裸机时候的模式0大部分功能

由于OLED刷新的任务对实时性要求不高,所以我们优先级设置低一些
在这里插入图片描述
这里优先级设置低于正常优先级
在这里插入图片描述
然后点击生成代码,可以观察到已经生成新的代码,
在这里插入图片描述这个就是我们OLED刷新任务对应的函数,我们在该函数中增加OLED刷新代码

将之前模式零的代码复制过去
在这里插入图片描述

			//0LED显示功能
		sprintf((char*)OledString, "V1:%.2fV2:%.2f", Motor1Speed,Motor2Speed);//显示速度
		OLED_ShowString(0,0,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char*)OledString, "Mileage:%.2f", Mileage);//显示里程
		OLED_ShowString(0,1,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char*)OledString, "U:%.2fV", adcGetBatteryVoltage());//显示电池电压
		OLED_ShowString(0,2,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char *)OledString,"HC_SR04:%.2fcm\r\n",HC_SR04_Read());//显示超声波数据
		OLED_ShowString(0,3,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char *)OledString,"p:%.2f r:%.2f \r\n",pitch,roll);//显示6050数据 俯仰角 横滚角
		OLED_ShowString(0,4,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
		sprintf((char *)OledString,"y:%.2f  \r\n",yaw);//显示6050数据  航向角
		OLED_ShowString(0,5,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		
	//蓝牙APP显示
		sprintf((char*)Usart3String, "V1:%.2fV2:%.2f", Motor1Speed,Motor2Speed);//显示速度
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		//阻塞方式发送可以保证数据发送完毕,中断发送不一定可以保证数据已经发送完毕才启动下一次发送
		sprintf((char*)Usart3String, "Mileage:%.2f", Mileage);//显示里程
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char*)Usart3String, "U:%.2fV", adcGetBatteryVoltage());//显示电池电压
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char *)Usart3String,"HC_SR04:%.2fcm\r\n",HC_SR04_Read());//显示超声波数据
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char *)Usart3String,"p:%.2f r:%.2f \r\n",pitch,roll);//显示6050数据 俯仰角 横滚角
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
		
		sprintf((char *)Usart3String,"y:%.2f  \r\n",yaw);//显示6050数据  航向角
		HAL_UART_Transmit(&huart3,( uint8_t *)Usart3String,strlen(( const  char  *)Usart3String),50);//阻塞式发送通过串口三输出字符 strlen:计算字符串大小
	
		//获得6050数据
//		while(mpu_dmp_get_data(&pitch,&roll,&yaw)!=0){}  //这个可以解决经常读不出数据的问题
		
		//在显示模式电机停转 设置小车速度为0
		motorPidSetSpeed(0,0);

有很多错误,我们解决一些,freeRTOS.c增加头文件
在这里插入图片描述

#include "oled.h"
#include "stdio.h"
#include "motor.h"
#include "niming.h"
#include "pid.h"

#include "cJSON.h"
#include <string.h>
#include "HC_SR04.h"



#include "mpu6050.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h" 



#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

然后把main.c里面定义和声明的变量到Freertos.c中都声明一下, 主要声明的时候不要赋值
在这里插入图片描述

extern short Encode1Count ;//电机1编码器计数值 short的类型
extern short Encode2Count ;//电机2编码器计数值 short的类型
extern float Motor1Speed ;//电机1速度 转/s
extern float Motor2Speed ;//电机2速度 转/s
extern uint16_t TimerCount ;//中断计数变量


extern tPid pidMotor1Speed;//声明电机1PID速度控制结构体类型变量
extern tPid pidMotor2Speed;
extern tPid pidFollow;    //定距离跟随PID
extern tPid pidMPU6050YawMovement;  //利用6050偏航角 进行姿态控制的PID
extern uint8_t Usart1_ReadBuf[255];	//串口1 缓冲数组
extern float p,i,d,a,b;//使用JSON时候使用的变量
extern uint8_t OledString[50];//OLED显示使用的字符串数组
extern float Mileage;//里程数

extern tPid pidHW_Tracking;//红外循迹的PID
extern tPid pidOpenmv_Tracking;//摄像头的PID

extern uint8_t g_ucaHW_Read[4] ;//保存红外对管电平的数组
extern int8_t g_cThisState ;//这次状态
extern int8_t g_cLastState ; //上次状态
extern float g_fHW_PID_Out;//红外对管PID计算输出速度
extern float g_fHW_PID_Out1;//电机1的最后循迹PID控制速度
extern float g_fHW_PID_Out2;//电机2的最后循迹PID控制速度

extern uint8_t g_ucUsart3ReceiveData;  //保存串口三接收的数据
extern uint8_t g_ucUsart2ReceiveData;  //保存串口二接收的数据

extern uint8_t Usart3String[50];//串口三输出字符串使用的字符串数组
extern float g_fHC_SR04_Read;//超声波传感器读取障碍物数据
extern float g_fFollow_PID_Out;//定距离跟随PID计算输出速度

extern float pitch,roll,yaw; //俯仰角 横滚角 航向角

extern float  g_fMPU6050YawMovePidOut ; //姿态PID运算输出
extern float  g_fMPU6050YawMovePidOut1 ; //第一个电机控制输出
extern float  g_fMPU6050YawMovePidOut2 ; //第一个电机控制输出

extern uint8_t g_ucMode ; 

extern int g_lHW_State;//帮助视觉调试 用于表示红外对管或者视觉摄像头识别状态

编译一下就没有错误了,然后我们把代码烧录观察现象

下面能够观察到OLED屏幕在快速刷新,同时LED函数

注意如果注释掉MPU6050初始化和数据获取函数,那么OLED上是不会显示6050数据值的。

而且OLED刷新的任务中一定要有osDelay 确保任务能供定期进入阻塞状态,使得其他任务能得到调度。

修改一下延时时间
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

好家伙VCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值