目录
- 1、利用STM32CubeMX配置FreeRTOS
- 2、完成流水灯、按键、蜂鸣器数码管工作
- 1、在gpio.c和.h文件里面书写并声明按键扫描和led、数码管子程序
- 2、在freertos.c文件里面设置全局变量并且在各自任务中载入程序
- 3、关于FreeRTOS的注意事项
1、利用STM32CubeMX配置FreeRTOS
假设我们之前的配置引脚、配置定时器、配置时钟的步骤均已完成,现在开始导入FreeRTOS。
接下来为我们的程序配置四个任务,注意这里我们的三个任务的优先级是一样的。如果你设置了某一个任务的优先级高,那么程序运行时会一直运行那个任务而无法进入其他任务。
数码管的优先级设高,不然数码管的扫描如果受键码的解析的拖延会产生闪烁!(可以试着把优先级改为low,然后你就会发现按键按下的时候数码管会闪烁。)这个道理和中断优先级是一样的。具体可以看这篇文章:
关于优先级的一点问题思考
这里的function名字最好也修改成和task名字相对应,我这边是当时上课没注意。。。
最后导出文件即可。
2、完成流水灯、按键、蜂鸣器数码管工作
1、在gpio.c和.h文件里面书写并声明按键扫描和led、数码管子程序
void SetLeds(uint8_t sta)
{HAL_GPIO_WritePin(L1_GPIO_Port,L1_Pin,(sta & 0x01) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L2_GPIO_Port,L2_Pin,(sta & 0x02) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L3_GPIO_Port,L3_Pin,(sta & 0x04) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L4_GPIO_Port,L4_Pin,(sta & 0x08) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L5_GPIO_Port,L5_Pin,(sta & 0x10) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L6_GPIO_Port,L6_Pin,(sta & 0x20) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L7_GPIO_Port,L7_Pin,(sta & 0x40) ? GPIO_PIN_RESET:GPIO_PIN_SET);HAL_GPIO_WritePin(L8_GPIO_Port,L8_Pin,(sta & 0x80) ? GPIO_PIN_RESET:GPIO_PIN_SET);
}uint8_t KeyScan()
{uint8_t key = 0;if(HAL_GPIO_ReadPin(SW5_GPIO_Port,SW5_Pin) == GPIO_PIN_SET){key = 5;HAL_Delay(50);if(HAL_GPIO_ReadPin(SW5_GPIO_Port,SW5_Pin) == GPIO_PIN_SET)return key;elsereturn 0;}if(HAL_GPIO_ReadPin(SW6_GPIO_Port,SW6_Pin) == GPIO_PIN_SET){key = 6;HAL_Delay(50);if(HAL_GPIO_ReadPin(SW6_GPIO_Port,SW6_Pin) == GPIO_PIN_SET)return key;elsereturn 0;}if(HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET){key = 1;HAL_Delay(50);if(HAL_GPIO_ReadPin(SW1_GPIO_Port,SW1_Pin) == GPIO_PIN_RESET)return key;elsereturn 0;}if(HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET){key = 2;HAL_Delay(50);if(HAL_GPIO_ReadPin(SW2_GPIO_Port,SW2_Pin) == GPIO_PIN_RESET)return key;elsereturn 0;}if(HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET){key = 3;HAL_Delay(50);if(HAL_GPIO_ReadPin(SW3_GPIO_Port,SW3_Pin) == GPIO_PIN_RESET)return key;elsereturn 0;}if(HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET){key = 4;HAL_Delay(50);if(HAL_GPIO_ReadPin(SW4_GPIO_Port,SW4_Pin) == GPIO_PIN_RESET)return key;elsereturn 0;}return 0;
}
void Write595(uint8_t sel,uint8_t num,uint8_t bdot) //共阴数码管 '0'~'7' , '8'~'F'
{static const uint8_t TAB[16] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};//71HC138输出高电平,关掉数码管显示HAL_GPIO_WritePin(A3_GPIO_Port,A3_Pin,GPIO_PIN_RESET);uint8_t dat = TAB[num & 0x0F] |(bdot?0x80:0x00); //74HC595锁存8段数据for(uint8_t i=0;i<8;++i){HAL_GPIO_WritePin(SCK_GPIO_Port,SCK_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(SER_GPIO_Port,SER_Pin,(dat & 0x80)? GPIO_PIN_SET:GPIO_PIN_RESET);dat<<=1;HAL_GPIO_WritePin(SCK_GPIO_Port,SCK_Pin,GPIO_PIN_SET);}HAL_GPIO_WritePin(DISLK_GPIO_Port,DISLK_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(DISLK_GPIO_Port,DISLK_Pin,GPIO_PIN_SET);//74HC138译码,sel(0~3)对应4位片选信号输出HAL_GPIO_WritePin(A0_GPIO_Port,A0_Pin,(sel & 0x01) ? GPIO_PIN_SET:GPIO_PIN_RESET);HAL_GPIO_WritePin(A1_GPIO_Port,A1_Pin,(sel & 0x02) ? GPIO_PIN_SET:GPIO_PIN_RESET);HAL_GPIO_WritePin(A2_GPIO_Port,A2_Pin,GPIO_PIN_RESET);HAL_GPIO_WritePin(A3_GPIO_Port,A3_Pin,GPIO_PIN_SET);
}
2、在freertos.c文件里面设置全局变量并且在各自任务中载入程序
1、定义全局变量
2、四个任务依次对应着我们当初配置
1、流水灯任务
void StartDefaultTask(void *argument)
{/* USER CODE BEGIN StartDefaultTask *//* Infinite loop */for(;;){SetLeds(sta);osDelay(interval);if(run){if(sta < 0x80) sta<<=1;else sta = 0x01;}osDelay(100);}/* USER CODE END StartDefaultTask */
}
2、按键任务
void StartTask02(void *argument)
{/* USER CODE BEGIN StartTask02 *//* Infinite loop */for(;;){key=KeyScan();if(key!=0) seg[0]=key;if(key == 1) //start{run = 1;}if(key == 2){run = 0;}if(key == 3) //speed up{interval/=2;if(interval <= 100) interval=100;}if(key == 4) //speed down{interval*=2;if(interval >= 2000) interval=2000;}osDelay(100);}/* USER CODE END StartTask02 */
}
3、蜂鸣器任务
void StartTask03(void *argument)
{/* USER CODE BEGIN StartTask03 *//* Infinite loop */for(;;){beep_duty = key*100;TIM3->CCR1 = beep_duty;osDelay(100);}/* USER CODE END StartTask03 */
}
4、数码管任务
void StartTaskSEG(void *argument)
{/* USER CODE BEGIN StartTaskSEG *//* Infinite loop */for(;;){for(uint8_t i =0;i<4;i++){Write595(i,seg[i],0);osDelay(5);}osDelay(1);}/* USER CODE END StartTaskSEG */
}
3、关于FreeRTOS的注意事项
注意点:
1、每个任务函数中都要有延时delay
2、osdelay使当前任务挂起,当延时结束,又唤醒当前任务,相当于释放了cpu。
而HALdelay在延时中还是会占用cpu资源的。
3、时间戳可以在不使用delay的情况下得到当前时间
4、os函数都需要在任务函数中调用