前面的幾篇文章,介紹Qt例程,都是和硬體無關的,Windows平台和嵌入式平台都能運作。
本篇,來測試一下Qt界面控制嵌入式平台上的硬體,以野火i.MX6ULL闆子上的RGB LED為例,實作Qt界面控制3種顔色LED的不同亮度混合顯示。
1 設計Qt滑條控制LED界面
先來看一下最終設計的界面效果:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0gTMx81dsQWZ4lmZf1GLlpXazVmcvwFciV2dsQXYtJ3bm9CX9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SMyYDO1IGZxImNiBTYiZmZyYzX1UzNyADMwIzLchDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
有一個按鍵作為LED的總開關,控制LED的點亮與熄滅。下面的3個滑條,控制3種顔色LED以不同的亮度點亮。右邊是一個顔色混合顯示面闆,模拟RGB三種顔色的LED以不同亮度點亮後的混合亮度。
1.1 滑條控件
Qt Creator的UI設定界面中,有水準滑條和豎直滑條控件,可以直接使用:
右側的屬性窗戶可以設定滑條的取值範圍和初始值。
1.2 控件顔色
使用QPalette可以對界面顔色和控件的顔色進行自定義設定
- QPalete::Window——通常指視窗部件的背景色
- QPalette::WindowText——通常指視窗不見的前景色
- QPalette::Base——底色
- QPalette::Button——指按鈕視窗部件的背景色
- QPalette::ButtonText——指按鈕視窗部件的前景色
- QPalette::Text——文本輸入視窗的前景色
- QPalette::Background——背景色
- QPalette::Foreground——前景色(界面中文字的統一顔色)
界面的顔色
整個UI界面的顔色可以這樣設定:
QPalette color = palette();//控制窗體顔色
color.setColor(QPalette::Background, QColor(255,255,255));//背景顔色
//color.setColor(QPalette::Foreground, QColor(0,0,255,255));//前景顔色
setPalette(color);
這裡就是把整個界面的顔色設定為純白色
控件的顔色
例如文本标簽控件(QLabel)的文字顔色可以這樣設定:
QPalette pal;
pal.setColor(QPalette::WindowText,Qt::red);
ui->label_R->setPalette(pal); //設定滑條左側的R字型為紅色
pal.setColor(QPalette::WindowText,Qt::green);
ui->label_G->setPalette(pal);
pal.setColor(QPalette::WindowText,Qt::blue);
ui->label_B->setPalette(pal);
顔色混合面闆控件(QTextBrowser)的面闆顔色可以這樣設定:
QColor color;
int R = ui->Slider_R->value(); //讀取滑條的目前值
int G = ui->Slider_G->value();
int B = ui->Slider_B->value();
color.setRgb(R, G, B); //顔色混合
QPalette pal;
pal.setColor(QPalette::Base, color);
ui->textBrowser->setPalette(pal); //顯示到面闆上
1.3 滑條UI界面代碼編寫
構造函數
LedWidget::LedWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::LedWidget)
{
ui->setupUi(this);
ui->Value_R->setText(QString::number(ui->Slider_R->value()));
ui->Value_G->setText(QString::number(ui->Slider_G->value()));
ui->Value_B->setText(QString::number(ui->Slider_B->value()));
QPalette color = palette();//控制窗體顔色
color.setColor(QPalette::Background, QColor(255,255,255));//背景顔色
setPalette(color);
}
滑條滑動時的槽函數
void LedWidget::on_Slider_R_valueChanged(int value)
{
ui->Value_R->setText(QString::number(value));
UpdateShowColor();
}
void LedWidget::on_Slider_G_valueChanged(int value)
{
ui->Value_G->setText(QString::number(value));
UpdateShowColor();
}
void LedWidget::on_Slider_B_valueChanged(int value)
{
ui->Value_B->setText(QString::number(value));
UpdateShowColor();
}
更新RGB三種顔色的混合顯示
void LedWidget::UpdateShowColor()
{
QColor color;
int R = ui->Slider_R->value();
int G = ui->Slider_G->value();
int B = ui->Slider_B->value();
color.setRgb(R, G, B);
QPalette pal;
pal.setColor(QPalette::Base, color);
ui->textBrowser->setPalette(pal);
}
2 闆子上RGB LED的控制
2.1 i.MX6ULL系統燒錄
本篇的RGB LED測試,需要先燒錄野火i.MX6ULL自帶的系統固件,因為該系統已有Qt運作環境,且對應的RGB LED的驅動程式也已配置好了,這樣就不需要再自己寫RGB LED的驅動程式了,我們隻寫好Qt的應用程式,實作對闆子上LED的控制即可。
燒寫方法可參考:https://doc.embedfire.com/linux/imx6/quick_start/zh/latest/quick_start/install_debian/install_debian.html#
可以燒寫到SD卡中
燒寫到eMMC中
因為在SD卡中運作系統,無法使用WIFI連網,可以通過fire-config工具将SD卡的系統燒寫到eMMC中,刷機過程可參考:
https://doc.embedfire.com/linux/imx6/linux_base/zh/latest/linux_basis/fire-config_brief/fire-config_brief.html#id7
設定之後,選擇重新開機,重新開機後的系統将自動進行從SD卡到EMMC的刷機。刷機過程大約2分鐘左右。刷機完成後,控制台會重新進入序列槽登入頁面, 此時觀察開發闆的LED燈,如果LED在持續閃爍,說明刷機成功。然後調整撥碼開關為相應啟動方式,重新上電啟動系統即可。
也可以直接通過USB-OTG接口和 MFGTool2軟體燒寫到eMMC。ssh
燒寫到eMMC啟動,可以使用WIFI連網,WIFI配網步驟參考:https://doc.embedfire.com/linux/imx6/quick_start/zh/latest/quick_start/wifi/wifi.html
Qt系統界面
野火i.MX6ULL自帶的系統固件燒錄後自啟動Qt程式界面如下:
序列槽方式登入時:
普通使用者(帶sudo權限)
- 賬戶: debian
- 密碼: temppwd
ROOT使用者
- 賬戶: root
- 密碼: root
這個系統第一次運作時,會進行螢幕觸摸校準,若校準的不滿意,可删除掉**/etc/pointercal檔案**後重新開機再進行校準。
rm /etc/pointercal
2.2 無Qt的RGB LED測試
野火i.MX6ULL的RGB LED的原理圖如下,由于驅動程式不需要自己寫了,實際上我們也不需要關心具體的硬體引腳是哪個,隻需要使用驅動程式提供的裝置描述符進行LED的控制即可。
參考野火的測試代碼:https://doc.embedfire.com/linux/imx6/quick_start/zh/latest/quick_start/led_subsystem/led_subsystem.html#id4
測試代碼
編寫自己的沒有Qt界面的RGB LED測試代碼:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#define RLED_DEV_PATH "/sys/class/leds/red/brightness"
#define GLED_DEV_PATH "/sys/class/leds/green/brightness"
#define BLED_DEV_PATH "/sys/class/leds/blue/brightness"
int main(int argc,int *argv[])
{
int r_fd;
int g_fd;
int b_fd;
r_fd = open(RLED_DEV_PATH,O_WRONLY);
if(r_fd < 0)
{
perror(RLED_DEV_PATH);
exit(1);
}
g_fd = open(GLED_DEV_PATH,O_WRONLY);
if(r_fd < 0)
{
perror(GLED_DEV_PATH);
exit(1);
}
b_fd = open(BLED_DEV_PATH,O_WRONLY);
if(r_fd < 0)
{
perror(BLED_DEV_PATH);
exit(1);
}
while(1)
{
write(r_fd,"255",3);
sleep(1);
write(r_fd,"0",3);
sleep(1);
write(g_fd,"255",3);
sleep(1);
write(g_fd,"0",3);
sleep(1);
write(b_fd,"255",3);
sleep(1);
write(b_fd,"0",3);
sleep(1);
}
close(r_fd);
close(g_fd);
close(b_fd);
}
将該程式在Ubuntu進行交叉編譯
arm-linux-gnueabihf-gcc led_noqt.c -o led_noqt
測試效果
運作效果如下,3種顔色的燈每隔1s依次點亮熄滅:
對于亮度的控制,可以先參考教程中的指令行點燈測試:https://doc.embedfire.com/linux/imx6/linux_base/zh/latest/linux_basis/led_key_command_line_testing/led_key_command_line_testing.html
實際測試,序列槽指令無法控制燈的亮度,隻能控制亮滅,亮度為1和亮度為255的效果一樣,都是同樣的亮度,不知道是硬體的問題還是軟體驅動的問題。
2.3 Qt中移植RGB LED控制代碼
在滑條UI界面代碼工程的基礎上,添加一個自定義的類,名字可起為regled:
然後在這個類中,将無Qt的RGB LED測試用到的代碼移植進來,并結合Qt的滑動條對三種顔色的燈進行控制。
這個是構造函數,先打開3個LED燈的檔案描述符:
rgbled::rgbled(QObject *parent) : QObject(parent)
{
r_fd = open(RLED_DEV_PATH,O_WRONLY);
if(r_fd < 0)
{
return;
}
g_fd = open(GLED_DEV_PATH,O_WRONLY);
if(r_fd < 0)
{
return;
}
b_fd = open(BLED_DEV_PATH,O_WRONLY);
if(r_fd < 0)
{
return;
}
}
編寫一個RGB燈的顔色和亮度的控制函數,供外部調用:
void rgbled::SetRGBLedValue(LED_TYPE type, int val)
{
if (val > 255)
{
val = 255;
}
else if (val < 0)
{
val = 0;
}
std::string value = std::to_string(val);
switch (type)
{
case T_R_LED:
write(r_fd, value.c_str(), 3);
break;
case T_G_LED:
write(g_fd, value.c_str(), 3);
break;
case T_B_LED:
write(b_fd, value.c_str(), 3);
break;
default:break;
}
}
在UI界面類中,可以對RGB LED進行控制:
//LedWidget類中定義一個rgbled成員變量
rgbled *m_pRGBLed;
//LedWidget構造函數中執行個體化一個rgbled對象
m_pRGBLed = new rgbled(this);
在更新UI界面上的模拟顔色面闆的同時,也将闆子上的RGB LED的亮度進行同步控制:
void LedWidget::UpdateShowColor()
{
QColor color;
int R = ui->Slider_R->value();
int G = ui->Slider_G->value();
int B = ui->Slider_B->value();
color.setRgb(R, G, B);
QPalette pal;
pal.setColor(QPalette::Base, color);
ui->textBrowser->setPalette(pal);
//控制闆子上的RGB LED的亮度
m_pRGBLed->SetRGBLedValue(T_R_LED, R);
m_pRGBLed->SetRGBLedValue(T_G_LED, G);
m_pRGBLed->SetRGBLedValue(T_B_LED, B);
}
2.4 編譯時遇到的問題
程式首先在Windows的Qt Creator上進行編譯,遇到了一些問題,記錄下解決方法。
-
找不到unistd.h
在Windows中編譯時,Qt Creater提示找不到unistd.h,這個其實是Visual Stidio編譯器找不這個頭檔案。
這個頭檔案都是Linux系統中常用的,Windows中一般用不到,要消除這個編譯錯誤,可以在VS的安裝目錄手動添加一個這個檔案。
我的目錄是:
D:\Tools1\vs2015\VC\include
建立一個unistd.h:
//for qt creater, 2022/8/13
#ifndef _UNISTD_H
#define _UNISTD_H
#include <io.h>
#include <process.h>
#endif
-
open、write等函數的警告提示
這些也是Linux中用到的函數,在Window平台編譯隻是警告資訊,沒有報錯,可以不用管
3 實驗示範
3.1 交叉編譯
和之前一樣,将Windows的Qt Creator中的源碼複制到Ubuntu中進行交叉編譯,具體操作過程可參考之前的文章:
嵌入式Qt-動手編寫并運作自己的第1個ARM-Qt程式
這裡僅記錄下編譯指令:
/home/xxpcb/myTest/imx6ull/otherlib/qt/qt-everywhere-src-5.12.9/arm-qt/bin/qmake
3.2 檔案複制到闆子中
由于這次測試使用的是野火的系統固件,不能和之前用網絡位置挂載根檔案系統的方式,在Ubuntu中直接将檔案複制到闆子中(Ubuntu中的網絡挂載位置),是以本篇需要使用其它的方法将Ubuntu中編譯的檔案複制到闆子中。
這裡使用SSH的方式進行拷貝,首先要在Ubuntu中和i.MX6ULL闆子中配置SSH功能,配置方法如下:
配置ssh
sudo apt update
sudo apt install openssh-server -y
sudo systemctl status ssh #檢視狀态
# 如果你的防火牆開啟了,使用下面語句
sudo ufw allow ssh
連接配接方式
基本的ssh連接配接方法是:
ssh username@ip
- username表示該機器的使用者名,ip表示對應的ip位址
- ssh方式檔案複制
從Ubuntu拉取檔案到闆子中
# 從伺服器拉取檔案
# scp 伺服器上的某個使用者@伺服器IP::/伺服器檔案存放路徑 拉取檔案儲存路徑
scp [email protected]:server_file_path local_path
# 我的闆子的拉取指令
cd /usr/local/qt-app/mytest/
scp [email protected]:~/myTest/imx6ull/qt-test/4-led/led ./
3.3 測試效果
在測試自己的例程之前,需要先将野火的自啟動Qt例程kill掉,否則兩個Qt程式會同步運作互相遮擋。
kill掉自啟動Qt程式
通過ps 、top 等指令查詢到ebf-qtdemo的pid,然後通過kill指令停止App運作
#879 為目前 App 的 PID 值,每次可能不一樣
sudo kill 879
運作自己的Qt程式
野火的系統中,提供了一個運作腳本run_myapp.sh,需要調用這個腳本來運作自己的Qt程式
sudo /usr/local/qt-app/run_myapp.sh /usr/local/qt-app/Control_1
實際測試效果如下:
https://www.bilibili.com/video/BV1kF411w7YN
- 闆子上的LED的亮度其實不能調節,隻能亮或滅,需要确認下是不是LED驅動的問題
- 觸摸的方式拖動闆子上的滑條,不太靈活,可能是觸摸和滑鼠都在起作用,兩者幹擾了
- Qt界面中模拟的顔色混合面闆,顔色混合顯示正常