一、思维导图
二、流程图
三、DFD数据流图
四、时序图
五、UML类图
一、思维导图
二、流程图
三、DFD数据流图
四、时序图
五、UML类图
个人比较喜欢c语言,所以后面的编程都会使用c语言。
使用c语言的话可以使用用wiringPi类库。
1、查看是否安装wiringPi类库,输入下面的命令,如果返回版本信息则表示已安装wiringPi库
1 |
$ gpio -v |
2、如果没有安装,输入下面的命令安装
1 |
sudo apt-get install wiringpi |
3、wiringPi源码
github上有一个wiringPi的代码库,但那个并不是wiringPi的源码,其源码在下面这个地址中
将Led灯的两个针脚分别连到GND和GPIO0两个接口上,网上有的教程还说要连上一个电阻,但是俺没有,就直接连上了。
新建一个ledblink.c文件,然后输入下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <stdio.h> #include <wiringPi.h> #define LED 0 #define BLINK_INTERVAL 500 int main(void){ printf("LED blink!\n"); wiringPiSetup(); pinMode(LED, OUTPUT); for(;;){ digitalWrite(LED, 1); delay(BLINK_INTERVAL); digitalWrite(LED, 0); delay(BLINK_INTERVAL); } return 0; } |
输入下面的命令编译
1 |
gcc -o ledblink ledblink.c -lwiringPi |
编译完成后,会生成一个ledblink的可执行程序,输入./ledblink运行,看led灯是不是开始闪烁了!
本文基于Ubuntu16,pi zero WH,树莓派镜像版本2019-06-20_raspbian_full
树梅派官方推荐使用Etcher制作镜像,但是下载速度实在是太慢了,使用dd也可以搞定。
官网镜像下载地址:https://www.raspberrypi.org/downloads/raspbian/
首先下载树梅派系统镜像包,是一个zip文件,如:2019-06-20_raspbian_full_latest.zip
解决zip包后得到img镜像文件,如:2019-06-20-raspbian-buster-full.img
将sd卡连接电脑,然后执行df -h
拔掉sd卡后再执行一次df -h
有变化的那一项即是sd卡的设备名称,如:/dev/sdc1
/dev/sdc即是sd卡的主设备名,先执行下面命令卸载它的子分区
1 |
umount /dev/sdc1 |
假如还有sdc2、sdc3统统卸载掉
执行下面的命令烧录系统
1 |
dd bs=4M if=./2019-06-20-raspbian-buster-full.img of=/dev/sdc |
if=后面是镜像所在的路径
of=后面是sd卡设备名称
转载自:http://shumeipai.nxez.com/2017/09/13/raspberry-pi-network-configuration-before-boot.html
不算是什么新功能了,在树莓派3B发布后不久,树莓派官方 Raspbian 系统久加入了允许在开机前对 WiFi 网络进行配置的机制。
注意,这个方法仅适用于全新安装树莓派系统到 SD 卡之后没有做过任何 Wi-Fi 配置的情况下有效。如果你之前配置过 Wi-Fi,再用本方法系统会默认使用已有的配置而忽略这里的配置。因此建议使用前重新安装系统。
用户可以在未启动树莓派的状态下单独修改 /boot/wpa_supplicant.conf
文件配置 WiFi 的 SSID 和密码,这样树莓派启动后会自行读取 wpa_supplicant.conf 配置文件连接 WiFi 设备。
操作方法简单:将刷好 Raspbian 系统的 SD 卡用电脑读取。在 boot 分区,也就是树莓派的 /boot
目录下新建 wpa_supplicant.conf 文件,按照下面的参考格式填入内容并保存 wpa_supplicant.conf 文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
country=CN ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="WiFi-A" psk="12345678" key_mgmt=WPA-PSK priority=1 } network={ ssid="WiFi-B" psk="12345678" key_mgmt=WPA-PSK priority=2 scan_ssid=1 } |
说明以及不同安全性的 WiFi 配置示例:
#ssid:网络的ssid
#psk:密码
#priority:连接优先级,数字越大优先级越高(不可以是负数)
#scan_ssid:连接隐藏WiFi时需要指定该值为1
如果你的 WiFi 没有密码
1
2
3
4
|
network={ ssid="你的无线网络名称(ssid)" key_mgmt=NONE } |
如果你的 WiFi 使用WEP加密
1
2
3
4
5
|
network={ ssid="你的无线网络名称(ssid)" key_mgmt=NONE wep_key0="你的wifi密码" } |
如果你的 WiFi 使用WPA/WPA2加密
1
2
3
4
5
|
network={ ssid="你的无线网络名称(ssid)" key_mgmt=WPA-PSK psk="你的wifi密码" } |
如果你不清楚 WiFi 的加密模式,可以在安卓手机上用 root explorer 打开 /data/misc/wifi/wpa/wpa_supplicant.conf
,查看 WiFi 的信息。
如果通过 ssh 连接树莓派出现 Access denied 这个提示则说明 ssh 服务没有开启。要手动开启的话,和 WiFi 配置相似,同样在 boot 分区新建一个文件,空白的即可,文件命名为 ssh。注意要小写且不要有任何扩展名。
树莓派在启动之后会在检测到这个文件之后自动启用 ssh 服务。随后即可通过登录路由器找到树莓派的 IP 地址,通过 ssh 连接到树莓派了。(有关开启 SSH 服务的详细方法)
如果需要远程桌面方式操作树莓派,可以通过 ssh 安装 xrdp,再用 Windows 的远程桌面客户端连接到树莓派。
这个小技巧对于没有有线网卡、没有标准 USB 接口来直连键鼠,但集成了 WiFi 的树莓派 Zero W 尤其实用。
对对象每次执行一次connect的操作,都会增加一个信号槽连接
如果我们想断开某个对象的所有信号槽,调用对象的disconnect()方法
如果想断开某一个信号槽,在connect时将返回的对象保存一下,然后调用QObject的disconnect()就可以了,如下面的代码:
dialog.cpp文件
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 |
#include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); } Dialog::~Dialog() { delete ui; } void Dialog::on_pushButton_2_clicked() { Connection1 = connect(ui->btnTest, SIGNAL(clicked(bool)), this, SLOT(connectFunc1(bool))); } void Dialog::on_pushButton_3_clicked() { connect(ui->btnTest, SIGNAL(clicked(bool)), this, SLOT(connectFunc2(bool))); } void Dialog::connectFunc1(bool b) { qDebug() << "connectFunc1"; } void Dialog::connectFunc2(bool b) { qDebug() << "connectFunc2"; } void Dialog::on_pushButton_clicked() { // 断开所有的connect ui->btnTest->disconnect(); } void Dialog::on_pushButton_4_clicked() { // 只断开其中的某个connect disconnect(Connection1); } |
dialog.h头文件
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 |
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QMetaObject> #include <QDebug> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); private slots: void on_pushButton_2_clicked(); void on_pushButton_3_clicked(); void connectFunc1(bool b); void connectFunc2(bool b); void on_pushButton_clicked(); void on_pushButton_4_clicked(); private: Ui::Dialog *ui; QMetaObject::Connection Connection1; }; #endif // DIALOG_H |
界面图片:
开发环境:QT+Vs2015
想使用SetCursorPos来控制鼠标的位置
#include <Winuser.h>
但是编译时,总时提示无法解析的外部符号
网上搜了一上,需要引用User32.lib库,最后发现需要在项目的.pro文件中加入user32的库的引用,如下:
1 2 3 4 5 6 |
FORMS += \ mainwindow.ui win32 { LIBS += -luser32 } |
如果编译还是不成功,把项目目录下生成的debug目录(build-xxxx-Desktop_Qt_5_10_1_MSVC2015_32bit-Debug)删除掉,再重新编译一下
QLabel并不支持鼠标按下、松开等事件,我们需要新建一个QLabel的子类来支持。
编写qadvancedlabel.h
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 |
#ifndef QADVANCEDLABEL_H #define QADVANCEDLABEL_H #include <QLabel> class QAdvancedLabel : public QLabel { Q_OBJECT public: QAdvancedLabel(QWidget *parent = nullptr); protected: virtual void mousePressEvent(QMouseEvent *event); //鼠标按下 virtual void mouseReleaseEvent(QMouseEvent *event); //鼠标松开 virtual void mouseDoubleClickEvent(QMouseEvent *event); //双击鼠标 virtual void mouseMoveEvent(QMouseEvent *event); //鼠标移动 signals: void pressed(QMouseEvent *event); //鼠标按下 void clicked(QMouseEvent *event); //鼠标松开 void doubled(QMouseEvent *event); //双击鼠标 void moved(QMouseEvent *event); //鼠标移动 public slots: }; #endif // QADVANCEDLABEL_H |
然后增加QAdvancedLabel的cpp文件,qadvancedlabel.cpp
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 |
#include "include/qadvancedlabel.h" QAdvancedLabel::QAdvancedLabel(QWidget *parent) : QLabel(parent) { } void QAdvancedLabel::mousePressEvent(QMouseEvent *event) { emit pressed(event); } void QAdvancedLabel::mouseReleaseEvent(QMouseEvent *event) { emit clicked(event); } void QAdvancedLabel::mouseDoubleClickEvent(QMouseEvent *event) { emit doubled(event); } void QAdvancedLabel::mouseMoveEvent(QMouseEvent *event) { emit moved(event); } |
然后在程序中的实现:
mainwindow.h文件
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 |
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QObject> #include <QMainWindow> #include <QMouseEvent> #include "qadvancedlabel.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void onQAdvLabelMouseEvent(QMouseEvent *event); private: Ui::MainWindow *ui; QAdvancedLabel *testQAdvLabel; }; #endif // MAINWINDOW_H |
mainwindow.cpp文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); testQAdvLabel = new QAdvancedLabel(ui->centralWidget); testQAdvLabel->setText("test mouse move"); connect(testQAdvLabel, SIGNAL(moved(QMouseEvent*)), this, SLOT(onQAdvLabelMouseEvent(QMouseEvent*))); testQAdvLabel->setMouseTracking(true); } void MainWindow::onQAdvLabelMouseEvent(QMouseEvent *event) { qDebug("x: %d, y: %d", event->x(), event->y()); } |
在QT中发送http请求要使用下面的几个类
首先要在项目文件里增加network的支持,在xxx.pro里面加上如下代码
1 2 |
QT += core gui QT += network |
下面是具体的代码:
logindialog.h
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 |
#ifndef LOGINDIALOG_H #define LOGINDIALOG_H #include <QDialog> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QNetworkRequest> #include <QUrl> #include "constants.h" #include "jsonobjs/jsonloginres.h" namespace Ui { class LoginDialog; } class LoginDialog : public QDialog { Q_OBJECT public: explicit LoginDialog(QWidget *parent = 0); ~LoginDialog(); private slots: void on_btnLogin_clicked(); void onLoginReqFinished(); private: Ui::LoginDialog *ui; QNetworkAccessManager* mNam = NULL; QNetworkReply* mLoginReply = NULL; void reqLogin(); }; #endif // LOGINDIALOG_H |
logindialog.cpp
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 |
#include "logindialog.h" #include "ui_logindialog.h" LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) { ui->setupUi(this); mNam = new QNetworkAccessManager(this); //连接返回的信号槽 //connect(mNam, SIGNAL(finished(QNetworkReply*)), this, SLOT(onLoginReqFinished(QNetworkReply*))); } LoginDialog::~LoginDialog() { delete mLoginReply; delete mNam; delete ui; } void LoginDialog::on_btnLogin_clicked() { reqLogin();; } void LoginDialog::reqLogin() { if(NULL != mLoginReply && !mLoginReply->isFinished()){ return; } QNetworkRequest request; std::string url("http://bcoder.com/loginapi"); QByteArray params ; params.append("ucode=" + ui->edtUserName->text()); params.append("&password=" + ui->edtPassword->text()); request.setUrl(QUrl(url.c_str())); //request.setRawHeader("Content-Type","application/json"); request.setRawHeader("Content-Type","application/x-www-form-urlencoded"); // request->setRawHeader("Accept","text/html, application/xhtml+xml, */*"); // request->setRawHeader("Referer","http://localhost:8888/login"); // request->setRawHeader("Accept-Language","zh-CN"); // request->setRawHeader("X-Requested-With","XMLHttpRequest"); // request->setRawHeader("User-Agent","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"); // request->setRawHeader("Content-Type","application/x-www-form-urlencoded"); // request->setRawHeader("Accept-Encoding","gzip,deflate"); // request->setRawHeader("Host","localhost:8888"); // request->setRawHeader("Content-Length","18"); // request->setRawHeader("Connection","Keep-Alive"); // request->setRawHeader("Cache-Control","no-cache"); mLoginReply = mNam->post(request, params); connect(mLoginReply, SIGNAL(finished()), this, SLOT(onLoginReqFinished())); } void LoginDialog::onLoginReqFinished() { QByteArray bytes = mLoginReply->readAll(); // bytes //QString string(bytes); // string QString string = QString::fromUtf8(bytes); JsonLoginRes res(string.toStdString()); qDebug() << "---------------------------------\n" << string; mLoginReply->close(); // mLoginReply->deleteLater(); } |
Android.mk是Android源码编译系统的Makefile,用于编译系统中的C++和Java的动态库\静态库\可执行文件和apk等.
其大概格式如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := Calculator
include $(BUILD_PACKAGE)
##################################################
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libarity:arity-2.1.2.jar
include $(BUILD_MULTI_PREBUILT)
# Use the folloing include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))
上面的示例中共涉及到三类语法
1)变量的定义,比如其中的LOCAL_PATH为定义的变量,可以在其他地方被调用
变量不是必须全部大写或者必须以LOCAL_开头,可以是其他形式的,因为安卓的编译系统会加载所有的mk文件到一个环境里面,所以定义变量应该加上一个特殊的前缀,防止覆盖一些全局的变量.
2)my-dir为mk系统中预定义的宏,通过$(call my-dir)来调用
mk系统中还定义了很多其他的宏,这些定义均在build/core/definitions.mk中,有兴趣的可以浏览一下这个文件
3)include语法包含其他的mk文件
我们可以看到示例中有一个include $(BUILD_PACKAGE),其实BUILD_PACKAGE是在buile/core/config.mk中定义一个变量,如下:
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
这一行代码其实是把package.mk包含到了编译步骤中,用于编译Calculator这个apk
4)shell命令
1)通常都以LOCAL_PATH开始,指定当前工程的路径,一般也是使用my-dir宏指定,如下:
LOCAL_PATH := $(call my-dir)
2)编写具体模块编译脚本
首先确定编译模块的类型,是静态c++库\动态C++库还是可执行程序,或者jar包或者apk,参见"模块编译类型定义"部分.
a. 一个mk文件中可以编译多种类型的模块,每个模块一般都是以include $(CLEAR_VARS)开始
CLEAR_VARS实际上是引用的build/core/clear_vars.mk文件,用于清除部分以LOCAL_开始的变量(不会清除LOCAL_PATH),具体可以浏览clear_vars.mk
b. 然后定义编译这个模块所需要用到的一些LOCAL_变量,比如如下:
LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 guava #编译apk用到的静态库
LOCAL_SRC_FILES := $(call all-java-files-under, src) # 要编译的源码
LOCAL_PACKAGE_NAME := Calculator #包名
c. include + 编译类型 结尾,如:
include $(BUILD_PACKAGE)
mk系统支持多种类型的编译,这些类型都在build/core/config.mk中定义,每种编译类型由一个特定的mk文件去处理,如下是在Android4.4系统中抓取的编译类型定义.
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE – 构建一个Android apk
BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk
LOCAL_PATH – 工程路径,通常为$(call my-dir),代表本目录和所有子目录
LOCAL_SRC_FILES – 项目源文件,不只是c或者java代码,也可以是apk或者so等文件,可添加多个,使用\加换行连接多个源文件
LOCAL_MODULE_CLASS – 可以为以下值:EXECUTABLES、FIRMWARE、SHARED_LIBRARIES、ETC、APPS、STATIC_LIBRARIES、NATIVE_TESTS、JAVA_LIBRARIES、FAKE、HEADER_LIBRARIES等
LOCAL_MODULE_TAGS – 在哪些系统版本下编译此项目,可以为eng、user、debug、tests、optional,optional表示在所有版本下都
LOCAL_MODULE – 项目名称
LOCAL_CERTIFICATE – 项目签名类型,可以为testkey、platform、shared、media、PRESIGNED(使用原签名),platform代表为系统应用
LOCAL_MODULE_PATH – 项目输出路径
LOCAL_PRIVILEGED_MODULE – 不设置或者设置为false,安装位置为system/app,如果设置为true,则安装位置为system/priv-app
LOCAL_MODULE_SUFFIX – module的后缀,可不设置
LOCAL_DEX_PREOPT – 是否对apk或者jar包进行odex优化,不设置代表默认优化,设置为false代表不优化
LOCAL_JACK_ENABLED – 有三种模式:full、incremental、disabled
首选在mainwindow.h中加入头文件引用
1 2 |
#include <QUuid> #include <QDebug> |
然后在mainwindow.cpp的构造函数中加入下面的代码:
1 2 3 4 5 6 7 8 9 10 |
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QUuid uuid = QUuid::createUuid(); QString uuidstr = uuid.toString(); qDebug() << "RmcTOKEN: " << uuidstr; } |