命令$:python3 wifitz.py(程序的路径最好是绝对路径,比如我这里应该是
$:python3 /program/wifitz.py))
六、如果需要启动多个程序,我试过用上述方法添加三个.desktop文件,结果失败了;所以,如果需要启动多个程序,建议创建一个.sh脚本文件,将多个程序的终端启动命令添加到.sh文件中,然后将上述第三步中的第4行改为Exec=./filename.sh。接下来执行第4步和第5步查看执行结果,我这里能够成功启动三个python程序,如下图:
WiringPi是应用于树莓派平台的GPIO控制库函数,WiringPi遵守GUN Lv3。wiringPi使用C或者C++开发并且可以被其他语言包转,例如python、ruby或者PHP等。WiringPi中的函数类似于Arduino的wiring系统,这使得熟悉arduino的用户使用wringPi更为方便。
树莓派具有26个普通输入和输出引脚。在这26个引脚中具有8个普通输入和输出管脚,这8个引脚既可以作为输入管脚也可以作为输出管脚。除此之外,树莓派还有一个2线形式的I2C、一个4线形式的SPI和一个UART接口。树莓派上的I2C和SPI接口也可以作为普通端口使用。如果串口控制台被关闭便可以使用树莓派上的UART功能。如果不使用I2C,SPI和UART等复用接口,那么树莓派总共具有8+2+5+2 =17个普通IO。wiringPi包括一套gpio控制命令,使用gpio命令可以控制树莓派GPIO管脚。用户可以利用gpio命令通过shell脚本控制或查询GPIO管脚。wiringPi是可以扩展的,可以利用wiringPi的内部模块扩展模拟量输入芯片,可以使用MCP23x17/MCP23x08(I2C 或者SPI)扩展GPIO接口。另外可通过树莓派上的串口和Atmega(例如arduino等)扩展更多的GPIO功能。另外,用户可以自己编写扩展模块并把自定义的扩展模块集成到wiringPi中。WiringPi支持模拟量的读取和设置功能,不过在树莓派上并没有模拟量设备。但是使用WiringPi中的软件模块却可以轻松地应用AD或DA芯片。
wiringPi的安装存在方案A和方案B。wiringPi使用GIT工具维护个更新代码,但是如果处于一些其他原因不能使用GIT,那么也可以使用方案B下载和安装wiringPi。
从上图可以知道树莓派管脚有三种编号方式,第一种为板上编号(37),即中间两列,表示第几号插针。第二中为wiringPi编码(25),使用wiringPi库编程时是用wiringPi编号,第三种为BCM编号,这个是更加BCM管脚来编号的,使用bcm2837库或python的RPi.GPIO编程时使用BCM编号。
你可能下载到一个名为wiringPi-98bcb20.tar.gz的压缩包,需要助于的是98bcb20只是一个版本号,当你下载wiringPi的时候该版本号可能会发生改变。
树莓派各种系统默认密码合集(欢迎补充)
由于树莓派系统众多,各个密码也不一样,所以整理出来一个合计给大家参考。
如果有不对或者不足的地方 还请大家多多留言、指正。
谢谢大家,树莓派社区的发展离不开大家的支持!
Raspberry Pi
默认用户是 pi 密码为 raspberry
FreeBSD
默认的密码是 freebsd/freebsd 和 root/root。
CentOS 7
默认主机名:rpi2 默认用户名 root 密码 centos
recalbox
默认主机名 root 密码 recalboxroot
OpenELEC
默认主机名 root 密码 openelec
树莓派家庭影院安装
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install kodi
安装完后启动可设置为中文
安装视屏
也可以用 kodi系统
https://kodi.tv/download
修改树莓派的软件源
默认情况下,树莓派软件源地址是 http://archive.raspbian.org/,位于欧洲,在国内访问是非常慢的,经常只有几 k 每秒的下载速率。所以我们在玩转树莓派之前,强烈推荐替换成国内的软件源
树莓派的所有软件源地址可以从这里找到:https://www.raspbian.org/RaspbianMi
一般我们找个国内的就行了,比如清华大学的(下图表格的第一行)
首先点击桌面左上角的命令行按钮,进入命令行窗口
然后在命令行窗口内输入 sudo nano /etc/apt/sources.list 并回车,进入编辑器。
sudo 是指用系统管理员权限启动,nano 是树莓派内置的轻量文本编辑器,而 /etc/apt/sources.list 就是软件源的配置文件地址了。
接着编辑这个文件,如下图所示,把原来的内容注释掉(最前面加 # 号),在文件最顶部添加下面的内容:
deb http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib
deb-src http://mirrors.tuna.tsinghua.edu.cn/raspbian/raspbian/ buster main non-free contrib
按 ctrl-o 保存,按 ctrl-x 关闭。
同样的方法,把 /etc/apt/sources.list.d/raspi.list 文件也替换成下面的内容:
deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui
至此,树莓派软件源就替换好了。是不是很简单,就改两行配置即可。
最后,你可以试下执行 sudo apt-get update
,会发现更新速度快了很多。
【实用手记】树莓派旋转屏幕
注:带有【实用手记】标题的文章主要用于临时备忘,内容不甚详尽,但之后也会视需要对相关知识进行完善。
有时候我们在树莓派上进行开发,需要让屏幕旋转90°放置,这样的话我们需要对显示内容也进行旋转。
打开终端,修改树莓派的config.txt文件:
sudo gedit /boot/config.txt
如果需要屏幕内容顺时针旋转90°,那么在config.txt文件里添加以下内容:
display_rotate=1
display_rotate是用于设置屏幕旋转角度的,设置参数如下:
#display_rotate=0 Normal
#display_rotate=1 90 degrees
#display_rotate=2 180 degrees
#display_rotate=3 270 degrees
建议在加入修改的内容时顺便把上面四行注释也一起写入以备忘。
更行
sudo apt-get update
sudo apt-get install gedit-gmate
sudo apt-get install gedit-plugins
sudo apt-get remove gedit
sudo apt-get install gedit
树莓派3B+配置QT5开发环境
没事不要进行sudo apt-get upgrade
如果安装QT失败那么把软件源恢复到原来的地址
执行如下步骤:
1.命令行输入:sudo apt-get update
2.命令行输入:sudo apt-get upgrade
3.命令行输入:sudo rpi-update
4.命令行输入:sudo apt-get install qt5-default
5.命令行输入:sudo apt-get install qtcreator
6.命令行安装cmake sudo apt-get install cmake
如果之前安装过
配置
工具 ->选项
树莓派安装windows远程
树莓派安装windows远程
sudo apt-get install xrdp
添加用户 sudo adduser xn
查看IP地址:
$hostname -I
首先提一下我之前做的部分:
1、安装rasbian系统
2、因为家里操作方便,于是安装触摸屏
3、接入鼠标
4、更新系统 sudo apt-get update(利用系统自身的keyword)
读取源列表中的每个软件列表并进行更新
5、sudo apt-get upgrade -y
更新软件,一般update 后需要upgrade
6、sudo apt-get dist-upgrade -y
此类更新一般为解决依赖关系,并做出处理
一般安装软件前需要update
7、安装xrdp服务,通过ssl方式连接到电脑
sudo apt-get install xrdp
sudo apt-get purge tightvnc xrdp
sudo apt-get install tightvncserver xrdp
8、检查通道是否处于监听,3350和3389端口
terminal输入netstat -tnl
9、通过计算机登录远程桌面,输入树莓派的ip地址
QT全屏和恢复
全屏显示:
VideoWidget->setWindowFlags (Qt::Window);
VideoWidget->showFullScreen ();
退出全屏时:
VideoWidget->setWindowFlags (Qt::SubWindow);
VideoWidget->showNormal ();
树莓派3B--Qt中使用wiringPi来开发工程
按照上一篇安装好wiring Pi后,然后开始建立Qt工程。
1、 .Pro文件中配置如下
- //
- # 下面这个LIBS很关键
- LIBS += -lwiringPi
- //
2、添加对应的头文件
#include <wiringPi.h>
#include <wiringSerial.h>
然后开发就行,具体可看下一篇。
致敬:
我的QT第一个程序MyQT
MyQT.pro添加库
LIBS += -lwiringPi
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <wiringPi.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
private:
int LEDPort;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
LEDPort=5;
ui->setupUi(this);
wiringPiSetup();
pinMode(LEDPort,OUTPUT);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
this->setWindowFlags (Qt::Window);
this->showFullScreen ();
}
void MainWindow::on_pushButton_2_clicked()
{
this->setWindowFlags (Qt::SubWindow);
this->showNormal ();
}
void MainWindow::on_pushButton_3_clicked()
{
digitalWrite(LEDPort,HIGH);
}
void MainWindow::on_pushButton_4_clicked()
{
digitalWrite(LEDPort,LOW);
}
安装BCM2835
C library for Broadcom BCM 2835 as used in Raspberry Pi
This is a C library for Raspberry Pi (RPi). It provides access to GPIO and other IO functions on the Broadcom BCM 2835 chip, as used in the RaspberryPi, allowing access to the GPIO pins on the 26 pin IDE plug on the RPi board so you can control and interface with various external devices.
It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, and for accessing the system timers. Pin event detection is supported by polling (interrupts are not supported).
It is C++ compatible, and installs as a header file and non-shared library on any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with BCM 2835).
Several example programs are provided.
You can also find online help and discussion at
http://groups.google.com/group/bcm2835 Please use that group for all questions and discussions on this topic. Do not contact the author directly, unless it is to discuss commercial licensing. Before asking a question or reporting a bug, please read
Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian and Occidentalisv01, 2016-02-09 Raspbian Jessie. CAUTION: it has been observed that when detect enables such as
bcm2835_gpio_len() are used and the pin is pulled LOW it can cause temporary hangs on 2012-07-15-wheezy-raspbian, 2013-07-26-wheezy-raspbian and Occidentalisv01. Reason for this is not yet determined, but we suspect that an interrupt handler is hitting a hard loop on those OSs. If you must use
bcm2835_gpio_len() and friends, make sure you disable the pins with
bcm2835_gpio_clr_len() and friends after use.
Running as root
Prior to the release of Raspbian Jessie in Feb 2016, access to any peripheral device via /dev/mem on the RPi required the process to run as root. Raspbian Jessie permits non-root users to access the GPIO peripheral (only) via /dev/gpiomem, and this library supports that limited mode of operation.
If the library runs with effective UID of 0 (ie root), then
bcm2835_init() will attempt to open /dev/mem, and, if successful, it will permit use of all peripherals and library functions.
If the library runs with any other effective UID (ie not root), then
bcm2835_init() will attempt to open /dev/gpiomem, and, if successful, will only permit GPIO operations. In particular,
bcm2835_spi_begin() and
bcm2835_i2c_begin() will return false and all other non-gpio operations may fail silently or crash.
Installation
This library consists of a single non-shared library and header file, which will be installed in the usual places by make install
# download the latest version of the library, say bcm2835-1.xx.tar.gz, then:
tar zxvf bcm2835-1.xx.tar.gz
cd bcm2835-1.xx
./configure
make
sudo make check
sudo make install
Physical Addresses
The functions
bcm2835_peri_read(),
bcm2835_peri_write() and
bcm2835_peri_set_bits() are low level peripheral register access functions. They are designed to use physical addresses as described in section 1.2.3 ARM physical addresses of the BCM2835 ARM Peripherals manual. Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus addresses for peripherals are set up to map onto the peripheral bus address range starting at 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at physical address 0x20nnnnnn.
On RPI 2, the peripheral addresses are different and the bcm2835 library gets them from reading /proc/device-tree/soc/ranges. This is only availble with recent versions of the kernel on RPI 2.
After initialisation, the base address of the various peripheral registers are available with the following externals: bcm2835_gpio bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spio0 bcm2835_st bcm2835_bsc0 bcm2835_bsc1 bcm2835_aux bcm2835_spi1
Raspberry Pi 2 (RPI2)
For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel. You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 with 2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29.
When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system, and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). Without device tree support enabled and the presence of this file, it will not work on RPI2.
To enable device tree support:
sudo raspi-config
under Advanced Options - enable Device Tree
Reboot.
Pin Numbering
RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the IDE header.
RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd.
The functions in this library are designed to be passed the BCM 2835 GPIO pin number and
not the RPi pin number. There are symbolic definitions for each of the available pins that you should use for convenience. See
RPiGPIOPin.
SPI Pins
When
bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). When
bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be configured and controled with the usual bcm2835_gpio_* calls.
The Raspberry Pi GPIO pins used for SPI are:
- P1-19 (MOSI)
- P1-21 (MISO)
- P1-23 (CLK)
- P1-24 (CE0)
- P1-26 (CE1)
Although it is possible to select high speeds for the SPI interface, up to 125MHz (see
bcm2835_spi_setClockDivider()) you should not expect to actually achieve those sorts of speeds with the RPi wiring. Our tests on RPi 2 show that the SPI CLK line when unloaded has a resonant frequency of about 40MHz, and when loaded, the MOSI and MISO lines ring at an even lower frequency. Measurements show that SPI waveforms are very poor and unusable at 62 and 125MHz. Dont expect any speed faster than 31MHz to work reliably.
The bcm2835_aux_spi_* functions allow you to control the BCM 2835 SPI1 interface, allowing you to send and received data by SPI (Serial Peripheral Interface).
The Raspberry Pi GPIO pins used for AUX SPI (SPI1) are:
- P1-38 (MOSI)
- P1-35 (MISO)
- P1-40 (CLK)
- P1-36 (CE2)
I2C Pins
The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . For more information about I?C, see
http://en.wikipedia.org/wiki/I%C2%B2CThe Raspberry Pi V2 GPIO pins used for I2C are:
PWM
The BCM2835 supports hardware PWM on a limited subset of GPIO pins. This bcm2835 library provides functions for configuring and controlling PWM output on these pins.
The BCM2835 contains 2 independent PWM channels (0 and 1), each of which be connnected to a limited subset of GPIO pins. The following GPIO pins may be connected to the following PWM channels (from section 9.5):
GPIO PIN RPi pin PWM Channel ALT FUN
12 0 0
13 1 0
18 1-12 0 5
19 1 5
40 0 0
41 1 0
45 1 0
52 0 1
53 1 1
In order for a GPIO pin to emit output from its PWM channel, it must be set to the Alt Function given above. Note carefully that current versions of the Raspberry Pi only expose one of these pins (GPIO 18 = RPi Pin 1-12) on the IO headers, and therefore this is the only IO pin on the RPi that can be used for PWM. Further it must be set to ALT FUN 5 to get PWM output.
Each PWM channel can run in either Balanced or Mark-Space mode. In Balanced mode, the hardware sends a combination of clock pulses that results in an overall DATA pulses per RANGE pulses. In Mark-Space mode, the hardware sets the output HIGH for DATA clock pulses wide, followed by LOW for RANGE-DATA clock pulses.
The PWM clock can be set to control the PWM pulse widths. The PWM clock is derived from a 19.2MHz clock. You can set any divider, but some common ones are provided by the BCM2835_PWM_CLOCK_DIVIDER_* values of bcm2835PWMClockDivider.
For example, say you wanted to drive a DC motor with PWM at about 1kHz, and control the speed in 1/1024 increments from 0/1024 (stopped) through to 1024/1024 (full on). In that case you might set the clock divider to be 16, and the RANGE to 1024. The pulse repetition frequency will be 1.2MHz/1024 = 1171.875Hz.
Interactions with other systems
In order for bcm2835 library SPI to work, you may need to disable the SPI kernel module using:
sudo raspi-config
under Advanced Options - enable Device Tree
under Advanced Options - disable SPI
Reboot.
Since bcm2835 accesses the lowest level hardware interfaces (in eh intererests of speed and flexibility) there can be intercations with other low level software trying to do similar things.
It seems that with "latest" 8.0 Jessie 4.9.24-v7+ kernel PWM just won't work unless you disable audio. There's a line
dtparam=audio=on
in the /boot/config.txt. Comment it out like this:
#dtparam=audio=on
Real Time performance constraints
The bcm2835 is a library for user programs (i.e. they run in 'userland'). Such programs are not part of the kernel and are usually subject to paging and swapping by the kernel while it does other things besides running your program. This means that you should not expect to get real-time performance or real-time timing constraints from such programs. In particular, there is no guarantee that the
bcm2835_delay() and
bcm2835_delayMicroseconds() will return after exactly the time requested. In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times than the one you asked for. So please dont expect to get exactly the time delay you request.
Arjan reports that you can prevent swapping on Linux with the following code fragment:
#define <sched.h>
#define <sys/mman.h>
struct sched_param sp;
memset(&sp, 0, sizeof(sp));
sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
sched_setscheduler(0, SCHED_FIFO, &sp);
mlockall(MCL_CURRENT | MCL_FUTURE);
Bindings to other languages
Open Source Licensing GPL V2
This is the appropriate option if you want to share the source code of your application with everyone you distribute it to, and you also want to give them the right to share who uses it. If you wish to use this software under Open Source Licensing, you must contribute all your source code to the open source community in accordance with the GPL Version 2 when your application is distributed. See
https://www.gnu.org/licenses/gpl-2.0.html and COPYING
Commercial Licensing
This is the appropriate option if you are creating proprietary applications and you are not prepared to distribute and share the source code of your application. To purchase a commercial license, contact
[email protected]Acknowledgements
Some of this code has been inspired by Dom and Gert. The I2C code has been inspired by Alan Barr.
Revision History
Version
1.0 Initial release
1.1 Minor bug fixes
1.2 Added support for SPI
1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson.
1.7 Added bcm2835_spi_transfernb to support different buffers for read and write.
1.8 Improvements to read barrier, as suggested by maddin.
1.9 Improvements contributed by mikew: I noticed that it was mallocing memory for the mmaps on /dev/mem. It's not necessary to do that, you can just mmap the file directly, so I've removed the mallocs (and frees). I've also modified delayMicroseconds() to use nanosleep() for long waits, and a busy wait on a high resolution timer for the rest. This is because I've found that calling nanosleep() takes at least 100-200 us. You need to link using '-lrt' using this version. I've added some unsigned casts to the debug prints to silence compiler warnings I was getting, fixed some typos, and changed the value of BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at
http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 Also added a define for the passwrd value that Gert says is needed to change pad control settings.
1.11 Fixed incorrect link to download file
1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping)
1.13 New GPIO pin definitions for RPi version 2 plug P5 Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0.
1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. Reported by Ben Simpson.
1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi to allow a mask of pins to be set all at once. Requested by Sebastian Loncar.
1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar.
1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. No need to link with -lrt now. Contributed by Arjan van Vught.
1.19 Removed inlines added by previous patch since they don't seem to work everywhere. Reported by olly.
1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted.
1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. Patch courtesy Jeremy Mortis.
1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set falling edge events. Reported by Mark Dootson.
1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions to fix ocasional reads not completing. Patched by Mark Dootson.
1.24 Mark Dootson p[atched a problem with his previously submitted code under high load from other processes.
1.25 Updated author and distribution location details to airspayce.com
1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. Reported by Hartmut Henkel.
1.27
bcm2835_gpio_set_pad() no longer needs BCM2835_PAD_PASSWRD: it is now automatically included. Added support for PWM mode with bcm2835_pwm_* functions.
1.28 Fixed a problem where
bcm2835_spi_writenb() would have problems with transfers of more than 64 bytes dues to read buffer filling. Patched by Peter Würtz.
1.29 Further fix to SPI from Peter Würtz.
1.30 10 microsecond delays from bcm2835_spi_transfer and bcm2835_spi_transfern for significant performance improvements, Patch by Alan Watson.
1.31 Fix a GCC warning about dummy variable, patched by Alan Watson. Thanks.
1.32 Added option I2C_V1 definition to compile for version 1 RPi. By default I2C code is generated for the V2 RPi which has SDA1 and SCL1 connected. Contributed by Malcolm Wiles based on work by Arvi Govindaraj.
1.33 Added command line utilities i2c and gpio to examples. Contributed by Shahrooz Shahparnia.
1.34 Added
bcm2835_i2c_write_read_rs() which writes an arbitrary number of bytes, sends a repeat start, and reads from the device. Contributed by Eduardo Steinhorst.
1.35 Fix build errors when compiled under Qt. Also performance improvements with SPI transfers. Contributed b Udo Klaas.
1.36 Make automake's test runner detect that we're skipping tests when not root, the second one makes us skip the test when using fakeroot (as used when building Debian packages). Contributed by Guido Günther.
1.37 Moved confiure.in to configure.ac as receommnded by autoreconf.
Improvements to bcm2835_st_read to account for possible timer overflow, contributed by 'Ed'.
Added definitions for Raspberry Pi B+ J8 header GPIO pins.
1.38 Added bcm2835_regbase for the benefit of C# wrappers, patch by Frank Hommers
1.39 Beta version of RPi2 compatibility. Not tested here on RPi2 hardware. Testers please confirm correct operation on RPi2.
Unnecessary 'volatile' qualifiers removed from all variables and signatures.
Removed unsupportable PWM dividers, based on a report from Christophe Cecillon.
Minor improvements to spi.c example.
1.40 Correct operation on RPi2 has been confirmed.
Fixed a number of compiler errors and warnings that occur when
bcm2835.h is included in code compiled with -Wall -Woverflow -Wstrict-overflow -Wshadow -Wextra -pedantic. Reported by tlhackque.
Fixed a problem where calling bcm2835_delayMicroseconds loops forever when debug is set. Reported by tlhackque.
Reinstated use of volatile in 2 functions where there was a danger of lost reads or writes. Reported by tlhackque.
1.41 Added BCM2835_VERSION macro and new function
bcm2835_version(); Requested by tlhackque.
Improvements to peripheral memory barriers as suggested by tlhackque.
Reinstated some necessary volatile declarations as requested by tlhackque.
1.42 Further improvements to memory barriers with the patient assistance and patches of tlhackque.
1.43 Fixed problems with compiling barriers on RPI 2 with Arch Linux and gcc 4.9.2. Reported and patched by Lars Christensen.
Testing on RPI 2, with ArchLinuxARM-rpi-2-latest and 2015-02-16-raspbian-wheezy.
1.44 Added documention about the need for device tree to be enabled on RPI2.
Improvements to detection of availability of DMB instruction based on value of __ARM_ARCH macro.
1.46 2015-09-18 Added symbolic definitions for remaining pins on 40 pin GPIO header on RPi 2.
1.47 2015-11-18 Fixed possibly incorrect reads in bcm2835_i2c_read_register_rs, patch from Eckhardt Ulrich.
1.48 2015-12-08 Added patch from Eckhardt Ulrich that fixed problems that could cause hanging with bcm2835_i2c_read_register_rs and others.
1.50 2016-02-28 Added support for running as non-root, permitting access to GPIO only. Functions
bcm2835_spi_begin() and
bcm2835_i2c_begin() will now return 0 if not running as root (which prevents access to the SPI and I2C peripherals, amongst others). Testing on Raspbian Jessie.
1.51 2016-11-03 Added documentation about SPI clock divider and resulting SPI speeds on RPi3. Fixed a problem where seg fault could occur in
bcm2835_delayMicroseconds() if not running as root. Patch from Pok.
1.52 2017-02-03 Added link to commercial license purchasing.
1.54 2018-01-17 Fixed compile errors in new AUX spi code under some circumstances.
1.55 2018-01-20 Fixed version numbers. Fixed some warnings.
1.56 2018-06-10 Supports bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST), after which SPI bytes are reversed on read or write. Based on a suggestion by Damiano Benedetti.
Author
树莓派C所在的库和include
树莓派,(英语:Raspberry Pi,简写为RPi,别名为RasPi / RPI)是为学习计算机编程教育而设计,只有信用卡大小的微型电脑,其系统基于Linux。随着Windows 10 IoT的发布,用户可以用上运行Windows的树莓派。树莓派自问世以来,受众多计算机发烧友和创客的追捧
树莓派C所在的库和include
/usr/include
/usr/lib
/usr/local/include
/usr/local/lib
基于RFID RC522模块制作树莓派通读卡器
RC522 RFID模块在单片机开发中常用来作为读卡器使用,在本文中我们把它连接到树莓派,然后就可以制作读卡器了,比如读取门禁卡的UID。本项目只是一个读卡器的雏形,如果需要运用到实际项目中,还需要你的更多深加工。读卡器常见的应用场景还是安全管理系统,其它常见的应用场景还有按卡计时、考勤系统和游戏系统授权等。
RC522 RFID模块支持的卡片标准
使用RC522芯片的模块支持以下标准的卡片:
MIFARE Mini
MIFARE 1K
MIFARE 4K,
MIFARE Ultralight
MIFARE DESFire EV1
MIFARE Plus RF
当我们购买卡片时,应该确保卡片支持以上标准。
RC522 RFID模块接口定义
市面上的RC522 RFID模块可能因为生产厂家不同外观上会有些许不同,常见的是下图蓝色外观,8个引脚的这种。在模块的PCB上我们可以看到天线的线路布局,模块就是通过天线与靠近它的卡片进行通信的。
上图左上角,蓝色圆扣状卡片是一种可以挂在钥匙扣上的卡片,所有的卡片都有一个惟一的UID,我们可以使用Python脚本来读取它。
上图是RC522 RFID模块的接口定义,从图中可以看出RC522 RFID模块支持UART接口、I2C总线接口和SPI可编程接口。
RC522 RFID模块与树莓派的电路连接
RC522模块有8个引脚,但我们只需要将其中7个引脚连接到树莓派的GPIO接口即可。RC522模块的引脚定义见上图,电路连接见下图。
RC522 Header | Diagram Colour | Pi Header | Notes |
3.3V | Grey | 1 | 3.3V |
RST | White | 22 | GPIO25 |
GND | Black | 6 | Ground |
IRQ | – | – | Not connected |
MISO | Purple | 21 | GPIO9 |
MOSI | Blue | 19 | GPIO10 |
SCK | Green | 23 | GPIO11 |
SDA | Yellow | 24 | GPIO8 |
树莓派3B+如何打开SPI接口
在本项目中,RC522模块使用SPI接口与树莓派进行通信。因此,树莓派的SPI接口必须要先启用,默认情况下树莓派的SPI接口是禁用的,SPI接口如何打开可以参照 修改树莓派I2C总线接口速度 中的做法。也就是从命令行“sudo raspi-config”进入系统配置打开,或者从桌面进入“Raspberry Pi Configuration”面板中去打开。
安装树莓派3B+的SPI接口支持库
这里的支持库分别是“Py-spidev”和“SPI-Py”,安装“Py-spidev”可以使用命令来安装:
sudo apt-get install python-spidev python3-spidev
这样“Py-spidev”就可以同时支持Python 2和Python 3了。虽然使用“py-spidev”可以驱动Python中的SPI接口,但是项目中我们使用了“SPI-Py”,可以通过以下命令来完成安装“SPI-Py”:
cd ~
git clone https://github.com/lthiery/SPI-Py.git
cd SPI-Py
sudo python setup.py install
sudo python3 setup.py install
同样的“SPI-Py”也可以同时支持Python 2和Python 3了。
下载RC522 的Python库
最后我们还需要下载一个RC522 的Python库,它可以实现SPI接口与RC522模块的通信,这个库依赖于上一步中安装的“SPI-Py”。
cd ~
git clone https://github.com/mxgxw/MFRC522-python.git
Python脚本示例
在“MFRC522-python”目录中有一些示例脚本。可以这样使用它:
cd MFRC522-python
进入“MFRC522-python”目录,然后运行“Read.py”
python Read.py
这个脚本的功能是,首先等待RFID模块检测可识别卡。当它检测到一张卡时,读取该卡的UID并将其显示在屏幕上。该脚本可循环执行,也就是当它读取一个UID后,它还会继续等待读取并显示任何检测到的卡片UID。
Python 2 或 Python 3代码
默认情况下,MFRC522的库只支持Python 2。如果使用Python 3也可以很容易的进行修改。我们只需要修改“MFRC522.py”文件即可,按Python 3的语法格式修改9个 print 语句即可。例如,
print "Authentication Error" 修改为:print("Authentication Error")
Python 3语法中,print语句之后的所有内容都应该用括号“()”括起来。这样示例程序也可以在Python 3下运行了,依然采用“python Read.py”。
本项目的Python脚本
为了简化输出,本项目代码中创建了一个修改过的示例脚本。它首先读取一张卡片,打印出UID后等待2秒,这样就不会重复打印相同的UID了,除非你将卡片放置天线感应到的区域超过2秒。
import time
import RPi.GPIO as GPIO
import MFRC522
# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()
# Welcome message
print("Looking for cards")
print("Press Ctrl-C to stop.")
# This loop checks for chips. If one is near it will get the UID
try:
while True:
# Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
# Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()
# If we have the UID, continue
if status == MIFAREReader.MI_OK:
# Print UID
print("UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]))
time.sleep(2)
except KeyboardInterrupt:
GPIO.cleanup()
将上面的代码保存为“rc522_read_card.py”。然后运行:
python rc522_read.py
输出结果如下:
UID是由四个元素组成的数组,脚本将每个元素组合成一个由逗号分隔的字符串。数组的4个元素可以组合成一个纯数字。例如,我的卡片UID是“1483565119”,而不是“148,35,65,119”。至此读卡器项目的雏形就完成了。
C语言操作的是wirePI角
树莓派学习笔记——wiringPi I2C设备使用详解
1.前言
最近认真学习了树莓派,从浅到深认真分析了wiringPi实现代码,借助树莓派学习linux收获颇丰。深入学习linux一段时间后发现它非常有魅力,一个简单的IO口输出操作尽有那么多的“玩法”。wiringPi是一个简单易用的函数库,通过wiringPi可以扩展SPI和I2C等芯片,关于wiringPi的介绍和安装请参考我的另一篇【博文】。 本篇博文将通过一个简单的例子呈现wiringPi的使用,虽然例子简单但会深入分析wiringPi内部实现代码。
2.若干简述
2.1 MCP23107简述
a) 硬件基本信息
MCP23017的采用7位I2C地址,7位I2C地址中的低3位从高到低分别为A2 A1和A0,该3位为地址选择位,若地址选择全部接GND,那么MCP23017的I2C从机地址为0x20。下图为MCP23017的硬件基本信息,左侧为MCP23017引脚图,右侧为I2C从机地址组成示意图,从机地址的高4位为0100,高4位数字固定不变。
MCP23017具有GPA和GPB共16个扩展端口,另外INTA和INTB为IO中断管脚,可反映GPA或GPB的电平变化情况。请注意,RESET为复位管脚低电平有效,可直接上拉到VDD或接一个1K到10K的电阻上拉至VDD。(经过两天的调试,我发现MCP23017运行几秒便不能运行,后来发现RESET管脚悬空,之后RESET和VDD相连问题解决。)
b) 字节模式
MCP23X17 系列能够工作于字节模式或顺序模式 (IOCON.SEQOP)。
字节模式禁止地址指针自动递增。工作于字节模式时,MCP23X17系列在数据传送期间,传送每个字节后不会递增其内部地址计数器。顺序模式可使地址指针自动递增。工作于顺序模式时,MCP23X17系列在数据传送期间,传送每个字节后会递增其地址计数器。访问最后一个寄存器后,地址指针自动返回到地址00h。(SEQOP位默认值为0)
c) 寄存器映射关系
BANK位用于更改寄存器的映射方式
如果BANK = 1,与每个端口关联的寄存器将相互独立。与PORTA关联的寄存器从地址00h - 0Ah 映射,与PORTB关联的寄存器从10h - 1Ah映射;如果BANK = 0,A/B寄存器将配对组合。例如,IODIRA将映射到地址00h,而IODIRB将映射到 下一地址 (地址01h)。所有寄存器的映射是从00H到15H。(BANK默认值为0)
图2 寄存器地址映射关系
【其他重要寄存器】
【IODIR I/O方向寄存器。
写1为输入状态,写0为输出状态。请注意在大多数MCU中,写1为输出状态,而MCP23017这样类似的设置完全是microchip的特色。
【GPPU】GPPU上拉电阻寄存器
写1为使能上拉,写入0为禁止上拉。使能芯片内部的上拉电阻往往有很有用。
【GPIO】通用I/O端口寄存器
写1可以使相应的端口输出高电平,写0可以使响应的端口输出低电平。读取该寄存器可以获得相应端口的输入值。
2.2 用户空间开发I2C设备
通常情况下I2C设备由内核控制。但是在用户空间也可以通过 /dev设备接口访问I2C设备。每一个在内核注册的I2C设备都具有一个编号,该编号从0开始计数,可以查看 /sys/class/i2c-dev/查看具体编号,也可以通过i2ctool工具中的i2cdetect查看。【i2cdetect工具的安装和使用】【I2C操作时序介绍】
在linux系统中所有的设备都可以采用文件的形式访问,树莓派的i2c设备位于/dev/i2c-x(对应树莓派版本2为/dev/i2c-1),可通过open,close,wirte,read和ioclt控制i2c设备。例如open为打开I2C设备,close为关闭I2C设备,wirte为向I2C设备写入字节内容,read为从I2C设备获得字节内容,ioctl可控制I2C设备的运行参数,例如从机地址或I2C速度等参数。更多内容请参考【linux内核 I2C驱动说明】。 默认情况下,I2C和SPI设备被拉入了“黑名单”,换句话说在树莓派初始化时SPI和I2C设备并没有载入内核。在使用I2C设备之前需要载入SPI和I2C设备,具体参开请参考博文【树莓派I2C和SPI设备配置】
3.简单测试代码
- #include <stdio.h>
- #include <wiringPi.h>
- #include <mcp23017.h>
- // 扩展MCP23017 起始PIN地址
- // MCP23017占用 100-115
- #define EXTEND_BASE 100
- int main (void)
- {
- // wiringPi初始化
- wiringPiSetup( );
- // mcp23017初始化,此时MCP23017的I2C地址为0x20
- mcp23017Setup( EXTEND_BAS E, 0x20 );
-
- int i;
- for( i = 0 ; i < 16 ; i++ )
- {
- pinMode( EXTEND_BASE + i, OUTPUT );
- }
- for (;;)
- {
- for( i = 0 ; i < 16; i++)
- {
- digitalWrite ( EXTEND_BASE + i, HIGH);
- delay (500);
- digitalWrite ( EXTEND_BASE + i, LOW);
- delay (500);
- }
- }
- return 0 ;
- }
4.代码详解
4.1 wiringPiSetup
4.2 mcp23017Setup
- int mcp23017Setup (const int pinBase, const int i2cAddress)
- {
- int fd ;
- struct wiringPiNodeStruct *node ;
- // 初始化I2C设备
- if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
- return fd ;
- // 附加操作,设置MCP23017设备 I2C操作地址不自动递增
- wiringPiI2CWriteReg8 (fd, MCP23x17_IOCON, IOCON_INIT) ;
- // MCP23017加入链表
- node = wiringPiNewNode (pinBase, 16) ;
- // 赋值相应的操作函数 my开头的函数均位于mcp23017.c文件中
- node->fd = fd ;
- node->pinMode = myPinMode ;
- node->pullUpDnControl = myPullUpDnControl ;
- node->digitalRead = myDigitalRead ;
- node->digitalWrite = myDigitalWrite ;
- node->data2 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATA) ;
- node->data3 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATB) ;
- return 0 ;
- }
mcp23017Setup是一个较为复杂的函数,主要实现三部分功能——第一,初始化树莓派I2C设备,通过打开/dev/i2c-1实现(相对于树莓派2版本),通过open可返回一个文件fd(可理解为设备的标记或编号,就是一个数字,好比你的身份证号);第二,加入新节点,wiringPi通过一个链表维护所有的pin,在树莓派中pin是一个比较有趣的概念,例如一个MCP23017具有16个输入或输出PIN,这使得wiringPi增加额外的16个PIN,该16个PIN起始地址可以设定,但必须大于64,16个PIN的地址连续;第三,增加控制函数,例如digitalRead,digitalWrite和pullUpDnControl等。
4.2.1 I2C初始化 wiringPiI2CSetup
初始化的最终目标为 fd = open (device, O_RDWR) 和 ioctl (fd, I2C_SLAVE, devId)
【调用关系】 【wiringPiI2CSetup】 --> 【wiringPiI2CSetupInterface】
【wiringPiI2CSetupInterface】 --> 【 fd = open (device, O_RDWR) 】
--> 【 ioctl (fd, I2C_SLAVE, devId) 】
4.2.2 加入新节点 wiringPiNewNode
wiringPi的外部设备有一个链表构成,相应的数字量读写和模拟量读写均根据该链表完成。该链表是wiringPi的"核心",链表结构体见以下代码。在该结构体中记录了节点编号(设备的起始编号 pinBase),以及各种操作函数【操作函数的说明请看4.2.3】。
- struct wiringPiNodeStruct
- {
- int pinBase ;
- int pinMax ;
- int fd ; // Node specific
- unsigned int data0 ; // ditto
- unsigned int data1 ; // ditto
- unsigned int data2 ; // ditto
- unsigned int data3 ; // ditto
- void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ;
- void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ;
- int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ;
- void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
- void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
- int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ;
- void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
- struct wiringPiNodeStruct *next ;
- } ;
wiringPiNewNode相关操作可分为3步
【1】查找MCP23017的pin是否被占用。
【2】在内存中开辟一个wiringPiNewNode。
【3】给该结构体变量设置默认值,并添加到控制链表中。
4.2.3 编写控制函数
【pinMode】IO口功能设置函数,mode参数——INPUT为输入状态,OUTPUT为输出状态
【pullUpDnControl】IO口输入功能设置,mode参数
【digitalRead】读取IO口管脚电平状态
【digitalWrite】设置IO口电平状态
【analogRead】若该IO为模拟量输入端口,读取该端口的模拟输入
【analogWrite】若该IO为模拟量输出端口,设置该端口的模拟输出
4.3 pinMode
MCP23017的扩展pin必须大于64,在MCP23017Setup函数中注册了相应的pin,此处通过wiringPiFindNode在链表中查找MCP23017的node信息,node信息包括pin编号、设置IO方向、读取和设置IO管脚等。请注意 node->pinMode (node, pin, mode) 指向 MCP23017中的myPinMode函数,该注册工作在mcp23017Setup发生。
- // 位于wiringPi.c
- void pinMode (int pin, int mode)
- {
- int fSel, shift, alt ;
- struct wiringPiNodeStruct *node = wiringPiNodes ;
-
- // PIN编号小于64,内部设备
- if ((pin & PI_GPIO_MASK) == 0)
- {
- // 代码省略
- }
- else
- {
- // 查找是否存在该设备
- if ((node = wiringPiFindNode (pin)) != NULL)
- node->pinMode (node, pin, mode) ;
- return ;
- }
- }
- // 位于mcp23017.c
- static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
- {
- int mask, old, reg ;
- pin -= node->pinBase ;
- // 操作GPA 或 GPB
- if (pin < 8)
- reg = MCP23x17_IODIRA ;
- else
- {
- reg = MCP23x17_IODIRB ;
- pin &= 0x07 ;
- }
-
- // 获得IODIRx原始值
- mask = 1 << pin ;
- old = wiringPiI2CReadReg8 (node->fd, reg) ;
- // 设置新值
- if (mode == OUTPUT)
- old &= (~mask) ;
- else
- old |= mask ;
- wiringPiI2CWriteReg8 (node->fd, reg, old) ;
- }
4.4 digitalWrite
digitalWrite函数和pinMode函数操作思路相同,先检测该pin位于板载区域还是扩展区域,如果是扩展区域该pin是否有效,如果有效则调用digitalRead函数。
- // 位于wiringPi.c
- int digitalWrite (int pin)
- {
- char c ;
- struct wiringPiNodeStruct *node = wiringPiNodes ;
- // PIN编号小于64,内部设备
- if ((pin & PI_GPIO_MASK) == 0)
- {
- // 代码省略
- }
- else
- {
- // 查找是否存在该设备
- if ((node = wiringPiFindNode (pin)) == NULL)
- return LOW ;
- return node->digitalWrite (node, pin) ;
- }
- }
- // 位于mcp23017.c
- static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
- {
- int bit, old ;
- pin -= node->pinBase ;
- bit = 1 << (pin & 7) ;
- // 操作GPA
- if (pin < 8)
- {
- old = node->data2 ;
- if (value == LOW)
- old &= (~bit) ;
- else
- old |= bit ;
- wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOA, old) ;
- node->data2 = old ;
- }
- // 操作GPB
- else
- {
- old = node->data3 ;
- if (value == LOW)
- old &= (~bit) ;
- else
- old |= bit ;
- wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOB, old) ;
- node->data3 = old ;
- }
- }
4.6 wiringPiI2CReadReg8 和 wiringPiI2CWriteReg8
这两个函数涉及到linux驱动方面的内容,均通过ioctl (fd, I2C_SMBUS, &args)实现,具体请看以下代码,更多底层的内容请参考【linux内核 I2C驱动说明】 - struct i2c_smbus_ioctl_data
- {
- char read_write ;
- uint8_t command ;
- int size ;
- union i2c_smbus_data *data ;
- } ;
- static inline int i2c_smbus_access (int fd, char rw, uint8_t command, int size, union i2c_smbus_data *data)
- {
- struct i2c_smbus_ioctl_data args ;
- args.read_write = rw ;
- args.command = command ;
- args.size = size ;
- args.data = data ;
- return ioctl (fd, I2C_SMBUS, &args) ;
- }
- int wiringPiI2CReadReg8 (int fd, int reg)
- {
- union i2c_smbus_data data;
- if (i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data))
- return -1 ;
- else
- return data.byte & 0xFF ;
- }
- int wiringPiI2CWriteReg8 (int fd, int reg, int value)
- {
- union i2c_smbus_data data ;
- data.byte = value ;
- return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &data) ;
- }
5.总结与提高
wiringPi提供了一个很好的封装,但是也是一把双刃剑。对于初学而言可以很好的利用树莓派实现应用,绕开linux驱动方面的知识,但是慢慢熟悉之后还是要补充linux驱动方面的内容个,使用open、wirte和ioctl实现I2C设备的控制。
国外有很多博文指出,BCM2835的I2C存在问题,该问题发生在I2C Stop时序保持的时间太短导致I2C从设备无法正常体质。参考资料中的第1项包含对I2C硬件问题的讨论和解决方法,请各位参考。
QT 添加自定义类中使用Q_OBJECT宏问题
今天在使用Qt5中,使用类向导添加自定义类后,并添加Q_OBJECT宏,出现报错:error: undefined reference to `vtable for xxxx'
印象中,VS 报此错误一般是虚函数没有实现,仔细检查自定义类,并未发现代码异常。
在Qt中如果要使用信号槽就必须添加Q_OBJECT宏,至于Q_OBJECT宏的作用可以查看帮助里的介绍。要使用Q_OBJECT宏,就必须继承QObject类
如果自定义类型要添加使用Q_OBJECT宏可以通过如下方法:
1. 继承QObject
2. 修改pro文件(也就是文件带*),以达到修改makefile文件的目的(添加删除,空行空格都可以),只要修改pro文件就行。
3. 重新编译
树莓派wiringPi库详解
wiringPi是一个很棒的树莓派IO控制库,使用C语言开发,提供了丰富的接口:GPIO控制,中断,多线程,等等。java 的pi4j项目也是基于wiringPi的,我最近也在看源代码,到时候整理好了会放出来的。
下面开始wiringPi之旅吧!
安装
进入 wiringPi的github (https://git.drogon.net/?p=wiringPi;a=summary) 下载安装包。点击页面的第一个链接的右边的snapshot,下载安装压缩包。
然后进入安装包所在的目录执行以下命令:
>tar xfz wiringPi-98bcb20.tar.gz //98bcb20为版本标号,可能不同
>cd wiringPi-98bcb20
>./build
验证wiringPi的是否安装成功,输入gpio -v,会在终端中输出相关wiringPi的信息。否则安装失败。
编译 和运行
假如你写了一个LEDtest.c 的项目,则如下。
编译:
g++ -Wall -o LEDtest LEDtest.cpp -lwiringPi //使用C++编程 , -Wall 是为了使能所有警告,以便发现程序中的问题
gcc -Wall -o LEDtest LEDtest.c -lwiringPi //使用C语言编程
运行:
sudo ./LEDtest
查看引脚编号表格
使用如下控制台下命令
> gpio readall
也可以查看下面的图。
注意:查看时,将树莓派的USB接口面对自己,这样看才是正确的。
wiringPi库API大全
在使用wiringPi库时,你需要包含头文件 #include<wiringPi.h>。凡是写wiringPi的程序,都包含这个头文件。
硬件初始化函数
使用wiringPi时,你必须在执行任何操作前初始化树莓派,否则程序不能正常工作。
可以调用下表函数之一进行初始化,它们都会返回一个int , 返回 -1 表示初始化失败。
int wiringPiSetup (void) | 返回:执行状态,-1表示失败 | 当使用这个函数初始化树莓派引脚时,程序使用的是wiringPi 引脚编号表。引脚的编号为 0~16 需要root权限 |
int wiringPiSetupGpio (void) | 返回执行状态,-1表示失败 | 当使用这个函数初始化树莓派引脚时,程序中使用的是BCM GPIO 引脚编号表。 需要root权限 |
wiringPiSetupPhys(void) | 不常用,不做介绍 | / |
wiringPiSetupSys (void) ; | 不常用,不做介绍 | / |
通用GPIO控制函数
void pinMode (int pin, int mode) | pin:配置的引脚 mode:指定引脚的IO模式 可取的值:INPUT、OUTPUT、PWM_OUTPUT,GPIO_CLOCK | 作用:配置引脚的IO模式 注意: 只有wiringPi 引脚编号下的1脚(BCM下的18脚) 支持PWM输出 只有wiringPi编号下的7(BCM下的4号)支持GPIO_CLOCK输出 |
void digitalWrite (int pin, int value) | pin:控制的引脚 value:引脚输出的电平值。 可取的值:HIGH,LOW分别代表高低电平 | 让对一个已近配置为输出模式的 引脚 输出指定的电平信号 |
int digitalRead (int pin) | pin:读取的引脚 返回:引脚上的电平,可以是LOW HIGH 之一 | 读取一个引脚的电平值 LOW HIGH ,返回 |
void analogWrite(int pin, int value) | pin:引脚 value:输出的模拟量 | 模拟量输出 树莓派的引脚本身是不支持AD转换的,也就是不能使用模拟量的API, 需要增加另外的模块 |
int analogRead (int pin) | pin:引脚 返回:引脚上读取的模拟量 | 模拟量输入 树莓派的引脚本身是不支持AD转换的,也就是不能使用模拟量的API, 需要增加另外的模块 |
void pwmWrite (int pin, int value) | pin:引脚 value:写入到PWM寄存器的值,范围在0~1024之间。 | 输出一个值到PWM寄存器,控制PWM输出。 pin只能是wiringPi 引脚编号下的1脚(BCM下的18脚) |
void pullUpDnControl (int pin, int pud) | pin:引脚 pud:拉电阻模式 可取的值:PUD-OFF 关闭拉电阻 PUD_DOWN 引脚电平拉到0.0v PUD_UP 引脚电平拉到3.3v 接地 | 对一个设置IO模式为 INPUT 的输入引脚设置拉电阻模式。 与Arduino不同的是,树莓派支持的拉电阻模式更丰富。 树莓派内部的拉电阻达50K欧姆 |
LED闪烁程序
#include<iostream>
#include<cstdlib>
#include<wiringPi.h>
const int LEDpin = 1;
int main()
{
if(-1==wiringPiSetup())
{
cerr<<"setup error\n";
exit(-1);
}
pinMode(LEDpin,OUTPUT);
for(size_t i=0;i<10;++i)
{
digitalWrite(LEDpin,HIGH);
delay(600);
digitalWrite(LEDpin,LOW);
delay(600);
}
cout<<"------------bye-------------"<<endl;
return 0;
}
PWM输出控制LED呼吸灯的例子
#include<iostream>
#include<wiringPi.h>
#include<cstdlib>
using namespace std;
const int PWMpin = 1; //只有wiringPi编号下的1脚(BCM标号下的18脚)支持
void setup();
int main()
{
setup();
int val = 0;
int step = 2;
while(true)
{
if(val>1024)
{
step = -step;
val = 1024;
}
else if(val<0)
{
step = -step;
val = 0;
}
pwmWrite(PWMpin,val);
val+=step;
delay(10);
}
return 0;
}
时间控制函数
unsigned int millis (void) | 这个函数返回 一个 从你的程序执行 wiringPiSetup 初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 毫秒数。 返回类型是unsigned int,最大可记录 大约49天的毫秒时长。 |
unsigned int micros (void) | 这个函数返回 一个 从你的程序执行 wiringPiSetup 初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 微秒数。 返回类型是unsigned int,最大可记录 大约71分钟的时长。 |
void delay (unsigned int howLong) | 将当前执行流暂停 指定的毫秒数。因为Linux本身是多线程的,所以实际暂停时间可能会长一些。参数是unsigned int 类型,最大延时时间可达49天 |
void delayMicroseconds (unsigned int howLong) | 将执行流暂停 指定的微秒数(1000微秒 = 1毫秒 = 0.001秒)。 因为Linux本身是多线程的,所以实际暂停时间可能会长一些。参数是unsigned int 类型,最大延时时间可达71分钟 |
中断
wiringPi提供了一个中断处理注册函数,它只是一个注册函数,并不处理中断。他无需root权限。
int wiringPiISR (int pin, int edgeType, void (*function)(void)) | 返回值:返回负数则代表注册失败 pin:接受中断信号的引脚 edgeType:触发的方式。 INT_EDGE_FALLING:下降沿触发 INT_EDGE_RISING:上升沿触发 INT_EDGE_BOTH :上下降都会触发 INT_EDGE_SETUP:编程时用不到。 function:中断处理函数的指针,它是一个无返回值,无参数的函数。 | 注册的函数会在中断发生时执行 和51单片机不同的是:这个注册的中断处理函数会和main函数并发执行(同时执行,谁也不耽误谁) 当本次中断函数还未执行完毕,这个时候树莓派又触发了一个中断,那么这个后来的中断不会被丢弃,它仍然可以被执行。但是wiringPi最多可以跟踪并记录后来的仅仅1个中断,如果不止1个,则他们会被忽略,得不到执行。 |
通过1脚检测 因为按键按下引发的 下降沿,触发中断,反转11控制的LED
#include<iostream>
#include<wiringPi.h>
#include<cstdlib>
using namespace std;
void ButtonPressed(void);
void setup();
/********************************/
const int LEDPin = 11;
const int ButtonPin = 1;
/*******************************/
int main()
{
setup();
//注册中断处理函数
if(0>wiringPiISR(ButtonPin,INT_EDGE_FALLING,ButtonPressed))
{
cerr<<"interrupt function register failure"<<endl;
exit(-1);
}
while(1)
;
return 0;
}
void setup()
{
if(-1==wiringPiSetup())
{
cerr<<"wiringPi setup error"<<endl;
exit(-1);
}
pinMode(LEDPin,OUTPUT); //配置11脚为控制LED的输出模式
digitalWrite(LEDPin,LOW); //初始化为低电平
pinMode(ButtonPin,INPUT); //配置1脚为输入
pullUpDnControl(ButtonPin,PUD_UP); //将1脚上拉到3.3v
}
//中断处理函数:反转LED的电平
void ButtonPressed(void)
{
digitalWrite(LEDPin, (HIGH==digitalRead(LEDPin))?LOW:HIGH );
}
多线程
wiringPi提供了简单的Linux系统下的通用的 Posix threads线程库接口来支持并发。
int piThreadCreate(name) | name:被包装的线程执行函数 返回:状态码。返回0表示成功启动,反之失败。 源代码: int piThreadCreate (void *(*fn)(void *)) { pthread_t myThread ; return pthread_create (&myThread, NULL, fn, NULL) ; } | 包装一个用PI_THEEAD定义的函数为一个线程,并启动这个线程。 首先你需要通过以下方式创建一个特特殊的函数,这个函数中的代码就是在新的线程中将执行的代码。,myTread是你自己线程的名字,可自定义。 PI_THREAD (myThread) { //在这里面写上的代码会和主线程并发执行。 } 在wiringPi.h中,我发现这样一个宏定义:#define PI_THREAD(X) void *X (void *dummy) 那么,被预处理后我们写的线程函数会变成下面这个样子,请注意返回值,难怪我每次写都会警告,因为没有返回一个指针, 那么,以后注意返回NULL,或者 (void*)0 void *myThread (void *dummy) { //在这里面写上的代码会和主线程并发执行。 } |
piLock(int keyNum) | keyNum:0-3的值,每一个值代表一把锁 | 使能同步锁。wiringPi只提供了4把锁,也就是keyNum只能取0~3的值,官方认为有这4把锁就够了。 keyNum:0,1,2,3 每一个数字就代表一把锁。 源代码: void piLock (int keyNum) { pthread_mutex_lock (&piMutexes [keyNum]) ; } |
piUnlock(int keyNum) | keyNum:0-3的值,每一个值代表一把锁 | 解锁,或者说让出锁。 源代码: void piUnlock (int key) { pthread_mutex_unlock (&piMutexes [key]) ; } |
int piHiPri (int priority) | priority:优先级指数,0~99 返回值:0,成功 -1:,失败 | 设定线程的优先级,设定线程的优先级变高,不会使程序运行加快,但会使这个线程获得相当更多的时间片。priority是相对的。比如你的程序只用到了主线程, 和另一个线程A,主线程设定优先级为1,A线程设定为2,那也代表A比main线程优先级高。 |
凡是涉及到多线程编程,就会涉及到线程安全的问题,多线程访问同一个数据,需要使用同步锁来保障数据操作正确性和符合预期。
当A线程锁上 锁S 后,其他共用这个锁的竞争线程,只能等到锁被释放,才能继续执行。
成功执行了piLock 函数的线程将拥有这把锁。其他线程想要拥有这把锁必须等到这个线程释放锁,也就是这个线程执行piUnlock后。
同时要扩展的知识是:volatile 这个C/C++中的关键字,它请求编译器不缓存这个变量的数据,而是每次都从内存中读取。特别是在多线程下共享放变量,必须使用volatile关键字声明才是保险的。
softPwm,软件实现的PWM
树莓派硬件上支持的PWM输出的引脚有限,为了突破这个限制,wiringPi提供了软件实现的PWM输出API。
需要包含头文件:#include <softPwm.h>
编译时需要添pthread库链接 -lpthread
int softPwmCreate (int pin, int initialValue, int pwmRange) | pin:用来作为软件PWM输出的引脚 initalValue:引脚输出的初始值 pwmRange:PWM值的范围上限 建议使用100. 返回:0表示成功。 | 使用一个指定的pin引脚创建一个模拟的PWM输出引脚 |
void softPwmWrite (int pin, int value) | pin:通过softPwmCreate创建的引脚 value:PWM引脚输出的值 | 更新引脚输出的PWM值 |
串口通信
使用时需要包含头文件:#include <wiringSerial.h>
int serialOpen (char *device, int baud) | device:串口的地址,在Linux中就是设备所在的目录。 默认一般是"/dev/ttyAMA0",我的是这样的。 baud:波特率 返回:正常返回文件描述符,否则返回-1失败。 | 打开并初始串口 |
void serialClose (int fd) | fd:文件描述符 | 关闭fd关联的串口 |
void serialPutchar (int fd, unsigned char c) | fd:文件描述符 c:要发送的数据 | 发送一个字节的数据到串口 |
void serialPuts (int fd, char *s) | fd:文件描述符 s:发送的字符串,字符串要以'\0'结尾 | 发送一个字符串到串口 |
void serialPrintf (int fd, char *message, …) | fd:文件描述符 message:格式化的字符串 | 像使用C语言中的printf一样发送数据到串口 |
int serialDataAvail (int fd) | fd:文件描述符 返回:串口缓存中已经接收的,可读取的字节数,-1代表错误 | 获取串口缓存中可用的字节数。 |
int serialGetchar (int fd) | fd:文件描述符 返回:读取到的字符 | 从串口读取一个字节数据返回。 如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1 所以,在读取前,做好通过serialDataAvail判断下。 |
void serialFlush (int fd) | fd:文件描述符 | 刷新,清空串口缓冲中的所有可用的数据。 |
*size_t write (int fd,const void * buf,size_t count) | fd:文件描述符 buf:需要发送的数据缓存数组 count:发送buf中的前count个字节数据 返回:实际写入的字符数,错误返回-1 | 这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h> 当要发送到的数据量过大时,wiringPi建议使用这个函数。 |
*size_t read(int fd,void * buf ,size_t count); | fd:文件描述符 buf:接受的数据缓存的数组 count:接收的字节数. 返回:实际读取的字符数。 | 这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h> 当要接收的数据量过大时,wiringPi建议使用这个函数。 |
初次使用树莓派串口编程,需要配置。我开始搞了很久,以为是程序写错了 还一直在调试。。。(~ ̄— ̄)
/* 修改 cmdline.txt文件 */
>cd /boot/
>sudo vim cmdline.txt
删除【】之间的部分
dwc_otg.lpm_enable=0 【console=ttyAMA0,115200】 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
/*修改 inittab文件 */
>cd /etc/
>sudo vim inittab
注释掉最后一行内容:,在前面加上 # 号
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
sudo reboot 重启
下面是双机通信的一个例子
C51代码,作为串口通信的接发送。serial库请看另一篇文章
#include<reg52.h>
#include"serial.h"
/**********function****************/
bit isOpenPressed(void);
bit isClosePressed(void);
void delay(unsigned int t);
/*********************************/
sbit closeButton = P2^0; //与关闭按键相连的引脚
sbit openButton = P2^1; //与打开按键相连的引脚
void main(void)
{
closeButton = 1; //拉高
openButton = 1; //拉高
EA =1; //打开总中断
serial_init(9600); //初始化51串口
while(1)
{
if(isClosePressed()) //如果关闭按钮按下
{
serial_write(0); //发送数据 0给树莓派
delay(10);
}
else if(isOpenPressed()) //如果打开按钮按下
{
serial_write(1); //发送数据 1给树莓派
delay(10);
}
}
}
bit isOpenPressed(void)
{
bit press =0;
if(0==openButton)
{
delay(5);
if(0==openButton)
{
while(!openButton)
;
press = 1;
}
}
return press;
}
bit isClosePressed(void)
{
bit press =0;
if(0==closeButton)
{
delay(5);
if(0==closeButton)
{
while(!closeButton)
;
press = 1;
}
}
return press;
}
void delay(unsigned int t)
{
unsigned int i ;
unsigned char j;
for(i = t;i>0;i--)
for(j=120;j>0;j--)
;
}
shift移位寄存器芯片API
需要包含头文件 #include <wiringShift.h>
void shiftOut (uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val) | dPin:移位芯片的串行数据入口引脚,比如74HC595的SER脚 cPin:移位芯片的时钟引脚。如74HC595的11脚 order: LSBFIRST 先发送数据的低位 MSBFIRST先发送数据的高位 val:要发送的8位数据 | 将val串化,通过芯片转化为并行输出 如常见的74HC595 |
uint8_t shiftIn (uint8_t dPin, uint8_t cPin, uint8_t order) | 同上。 | 将并行数据,通过芯片转化为串行输出。 |
用过595的都知道还有一个引脚:12脚,Rpin,用于把移位寄存器中的数据更新到存储寄存器中,然后wiringPi的API中没有使用这个引脚。我建议使用的时候自己加上
#include<iostream>
#include<cstdlib>
#include<wiringPi.h>
#include<wiringSerial.h>
using namespace std;
void setup();
const int LEDPin = 11;
int main()
{
setup();
int fd; //Linux 的思想是:将一切IO设备,都看做 文件,fd就是代表串口抽象出来的文件
if((fd = serialOpen("/dev/ttyAMA0",9600))==-1) //初始化串口,波特率9600
{
cerr<<"serial open error"<<endl;
exit(-1);
}
while(true)
{
if(serialDataAvail(fd) >= 1) //如果串口缓存中有数据
{
int data = serialGetchar(fd);
if(data==0) //接受到51发送的 数据 0
{
// close led
digitalWrite(LEDPin,LOW);
}
else if(data==1) //接受到51发送的 数据 1
{
//open led
digitalWrite(LEDPin,HIGH);
}
}
}
return 0;
}
void setup()
{
if(-1==wiringPiSetup())
{
cerr<<"set up error"<<endl;
exit(-1);
}
pinMode(LEDPin,OUTPUT);
digitalWrite(LEDPin,HIGH);
}
树莓派硬件平台特有的API
并没有列全,我只是列出了相对来说有用的,其他的,都基本不会用到。
pwmSetMode (int mode) | mode:PWM运行模式 | 设置PWM的运行模式。 pwm发生器可以运行在2种模式下,通过参数指定: PWM_MODE_BAL :树莓派默认的PWM模式 PWM_MODE_MS :传统的pwm模式, |
pwmSetRange (unsigned int range) | range,范围的最大值 0~range | 设置pwm发生器的数值范围,默认是1024 |
pwmSetClock (int divisor) |
| This sets the divisor for the PWM clock. To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual. |
piBoardRev (void) | 返回:树莓派板子的版本编号 1或者2 | / |
就这样,以后会更新。
树莓派上的QT
QT Quick在liunx上的可看/usr/lib/arm-linux-gnueabihf/qt5/qml/Quick
树莓派上的QT
import QtQuick 2.7
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.0
ApplicationWindow {
visible: true;
width: 640;
height: 480;
title: qsTr("Hello World")
Rectangle{
anchors.fill: parent;
RowLayout{
id:list;
anchors.top: parent.top;
anchors.topMargin:20;
anchors.left: parent.left;
anchors.right: parent.right;
anchors.leftMargin:10;
anchors.rightMargin:10;
spacing: 20;
Button{
id:open;
text:"打开";
}
Button{
id:save;
text:"Save";
}
Button{
id:close;
text:"Close";
Layout.fillWidth: true;
}
}
}
}
树莓派安装编译好的库
树莓派安装编译好的库
make install
go编译树莓派上运行的程序
go编译树莓派上运行的程序
选编译为:cross-arm6
命令行arm
set GOOS=linux
set GOARCH=arm
set GOARM=6
命令行Windows
set GOOS=windows
set GOARCH=amd64
命令行Mac
set GOOS=darwin
set GOARCH=amd64
GOOS:目标平台的操作系统(darwin、freebsd、linux、windows)
GOARCH:目标平台的体系架构(386、amd64、arm)
交叉编译不支持 CGO 所以要禁用它
禁止用用:
SET CGO_ENABLED=0