【教程】簡易Python上位機之LED控制

  電子愛好者應該不會對「上位機」這個詞感到陌生,畢竟或多或少有過接觸。但如果說到上位機的開發的話,你們就不必定熟悉了。不少電子愛好者徹底沒有接觸過上位機的開發工做,他們真的沒有相應的需求嗎?不,究其緣由,國內相關開發資料和例子不足,因此初學者在學習過程當中幾乎不會接觸到相關內容。html

  近來恰好手上有個小東西須要作個上位機,在C#、Matlab、QT、Labview之間徘徊許久以後最終選擇了Python,繼而瞭解了一些相關知識,在此分享一些我整理的經驗,但願可以幫助後來者。python

從一個按鍵開始

一個簡單的demo

  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當前的狀態。併發

改造demo

  咱們把槽函數修改以下: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

P1.jpg

  修改後的demo的完整代碼在這裏

創建橋樑——串口和JSON

serial庫的簡單使用

  在單片機上,串口是極經常使用的通訊接口,上位機對單片機的控制能夠基於串口來進行,python中控制串口須要使用serial庫。

  serial庫下的Serial方法能夠建立並返回一個串口對象,使用的例子以下:

ser = serial.Serial('COm10',115200,timeout=0.5) #打開指定串口

  該方法默認設置數據爲「8N1」格式,通常指定com口、波特率和超時時間(單位:ms)便可。

  (com端口本身開設備管理器看)

  有了串口對象就能夠發數據了,寫入的例子以下:

ser.write(b"hello serial!")

  b表示將字符串以字節(bytes)形式編碼併發送。

json庫的簡單使用

  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)); //清空數組
    }
}

  完整工程在這裏

  最終的演示效果以下:

demo演示.gif

(PS. 因爲做者水平有限,再加上編寫時儘可能追求「新手友好」而不是代碼量或效率的最優,因此不少地方可能並不簡潔優雅,這一點還請原諒)

相關文章
相關標籤/搜索