樹莓派c++實驗三:按鍵監測實驗
阿新 • • 發佈:2021-04-23
一、實驗目的
1、 瞭解樹莓派處理中斷的方式
2、 瞭解樹莓派是如何通過事件來代替傳統中斷的
3、 掌握利用C++語言,通過樹莓派的 GPIO 口讀取3按鈕模組的按下狀態
4、 利用QT編寫一個視窗介面,在介面中顯示按鈕被按下的狀態
二、實驗原理
本實驗以樹莓派作為控制器,以 C++ 作為開發工具,利用樹莓派的 GPIO,讀取一 個 3 按鈕模組的狀態,使用一個全域性變數 X,當按下綠色按鈕,X 加 1;當按下黃色按鈕, X 清零;當按下紅色按鈕,X 減 1。並在 LED 模組中顯示 X;利用 QT 編寫一個視窗介面, 將X的資料實時顯示出來,並顯示按鈕狀態
三、使用儀器、材料
1.樹莓派的GPIO模組 (General Purpose Input/Output通用型輸入輸出)
3.按鈕模組
4.直流電源
5.電源模組
6.開發工具:基於QT上的C++開發樹莓派
四、實驗步驟
- 連線:用杜邦線,將樹莓派、電源模組、1個LED模組、按鍵模組的相應引腳連起來;
- 編制LED模組顯示程式,能顯示給定數字;
- 用按鍵對全域性變數分別進行加、減、清零操作,並在LED 中顯示;
- 編制QT的視窗介面,在顯示器上顯示全域性變數的值、顯示各個按鍵輸出的值(0還是 1?)。5. 實驗完成後,反向上述步驟斷電、拆線並整理收拾好
五、實驗過程原始記錄(計算機原始碼)
#ifndef THREAD1_H
#define THREAD1_H
#include "wiringPi.h" //
#include <QThread>//
class Thread1 : public QThread//
{
Q_OBJECT
public:
Thread1();//
protected:
void run();//
signals:// 用於傳送的訊號函式
void send(int a, int b, int c, int d);
};
#endif
#ifndef THREAD2_H
#define THREAD2_H
#include "wiringPi.h"//
#include <QThread>//
static unsigned char LED_f[] ={ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80,
0x90, 0x8c, 0xbf, 0xc6, 0xa1, 0x8e, 0xbf, 0xff, 0x7f, 0xbf
};
class Thread2 : public QThread//
{
Q_OBJECT
public:
Thread2();//
int SCLK = 0, RCLK = 2, DIO = 3;//LED的SCLK(序列時鐘),RCLK(接收時鐘),DIO(資料),分別連線GPIO的三個數字引腳
void LED_init(){//
wiringPiSetup();
pinMode(SCLK, OUTPUT);
pinMode(RCLK, OUTPUT);
pinMode(DIO, OUTPUT);
}
//在SCLK上輸出脈衝訊號
void LED_out(char data){
for (int i = 8; i >= 1; i--) // 迴圈8次為1位元組
{
if (data & 0x80)
digitalWrite(DIO, HIGH);
else
digitalWrite(DIO, LOW);
delayMicroseconds(1);
data <<= 1;
digitalWrite(SCLK, LOW);
delayMicroseconds(1);
digitalWrite(SCLK, HIGH);
delayMicroseconds(1);
}
}
// 在RCLK上輸出脈衝訊號
void LED_display(unsigned char p, int v){
unsigned char* led_table;
unsigned char i;
led_table = LED_f + v;//
i = *led_table;
LED_out(i);
LED_out(p);
digitalWrite(RCLK, LOW);//
delayMicroseconds(1);
digitalWrite(RCLK, HIGH);
delayMicroseconds(1);
}
//在4位的LED上顯示一個4位資料
void LED_loop(int data)
{
LED_display(0x08, data / 1000 % 10);
delayMicroseconds(10);
LED_display(0x04, data / 100 % 10);
delayMicroseconds(10);
LED_display(0x02, data / 10 % 10);
delayMicroseconds(10);
LED_display(0x01, data % 10);
delayMicroseconds(10);
}
protected://
void run();
};
#endif
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "thread1.h"
#include "thread2.h"//
#include <QMainWindow>//
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow{//
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
Thread1 *th_1;
Thread2 *th_2;
private://
Ui::MainWindow *ui;
public slots:// 用於接收的槽函式
void receive(int a, int b, int c, int d);
};
#endif
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow){
ui->setupUi(this);
th_1 = new Thread1();// 建立執行緒和開啟執行緒
th_2 = new Thread2();
th_1 -> start();//
th_2 -> start();
connect(th_1,SIGNAL(send(int, int, int, int)),this,SLOT(receive(int, int, int, int))); // 連線訊號與槽
}
MainWindow::~MainWindow(){
delete ui;
}
void MainWindow::receive(int a, int b, int c, int d){ // 將資料顯示到Qt介面
ui -> label_5 -> setText(QString::fromStdString(std::to_string(a)));
ui -> label_6 -> setText(QString::fromStdString(std::to_string(b)));
ui -> label_7 -> setText(QString::fromStdString(std::to_string(c)));
ui -> label_8 -> setText(QString::fromStdString(std::to_string(d)));
}
#include "thread1.h"
#include "thread2.h"//
#include "wiringPi.h"//
static int data1 = 0,data2 = 0,data3 = 0;//
static int value = 10;
static int nums[3] = {12,13,14};//定義陣列,代表按鍵模組k1\k2\k3連線的GPIO數字引腳編號
void key_interrupt_service_1() // 中斷函式
{
delay(20); // 按鍵消抖
if (digitalRead(12) == 0){
data1 = 1;
data2 = 0;
data3 = 0;
value++;
}
if (digitalRead(14) == 0){
data1 = 0;
data2 = 1;
data3 = 0;
if(value > 0){
value--;
}
}
if (digitalRead(13) == 0){
data1 = 0;
data2 = 0;
data3 = 1;
value=0;
}
}
void key_init() {//
wiringPiSetup();// 初始化wiringPi
for(int i = 0;i<3;i++){
pinMode(nums[i], INPUT);
pullUpDnControl(nums[i], PUD_UP); // 設定上拉電阻
wiringPiISR(nums[i], INT_EDGE_FALLING, &key_interrupt_service_1); // 註冊中斷程式
}
}
Thread1::Thread1()
{}
void Thread1::run(){//
key_init(); // 初始化按鍵
while (1){
delay(10);
emit send(value, data1, data2, data3);
delay(1000);
}
}
Thread2::Thread2()
{}
void Thread2::run(){//
LED_init(); // 初始化LED
while(1){
LED_loop(value); //
}
}
實驗結果