目錄
- 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函數都需要在任務函數中調用