用於微控制器程式設計的一種簡單的主函式框架
阿新 • • 發佈:2018-12-12
常見的微控制器最小系統(最小外圍電路)中,會帶有微控制器、晶振、LDO、按鍵、LED指示燈。假如是使用STM32,現在通常會配合STM32CubeMX,快速生成初始化程式碼和工程專案檔案。在生成了一套工程專案後,需要在檔案的特定位置加上使用者程式碼。
我對作業系統程式設計不熟悉,但需要把微控制器對外擴模組的操作程式編成任務,每個任務在一秒鐘內執行的次數不同。因此需要編個簡單的框架,控制每個任務的執行次數。
/* Private variables ---------------------------------------------------------*/ uint32_t counter_10ms, counter_50ms, counter_100ms, counter_500ms, counter_1000ms, counter_2000ms, counter_3s, counter_5s, counter_10s, counter_20s, counter_50s; uint8_t flag_1ms, flag_10ms, flag_50ms, flag_100ms, flag_500ms, flag_1000ms, flag_2000ms, flag_3s, flag_5s, flag_10s, flag_20s, flag_50s; int main(void) { //這裡執行初始化程式碼 /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { if(flag_1ms ==1) { LEDSoftTimer(b_LED1Freq, b_LED1Duty, b_LED2Freq, b_LED2Duty); flag_1ms = 0; if(flag_ADCbusy==RESET) { ADC_GetData(); flag_ADCbusy = SET; if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)a_ADCxConvertedValues, 2) != HAL_OK) { Error_Handler(); } } } if(flag_10ms==1) { flag_10ms=0; } if(flag_50ms==1) { flag_50ms=0; } if(flag_100ms==1) { flag_100ms=0; SerialDisplay(); } if(flag_500ms==1) { flag_500ms=0; } if(flag_1000ms==1) { flag_1000ms=0; sec++; if(sec>0xff) sec = 0; } if(flag_2000ms==1) { flag_2000ms=0; } if(flag_3s==1) { flag_3s=0; } if(flag_5s==1) { flag_5s=0; } if(flag_10s==1) { flag_10s=0; } if(flag_20s==1) { flag_20s=0; } if(flag_50s==1) { flag_50s=0; } } /* USER CODE END 3 */ } //然後在systick中更新時間計數器和相關flag的值,systick中斷由CPU定時器生成,每1ms中斷一次 void HAL_SYSTICK_Callback(void) { flag_1ms = 1; /*update counters*/ if(counter_10ms<9) { counter_10ms++; } else { counter_10ms = 0; flag_10ms = 1; } if(counter_50ms<49) { counter_50ms++; } else { counter_50ms = 0; flag_50ms = 1; } if(counter_100ms<99) { counter_100ms++; } else { counter_100ms = 0; flag_100ms = 1; if(counter_500ms<4) { counter_500ms++; } else { counter_500ms = 0; flag_500ms = 1; } if(counter_1000ms<9) { counter_1000ms++; } else { counter_1000ms = 0; flag_1000ms = 1; UpdateDateTime(); if(counter_3s < 2) { counter_3s++; } else { counter_3s = 0; flag_3s = 1; } if(counter_5s < 4) { counter_5s++; } else { counter_5s = 0; flag_5s = 1; } if(counter_10s < 9) { counter_10s++; } else { counter_10s = 0; flag_10s = 1; } } if(counter_2000ms<19) { counter_2000ms++; } else { counter_2000ms = 0; flag_2000ms = 1; } } }
上面的程式中,每1ms執行一次ADC取樣。還有每100ms執行一次程式把資料傳輸到上位機顯示。直接把上面的程式碼複製到STM32CubeMX生成的專案檔案,即可快速的分配CPU運算資源。
另外,最簡單的狀態機程式設計結構如下。
本例子用STM32和NodeMCU通訊,驅動NodeMCU和手機連線,並通過TCP協議把一句句的資訊傳輸到手機。
void Proc_NodeMCU(void) { uint8_t CIPSEND_CustomSize[2]; uint8_t NodeMCU_ACK_res; if(Status_NodeMCU == 1) { 清空UART接收資料 傳送AT指令 採用阻塞,超時的方式檢查NodeMCU有沒回傳"OK\r\n"字元, 如果收到"OK\r\n": Status_NodeMCU=2;且flag_ProcNodeMCUActive=1;代表NodeMCU程式有效 否則無NodeMCU連線 } else if(Status_NodeMCU == 2) { 清空UART接收資料 傳送AT指令配置成STATION模式 採用阻塞,超時的方式檢查NodeMCU有沒回傳"OK\r\n"字元, 如果收到"OK\r\n": Status_NodeMCU=3; } else if(Status_NodeMCU == 3) { 清空UART接收資料 傳送AT指令,控制NodeMCU連線AP 採用阻塞,超時的方式檢查NodeMCU有沒回傳"OK\r\n"字元, 如果收到"OK\r\n": Status_NodeMCU=4; } else if(Status_NodeMCU == 4) { 清空UART接收資料 傳送AT指令,NodeMCU和手機建立TCP連線 處理回傳資料 如果正常:Status_NodeMCU=10; } else if(Status_NodeMCU == 10) { 清空UART接收資料 傳送AT指令,控制NodeMCU進入資料透傳模式,併發送資訊包至手機 處理回傳資料 如果正常:Status_NodeMCU=11; 如果不正常:Status_NodeMCU=4;將重新連線 } else if(Status_NodeMCU == 11) { 清空UART接收資料 傳送AT指令控制NodeMCU進入低功率傳送模式,減少射頻干擾和功耗 Status_NodeMCU = 10;下次執行本程式可省去連線部分,直接控制NodeMCU進入資料透傳模式 本次傳送資料完成,flag_ProcNodeMCUActive=0; } else { Status_NodeMCU = 1; } }
還有一種狀態機寫法,