系列文章目录
【STM32】HAL库 新建MDK工程
【STM32】HAL库 串口轮询发送
【STM32】HAL库 LED闪烁、流水灯
【STM32】HAL库 定时器中断
【STM32】HAL库 外部中断
前言
使用STM32F103C8T6开发板,用STM32CubeMX配置FreeRTOS,可以适配正点原子FreeRTOS所有实验的基础工程
一、STM32CubeMX设置
选择芯片
配置系统时钟
HAL的时基不能选择系统定时器
GPIO
PA0和PA1输出模式,驱动两个LED灯。
PB4、PB6和PB11输入模式,PB1外部中断下降沿触发,全部上拉,检测按键。
定时器
定时器2和定时器3的周期设置为1秒
定时器4,设置为1000Hz的10到100倍,100倍为100000Hz。用于测任务运行时间。
串口
用于打印信息
FreeRTOS设置
中断
把定时器3优先级改为6,生成工程文件后,再将定时器2优先级改为4。
定时器1优先级改为最高,可以在任务中使用HAL_Delay代替正点原子的delay_ms
设置堆空间
这款芯片的RAM空间为20k,可以设置堆空间为10k
Config parameters
Include parameters
互斥量
事件
任务
给它们设置不同的优先级
队列
按键队列和大数据队列
软件定时器
单次和周期
二值信号量
计数信号量
工程设置
二、代码
LED闪烁
void LED0_TOGGLE(void)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);
}
void LED1_TOGGLE(void)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
}
void task1(void *argument)
{
/* USER CODE BEGIN task1 */
/* Infinite loop */
for(;;)
{
LED0_TOGGLE();
osDelay(500);
}
/* USER CODE END task1 */
}
void task2(void *argument)
{
/* USER CODE BEGIN task2 */
/* Infinite loop */
for(;;)
{
LED1_TOGGLE();
osDelay(500);
}
/* USER CODE END task2 */
}
串口
#include <stdio.h>
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t*)&ch ,1,1000);
return (ch);
}
void task1(void *argument)
{
/* USER CODE BEGIN task1 */
/* Infinite loop */
uint32_t task1_num = 0;
for(;;)
{
printf("task1_num:%d\r\n",++task1_num);
LED0_TOGGLE();
osDelay(500);
}
/* USER CODE END task1 */
}
void task2(void *argument)
{
/* USER CODE BEGIN task2 */
/* Infinite loop */
uint32_t task2_num = 0;
for(;;)
{
printf("task2_num:%d\r\n",++task2_num);
LED1_TOGGLE();
osDelay(500);
}
/* USER CODE END task2 */
}
按键扫描
uint8_t key_scan(uint8_t mode);
#define KEY0 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)
#define KEY1 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)
#define KEY2 HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)
#define WK_UP HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_11)
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
#define WKUP_PRES 4
uint8_t key_scan(uint8_t mode)
{
static uint8_t key_up = 1;
uint8_t keyval = 0;
if (mode) key_up = 1;
if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 0))
{
HAL_Delay (10);
key_up = 0;
if (KEY0 == 0) keyval = KEY0_PRES;
if (KEY1 == 0) keyval = KEY1_PRES;
if (KEY2 == 0) keyval = KEY2_PRES;
if (WK_UP == 0) keyval = WKUP_PRES;
}
else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 1)
{
key_up = 1;
}
return keyval;
}
void task3(void *argument)
{
/* USER CODE BEGIN task3 */
/* Infinite loop */
uint8_t key = 0;
for(;;)
{
key = key_scan(0);
if(key) printf("key = %d\r\n",key);
osDelay(10);
}
/* USER CODE END task3 */
}
定时器
修改定时器2的优先级
HAL_NVIC_SetPriority(TIM2_IRQn, 4, 0);
打开定时器中断
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
定时器回调函数,打印定时器的优先级文章来源:https://www.toymoban.com/news/detail-825183.html
uint32_t FreeRTOSRunTimeTicks;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
uint32_t preemptPriority, subPriority;
/* USER CODE END Callback 0 */
if (htim->Instance == TIM1) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
if (htim->Instance == TIM2) {
HAL_NVIC_GetPriority(TIM2_IRQn, NVIC_PRIORITYGROUP_4, &preemptPriority, &subPriority);
printf("TIM2_Priority:%d\r\n",preemptPriority);
}
if (htim->Instance == TIM3) {
HAL_NVIC_GetPriority(TIM3_IRQn, NVIC_PRIORITYGROUP_4, &preemptPriority, &subPriority);
printf("TIM3_Priority:%d\r\n",preemptPriority);
}
if (htim->Instance == TIM4) {
FreeRTOSRunTimeTicks++;
}
/* USER CODE END Callback 1 */
}
开启定时器4,用于任务运行时间统计文章来源地址https://www.toymoban.com/news/detail-825183.html
void configureTimerForRunTimeStats(void)
{
HAL_TIM_Base_Start_IT(&htim4);
}
unsigned long getRunTimeCounterValue(void)
{
return FreeRTOSRunTimeTicks;
}
FreeRTOSConfig.h
#define configUSE_QUEUE_SETS 1 /* 1: 使能队列集, 默认: 0 */
到了这里,关于【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!