【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设置

    选择芯片


    配置系统时钟


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

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

    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 */
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 【STM32】使用CubeMX快速创建FreeRTOS的基础工程,基于正点原子

    发表评论