<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Wiringpi :: 标签 :: yafeng 的博客</title><link>http://yafengabc.github.io/tags/wiringpi/index.html</link><description/><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 19 Sep 2026 14:36:30 +0800</lastBuildDate><atom:link href="http://yafengabc.github.io/tags/wiringpi/index.xml" rel="self" type="application/rss+xml"/><item><title>树莓派提高实时性的新思路[原创]</title><link>http://yafengabc.github.io/cnblogs/p6292265/index.html</link><pubDate>Tue, 17 Jan 2017 11:15:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p6292265/index.html</guid><description>树莓派提高实时性的新思路&#10;by yafeng 转载请注明&#10;树莓派是一台应用linux系统的ARM电脑，由于linux是非实时性系统，所以各个任务之间会不停的切换，时间片20ms-100ms不等，所以很难获得实时的输出，这里先贴个小例子，内容很简单，把一个IO点置为高电平，等待1000us（1ms）然后置为低电平，并记录需要的时间，记录10000次（2ms*10000=20秒）。&#10;#include "stdio.h" #include "wiringPi.h" #define rec_num 10000 int main(){ int time_arry[rec_num]; int current_time=0; wiringPiSetup(); pinMode(0,OUTPUT); for(int i=0;i&lt;rec_num;i++){ current_time=micros(); digitalWrite(0,HIGH); delayMicroseconds(1000); digitalWrite(0,LOW); delayMicroseconds(1000); time_arry[i]=micros()-current_time; } for(int j=0;j&lt;rec_num;j++){ printf("%d ",time_arry[j]); } } 代码很简单，最后打印10000次时间结果，单位为微秒,部分结果如下：&#10;$ gcc set_io_pluse_nort.c -lwiringPi $ sudo ./a.out 2189 2127 2127 2128 2127 2126 2125 2125 2128 2126 2125 2126 2126 2128 2126 2126 2125 2133 2134 2133 2132 2132 2134 2132 2132 2133 2132 2134 2133 2132 2132 2133 2132 2133 2132 2132 2135 2132 2132 2132 2132 2133 2131 2132 2133 2137 2133 2132 2132 2131 2133 2132 2132 2132 2132 2133 2132 2132 2132 2137 2126 2126 2125 2126 2132 2133 2132 2132 2132 2133 2134 2133 2132 2132 2133 2132 2132 2132 2133 2132 2132 2132 2132 2133 2132 2132 2131 2132 2135 2126 2126 2125 2130 2132 2131 2131 2131 2133 2131 2131 2131 2132 2138 2131 2132 2131 2132 2132 2131 2131 2131 2132 2131 2133 2132 2131 2128 2126 2125 2125 2129 2128 2127 2126 2131 2129 2126 2125 2125 2126 2129 2126 2126 2126 2125 2128 2126 2126 2126 2128 2127 2126 2126 2125 2134 2155 2140 2139 2138 2138 2138 2138 2137 2137 2139 2137 2136 2136 21 由于数据太多，不容易看出结果，所以我用Python写了个统计结果的程序，分析均值以及偏差。代码很简单，我就不贴出来了，只贴结果：&#10;平均时间: 2132 &lt;10us: 9621 &gt;10us: 282 &gt;20us: 49 &gt;30us: 19 &gt;40us: 7 &gt;50us: 4 &gt;60us: 2 &gt;70us: 2 &gt;80us: 2 &gt;90us: 2 &gt;100us: 2 &gt;110us: 2 &gt;120us: [2488, 2346] 可以看出，现在结果还是不错的，只有2个结果误差超过均值60us，但是平均时间是2.132ms，跟预计时间有132us的误差。&#10;下边是该程序在CPU满载的情况下的测试结果（我写了个多进程程序，把所有CPU撑到100%）：&#10;平均时间: 2128 &lt;10us: 73 &gt;10us: 9902 &gt;20us: 175 &gt;30us: 153 &gt;40us: 71 &gt;50us: 24 &gt;60us: 15 &gt;70us: 15 &gt;80us: 15 &gt;90us: 15 &gt;100us: 15 &gt;110us: 15 &gt;120us: [12448, 5813, 9480, 13708, 7936, 11588, 14554, 10433, 13771, 14565, 12347, 5887, 9486, 13725, 2955] 这时，出现了非常差的情况，15次误差大于120us，并且有多次10-15ms误差的！</description></item><item><title>树莓派高级GPIO库，wiringpi2 for python使用笔记（五）i2c读取测试</title><link>http://yafengabc.github.io/cnblogs/p5107768/index.html</link><pubDate>Wed, 06 Jan 2016 22:52:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p5107768/index.html</guid><description>wiringpi2显然也把i2c驱动带给了Python，手头上正巧有一个DS3231的模块，上边带了一个DS3231 RTC（实时时钟），与一片24C32，两个芯片均为iic总线设备，与树莓派接线如下：&#10;也就是VCC GND SDA SCL四个脚分别接到树莓派的1（3.3v）、9（0v）、3（SDA.1）、5（SCL.1）上，因为树莓派的I2C接口默认是关闭的，需要先编辑一下/boot/config.txt,去掉 device_tree_param=i2c_arm=on上的注释（ArchlinuxARM RasperryPi2），然后重启（注：Raspbian可以用raspi-config打开）&#10;然后重启，重启完成后，运行&#10;modprobe i2c-dev 若想这个模块自动装载，请把它写到 /etc/modules-load.d/raspberrypi.conf&#10;安装i2c-tools，Archlinux下为：&#10;pacman –S i2c-tools 安装后，运行i2cdetect –y 1结果如下：&#10;嗯，发现了57，68两个设备，哪个是DS3231，哪个又是24C32呢，我们把里边的数据dump出来看看：&#10;可以看到0x57设备里边是空的，应该就是24C32了，0x68里边读出来20个字节，就是DS3231了。&#10;我先解释下这几个命令：&#10;i2cdetect顾名思义就是搜索i2c总线的设备，树莓派有2条i2c总线，咱们接的SDA.1,SCL.1，当然就是搜索1这条总线了（另外一条是SDA.0 SCL.0）&#10;-y参数没啥意义，就是自己帮你按下y(yes).&#10;i2cdump也很容易理解，就是dump出指定总线，指定设备的数据这里是1总线0x57 0x68两个设备。-y参数跟上个命令是一样的。&#10;这样，我们的i2c设备就都通讯上了，下边就是用wiringpi2库读写之。&#10;wringpi中操作i2c设备的函数主要有一下几个：</description></item><item><title>树莓派高级GPIO库，wiringpi2 for python使用笔记（四）实战DHT11解码</title><link>http://yafengabc.github.io/cnblogs/p5100741/index.html</link><pubDate>Tue, 05 Jan 2016 00:12:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p5100741/index.html</guid><description>DHT11是一款有已校准数字信号输出的温湿度传感器。 精度湿度+-5%RH， 温度+-2℃，量程湿度20-90%RH， 温度0~50℃。&#10;我买的封装好的模块，上边自带了上拉电阻，直接查到树莓派上即可灰、紫、蓝分别代表数据、3.3V、0V,接到树莓派的3，1，10脚，分别对应PIN8，3.3V，0V。&#10;DHT11与单片机通讯协议为单线协议（1-wire），其实单线协议蛮厉害的，一个GPIO就能实现数据的读取，但是这个协议没有同步脉冲，所以对时序要求比较高，比如DHT11对高低电平定义如下：&#10;低电平50us，然后一个26-28us的高电平，代表0&#10;低电平50us，然后一个70us的高电平，代表1&#10;也就是说，需要能分辨出40us以下的时间才能准确的测出，下边看看具体的时序：&#10;总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号.主机发送开始信号结束后,延时等待20-40us后, 读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可, 总线由上拉电阻拉高。&#10;数字0表示如下图：&#10;数字1表示如下图：&#10;可以看出，每一位包括一开始的响应信号，都是由一个低电平跟一个高电平组成，其中响应信号为80us+80us=160us&#10;数字0为50+26=76us&#10;数字1为50+70=120us&#10;为读到DHT11的状态，我编写了以下的程序：&#10;import wiringpi2 as gpio owpin=8 #第8脚为1-wire脚 tl=[] #存放每个数据位的时间 gpio.wiringPiSetup() #初始化wiringpi库 gpio.pinMode(owpin,1) #设置针脚为输出状态 gpio.digitalWrite(owpin,1) #输出高电平 gpio.delay(1) ###发开始指令，要求DHT11传输数据 gpio.digitalWrite(owpin,0) #拉低25ms开始指令 gpio.delay(25) gpio.digitalWrite(owpin,1) #输出高电平，开始指令结束 gpio.pinMode(owpin,0) #设针脚为输入状态 ###开始指令发送完毕，把管脚设置为高电平，并等待DHT11拉低管脚。传输数据 while(gpio.digitalRead(owpin)==1): pass #如果管脚一直是1，则一直等待。 ###若被拉低，说明传输开始，应答信号+40位数据+结束标志共42位 ###下边共循环45次，故意多循环几次看结果。 for i in range(45): #测试每个数据周期的时间（包括40bit数据加一个发送开始标志 tc=gpio.micros() #记下当前us数（从初始化开始算起，必要时重新初始化） ''' 一个数据周期，包括一个低电平，一个高电平，从DHT11第一次拉低信号线开始 到DHT11发送最后一个50us的低电平结束（然后被拉高，一直维持高电平，所以 最后的完成标志是一直为高，超过500ms） ''' while(gpio.digitalRead(owpin)==0):pass #一位数据由一个低电平 while(gpio.digitalRead(owpin)==1): #加一个高电平组成 if gpio.micros()-tc&gt;500: #如果超过500us就结束了本次循环,传输结束后 break #会被上拉电阻拉成高电平，防止进入死循环 tl.append(gpio.micros()-tc) #记录每个周期时间的us数，存到tl这个列表 print(tl) #打印结果 程序里有详细的解释，我就不再赘述，这里贴出我这里的执行结果：</description></item><item><title>树莓派高级GPIO库，wiringpi2 for python使用笔记（三）GPIO操作</title><link>http://yafengabc.github.io/cnblogs/p5096720/index.html</link><pubDate>Sun, 03 Jan 2016 16:57:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p5096720/index.html</guid><description>GPIO库的核心功能，当然就是操作GPIO了，GPIO就是“通用输入/输出”接口，比如点亮一个LED、继电器等，或者通过iic spi 1-wire等协议，读取、写入数据，这都是GPIO的用处，可以说没有GPIO，树莓派只能当小电脑用，有了GPIO，就升级成一个控制器了。先来说说怎么操作一个数字量（高低电平）。&#10;先看代码：&#10;import wiringpi2 as gpio from wiringpi2 import GPIO gpio.wiringPiSetup() #初始化 gpio.pinMode(25,GPIO.OUTPUT) # 把pin25设置为输出模式 gpio.digitalWrite(25,GPIO.HIGH) #pin25输出为高电平 print(gpio.digitalRead(25)) #打印pin25的状态 值的注意的是，GPIO在输出模式时，也可以读取GPIO状态。&#10;wiringpi对树莓派2的GPIO定义如下：&#10;[root@RasPi ~/testcode]# gpio readall +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | | | 3.3v | | | 1 || 2 | | | 5v | | | | 2 | 8 | SDA.1 | IN | 1 | 3 || 4 | | | 5V | | | | 3 | 9 | SCL.1 | IN | 1 | 5 || 6 | | | 0v | | | | 4 | 7 | GPIO. 7 | IN | 1 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 | | | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 | | 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 | | 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | | | 22 | 3 | GPIO. 3 | IN | 0 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 | | | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 | | 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | | | 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 | | 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 | | | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 | | 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 | | 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | | | 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 | | 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | | | 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 | | 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 | | | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 | +-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+ | BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM | +-----+-----+---------+------+---+---Pi 2---+---+------+---------+-----+-----+ 我们看到，wringpi对针脚有三种定义方式，BCM代表GPIO模式，wPi代表pin模式，Physical代表物理针脚模式。</description></item><item><title>树莓派高级GPIO库，wiringpi2 for python使用笔记（二）高精度计时、延时函数</title><link>http://yafengabc.github.io/cnblogs/p5096445/index.html</link><pubDate>Sun, 03 Jan 2016 15:11:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p5096445/index.html</guid><description>学过单片机的同学应该清楚，我们在编写传感器驱动时，需要用到高精度的定时器、延时等功能，wiringpi提供了一组函数来实现这些功能，这些函数分别是：&#10;micros() #返回当前的微秒数，这个数在调用wiringPiSetup()后被清零并重新计时&#10;millis() #返回当前的毫秒数，同上，这个数在调用wiringPiSetup()后被清零并重新计时&#10;delayMicroseconds() #高精度微秒延时&#10;delay() #毫秒延时。&#10;python相对于C，一个很大的问题就是执行速度慢，所以指令执行速度不可忽视，我们可以用micos函数来检测指令执行时间，用来避免实际使用中遇到的坑，请看以下代码：&#10;import wiringpi2 as gpio for i in range(5): t1=gpio.micros() t2=gpio.micros() print(t2-t1) 连续调用两次micros，然后打印出差值，运行结果如下：&#10;[root@RasPi ~/testcode]# python testus.py 12 4 4 5 5 我们看到第一次的结果明显比以后的结果要大，多了接近10微秒，一般的程序来说，这无关紧要，要是要求更高，可以把代码改成这个样子:&#10;import wiringpi2 as gpio for i in range(5): t1=gpio.micros() t1=gpio.micros() t2=gpio.micros() print(t2-t1) 运行结果如下：&#10;[root@RasPi ~/testcode]# python testus.py 3 3 3 3 2 基本一致了再看以下代码：&#10;import wiringpi2 as gpio for i in range(5): t1=gpio.micros() t1=gpio.micros() gpio.delayMicroseconds(10) t2=gpio.micros() print(t2-t1) 延时10us，结果如下：&#10;[root@RasPi ~/testcode]# python testus.py 21 21 18 18 18 减去两次调用micros()之间的5us左右的延时，实际延时10us会有5us左右的延时。</description></item><item><title>树莓派高级GPIO库，wiringpi2 for python使用笔记（一）安装</title><link>http://yafengabc.github.io/cnblogs/p5096300/index.html</link><pubDate>Sun, 03 Jan 2016 14:06:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p5096300/index.html</guid><description>网上的教程，一般Python用RPi.GPIO来控制树莓派的GPIO，而C/C++一般用wringpi库来操作GPIO，RPi.GPIO过于简单，很多高级功能不支持，比如i2c/SPI库等，也缺乏高精度定时等高级特性。相比之下，wiringpi则功能丰富的多，其实wringpi已经有了python绑定，可以非常简单的在python中使用这个库。鉴于网上基本没有这个库的中文说明，我一边学习，一边以做笔记的形式，写几篇关于这个库的基本使用的文章。&#10;安装：首先安装python-pip：&#10;我用的Archlinux，python3，安装命令为：&#10;pacman -S python-pip 如果用python2，安装命令为：&#10;pacman -S python2-pip Raspbian下则为：&#10;apt-get install python3-pip apt-get install python-pip 安装完后，就可以用pip install来安装python库了。为避免繁琐，我下边的命令都以pip命令安装，Archlinux下默认为python3的pip3，如果使用个python2则用pip2来代替pip，debian下pip默认为pip2，若使用python3，则使用pip3来代替。&#10;pip install wiringpi2 pip库里除了wiringpi2外，还有老版本的wiringpi库，大家按需安装。&#10;安装完后，运行pip list，可以看到列表中包含了新装的wringpi2库了：&#10;在终端中敲入python，进入python控制台，导入一下，如果不报错，说明安装成功：</description></item><item><title>树莓派读取DHT11传感器的源代码</title><link>http://yafengabc.github.io/cnblogs/p5096184/index.html</link><pubDate>Sun, 03 Jan 2016 13:27:00 +0800</pubDate><guid>http://yafengabc.github.io/cnblogs/p5096184/index.html</guid><description>import wiringpi2 as gpio owpin=8 #第8脚为1-wire脚 def getval(owpin): tl=[] #存放每个数据位的时间 tb=[] #存放数据位 gpio.wiringPiSetup() #初始化wiringpi库 gpio.pinMode(owpin,1) #设置针脚为输出状态 gpio.digitalWrite(owpin,1) #输出高电平 gpio.delay(1) gpio.digitalWrite(owpin,0) #拉低20ms开始指令 gpio.delay(25) gpio.digitalWrite(owpin,1) #抬高20-40us gpio.delayMicroseconds(20) gpio.pinMode(owpin,0) #设针脚为输入状态 while(gpio.digitalRead(owpin)==1): pass #等待DHT11拉低管脚 for i in range(45): #测试每个数据周期的时间（包括40bit数据加一个发送开始标志 tc=gpio.micros() #记下当前us数（从初始化开始算起，必要时重新初始化） ''' 一个数据周期，包括一个低电平，一个高电平，从DHT11第一次拉低信号线开始 到DHT11发送最后一个50us的低电平结束（然后被拉高，一直维持高电平，所以 最后的完成标志是一直为高，超过500ms） ''' while(gpio.digitalRead(owpin)==0):pass while(gpio.digitalRead(owpin)==1): if gpio.micros()-tc&gt;500: #如果超过500ms就结束了 break if gpio.micros()-tc&gt;500: #跳出整个循环 break tl.append(gpio.micros()-tc) #记录每个周期时间的us数，存到tl这个列表 # print(tl) #反注释后可打印时间列表 tl=tl[1:] #去掉第一项，剩下40个数据位 for i in tl: if i&gt;100: #若数据位为1，时间为50us低电平+70us高电平=120us tb.append(1) else: tb.append(0) #若数据位为0，时间为50us低电平+25us高电平=75us #这里取大于100us就为1 # print(tb) #反注释可查看每一位状态 return tb def GetResult(owpin): for i in range(10): SH=0;SL=0;TH=0;TL=0;C=0 result=getval(owpin) # print(len(result)) if len(result)==40: for i in range(8): #计算每一位的状态，每个字8位，以此为湿度整数，湿度小数，温度整数，温度小数，校验和 SH*=2;SH+=result[i] SL*=2;SL+=result[i+8] TH*=2;TH+=result[i+16] TL*=2;TL+=result[i+24] C*=2;C+=result[i+32] if ((SH+SL+TH+TL)%256)==C and C!=0: break else: print("Read Sucess,But checksum error! retrying") else: print("Read failer! Retrying") gpio.delay(200) return SH,SL,TH,TL SH,SL,TH,TL=GetResult(owpin) print("湿度:",SH,SL,"温度:",TH,TL)</description></item></channel></rss>