电子爱好者应该不会对“上位机”这个词感到陌生,毕竟或多或少有过接触。但如果说到上位机的开发的话,你们就不必定熟悉了。不少电子爱好者彻底没有接触过上位机的开发工做,他们真的没有相应的需求吗?不,究其缘由,国内相关开发资料和例子不足,因此初学者在学习过程当中几乎不会接触到相关内容。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. 因为做者水平有限,再加上编写时尽可能追求“新手友好”而不是代码量或效率的最优,因此不少地方可能并不简洁优雅,这一点还请原谅)