電子愛好者應該不會對「上位機」這個詞感到陌生,畢竟或多或少有過接觸。但如果說到上位機的開發的話,你們就不必定熟悉了。不少電子愛好者徹底沒有接觸過上位機的開發工做,他們真的沒有相應的需求嗎?不,究其緣由,國內相關開發資料和例子不足,因此初學者在學習過程當中幾乎不會接觸到相關內容。html
近來恰好手上有個小東西須要作個上位機,在C#、Matlab、QT、Labview之間徘徊許久以後最終選擇了Python,繼而瞭解了一些相關知識,在此分享一些我整理的經驗,但願可以幫助後來者。python
Python做爲一種腳本語言,一大優點就是能夠方便地調用各類各樣的庫。好比,可使用Qt的一些組件,在Python中調用Qt~~~~能夠參考這個官方示例。git
例子裏面的核心代碼以下:json
@Slot() def say_hello(): print("Button clicked, Hello!") # Create the Qt Application app = QApplication(sys.argv) # Create a button, connect it and show it button = QPushButton("Click me") button.clicked.connect(say_hello) button.show() # Run the main Qt loop app.exec_()
首先,定義了一個函數say_hello來打印輸出信息,「@Slot()」是一個裝飾器,代表該函數是一個「槽」,對此概念不瞭解的童鞋須要補一點QT的知識。而後,建立了一個QT應用、建立了一個按鈕控件、將函數say_hello鏈接到按鍵、顯示按鈕控件,最後,啓動QT主循環。segmentfault
建立應用和啓動主循環能夠說是調用QT組件的「套路」,關於button的操做則示範了一個操做空間的大概流程。此外,做爲按鈕控件,say_hello能夠理解爲button的「事件函數」,每發生一次按鈕按下的事件,函數就被執行一次。數組
基於官方的demo,咱們能夠進行一些修改來建立本身的應用。固然,首先要明確需求,咱們的上位機應當可以對下位機進行控制,就以LED的控制爲例子把,上位機具備一個按鍵,按一下板載LED(單個)亮起,再按一下熄滅,同時,按鍵上最好可以經過顏色或文字顯示LED當前的狀態。併發
咱們把槽函數修改以下:app
led = "ON" # @Slot()是一個裝飾器,標誌着這個函數是一個slot(槽) @Slot() def led_toggle(): '''按下按鈕,翻轉LED狀態''' global led if led == "ON": led = "OFF" button.setText("LED OFF!") else : led = "ON" button.setText("LED ON!") print(led)
在定義函數前咱們建立了一個叫led的字符串並指向「ON」,在函數內部咱們聲明led爲全局的(python默認指定爲局部變量),並對led的內容進行判斷,若是其指向的內容爲「ON」,修改它以指向「OFF」,並經過setText這一方法設置按鍵上的文字爲「LED OFF!」。不爲「ON」時的操做基本也是這樣。函數
修改以後demo的運行效果以下:(按下後變爲LED ON!/LED OFF!)oop
修改後的demo的完整代碼在這裏
在單片機上,串口是極經常使用的通訊接口,上位機對單片機的控制能夠基於串口來進行,python中控制串口須要使用serial庫。
serial庫下的Serial方法能夠建立並返回一個串口對象,使用的例子以下:
ser = serial.Serial('COm10',115200,timeout=0.5) #打開指定串口
該方法默認設置數據爲「8N1」格式,通常指定com口、波特率和超時時間(單位:ms)便可。
(com端口本身開設備管理器看)
有了串口對象就能夠發數據了,寫入的例子以下:
ser.write(b"hello serial!")
b表示將字符串以字節(bytes)形式編碼併發送。
json是一種經常使用的、跨平臺的數據交換格式,對於咱們這個「控制一個LED的亮滅」的需求,使用一個鍵值對就能夠解決。
例如,咱們首先建立一個data_on來存源數據。
data_on = { 'led' : 0 }
關於值的意義,咱們能夠規定0表示LED亮、1表示LED滅。
而後,把源數據打包爲json字符串。
json_led_on = json.dumps(data_on, sort_keys=True, separators=(',', ':'))
相似的,能夠建立一個內容爲「{"LED":1}」的json字符串。
串口發送json的測試用例在這裏
雖說咱們已經可以經過串口發數據了,可是本身指定串口號仍是有些麻煩,這裏提供一個搜索並返回可用串口列表的程序。
加上這個,再合併一下代碼,咱們控制LED的簡易上位機就完成了,代碼在這裏。
固然,下位機還等着寫呢。
在這篇文章中,我對在Keil裏面使用jansson庫處理JSON的方法進行了一些講解,此次的使用沒有超過原來的範圍,不贅述了。
核心業務部分的代碼以下:
void Task_LEDControl() { uint16_t len = 0; int led = 0; char json_RX_buffer[400] = {'\0'}; json_t *led_raw; json_error_t error; if(usart1_rx_ok == 1) { usart1_rx_ok = 0; len = usart1_rx_count; usart1_rx_count = 0; for(uint16_t i=0;i<len;i++) { json_RX_buffer[i] = usart1_rx_buffer[i]; } led_raw = json_loads(json_RX_buffer, JSON_ENCODE_ANY, &error); json_unpack(led_raw,"{s:i}","led",&led); if(led == 0) { Board_LED_ON(); printf("led on!\n"); } else { Board_LED_OFF(); printf("led off!\n"); } json_delete(led_raw); //刪除json對象 memset(json_RX_buffer,0x00,sizeof(json_RX_buffer)); //清空數組 } }
完整工程在這裏
最終的演示效果以下:
(PS. 因爲做者水平有限,再加上編寫時儘可能追求「新手友好」而不是代碼量或效率的最優,因此不少地方可能並不簡潔優雅,這一點還請原諒)