您现在的位置是:网站首页> 智能硬件

树莓派相关技术汇集

摘要

树莓派相关技术汇集

树莓派外壳包装产品


树莓派注意

win32diskimager写镜像

树莓派主页

树莓派更改用户密码

树莓派安装ftp

树莓派中QT实现串口通讯

树莓派设置语言

树莓派开机自启动程序

树莓派3B--WiringPi控制GPIO

树莓派安装游戏系统

树莓派默认密码

树莓派家庭影院安装

修改树莓派的软件源

【实用手记】树莓派旋转屏幕

树莓派3B+配置QT5开发环境

树莓派安装windows远程

QT全屏和恢复

树莓派3B--Qt中使用wiringPi来开发工程

我的QT第一个程序MyQT

安装BCM2835

树莓派C所在的库和include

基于RFID RC522模块制作树莓派通读卡器

C语言操作的是wirePI角

树莓派学习笔记——wiringPi I2C设备使用详解

QT 添加自定义类中使用Q_OBJECT宏问题

树莓派wiringPi库详解

树莓派上的QT

树莓派安装编译好的库

go编译树莓派上运行的程序


树莓派注意

树莓派
1.外接电流大的模块,一定要单独供电,由于树莓派没有过流保护,很可能烧掉。
2.测试树莓派引脚,由于树莓派引脚间距很小,一定要注意不要接触到其他引脚,否则就短路了。




树莓派更改用户密码

在终端中输入命令,按照提示更改密码

sudo passwd pi  //更改pi用户密码
sudo passwd root  //更改root密码



树莓派安装ftp

步骤1 -安装vsftpd

使用以下命令更新您的系统库并安装vsftpd软件:

sudo apt-get update            
sudo apt-get install vsftpd            

步骤2 -更新配置文件

安装后,使用工具编辑vsftpd配置文件:

sudo nano /etc/vsftpd.conf            

在这个文件中找到以下几行,通过删除#字符取消注释:

anonymous_enable=NO            
local_enable=YES            
write_enable=YES            
local_umask=022            
chroot_local_user=YES            

在文件末尾添加以下几行:

user_sub_token=$USER            
local_root=/home/$USER/ftp            

使用CTRL-X、Y和ENTER保存和退出。

步骤3 -为默认用户创建FTP目录

为了允许您使用默认用户连接到FTP服务器,我们需要创建几个目录:

mkdir /home/pi/ftp            
mkdir /home/pi/ftp/files            

更改ftp目录的权限:

chmod a-w /home/pi/ftp            

步骤4 -创建新用户(可选)

如果您想用另一个用户名登录服务器,我们可以创建一个新用户。在本例中,我们将创建一个名为“camera”的新用户:

sudo adduser camera            

系统会提示您输入密码,根据喜好输入吧。

在屏幕上应该看到这样的显示

1.png

这个新用户还需要配置FTP目录:

mkdir /home/camera/ftp            
mkdir /home/camera/ftp/files            

更改目录权限:

chmod a-w /home/camera/ftp            

下面不是基本文件传输功能所必需的,但新用户可以通过运行命令获得使用“sudo”相同的权限:

sudo adduser camera sudo            

步骤5 -重新启动FTP服务器

最后重新启动vsftpd服务,使我们的更改生效:

sudo service vsftpd restart            



树莓派中QT实现串口通讯

先简单说一些开发过程中需要注意的问题

  • Linux 下设备为 tty ,对应在 windows 下为 COM    
  • ttyS0 与 ttyUSB0 不是一个东西
  • raspi-config 中, serial 应该被打开, 但是 Serial Console 不应该被打开,除非你想要用 Serial Console 去作为终端来控制树莓派
  • 默认pin8,10 是作为 Serial1 分配给蓝牙, 需要关闭蓝牙才可以使用
  • 在树莓派与本机中USB设备如何选择可以看这里    
  • 树莓派中QT要使用QtSerialPort需要安装库
sudo apt-get install libqt5serialport5
sudo apt-get install libqt5serialport5-dev

代码展示

widget.pro 中

QT       += core gui
LIBS     += -lwiringPi
QT       += serialport

widget.h 中

