FREERTOS系统移植+任务创建

本文介绍了如何在STM32微控制器上移植FREERTOS实时操作系统,并创建任务。重点包括选择heap4内存管理方式减少碎片,配置FREERTOS的系统时钟节拍,以及适配SysTick中断服务函数作为系统节拍源。同时,文中展示了如何创建并删除任务,例如start_task和motor_task,用于电机控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FREERTOS系统移植+任务创建


前言

关于5V电压驱动四个轮子驱动力不够的问题,换了一个9V的电池已经能够得到很好的解决。

本篇主要介绍一下FREERTOS在STM32上的移植以及两个TASK的创建

因为STM32控制不是重点,所以这里就简单移植一下


FREERTOS移植

1、下载FREERTOS源码,在原有工程基础上创建一个FREERTOS文件夹,把源码放进去。
在这里插入图片描述
然后把portable这个文件夹中无关平台的代码删除,只留下这三个文件夹
在这里插入图片描述
2、把新添加的文件添加到工程中去
在这里插入图片描述
这里创建了两个文件夹,FREERTOS_CORE放置内核文件,FREERTOS_PORTABLE放置适配文件。

这里适配文件根据硬件的平台以及自己需要的内存分配方法来选,因为我的芯片是M3的,且我选择的内存分配方法是heap4。
这里介绍一下heap4的内存管理方式:
在这里插入图片描述
heap4方式会把已经释放的相邻的内存碎片合并成一块整体的区域,有助于减少内存碎片化问题,heap1只能申请无法释放,heap2方式无法进行合并相邻碎片。

3、添加对应头文件路径
在这里插入图片描述
4、在FREERTOS源码的demo中找到对应平台,把里面的FreeRTOSConfig.h文件拷出来放到include里面,这个文件是一些条件编译的宏和一些配置信息,没有这个文件编译会报错。

5、修改之前的一些文件以便兼容FREERTOS系统,因为这个之前直接拿的正点原子的例程,这个例程是兼容UCOS的,所以现在要稍微修改一下:
(1)首先修改sys.h中,把SYSTEM_SUPPORT_OS宏置1,表示支持OS系统。
(2)在usart.c文件中,引用头文件FreeRTOS.h和task.h,然后把关于UCOS的OSIntEnter()和 OSIntExit()删掉。
(3)修改delay.c文件,删除UCOS对应函数,并且把滴答定时器中断频率设置为FREERTOS的主时钟频率

void SysTick_Handler(void)
{	
	if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行 
	{ 
		xPortSysTickHandler(); 
	}
}

SysTick_Handler是systick的中断服务函数,其意思是在系统已经运行的情况下,把systick中端当成FREERTOS系统运行的系统时钟节拍,相当于用systick来当FREERTOS的心脏。

然后设置systick的中断时间:

void delay_init()
{
	u32 reload; 
	 SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//不设置这个那systick默认就是HCLK/8分频也就是AHB/8分频,这里设置为HCLK也就是AHB分频
	 
	 reload=SystemCoreClock/1000000; 
	 reload*=1000000/configTICK_RATE_HZ; 
	  
	 SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; //开启 SYSTICK 中断 
	 SysTick->LOAD=reload; //每 1/configTICK_RATE_HZ 秒中断一次 
	 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; //开启 SYSTICK
	
	 fac_us=SystemCoreClock/1000000; 
	 fac_ms=1000/configTICK_RATE_HZ; 
}

这里介绍一下systick,SysTick 是一个 24 位的倒计数定时器,当计数到 0 时,将从RELOAD 寄存器中自动重装载定时初值,开始新一轮计数。只要不把它在 SysTick 控制及状态寄存器中的使能位清除,就永不停息。
默认systick的频率是HCLK/8,一般就是72M/8 = 9M ,这里调用SysTick_CLKSourceConfig函数设置systick时钟来源为HCLK也就是72M,所以RELOAD减少1的时间为1/72M。
这几行代码的意思就是设置systick中断一次的时间为1/configTICK_RATE_HZ(s),这个宏是在FreeRTOSConfig.h中配的,这里配的是1000,也就是FREERTOS系统的时钟节拍为1ms。

适配工作主要是设置这个FREERTOS的系统时钟节拍,其他的都没什么。

创建TASK

这里先创建一个start task,然后后面再在这个task里面创建一个motor_task用来控制电机,然后把start_task关掉。后续如果有什么别的task再作调整。main.c代码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "FreeRTOS.h" 
#include "task.h"
#include "motor.h"
#include "string.h"

