基于STM32F407的FreeRTOS学习笔记(2)

发布者:WhisperingRain最新更新时间:2024-03-21 来源: elecfans关键字:STM32F407  FreeRTOS  学习笔记 手机看文章 扫描二维码
随时随地手机看文章

上一期配置完FreeRTOS的环境后,这一期记录自己关于任务创建的学习过程。

图片

官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。

xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄

图片

vTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。

图片

因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。

图片

任务函数编写


/*

LED1翻转

*/

void LED_TOG(void * pvParameters)//参数为 void * pvParameters

{

  while(1)

  {

    printf('LED_TOG runningrn');//串口打印运行信息

    HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转

    vTaskDelay(500);//延迟500ms

  }

}


要注意的是vTaskDelay是FreeRTOS用来延时的函数。

图片


之后我们要创建任务函数的启动函数


TaskHandle_t Start_LED_Handler;



void Start_LED(void * pvParameters)

{

  xTaskCreate((TaskFunction_t        )LED_TOG,//任务函数

              (char *                )'LED_TOG',//任务名称

              (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte

              (void*                 ) NULL,//无返回

              (UBaseType_t          ) 1,//优先级1

              (TaskHandle_t *        )LED_TOG_Handler);//任务函数句柄

  vTaskDelete(NULL);

}

我们创建启动任务的函数,将 任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄 ,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。


同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务)


void FreeRTOS_Init()

{

  xTaskCreate((TaskFunction_t        )Start_LED,

              (char *                )'Start_LED',

              (configSTACK_DEPTH_TYPE) 128,

              (void*                 ) NULL,

              (UBaseType_t          ) 0,

              (TaskHandle_t *        )Start_LED_Handler);

  vTaskStartScheduler();//启动运行函数

}

这样子我们在主函数中添加刚刚定义的启动启动函数


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 */

  KEY_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();

  /* USER CODE BEGIN 2 */

  FreeRTOS_Init();

  /* USER CODE END 2 */



  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    /* USER CODE END WHILE */



    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}

我们的代码就可以正常运行啦!


我们在用上述的方法实现两个灯一起翻转


还是先编辑任务函数如下,并且定义其相关句柄


TaskHandle_t LED_TOG2_Handler;

void LED_TOG2(void * pvParameters)//参数为 void * pvParameters

{

  while(1)

  {

    printf('LED_TOG runningrn');//串口打印运行信息

    HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转

    vTaskDelay(500);//延迟500ms

  }

}

在任务启动函数中加入我们新建的任务。


void Start_LED(void * pvParameters)