#include <QWidget>#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDebug>
#include <QString>
namespace Ui 
{
class Widget;}
class Widget : public QWidget
{
    Q_OBJECTpublic:    explicit Widget(QWidget *parent = 0);
    ~Widget();
    private slots:    void on_pushButton_clicked();  
      void read();private:
    Ui::Widget *ui;
    QSerialPort *serial;

widget.cpp 中

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) : QWidget(parent),
    ui(new Ui::Widget) {
    ui->setupUi(this);
    serial = new QSerialPort;
    serial->close();
    serial->setPortName("ttyS0");
    serial->open(QIODevice::ReadWrite);
    serial->setBaudRate(115200);
    serial->setDataBits(QSerialPort::Data8);
    serial->setParity(QSerialPort::NoParity);
    serial->setStopBits(QSerialPort::OneStop);
    serial->setFlowControl(QSerialPort::NoFlowControl);

    connect(serial,&QSerialPort::readyRead,this,&Widget::read);
}

Widget::~Widget(){  
  delete ui;
}
void Widget::on_pushButton_clicked(){
    QByteArray a = QByteArray("\n");
    a.append(ui->textEdit->toPlainText().toLatin1());
    serial->write(a);
}
void Widget::read(){
    QByteArray buf;
    buf = serial->readAll();
    qDebug() << buf;
    QString a = QString(buf);
    ui->textEdit_2->setText(a);
}

说在最后

关于如何选择你的设备

在树莓派中选择你的串口

一般来说, 选择 ttyS0 即对应了你的pin8,10 serial1

详细可见

https://www.raspberrypi.org/documentation/configuration/uart.md    

在你的电脑上选择对应的USB

试试命令

ls -l /dev/ttyUSB*



树莓派设置语言

sudo raspi-config        

localisation Options  第4项

Change Locale  第1项

去掉(空格) (en_GB.UTF-8 UTF-8)

勾上(空格) (en_US.UTF-8 UTF-8) (zh_CN.UTF-8 UTF-8)  (zh_CN.GBK GBK)

回车后选择默认语言选 zh_CN.UTF-8

重启

sudo reboot        

安装中文拼音输入法
sudo apt-get install scim-pinyin        


   

   

树莓派开机自启动程序    

一、在/home/pi/.config下找到autostart(没有就新建一个)的文件夹


   

        进入/home/pi/.config文件夹:


   

$:cd /home/pi/.config

        查看autostart目录是否存在 :


   

$:ls -l

        如果不存在,创建autostart目录;否则,跳过这一步:


   

$: mkdir autostart

        进入autostart目录:


   

$: cd autostart

二、在该文件夹内创建一个.desktop结尾的文件(自拟文件名,注意后缀必须是.desktop)        


   

        创建.desktop文件:


   

$: touch filename.desktop

        编辑.desktop文件:


   

$: vim filename.desktop

        进去之后,按A键或O键键进入编辑模式。


   

三、在第二步中新建的文件中添加如下内容(添加是将后面小括号内的说明连同小括号一同去掉):


   

            [Desktop Entry](注意:方括号必须是英文格式的方括号)

            Name=python(名字自拟)

            Comment=Python program(内容说明自拟)


   

            Exec=python3 wifitz.py(这里是中端执行的命令,比如我这里在终端命令启动程序的话,我在命令提示符后面执行


   

                                                    命令$:python3 wifitz.py(程序的路径最好是绝对路径,比如我这里应该是


   

                                                     $:python3 /program/wifitz.py))


   

            Icon=/home/pi/python_games/4row_arrow.png(图标自拟,可以从系统其他地方直接法制个图标路径过来)

            Terminal=false

            MultipleArgs=false

            Type=Application

            Categories=Application;Development;

            StartupNotify=true


   

            (第三步操作具体详见上述链接)


   

            这里主要是第一行的方括号需要注意下(本人已入坑),还有第4行的执行程序语句最好加绝对路径。


   

四、保存文件重启树莓派,sudo reboot


   

        编辑结束后,先按Esc键,再按  :+;  键,左下角出现:时,用wq保存文件并返回到终端。


   

        重启树莓派,sudo reboot。


   

五、重启成功后,在linux终端使用命令ps aux查看当前运行的所有程序,如果程序正常启动,可以在这里找到,本人查找结果如下图:

1.png    

六、如果需要启动多个程序,我试过用上述方法添加三个.desktop文件,结果失败了;所以,如果需要启动多个程序,建议创建一个.sh脚本文件,将多个程序的终端启动命令添加到.sh文件中,然后将上述第三步中的第4行改为Exec=./filename.sh。接下来执行第4步和第5步查看执行结果,我这里能够成功启动三个python程序,如下图:

