STM32系列单片机标准库移植FreeRTOS V10.4.6详解

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

  文中所用到的资料下载地址 https://download.csdn.net/download/qq_20222919/87370679

  最近看正点原子新录制了手把手教你学FreeRTOS的视频教程看了一下教程发现视频里面讲的是使用HAL移植 FreeRTOS V10.4.6 版本以前的标准库移植的是FreeRTOS V9.0 版本。而自己平时写代码使用的都是标准库就想着能不能把FreeRTOS V10.4.6 版移植到标准库中去。
  为了移植简单直接下载正点原子的代码在上面修改。实现思路为下载一个标准库函数的FreeRTOS V9.0版的程序然后在下载一个HAL库函数的FreeRTOS V10.4.6 版的程序然后将HAL库函数中FreeRTOS 相关代码直接拷贝到标准库函数中替换FreeRTOS相关代码。

准备资料

  首先去正点原子网站上下载源码下载mini开发板和战舰开发板的资料。

在这里插入图片描述

  mini开发板里面有标准库函数的FreeRTOS代码战舰开发板里面有HAL库函数的FreeRTOS代码。

  下载mini开发板资料在mini开发板中找到扩展程序在里面打开FreeRTOS例程复制第一个程序到桌面。

在这里插入图片描述
在这里插入图片描述

  将文件夹重命名为FreeRTOS_demo

在这里插入图片描述

  随便打开一个FreeRTOS相关的文件可以看到这个FreeRTOS的版本为V9.0

在这里插入图片描述

  下载战舰开发板资料在战舰开发板中找到扩展程序在里面打开FreeRTOS例程一会要用到这些程序里面FreeRTOS相关代码。

在这里插入图片描述

  随便打开一个FreeRTOS相关的文件可以看到这个FreeRTOS的版本为V10.4.6

在这里插入图片描述

开始移植

删除main函数中无用代码

  准备工作已经完成了下面开始移植。打开桌面上FreeRTOS_demo工程。

在这里插入图片描述

  编译工程确保工程文件的正确接下来删除main文件中和FreeRTOS相关的代码和头文件。
  删除前代码如下

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "FreeRTOS.h"
#include "task.h"
/************************************************
 ALIENTEK Mini STM32F103开发板 FreeRTOS实验2-1
 FreeRTOS移植实验-库函数版本
 技术支持www.openedv.com
 淘宝店铺http://eboard.taobao.com 
 关注微信公众平台微信号"正点原子"免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者正点原子 @ALIENTEK
************************************************/

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

//任务优先级
#define LED0_TASK_PRIO		2
//任务堆栈大小	
#define LED0_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO		3
//任务堆栈大小	
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 	 
	delay_init();	    				//延时函数初始化	  
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	
	 
	//创建开始任务
    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 *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED0任务函数 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
    }
}   

//LED1任务函数
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
    }
}


  删除后代码如下

#include "led.h"
#include "delay.h"
#include "sys.h"
/************************************************
 ALIENTEK Mini STM32F103开发板 FreeRTOS实验2-1
 FreeRTOS移植实验-库函数版本
 技术支持www.openedv.com
 淘宝店铺http://eboard.taobao.com 
 关注微信公众平台微信号"正点原子"免费获取STM32资料。
 广州市星翼电子科技有限公司  
 作者正点原子 @ALIENTEK
************************************************/
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 	 
	delay_init();	    				//延时函数初始化	  
	LED_Init();		  					//初始化LED
}

  再次编译工程确保代码没有错误。

在这里插入图片描述

替换FreeRTOS文件

  接下来替换FreeRTOS相关文件。将FreeRTOS_demo工程中FreeRTOS文件夹中的所有文件全部删除。

在这里插入图片描述

  删除FreeRTOS V9.0 所有文件