#define START_TASK_PRIO 1 //任务优先级 
#define START_STK_SIZE 128 //任务堆栈大小 
TaskHandle_t StartTask_Handler; //任务句柄 
void start_task(void *pvParameters); //任务函数

#define MOTOR_TASK_PRIO 6 //任务优先级 
#define MOTOR_STK_SIZE 50 //任务堆栈大小 
TaskHandle_t MotorTask_Handler; //任务句柄 
void MOTOR_task(void *p_arg); //任务函数

#define DIRECTION_MAX_LEN 10

char stop[DIRECTION_MAX_LEN] = "0";
char top[DIRECTION_MAX_LEN] = "1";
char botton[DIRECTION_MAX_LEN] = "2";
char left[DIRECTION_MAX_LEN] = "3";
char right[DIRECTION_MAX_LEN] = "4";
		
int main(void)
{	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	delay_init();	     
	LED_Init();		  	
	uart_init(9600); 
	MOTOR_Init();
	 
	//创建开始任务 
	xTaskCreate((TaskFunction_t )start_task, //任务函数 
				(const char* )"start_task", //任务名称 
				(uint16_t )START_STK_SIZE, //任务堆栈大小 
				(void* )NULL, //传递给任务函数的参数 
				(UBaseType_t )START_TASK_PRIO, //任务优先级 
				(TaskHandle_t* )&StartTask_Handler); //任务句柄 
				vTaskStartScheduler(); //开启任务调度
}

void start_task(void *p_arg) 
{
	taskENTER_CRITICAL();  //临界区,关中断

	xTaskCreate((TaskFunction_t )MOTOR_task, 
	(const char* )"MOTOR_task", 
	(uint16_t )MOTOR_STK_SIZE, 
	(void* )NULL, 
	(UBaseType_t )MOTOR_TASK_PRIO, 
	(TaskHandle_t* )&MotorTask_Handler); 
	

	vTaskDelete(StartTask_Handler); //删除开始任务
	
	taskEXIT_CRITICAL(); //退出临界区
}

//LED0 任务函数 
void MOTOR_task(void *pvParameters) 
{ 
	MOTORA_Pin1 = 0;
	MOTORA_Pin2 = 0;
	MOTORB_Pin1 = 0;
	MOTORB_Pin2 = 0;
	MOTORC_Pin1 = 0;
	MOTORC_Pin2 = 0;
	MOTORD_Pin1 = 0;
	MOTORD_Pin2 = 0;
	
	for(;;) 
	{ 
		if(USART_RX_STA&0x8000)
		{		
			LED0 = !LED0;
		
			if (!strncmp((char *)USART_RX_BUF, top, DIRECTION_MAX_LEN))
			{
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 1;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 1;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 1;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 1;

				vTaskDelay(500);
				
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 0;
				
			}
			else if (!strncmp((char *)USART_RX_BUF, botton, DIRECTION_MAX_LEN))
			{
				MOTORA_Pin1 = 1;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 1;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 1;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 1;
				MOTORD_Pin2 = 0;	
				
				vTaskDelay(500);
				
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 0;
				
			}
			else if (!strncmp((char *)USART_RX_BUF, stop, DIRECTION_MAX_LEN))
			{
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 0;
			}
			else if (!strncmp((char *)USART_RX_BUF, left, DIRECTION_MAX_LEN))
			{
				MOTORA_Pin1 = 1;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 1;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 1;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 1;
				
				vTaskDelay(500);
				
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 0;
			}
			else if (!strncmp((char *)USART_RX_BUF, right, DIRECTION_MAX_LEN))
			{
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 1;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 1;
				MOTORC_Pin1 = 1;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 1;
				MOTORD_Pin2 = 0;
				
				vTaskDelay(500);
				
				MOTORA_Pin1 = 0;  
				MOTORA_Pin2 = 0;
				MOTORB_Pin1 = 0;
				MOTORB_Pin2 = 0;
				MOTORC_Pin1 = 0;
				MOTORC_Pin2 = 0;
				MOTORD_Pin1 = 0;
				MOTORD_Pin2 = 0;
			}
			
			memset(USART_RX_BUF,0,USART_REC_LEN);
			USART_RX_STA=0;
			
		}
	}	
		
}


这个和之前裸机的控制逻辑是一样的,不做赘述。主要是用xTaskCreate这个函数动态创建一个task,里面跑电机控制程序。
上STM32测试,没什么问题。


总结

下一章开始基于蓝牙3.0的安卓控制APP开发,就涉及到上下左右的控制就行,用的是Android Studio进行开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值