1.png    


   


   

        如有侵权,请您留言!谢谢!


   


   

树莓派3B--WiringPi控制GPIO    

1.jpg

1.WiringPi简介 (官网)


 


    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芯片。


 


更丰富的内容请参考——【树莓派学习笔记——索引博文】


 


2.wiringPi安装


wiringPi的安装存在方案A和方案B。wiringPi使用GIT工具维护个更新代码,但是如果处于一些其他原因不能使用GIT,那么也可以使用方案B下载和安装wiringPi。


方案A——使用GIT工具


如果在你的平台上还没有安装GIT工具,可以输入以下命令:


sudo apt-get install git-core


如果在这个过程中出现错误,尝试更新软件,例如输入以下指令:


sudo apt-get update


sudo apt-get upgrade


紧接着可以通过GIT获得wiringPi的源代码


git clone git://git.drogon.net/wiringPi


若需要更新wiringPi。


cd wiringPi


git pull origin


进入wiringPi目录并安装wiringPi


cd wiringPi


./build


build脚本会帮助你编译和安装wiringPi

1.jpg

测试wiringPi是否安装成功
wiringPi包括一套gpio命令,使用gpio命令可以控制树莓派上的各种接口,通过以下指令可以测试wiringPi是否安装成功。
gpio -v

2.jpg

可以看到树莓派的基本信息:树莓派 3 版本2,内存1G。
使用gpio readall命令来查看所有管脚的基本信息

3.jpg

从上图可以知道树莓派管脚有三种编号方式,第一种为板上编号(37),即中间两列,表示第几号插针。第二中为wiringPi编码(25),使用wiringPi库编程时是用wiringPi编号,第三种为BCM编号,这个是更加BCM管脚来编号的,使用bcm2837库或python的RPi.GPIO编程时使用BCM编号。


 


方案B——直接下载和解压


简单的输入以下网址:


https://git.drogon.net/?p=wiringPi;a=summary

1.png

图1 下载wiringPi最新版本源代码


点击图中的snapshot便可下载最新版本。


你可能下载到一个名为wiringPi-98bcb20.tar.gz的压缩包,需要助于的是98bcb20只是一个版本号,当你下载wiringPi的时候该版本号可能会发生改变。


你需要解压wiringPi源代码并进行安装,可输入以下指令:


tar xfz wiringPi-98bcb20.tar.gz


cd wiringPi-98bcb20


./build


再次说明,wiringPi压缩包的名称很可能不是98bcb20,请根据实际情况改变。


 


测试wiringPi是否安装成功


wiringPi包括一套gpio命令,使用gpio命令可以控制树莓派上的各种接口,通过以下指令可以测试wiringPi是否安装成功。


gpio -v


gpio readall


树莓派安装游戏系统

retropie下载系统

教程



树莓派默认密码

树莓派各种系统默认密码合集(欢迎补充)

由于树莓派系统众多,各个密码也不一样,所以整理出来一个合计给大家参考。
如果有不对或者不足的地方 还请大家多多留言、指正。
谢谢大家,树莓派社区的发展离不开大家的支持!

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



修改树莓派的软件源

默认情况下,树莓派软件源地址是 archive.raspbian.org/,位于欧洲,在国内访问是非常慢的,经常只有几 k 每秒的下载速率。所以我们在玩转树莓派之前,强烈推荐替换成国内的软件源

树莓派的所有软件源地址可以从这里找到:raspbian.org/RaspbianMi

一般我们找个国内的就行了,比如清华大学的(下图表格的第一行)

首先点击桌面左上角的命令行按钮,进入命令行窗口

1.jpg

然后在命令行窗口内输入 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 关闭。

1.jpg


同样的方法,把 /etc/apt/sources.list.d/raspi.list 文件也替换成下面的内容:


deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui

1.jpg


至此,树莓派软件源就替换好了。是不是很简单,就改两行配置即可。

最后,你可以试下执行 sudo apt-get update,会发现更新速度快了很多。

1.jpg

【实用手记】树莓派旋转屏幕

注:带有【实用手记】标题的文章主要用于临时备忘,内容不甚详尽,但之后也会视需要对相关知识进行完善。
有时候我们在树莓派上进行开发,需要让屏幕旋转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
如果之前安装过
配置

工具 ->选项

1.png

2.png

3.png

4.png

5.png



树莓派安装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文件中配置如下
  1. //
  2. # 下面这个LIBS很关键
  3. LIBS += -lwiringPi
  4. //


1.jpeg

2、添加对应的头文件

 

#include <wiringPi.h>

#include <wiringSerial.h>

1.jpeg

然后开发就行,具体可看下一篇。
  
致敬:


我的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).
The version of the package that this documentation refers to can be downloaded from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.58.tar.gz You can find the latest version at http://www.airspayce.com/mikem/bcm2835
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
The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs
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
The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, allowing you to send and received data by SPI (Serial Peripheral Interface). For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus
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%B2C
The Raspberry Pi V2 GPIO pins used for I2C are:
  • P1-03 (SDA)
  • P1-05 (SLC)
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.
Both PWM channels are driven by the same PWM clock, whose clock dvider can be varied using bcm2835_pwm_set_clock(). Each channel can be separately enabled with bcm2835_pwm_set_mode(). The average output of the PWM channel is determined by the ratio of DATA/RANGE for that channel. Use bcm2835_pwm_set_range() to set the range and bcm2835_pwm_set_data() to set the data in that ratio
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
mikem has made Perl bindings available at CPAN: http://search.cpan.org/~mikem/Device-BCM2835-1.9/lib/Device/BCM2835.pm Matthew Baker has kindly made Python bindings available at: https: github.com/mubeta06/py-libbcm2835 Gary Marks has created a Serial Peripheral Interface (SPI) command-line utility for Raspberry Pi, based on the bcm2835 library. The utility, spincl, is licensed under Open Source GNU GPLv3 by iP Solutions (http://ipsolutionscorp.com), as a free download with source included: http://ipsolutionscorp.com/raspberry-pi-spi-utility/
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 info@airspayce.com
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.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz
1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 Functions bcm2835_gpio_ren()bcm2835_gpio_fen()bcm2835_gpio_hen() bcm2835_gpio_len()bcm2835_gpio_aren() and bcm2835_gpio_afen() now changes only the pin specified. Other pins that were already previously enabled stay enabled. Added bcm2835_gpio_clr_ren()bcm2835_gpio_clr_fen()bcm2835_gpio_clr_hen() bcm2835_gpio_clr_len()bcm2835_gpio_clr_aren()bcm2835_gpio_clr_afen() to clear the enable for individual pins, suggested by Andreas Sundstrom.
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.10 Changed the names of the delay functions to bcm2835_delay() and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. Macros to map delay()-> bcm2835_delay() and Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY
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.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe.
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.45 Fixed an error in the pad group offsets that would prevent bcm2835_gpio_set_pad() and bcm2835_gpio_pad() working correctly with non-0 pad groups. Reported by Guido.
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.49 2016-01-05 Added patch from Jonathan Perkin with new functions bcm2835_gpio_eds_multi() and bcm2835_gpio_set_eds_multi().
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.53 2018-01-14 Added support for AUX SPI (SPI1) Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/)
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.
1.57 2018-08-28 Added SPI function bcm2835_spi_set_speed_hz(uint32_t speed_hz); Contributed by Arjan van Vught (http://www.raspberrypi-dmx.org/)
Author
Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS



树莓派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。本项目只是一个读卡器的雏形,如果需要运用到实际项目中,还需要你的更多深加工。读卡器常见的应用场景还是安全管理系统,其它常见的应用场景还有按卡计时、考勤系统和游戏系统授权等。

1.jpeg

RC522 RFID模块支持的卡片标准

使用RC522芯片的模块支持以下标准的卡片:

MIFARE Mini

MIFARE 1K

MIFARE 4K,

MIFARE Ultralight

MIFARE DESFire EV1

MIFARE Plus RF

当我们购买卡片时,应该确保卡片支持以上标准。

RC522 RFID模块接口定义

市面上的RC522 RFID模块可能因为生产厂家不同外观上会有些许不同,常见的是下图蓝色外观,8个引脚的这种。在模块的PCB上我们可以看到天线的线路布局,模块就是通过天线与靠近它的卡片进行通信的。

2.jpeg

上图左上角,蓝色圆扣状卡片是一种可以挂在钥匙扣上的卡片,所有的卡片都有一个惟一的UID,我们可以使用Python脚本来读取它。

3.jpeg

上图是RC522 RFID模块的接口定义,从图中可以看出RC522 RFID模块支持UART接口、I2C总线接口和SPI可编程接口。

RC522 RFID模块与树莓派的电路连接

RC522模块有8个引脚,但我们只需要将其中7个引脚连接到树莓派的GPIO接口即可。RC522模块的引脚定义见上图,电路连接见下图。

4.png

接口对应关系详见下表:(树莓派3b的GPIO接口定义可查阅:树莓派3的外围I/O数据接口  )


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

1.png



树莓派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。


1.png

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

输出结果如下:

2.png

UID是由四个元素组成的数组,脚本将每个元素组合成一个由逗号分隔的字符串。数组的4个元素可以组合成一个纯数字。例如,我的卡片UID是“1483565119”,而不是“148,35,65,119”。至此读卡器项目的雏形就完成了。


C语言操作的是wirePI角


1.png



树莓派学习笔记——wiringPi I2C设备使用详解
2014年01月09日 09:46:43 xukai871105 阅读数:27843
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位数字固定不变


1.png


  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操作时序介绍


1.png

在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.简单测试代码
  1. #include <stdio.h>
  2. #include <wiringPi.h>
  3. #include <mcp23017.h>
  4. // 扩展MCP23017 起始PIN地址
  5. // MCP23017占用 100-115
  6. #define EXTEND_BASE 100
  7. int main (void)
  8. {
  9.    // wiringPi初始化
  10.    wiringPiSetup( );
  11.    // mcp23017初始化,此时MCP23017的I2C地址为0x20
  12.    mcp23017Setup( EXTEND_BAS E, 0x20 );
  13.    
  14.    int i;
  15.    for( i = 0 ; i < 16 ; i++ )
  16.    {
  17.        pinMode( EXTEND_BASE + i, OUTPUT );
  18.    }
  19.    for (;;)
  20.    {
  21.        for( i = 0 ; i < 16; i++)
  22.        {
  23.            digitalWrite ( EXTEND_BASE + i, HIGH);
  24.            delay (500);
  25.            digitalWrite ( EXTEND_BASE + i, LOW);
  26.            delay (500);
  27.        }
  28.    }
  29.    return 0 ;
  30. }
4.代码详解
4.1 wiringPiSetup
    【见另一篇博文
4.2 mcp23017Setup
  1. int mcp23017Setup (const int pinBase, const int i2cAddress)
  2. {
  3.    int fd ;
  4.    struct wiringPiNodeStruct *node ;
  5.    // 初始化I2C设备
  6.    if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
  7.    return fd ;
  8.    // 附加操作,设置MCP23017设备 I2C操作地址不自动递增
  9.    wiringPiI2CWriteReg8 (fd, MCP23x17_IOCON, IOCON_INIT) ;
  10.    // MCP23017加入链表
  11.    node = wiringPiNewNode (pinBase, 16) ;
  12.    // 赋值相应的操作函数 my开头的函数均位于mcp23017.c文件中
  13.    node->fd = fd ;
  14.    node->pinMode = myPinMode ;
  15.    node->pullUpDnControl = myPullUpDnControl ;
  16.    node->digitalRead = myDigitalRead ;
  17.    node->digitalWrite = myDigitalWrite ;
  18.    node->data2 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATA) ;
  19.    node->data3 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATB) ;
  20.    return 0 ;
  21. }
    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】。
  1. struct wiringPiNodeStruct
  2. {
  3.    int pinBase ;
  4.    int pinMax ;
  5.    int fd ; // Node specific
  6.    unsigned int data0 ; // ditto
  7.    unsigned int data1 ; // ditto
  8.    unsigned int data2 ; // ditto
  9.    unsigned int data3 ; // ditto
  10.    void (*pinMode) (struct wiringPiNodeStruct *node, int pin, int mode) ;
  11.    void (*pullUpDnControl) (struct wiringPiNodeStruct *node, int pin, int mode) ;
  12.    int (*digitalRead) (struct wiringPiNodeStruct *node, int pin) ;
  13.    void (*digitalWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
  14.    void (*pwmWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
  15.    int (*analogRead) (struct wiringPiNodeStruct *node, int pin) ;
  16.    void (*analogWrite) (struct wiringPiNodeStruct *node, int pin, int value) ;
  17.    struct wiringPiNodeStruct *next ;
  18. } ;
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发生。
  1. // 位于wiringPi.c
  2. void pinMode (int pin, int mode)
  3. {
  4.    int fSel, shift, alt ;
  5.    struct wiringPiNodeStruct *node = wiringPiNodes ;
  6.  
  7.    // PIN编号小于64,内部设备
  8.    if ((pin & PI_GPIO_MASK) == 0)
  9.    {
  10.       // 代码省略
  11.    }
  12.    else
  13.    {
  14.        // 查找是否存在该设备
  15.        if ((node = wiringPiFindNode (pin)) != NULL)
  16.        node->pinMode (node, pin, mode) ;
  17.        return ;
  18.    }
  19. }
  20. // 位于mcp23017.c  
  21. static void myPinMode (struct wiringPiNodeStruct *node, int pin, int mode)
  22. {
  23.    int mask, old, reg ;
  24.    pin -= node->pinBase ;
  25.    // 操作GPA 或 GPB
  26.    if (pin < 8)
  27.    reg = MCP23x17_IODIRA ;
  28.    else
  29.    {
  30.        reg = MCP23x17_IODIRB ;
  31.        pin &= 0x07 ;
  32.    }
  33.  
  34.    // 获得IODIRx原始值
  35.    mask = 1 << pin ;
  36.    old = wiringPiI2CReadReg8 (node->fd, reg) ;
  37.    // 设置新值
  38.    if (mode == OUTPUT)
  39.    old &= (~mask) ;
  40.    else
  41.    old |= mask ;
  42.    wiringPiI2CWriteReg8 (node->fd, reg, old) ;
  43. }
4.4 digitalWrite
    digitalWrite函数和pinMode函数操作思路相同,先检测该pin位于板载区域还是扩展区域,如果是扩展区域该pin是否有效,如果有效则调用digitalRead函数。
  1. // 位于wiringPi.c
  2. int digitalWrite (int pin)    
  3. {
  4.    char c ;
  5.    struct wiringPiNodeStruct *node = wiringPiNodes ;
  6.    // PIN编号小于64,内部设备
  7.    if ((pin & PI_GPIO_MASK) == 0)
  8.    {
  9.       // 代码省略
  10.    }
  11.    else
  12.    {
  13.        // 查找是否存在该设备
  14.        if ((node = wiringPiFindNode (pin)) == NULL)
  15.        return LOW ;
  16.        return node->digitalWrite (node, pin) ;
  17.    }
  18. }
  19. // 位于mcp23017.c
  20. static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int value)
  21. {
  22.    int bit, old ;
  23.    pin -= node->pinBase ;
  24.    bit = 1 << (pin & 7) ;
  25.    // 操作GPA
  26.    if (pin < 8)
  27.    {
  28.        old = node->data2 ;
  29.        if (value == LOW)
  30.        old &= (~bit) ;
  31.        else
  32.        old |= bit ;
  33.        wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOA, old) ;
  34.        node->data2 = old ;
  35.    }
  36.    // 操作GPB
  37.    else    
  38.    {
  39.        old = node->data3 ;
  40.        if (value == LOW)
  41.        old &= (~bit) ;
  42.        else
  43.        old |= bit ;
  44.        wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOB, old) ;
  45.        node->data3 = old ;
  46.    }
  47. }