{

  xTaskCreate((TaskFunction_t        )LED_TOG,//任务函数

              (char *                )'LED_TOG',//任务名称

              (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte

              (void*                 ) NULL,//无返回

              (UBaseType_t          ) 1,//优先级1

              (TaskHandle_t *        )LED_TOG_Handler);//任务函数句柄


   xTaskCreate((TaskFunction_t        )LED_TOG2,//任务函数

              (char *                )'LED_TOG2',//任务名称

              (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte

              (void*                 ) NULL,//无返回

              (UBaseType_t          ) 2,//优先级2

              (TaskHandle_t *        )LED_TOG2_Handler);//任务函数句柄


  vTaskDelete(NULL);

}


再次运行我们的代码。


麦克阿瑟将军曾说过:点灯对于嵌入式来说,就像Hello World对于程序员一样重要。我们不能不去点灯,就像西方不能失去耶路撒冷。


关键字:STM32F407  FreeRTOS  学习笔记 引用地址:基于STM32F407的FreeRTOS学习笔记(2)

上一篇:基于STM32F407的FreeRTOS学习笔记(4)
下一篇:学习STM32单片机,要理解它的堆栈

推荐阅读最新更新时间:2024-11-13 16:45

MC9S08AW60学习笔记
想不到大学毕业后的另一段竟是从飞思卡尔的8位单片机开始,好吧,先用这个打基础吧。 学习这款芯片看的是《嵌入式技术基础与实践》(第二版),书写的不错,偶尔有些语句不太通顺。 下面就一一记录学习这款芯片所遇到的问题及解决方法: 1、问题:照着书中的历程写了串口的中断接收与发送程序,但使用上位机发送命令时程序会突然卡死,但使用原版程序就是没问题。 分析:本来完全可以弃用自己写的程序,用原版程序,但感觉那样就失去了意义,然后硬着头皮一点一点对比程序,后来直接进行了全部替换,把那些.c文件以及系统配置文件都做了替换,问题仍然存在。最后在对比了isr.h中发现我的里面少了对SCI.h的声明,后来添加上#include SCI.
[单片机]
MC9S08AW60<font color='red'>学习</font><font color='red'>笔记</font>
CAN总线学习笔记四:CAN总线通信
  在理解了CAN总线的自通信程序后,再来探讨CAN总线间的相互通信变得容易了许多。对于是自通信还是相互通信,这个肯定是需要对寄存器进行必要的设置的,分析PIAE的两个程序后不难发现,自通信和互通信需要设置的知识模式寄存器,这个是在SJA1000的初始化时进行设定的。 本文引用地址:http://www.eepw.com.cn/article/268271.htm   SJA1000的初始化程序我根据习惯,直接把它独立成一个子程序了。如下,是工作于自通信时的初始化程序。   ///////////////////////////////////////////////   //函数:init_sja1000   //说明
[嵌入式]
单片机超声波测距模块学习笔记_发射端学习
超声波测距--发射端电路原理图如下: 示波器波形图如下: 绿色的波形是单片机产生的40KHz的方波 黄色的波形是经三极管放大后送入超声波发射头之前的波形。 51单片机产生方波的汇编指令 mov R6,#8h ;超声波发射的完整波形个数:共计四个 FB: cpl p2.7 ;输出40kHz方波 nop nop nop nop nop nop nop nop nop djnz R6,FB RET 等价的C语言
[单片机]
单片机超声波测距模块<font color='red'>学习</font><font color='red'>笔记</font>_发射端<font color='red'>学习</font>
基于STM32F407 HAL库的Flash编程操作
flash的初始化,解锁flash和清除一些flash的异常状态标识 uint16_t MEM_If_Init_FS(void) { HAL_FLASH_Unlock(); __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); } uint16_t MEM_If_DeInit_FS(void) { HAL_FLASH_Lock(); } flash
[单片机]
STM32NET学习笔记 UDP部分
1.前言 嵌入式以太网开发是一个很有挑战性的工作。通过几个月的学习,我个人觉得大致有两条途径。第一条途径,先通过高级语言熟悉socket编程,例如C#或C++,对bind,listen,connect,accept等函数熟悉之后,应用 lwIP。第二种途径,通过分析嵌入式以太网代码,结合TCPIP协议栈规范逐步实践代码。第一种途径效率高,开发周期短,编写出来的代码性能稳定,第二种途径花的时间长,开发出来的代码功能不完善,但是由于紧紧结合TCPIP规范,可以了解的内容较多,适合学习。本文通过分析和修改AVRNET源码,逐步实现TCPIP协议栈的各个子部分,包括ETHERNET部分,ARP部分,IP部分,ICMP部分,UDP部分
[单片机]
STM32学习笔记之USB工程目录文件分析
接下去要分别分析下这几个文件: hw_config.c: 这个文件主要是配置一些跟板载及系统相关的代码,比如说USB系统时钟配置,上拉电阻引脚及LED灯配置,还有USB的中断灯。主要的函数如下: void Set_System(void); /*设置系统时钟,USB 及LED引脚配置*/ void Set_USBClock(void); /*设置USB的时钟频率*/ void GPIO_AINConfig(void); /*设置GPIO模拟输入(这里是空函数)*/ void Enter_LowPowerMode(void); /*进入低功耗模式(这里是空函数)*/ void Leave_LowPowerMode(vo
[单片机]
STM32F429HAL库时钟系统学习笔记
F4的系统的时钟和F1基本相同,和F1 不同的就是锁相环倍频系数提高,就是系统时钟PLL的时钟频率高达180M(做完电赛控制组,感觉100M以下的单片机以后都不用再学了,图像处理完全做不了)。 HSI:系统内部告诉时钟16M; HSE:外部高速时钟这里我们一般叫外部晶振正点原子的开发板是25M输入范围是(4-26M) 我们以外部时钟源25M为例外部时钟经过PLL锁仙环(VCO:压控振荡器,这个是电压控制振荡频率的一个元器件没必要深究) 经过*N倍频在/P就得到我们想要的系统时钟频率了 系统时钟=外部晶振/M*N/P; 我们在来看HAL库的配置函数 RCC- CR |= (uint32_t)0x00000
[单片机]
TQ2440 学习笔记—— 14、GPIO 接口【实验:用C语言实现】
1、使用C语言代码点亮一个LED C 语言程序执行的第一条指令,并不在main函数中。生成一个C程序的可执行文件时,编译器通常会在我们的代码中加上几个被称为启动文件的代码——crtl.o、crti.o、crtend.o、crtn.o等,它们都是标准库文件。这些代码设置C程序的堆栈等,然后调用main函数。它们依赖于操作系统,在裸板上这些代码无法执行,所以需要自己写一个。 a、crt0.s 它在第 13行设置好栈指针后,就可以通过第15行调用C函数main 了。C 函数在执行前必须设置栈。 【注意】韦东山老师那本教材上面是有点错误的,比如WATCHDOG寄存器的地址就写成了0x56000010。 b、代码:
[单片机]
TQ2440 <font color='red'>学习</font><font color='red'>笔记</font>—— 14、GPIO 接口【实验:用C语言实现】
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved