当前位置:   article > 正文

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_stm32cubemx freertos

stm32cubemx freertos

系列文章目录

【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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
void task1(void *argument)
{
  /* USER CODE BEGIN task1 */
  /* Infinite loop */
  for(;;)
  {
		LED0_TOGGLE();
    	osDelay(500); 
  }
  /* USER CODE END task1 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
void task2(void *argument)
{
  /* USER CODE BEGIN task2 */
  /* Infinite loop */
  for(;;)
  {
		LED1_TOGGLE();
    	osDelay(500); 
  }
  /* USER CODE END task2 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

串口

在这里插入图片描述

#include <stdio.h>

int fputc(int ch, FILE  *f)
{
	HAL_UART_Transmit(&huart1, (uint8_t*)&ch ,1,1000);
	return (ch);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
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 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
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 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

按键扫描

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    

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
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;              
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
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 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

定时器

修改定时器2的优先级

   HAL_NVIC_SetPriority(TIM2_IRQn, 4, 0);
  • 1

打开定时器中断

	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_Base_Start_IT(&htim3);
  • 1
  • 2

定时器回调函数,打印定时器的优先级

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 */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

开启定时器4,用于任务运行时间统计

void configureTimerForRunTimeStats(void)
{
	HAL_TIM_Base_Start_IT(&htim4);
}

unsigned long getRunTimeCounterValue(void)
{
	return FreeRTOSRunTimeTicks;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

FreeRTOSConfig.h

#define configUSE_QUEUE_SETS                            1                       /* 1: 使能队列集, 默认: 0 */
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/457871
推荐阅读
相关标签
  

闽ICP备14008679号