最近接触了FreeRTOS,基本看完FreeRTOS的语法知识点,终于可以动手实践了。第一篇,先实现 LED与按键扫描的移植。
功能:LED1周期性闪烁(300ms),LED0在按键按下后改变亮灭状态一次。
平台:STM32F767IGT6
PART1: main.c —— 调用系统初始化、任务创建、开启任务调度
#include "mytask.h"
#include "init.h"
TaskHandle_t LED_TaskHandler;
TaskHandle_t KEY_TaskHandler;
int main()
{
//系统初始化
SYS_Init();
//创建任务LED_Task, 是一个死循环的函数
//名称 LED_Task, 任意名称都可以,调试是方便知道函数名
//分配内存 256 Words, 注意单位不是 Byte
//传入LED_Task() 函数的参数,此处为 0,
//优先级 1, 优先级从低到高,同等情况下优先级越高越先执行
//任务句柄 LED_TaskHandler,用于任务删除、挂起等
xTaskCreate(LED_Task, "LED_Task", 256, (void*)0, 1, &LED_TaskHandler);
//创建任务KEY_Task, 名称 KEY_Task, 分配内存 256Word,传入参数 空,优先级 2,任务句柄 KEY_TaskHandler
xTaskCreate(KEY_Task, "KEY_Task", 256, NULL, 2, &KEY_TaskHandler);
//开始任务调度
vTaskStartScheduler();
}
PART2:init.h 与 init.c —— 实现IO口、时钟等初始化
init.h
#ifndef _INIT_H
#define _INIT_H
#include "sys.h"
#define LED_PIN GPIO_PIN_0 | GPIO_PIN_1
#define LED_PORT GPIOB
#define LED_CLK_EN() __HAL_RCC_GPIOB_CLK_ENABLE()
#define LED_Toggle(x) (HAL_GPIO_TogglePin(LED_PORT, GPIO_PIN_0+x)) //LED翻转 x=0 -- LED0; x=1 -- LED1
#define Get_KEY0() HAL_GPIO_ReadPin(LED_PORT, GPIO_PIN_3) //读取KEY0状态
#define KEY_PIN GPIO_PIN_3
#define KEY_PORT GPIOH
#define KEY_CLK_EN() __HAL_RCC_GPIOH_CLK_ENABLE();
void LED_Init(void);
void KEY_Init(void);
void SYS_Init(void);
#endif
init.c
#include "init.h"
//LED 硬件初始化
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
LED_CLK_EN();
GPIO_Initure.Pin = LED_PIN;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull = GPIO_PULLUP; //上拉
GPIO_Initure.Speed = GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(LED_PORT, &GPIO_Initure);
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET);
}
//KEY 硬件初始化
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
KEY_CLK_EN(); //开启时钟
GPIO_Initure.Pin = KEY_PIN;
GPIO_Initure.Mode = GPIO_MODE_INPUT; //输入
GPIO_Initure.Pull = GPIO_PULLUP; //上拉
GPIO_Initure.Speed = GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(KEY_PORT, &GPIO_Initure);
}
//系统初始化
void SYS_Init(void)
{
Cache_Enable(); //打开L1-Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz
LED_Init(); //初始化LED
KEY_Init(); //初始化KEY
}
PART3: 具体的任务函数 mytask.h 与 mytask.c
mytask.h
#ifndef _TASK_H
#define _TASK_H
#include "sys.h"
#include "init.h"
#include "FreeRTOS.h"
#include "task.h"
void LED_Task(void *pvParameters);
void KEY_Task(void *pvParameters);
#endif
mytask.c
#include "mytask.h"
#include "init.h"
//LED任务:LED1闪烁,间隔 300ms
void LED_Task(void *pvParameters)
{
while(1) //操作系统都有的无限循环
{
LED_Toggle(0);
vTaskDelay(300); //已经将系统心跳设置为1ms,故300 即300ms
}
}
//KEY任务:按下KEY0,LED0闪烁一次
void KEY_Task(void *pvParameters)
{
u8 key=1;
while(1)
{
key = Get_KEY0(); //KEY0,低电平有效,按下为0
vTaskDelay(20); //消抖
key = Get_KEY0();
if(key == 0)
{
LED_Toggle(1);
vTaskDelay(500); //保持当前状态0.5s
}
}
}
以上就是FreeRTOS实现LED 亮灭闪烁和按键扫描。操作系统实现的是任务管理,但是并没有改变硬件初始化,硬件要实现的功能流程。
对于小白,第一次自己实现这个已经有点沾沾自喜了,下次继续努力深入。