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

系列文章目录

【STM32】HAL库 新建MDK工程

【STM32】HAL库 串口轮询发送

【STM32】HAL库 LED闪烁、流水灯

【STM32】HAL库 定时器中断

【STM32】HAL库 外部中断

文章目录

  • 系列文章目录
  • 前言
  • 一、STM32CubeMX设置
    • 选择芯片
    • 配置系统时钟
    • GPIO
    • 定时器
    • 串口
    • FreeRTOS设置
      • 中断
      • 设置堆空间
      • Config parameters
      • Include parameters
      • 互斥量
      • 事件
      • 任务
      • 队列
      • 软件定时器
      • 二值信号量
      • 计数信号量
    • 工程设置
  • 二、代码
    • LED闪烁
    • 串口
    • 按键扫描
    • 定时器
    • FreeRTOSConfig.h


前言

使用STM32F103C8T6开发板,用STM32CubeMX配置FreeRTOS,可以适配正点原子FreeRTOS所有实验的基础工程

一、STM32CubeMX设置

选择芯片

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第1张图片
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第2张图片

配置系统时钟

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第3张图片
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第4张图片

HAL的时基不能选择系统定时器
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第5张图片

GPIO

PA0和PA1输出模式,驱动两个LED灯。
PB4、PB6和PB11输入模式,PB1外部中断下降沿触发,全部上拉,检测按键。
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第6张图片

定时器

定时器2和定时器3的周期设置为1秒
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第7张图片
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第8张图片

定时器4,设置为1000Hz的10到100倍,100倍为100000Hz。用于测任务运行时间。
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第9张图片

串口

用于打印信息
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第10张图片

FreeRTOS设置

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第11张图片

中断

把定时器3优先级改为6,生成工程文件后,再将定时器2优先级改为4。
定时器1优先级改为最高,可以在任务中使用HAL_Delay代替正点原子的delay_ms
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第12张图片

设置堆空间

这款芯片的RAM空间为20k,可以设置堆空间为10k
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第13张图片

Config parameters

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第14张图片

Include parameters

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第15张图片

互斥量

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第16张图片

事件

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第17张图片

任务

给它们设置不同的优先级
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第18张图片

队列

按键队列和大数据队列
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第19张图片

软件定时器

单次和周期
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第20张图片

二值信号量

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第21张图片

计数信号量

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第22张图片

工程设置

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第23张图片
【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第24张图片

二、代码

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

串口

【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子_第25张图片

#include 

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

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

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,用于任务运行时间统计

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,嵌入式硬件,单片机)