開源精選》是我們分享Github、Gitee等開源社區中優質項目的欄目,包括技術、學習、實用與各種有趣的內容。本期推薦的是一個功能強大的串口工具。支持Lua自動化處理、串口調試、串口監聽、串口曲線、TCP測試、MQTT測試、編碼轉換、亂碼恢復等功能。
使用Lua腳本提前處理待發送的數據
return uartData.."\r\n"
return uartData:fromHex()
此腳本可將形如30313233發送數據,處理為0123的結果
json = require("JSON")
t = uartData:split(",")
return json:encode({
key1 = t[1],
key2 = t[2],
key3 = t[3],
})
此腳本可將形如a,b,c發送數據,處理為{"key1":"a","key2":"b","key3":"c"}的結果。
獨立的Lua腳本自動處理串口收發
右側的Lua腳本調試區域,可直接運行你寫的串口測試腳本,如軟件自帶的:
--注冊串口接收函數
uartReceive = function (data)
log.info("uartReceive",data)
sys.publish("UART",data)--發布消息
end
--新建任務,等待接收到消息再繼續運行
sys.taskInit(function()
while true do
local _,udata = sys.waitUntil("UART")--等待消息
log.info("task waitUntil",udata)
local sendResult = apiSendUartData("ok!")--發送串口消息
log.info("uart send",sendResult)
end
end)
--新建任務,每休眠1000ms繼續一次
sys.taskInit(function()
while true do
sys.wait(1000)--等待1000ms
log.info("task wait",os.time())
end
end)
--1000ms循環定時器
sys.timerLoopStart(log.info,1000,"timer test")
甚至你可以利用xlua框架的特性,調用C#接口完成任何你想做的事情
request = CS.System.Net.WebRequest.Create("http://example.com")
request.ContentType = "text/html;charset=UTF-8";
request.Timeout = 5000;--超時時間
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 Vivaldi/2.2.1388.37";
response = request:GetResponse():GetResponseStream()
myStreamReader = CS.System.IO.StreamReader(response, CS.System.Text.Encoding.UTF8);
print(myStreamReader:ReadToEnd())--打印獲取的body內容
myStreamReader:Close()
response:Close()
使用此功能,你可以完成大部分的自動化串口調試操作。
-END-
開源協議:Apache-2.0
開源地址:https://gitee.com/chenxuuu/llcom
本篇介紹ESP32上通過MicroPython實現串口數據的收發。
ESP32 小板:
Micro USB線:
USB轉TTL:
1) PC端Wndows系統,Python 2.7環境 或者 Python 3.4以及更新的版本
2) 板子上Micropython 環境
將板子G12引腳和USB轉TTL的RXD引腳短接
將板子G13引腳和USB轉TTL的TXD引腳短接
將板子GND引腳和USB轉TTL的GND引腳短接
代碼如下:
from machine import UART,Pin
uart = UART(2, baudrate=115200, rx=13,tx=12,timeout=10)
uart.write("ESP32 uart send example!\r\n")
運行結果如下,
完成的功能即:ESP32通過串口發送數據給USB轉TTL
代碼如下:
from machine import UART,Pin
uart = UART(2, baudrate=115200, rx=13,tx=12,timeout=10)
while True:
if uart.any():
rev_data = uart.read()
print(rev_data)
結果如下:在左側窗口里發送什么,右側窗口就會接收到什么。
完成的功能即:USB轉TLL通過串口發送數據給ESP32
如果改為:
from machine import UART,Pin
uart = UART(2, baudrate=115200, rx=13,tx=12,timeout=10)
while True:
if uart.any():
rev_data = uart.read()
print(rev_data.decode())
結果如下:
兩者的輸出結果有差異,這里涉及到Python中bytes和str兩種數據類型的問題,readline函數的返回值是bytes類型。
strings可以被編碼(encode)成字bytes,bytes也可以解碼(decode)成strings
更多關于UART使用可以參考:docs.micropython.org/en/latest/library/machine.UART.html
cirmall.com/bbs/thread-102657-1-1.html 這里有個自發自收的例子,將G12和G13短接在一起。
運行結果如下:
使用上一篇介紹的通過 ampy --port COM3 run --no-output uart.py 方法,在串口中可以看到輸出結果如下:
細心的讀者,有沒有發現兩者輸出結果有什么不同嗎?
如果沒看出來的話,提示一下,大家看看Send Byte: 后面有什么不同。
這個原因我想了一段時間,大家知道什么原因嗎,歡迎評論區留言。
衡量通信速度的參數,表示每秒鐘傳送的bit的個數。例如9600波特表示每秒鐘發送9600個bit。常見的波特率:9600(QSerialPort::Baud9600),19200(QSerialPort::Baud19200),38400(QSerialPort::Baud38400),115200(QSerialPort::Baud115200)
衡量通信中實際數據位的參數,當計算機發送一個信息包,實際包含的有效數據位個數。常見設置:5(QSerialPort::Data5),6(QSerialPort::Data6),7(QSerialPort::Data7),8(QSerialPort::Data8)
用于表示單個包的最后一位。典型的值為1和2位。常見設置:1(QSerialPort::OneStop),1.5(QSerialPort::OneAndHalfStop),2(QSerialPort::TwoStop)
串口通信中一種檢錯方式。常用的檢錯方式有:偶、奇校驗。常見設置:None(QSerialPort::NoParity),Even(QSerialPort::EvenParity),Odd(QSerialPort::OddParity)等
QT上還提供設置數據流控
Qt資料領取→「鏈接」
這里講到的“流”,當然指的是數據流。數據在兩個串口之間傳輸時,常常會出現丟失數據的現象,或者兩臺計算機的處理速度不同,如臺式機與單片機之間的通訊,接收端數據緩沖區已滿,則此時繼續發送來的數據就會丟失。現在我們在網絡上通過modem進行數據傳輸,這個問題就尤為突出。流控制能解決這個問題,當接收端數據處理不過來時,就發出“不再接收”的信號,發送端就停止發送,直到收到“可以繼續發送”的信號再發送數據。因此流控制可以控制數據傳輸的進程,防止數據的丟失。 pc機中常用的兩種流控制是硬件流控制(包括rts/cts、dtr/cts等)和軟件流控制xon/xoff(繼續/停止),下面分別說明。
硬件流控制常用的有rts/cts流控制和dtr/dsr(數據終端就緒/數據設置就緒)流控制。
硬件流控制必須將相應的電纜線連上,用rts/cts(請求發送/清除發送)流控制時,應將通訊兩端的rts、cts線對應相連,數據終端設備(如計算機)使用rts來起始調制解調器或其它數據通訊設備的數據流,而數據通訊設備(如調制解調器)則用cts來起動和暫停來自計算機的數據流。
這種硬件握手方式的過程為:我們在編程時根據接收端緩沖區大小設置一個高位標志(可為緩沖區大小的75%)和一個低位標志(可為緩沖區大小的25%),當緩沖區內數據量達到高位時,我們在接收端將cts線置低電平(送邏輯0),當發送端的程序檢測到cts為低后,就停止發送數據,直到接收端緩沖區的數據量低于低位而將cts置高電平。rts則用來標明接收設備有沒有準備好接收數據。常用的流控制還有還有dtr/dsr(數據終端就緒/數據設置就緒)。
由于電纜線的限制,我們在普通的控制通訊中一般不用硬件流控制,而用軟件流控制。一般通過xon/xoff來實現軟件流控制。常用方法是:當接收端的輸入緩沖區內數據量超過設定的高位時,就向數據發送端發出xoff字符(十進制的19或control-s,設備編程說明書應該有詳細闡述),發送端收到 xoff字符后就立即停止發送數據;當接收端的輸入緩沖區內數據量低于設定的低位時,就向數據發送端發出xon字符(十進制的17或control- q),發送端收到xon字符后就立即開始發送數據。
//初始化波特率
ui->Net_S_BaudrateCombo->addItem(tr("自定義"));
ui->Net_S_BaudrateCombo->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
ui->Net_S_BaudrateCombo->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
ui->Net_S_BaudrateCombo->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
ui->Net_S_BaudrateCombo->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
ui->Net_S_BaudrateCombo->setCurrentText(tr("38400"));
//初始化數據位
ui->Net_S_DataCombo->addItem(QStringLiteral("5"), QSerialPort::Data5);
ui->Net_S_DataCombo->addItem(QStringLiteral("6"), QSerialPort::Data6);
ui->Net_S_DataCombo->addItem(QStringLiteral("7"), QSerialPort::Data7);
ui->Net_S_DataCombo->addItem(QStringLiteral("8"), QSerialPort::Data8);
ui->Net_S_DataCombo->setCurrentText(tr("8"));
//初始化停止位
ui->Net_S_StopCombo->addItem(QStringLiteral("1"), QSerialPort::OneStop);
ui->Net_S_StopCombo->addItem(tr("1.5"), QSerialPort::OneAndHalfStop);
ui->Net_S_StopCombo->addItem(QStringLiteral("2"), QSerialPort::TwoStop);
ui->Net_S_StopCombo->setCurrentText(tr("1"));
//初始化校驗位
ui->Net_S_ChkCombo->addItem(tr("None"), QSerialPort::NoParity);
ui->Net_S_ChkCombo->addItem(tr("Even"), QSerialPort::EvenParity);
ui->Net_S_ChkCombo->addItem(tr("Odd"), QSerialPort::OddParity);
ui->Net_S_ChkCombo->addItem(tr("Mark"), QSerialPort::MarkParity);
ui->Net_S_ChkCombo->addItem(tr("Space"), QSerialPort::SpaceParity);
ui->Net_S_ChkCombo->setCurrentText(tr("None"));
//初始化流控
ui->Net_S_FlowCombo->addItem(tr("None"), QSerialPort::NoFlowControl);
ui->Net_S_FlowCombo->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);
ui->Net_S_FlowCombo->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);
ui->Net_S_FlowCombo->setCurrentText(tr("None"));
//設置波特率和讀寫方向
qint32 baudRate;
if (ui->Net_S_BaudrateCombo->currentIndex() == 4){
baudRate = ui->Net_S_BaudrateCombo->currentText().toInt();
}else{
baudRate = static_cast<QSerialPort::BaudRate>(ui->Net_S_BaudrateCombo->itemData(ui->Net_S_BaudrateCombo->currentIndex()).toInt());
}
m_serialPort->setBaudRate(baudRate,QSerialPort::AllDirections);
//數據位
QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(ui->Net_S_DataCombo->itemData(ui->Net_S_DataCombo->currentIndex()).toInt());
m_serialPort->setDataBits(dataBits);
//停止位
QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(ui->Net_S_StopCombo->itemData(ui->Net_S_StopCombo->currentIndex()).toInt());
m_serialPort->setStopBits(stopBits);
//校驗位
QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(ui->Net_S_ChkCombo->itemData(ui->Net_S_ChkCombo->currentIndex()).toInt());
m_serialPort->setParity(parity);
//流控制
QSerialPort::FlowControl flowControl = static_cast<QSerialPort::FlowControl>(ui->Net_S_FlowCombo->itemData(ui->Net_S_FlowCombo->currentIndex()).toInt());
m_serialPort->setFlowControl(flowControl);
QStringList list;
QList<QSerialPortInfo> serialPortInfoList = QSerialPortInfo::availablePorts();//讀取所有可用的串口信息
int intID = 0;
foreach(QSerialPortInfo serialPortInfo,serialPortInfoList) //打印出端口信息
{
QString strComboShow = (serialPortInfo.portName() + ":" + serialPortInfo.description());
ui->Net_S_COMCombo->insertItem(intID,strComboShow,serialPortInfo.portName());
}
QSerialPortInfo 類中可獲取串口端口的名稱,如:COM1,COM2等。還有相關串口描述。
m_serialPort->setPortName("串口名字");//當前選擇的串口名字
if(!m_serialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式嘗試打開串口
{
QMessageBox::warning(this, "警告", "打開串口失敗");
return;
}
// 串口數據到來時,會觸發QSerialPort::readyRead事件,添加相應的響應函數
QObject::connect(m_serialPort, &QSerialPort::readyRead, this, &Nahai::serialReceiveData);
void serialReceiveData()
{
QByteArray buffer = m_serialPort->readAll();
//處理你要處理的數據
}
if(m_serialPort->isOpen())
{
m_serialPort->write(baPacket,baPacket.size());//QByteArray baPacket:為你要發送字節數組
}
文章轉自博客園(Bruce的筆記本):https://www.cnblogs.com/BruceMao/p/15410471.html
Qt資料領取(視頻教程+文檔+代碼+項目實戰)
*請認真填寫需求信息,我們會在24小時內與您取得聯系。