在这里插入图片描述

  接下来打开战舰资料中的FreeRTOS例程。文件目录为【正点原子】战舰STM32F103开发板V4 资料盘(A盘)\4程序源码\3扩展例程\2FreeRTOS例程\FreeRTOS实验例程2 FreeRTOS移植实验\Middlewares\FreeRTOS

请添加图片描述

  打开FreeRTOS这个文件夹将里面所有的文件复制到FreeRTOS_demo工程中FreeRTOS文件夹中。

在这里插入图片描述

复制初始化和配置文件

  接下来将 战舰STM32F103开发板V4 资料盘(A盘)\4程序源码\3扩展例程\2FreeRTOS例程\FreeRTOS实验例程2 FreeRTOS移植实验\User 文件夹中freertos_demo.c、freertos_demo.h、FreeRTOSConfig.h 这三个文件复制到 FreeRTOS_demo这个工程的USER文件夹中。

在这里插入图片描述

修改代码

  打开 FreeRTOS_demo工程可以看到此时FreeRTOS的版本已经成功替换为 V10.4.6版本了。

在这里插入图片描述
  将freertos_demo.c文件添加到USER文件夹中

在这里插入图片描述

  在main函数中添加 freertos_demo.h头文件在初始化代码中添加freertos_demo();函数。

在这里插入图片描述

调试编译工程

  将工程文件全部编译此时工程里面出现了好多错误。

在这里插入图片描述

  双击错误提示跳转到代码中。

在这里插入图片描述

  这里主要是头文件的路径错误将sys.h 和 usart.h前面的路径删除掉再次编译。

在这里插入图片描述

  此时编译错误减少了但是还有一个led.h的路径错误。双击错误提示跳转到文件中。

在这里插入图片描述

  这个freertos_demo.c文件中是FreeRTOS任务相关的代码正点原子的示例中用到了液晶屏和LED灯在这里删除液晶屏相关代码只保留LED灯相关代码。同时要修改LED头文件路径。

在这里插入图片描述

  删除文件中LCD相关的代码

在这里插入图片描述

  修改LED相关代码修改后代码如下:

#include "freertos_demo.h"
#include "usart.h"
#include "led.h"

/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO 1                   /* 任务优先级 */
#define START_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            StartTask_Handler;  /* 任务句柄 */
void start_task(void *pvParameters);        /* 任务函数 */

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO      2                   /* 任务优先级 */
#define TASK1_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task1Task_Handler;  /* 任务句柄 */
void task1(void *pvParameters);             /* 任务函数 */

/* TASK2 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK2_PRIO      3                   /* 任务优先级 */
#define TASK2_STK_SIZE  128                 /* 任务堆栈大小 */
TaskHandle_t            Task2Task_Handler;  /* 任务句柄 */
void task2(void *pvParameters);             /* 任务函数 */

/******************************************************************************************************/


/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{
     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();
}

/**
 * @brief       start_task
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           /* 进入临界区 */
    /* 创建任务1 */
    xTaskCreate((TaskFunction_t )task1,
                (const char*    )"task1",
                (uint16_t       )TASK1_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK1_PRIO,
                (TaskHandle_t*  )&Task1Task_Handler);
    /* 创建任务2 */
    xTaskCreate((TaskFunction_t )task2,
                (const char*    )"task2",
                (uint16_t       )TASK2_STK_SIZE,
                (void*          )NULL,
                (UBaseType_t    )TASK2_PRIO,
                (TaskHandle_t*  )&Task2Task_Handler);
    vTaskDelete(StartTask_Handler); /* 删除开始任务 */
    taskEXIT_CRITICAL();            /* 退出临界区 */
}

/**
 * @brief       task1
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task1(void *pvParameters)
{
    while(1)
    {        
        LED0=!LED0;                                                  /* LED0闪烁 */
        vTaskDelay(100);                                               /* 延时1000ticks */
    }
}

/**
 * @brief       task2
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void task2(void *pvParameters)
{
    while(1)
    {
       LED1=!LED1;
        vTaskDelay(200);                           /* 延时1000ticks */
    }
}

  修改完成后再次编译工程这时还有一个错误。

在这里插入图片描述

  双击错误提示定位到代码中。

在这里插入图片描述

  错误提示声明语句不能出现在可执行语句之后。将这行代码移动到函数开始位置处。再次编译工程。

在这里插入图片描述

  这时候工程0错误0警告。

下载验证

  在工程中可以看到正点原子的这个芯片用的是103RC系列的芯片LED口为PA8和PD2口如果自己有板子的话就可以下载程序验证了。

在这里插入图片描述

  电路板运行效果

请添加图片描述

  示波器测量LED波形。

请添加图片描述

  通过示波器波形可以看出一个LED100ms闪烁一次一个LED200ms闪烁一次。和代码中设置的一样说明程序功能正常。FreeRTOS的移植已经成功了。

将工程移植到其他型号MCU上

  这个工程用只能用到STM32F103RC系列的MCU上但是我们自己不一定都用的是这个系类的MCU如果我们用的是其他系列的MCU,那么此时还需要将次工程移植到我们自己的MCU上去。

  下面就将这个工程移植到STM32F103C8T6芯片上去首先将刚才的工程复制一份并重命名。

在这里插入图片描述

  将工程重命名为 FreeRTOS_demo_103C8T6打开工程。

修改单片机型号

  单击魔术棒按钮选择Device选项将单片机型号选为STM32F103C8

在这里插入图片描述

修改单片机类型

  由于STM32F103C8系列MCU是中等容量单片机而工程默认的STM32F103RC系列MCU是大容量单片机这里要在C/C++ 选项中将单片机宏定义的类型修改为STM32F10X_MD

在这里插入图片描述

修改下载文件

  选择debug选项单击setting按钮打开Flash Download 选项选择这个512K的下载文件然后单击Remove按钮将默认的这个下载文件删除掉。

在这里插入图片描述

  单击Add按钮添加新的下载文件。

在这里插入图片描述

  选择第一个128K的这个文件然后单击下面Add按钮。

在这里插入图片描述

  此时新的下载文件就添加进来了单击最下面的确定按钮。

在这里插入图片描述

  接着单击下面的OK按钮保存设置。

在这里插入图片描述

替换启动文件

  在工程中CORE文件夹中的 startup_stm32f10x_hd.s 文件上单击鼠标右键选择第二个删除当前文件。这个启动文件是大容量单片机的启动文件需要将它替换为中等容量单片机的启动文件。

在这里插入图片描述

  在弹出的对话框中选择是

在这里插入图片描述

  在CORE文件夹上单击鼠标右键选择第三个选项添加存在的文件到CORE分组中。

在这里插入图片描述

  打开当前项目中的CORE文件夹。

在这里插入图片描述

  选择文件夹中的 startup_stm32f10x_md.s文件然后单击Add按钮然后关闭窗口。

在这里插入图片描述
  此时启动文件就替换完成了。

在这里插入图片描述

编译下载

  编译工程

在这里插入图片描述

  没有错误和警告但是此时还不能直接下载因为这个项目的的LED的端口是PA8和PD2而STM32F103C8T6这个MCU没有PD2端口所以还需要修改LED文件。

在这里插入图片描述

  将LED端口初始化代码中的PD2端口修改为PC13同时将时钟初始的PD口改为PC口。

在这里插入图片描述

  修改led.h头文件中的宏定义

在这里插入图片描述

  将头文件中的LED1修改为PC13然后编译下载代码。
  电路板运行效果

请添加图片描述

  示波器测量LED波形

请添加图片描述

  通过示波器波形可以看出一个LED灯每隔100ms闪烁一次一个LED每隔200ms闪烁一次。说明程序已经正常运行了。

  到此为止在标准库代码上移植FreeRTOS V10.4.6系统和不同型号MCU的工程移植就全部完成了。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6