4.6 wiringPiI2CReadReg8 和 wiringPiI2CWriteReg8
    这两个函数涉及到linux驱动方面的内容,均通过ioctl (fd, I2C_SMBUS, &args)实现,具体请看以下代码,更多底层的内容请参考【linux内核 I2C驱动说明
  1. struct i2c_smbus_ioctl_data
  2. {
  3.    char read_write ;
  4.    uint8_t command ;
  5.    int size ;
  6.    union i2c_smbus_data *data ;
  7. } ;
  8. static inline int i2c_smbus_access (int fd, char rw, uint8_t command, int size, union i2c_smbus_data *data)
  9. {
  10.    struct i2c_smbus_ioctl_data args ;
  11.    args.read_write = rw ;
  12.    args.command = command ;
  13.    args.size = size ;
  14.    args.data = data ;
  15.    return ioctl (fd, I2C_SMBUS, &args) ;
  16. }
  17. int wiringPiI2CReadReg8 (int fd, int reg)
  18. {
  19.    union i2c_smbus_data data;
  20.    if (i2c_smbus_access (fd, I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data))
  21.    return -1 ;
  22.    else
  23.    return data.byte & 0xFF ;
  24. }
  25. int wiringPiI2CWriteReg8 (int fd, int reg, int value)
  26. {
  27.    union i2c_smbus_data data ;
  28.    data.byte = value ;
  29.    return i2c_smbus_access (fd, I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, &data) ;
  30. }
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接口面对自己,这样看才是正确的。

1.png

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

1.png

命令行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


























   


   


   


   


   


   















Top