介绍在树莓派上使用串口进行数据收发。开发环境依然使用之前介绍的PyCharm编写python代码和远程开发,然后使用QtCreator编写QML的GUI界面。
1、新建项目 1.1、新建工程 打开PyCharm,新建工程serialTesting,如下:
1.2、添加python主程序 serialTesting.py 主程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 import osimport sysfrom pathlib import Pathimport serialimport threadingfrom PySide2 import QtCorefrom PySide2.QtCore import Qt, QObject, Slotfrom PySide2.QtQml import QQmlApplicationEnginefrom PySide2.QtWidgets import QApplicationmserial1 = serial.Serial('/dev/ttyAMA1' ,115200 ) mserial2 = serial.Serial('/dev/ttyAMA2' ,115200 ) def Serial1Reading (): while True : while mserial1.inWaiting() > 0 : s = mserial1.read(mserial1.inWaiting()) s = s.decode() if s != "" : print ("serial1 recv:" , s) controler.uart1sig.emit(s) def Serial2Reading (): while True : while mserial2.inWaiting()>0 : s = mserial2.read(mserial2.inWaiting()) s = s.decode() if s != "" : print ("serail2 recv:" ,s) controler.uart2sig.emit(s) thread1 = threading.Thread(target=Serial1Reading) thread2 = threading.Thread(target=Serial2Reading) class Controler (QObject ): uart1sig = QtCore.Signal(str ) uart2sig = QtCore.Signal(str ) def __init__ (self ): super ().__init__() @Slot() def exit (self ): sys.exit() @Slot(str ) def uart1send (self,s ): print ("uart1 send:" ,s) if mserial1.isOpen(): mserial1.write(str (s).encode()) @Slot(str ) def uart2send (self,s ): print ("uart2 send:" ,s) if mserial2.isOpen(): mserial2.write(str (s).encode()) if __name__=='__main__' : os.environ["QT_IM_MODULE" ] = "qtvirtualkeyboard" a = QApplication(sys.argv) a.setOverrideCursor(Qt.BlankCursor) engine = QQmlApplicationEngine() controler = Controler() context = engine.rootContext() context.setContextProperty("_Controler" , controler) engine.load(os.fspath(Path(__file__).resolve().parent / "ui/main.qml" )) if not engine.rootObjects(): sys.exit(-1 ) root = engine.rootObjects()[0 ] controler.uart1sig.connect(root.uart1ReadyRead) controler.uart2sig.connect(root.uart2ReadyRead) thread1.daemon=True thread2.daemon=True thread1.start() thread2.start() sys.exit(a.exec_())
程序中建立了一个Controler类用于和qml界面进行交互,这样就可以通过界面来进行串口数据的发送和显示接收到的数据;
Controler类中有两个信号和两个槽函数分别用于串口数据的接收和串口数据的发送功能;
建立了两个线程来进行串口数据读取,当有串口数据到来就通过信号槽方式,将数据显示到界面;
1.3、添加界面文件
在项目中添加ui文件夹,并新建main.qml文件,然后使用QtCreator来编写界面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 import QtQuick 2.11 import QtQuick.Window 2.4 import QtQuick.Controls 2.4 import QtQuick.Controls .Styles 1.4 import QtQuick.Extras 1.4 import QtGraphicalEffects 1.0 import QtQuick.VirtualKeyboard 2.1 import QtQuick.VirtualKeyboard .Settings 2.1 ApplicationWindow{ id:root width : 800 height: 480 visible: true visibility: Window.FullScreen function uart1ReadyRead (string){ // console.log ("uart1 recv:",string) uart1recv.append(string) } function uart2ReadyRead(string){ // console.log(" uart2 recv:",string) uart2recv.append(string) } background: Rectangle{ color: " black" anchors.fill: parent } Button{ id:btnexit background: Rectangle{ color: " #a01010 " anchors.fill: parent radius:12 } width: 48 height: 48 anchors{ top: parent.top right: parent.right topMargin: 8 rightMargin: 8 } Text { text: qsTr(" X") anchors.centerIn: parent font{ pointSize: 32 } color: " white" } onClicked: { _Controler.exit(); } } Text { id: title text: qsTr(" Serial Testing") anchors{ top: parent.top horizontalCenter: parent.horizontalCenter topMargin: 20 } font{ pointSize: 24 } color: " #a0a0a0 " } TextField { id: uart1send width: 200 font.pointSize: 12 placeholderText: qsTr(" uart1 send text") anchors{ top: title.bottom left: parent.left topMargin: 20 leftMargin: 30 } color: " #DBD6D6 " background: Rectangle{ anchors.fill: parent color: " #303030 " } } Button{ id:btnsend text: " Send" width: 100 height: uart1send.height anchors{ left: uart1send.right leftMargin: 40 top: uart1send.top } background: Rectangle{ anchors.fill: parent color: btnsend.pressed ? " #216CB8 " : " #a0a0a0 " radius: 10 } font.pixelSize: 20 font.bold: true onClicked: { _Controler.uart1send(uart1send.text) } } TextArea{ id:uart1recv width: 360 height: 320 anchors{ top: uart1send.bottom topMargin: 10 left: parent.left leftMargin: 20 } font.pointSize: 12 color: " #20a0a0 " background: Rectangle{ anchors.fill: parent color: " #202020 " } } TextField { id: uart2send width: 200 font.pointSize: 12 placeholderText: qsTr(" uart2 send text") anchors{ top: title.bottom right: btn2send.left topMargin: 20 rightMargin: 20 } color: " #DBD6D6 " background: Rectangle{ anchors.fill: parent color: " #303030 " } } Button{ id:btn2send text: " Send" width: 100 height: uart2send.height anchors{ right: parent.right rightMargin: 30 leftMargin: 40 top: uart1send.top } background: Rectangle{ anchors.fill: parent color: btn2send.pressed ? " #216CB8 " : " #a0a0a0 " radius: 10 } font.pixelSize: 20 font.bold: true onClicked: { _Controler.uart2send(uart2send.text) } } TextArea{ id:uart2recv width: 360 height: 320 anchors{ top: btn2send.bottom topMargin: 10 right: parent.right rightMargin: 20 } font.pointSize: 12 color: " #a020b0 " background: Rectangle{ anchors.fill: parent color: " #202020 " } } InputPanel { id: inputPanel z: 99 x: 50 y: parent.height width: parent.width-100 states: State { name: " visible" when: inputPanel.active PropertyChanges { target: inputPanel y: parent.height - inputPanel.height } } transitions: Transition { from: " " to: " visible" reversible: true ParallelAnimation { NumberAnimation { properties: " y" duration: 250 easing.type: Easing.InQuart } } } } } /*##^## Designer { D{i:0;formeditorZoom:0.75;height:480;width:800} } ##^##*/
界面完成后如下图:
界面中主要建立了两个发送和接收窗口,然后可以测试向对方发送数据和数据的接收显示。
2、执行程序 2.1、上传程序到树莓派 在工程上右键将这个项目文件上传到树莓派中。
2.2、执行程序 上传后,在树莓派对应文件夹中,执行如下命令执行程序:
1 python3 serialTesting.py
执行后可以看到显示如下: 然后可以在输入框中分别输入数据,然后点击“Send”发送,这样就可以测试串口1和串口2间数据的发送和接收: