WiringPi
- 安装
- 使用 gpio readall查看所有引脚
- 使用继电器
- 配置引脚
- 输出指定电平信号
- 读取指定引脚电平信号
- 继电器使用代码编程
- 树莓派超声波测距
- struct timeval 结构体
- 时间控制函数
- 1.void delay (unsigned int howLong)
- 2.void delayMicroseconds (unsigned int howLong)
- 3. unsigned int millis (void)
- 4. unsigned int micros (void)
- 串口通信
- 打开并初始串口
- 关闭串口
- 发送一个字节
- 获取串口缓存字节数
- 读取一个串口缓存字符
- 清空串口缓存的数据
- 例子:
- 语音模块控制灯的打开和关闭
- 超声波测距 以及舵机的使用
精彩博文推荐
安装
进入 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的信息。否则安装失败。
使用 gpio readall查看所有引脚
使用的时候要包含头文件
#include <wiringPi.h>
int main()
{
int ret=wiringPiSetup();
if(ret==-1){
printf("失败\n");
exit(-1);
}
return 0;
}
当使用这个函数初始化树莓派引脚时,程序使用的是wiringPi 引脚编号表
使用该库的时候首先要初始化该函数
wiringPiSetup();进行初始化操作
返回执行结果 如果为-1 表示返回失败
使用继电器
继电器一共三个开关控制 三个开关分别是 VCC GND 还有一个继电器控制引脚
介绍 GPIO控制函数
配置引脚
void pinMode(int pin ,int mode);
//mode:指定引脚的IO模式
//可取的值:INPUT、OUTPUT、PWM_OUTPUT,GPIO_CLOCK
注意:
只有wiringPi 引脚编号下的1脚(BCM下的18脚) 支持PWM输出
只有wiringPi编号下的7(BCM下的4号)支持GPIO_CLOCK输出
输出指定电平信号
void digitalWrite(int pin,int value)
value 引脚输出的电平值 LOW HIGH
读取指定引脚电平信号
int digitalRead(int pin);
返回:引脚上的电平,可以是LOW HIGH 之一
继电器使用代码编程
继电器在低电平下面才会变亮
#include <wiringPi.h>
#include <stdio.h>
#define switch1 7 //指定连接的引脚是7
int main()
{
int cmd;
wiringPiSetup();
pinMode(switch1,OUTPUT);
digitalWrite(switch1,HIGH);//给他一个高电平 在最开始的时候不会变亮
while(1){
printf("请选择输入1/0 1表示高电平 0表示低电平\n");
scanf("%d",&cmd);
if(cmd==1){
digitalWrite(switch1,HIGH);
}else if(cmd==0){
digitalWrite(switch1,LOW);
}else{
cmd=10;
}
}
return 0;
}
strlen表示的就取到/0计算/0前面的元素个数
sizeof表示的是这个字符串的个数包括/0
树莓派超声波测距
Trig 引脚用来接收树莓派的控制信号。接任意 GPIO 口。
Echo 引脚用来向树莓派返回测距信息。接任意 GPIO 口。
trig 表示的是触发信号 发送一个10us的高电平触发信号
Echo表示的是输出回响信号 当一个超声波信号发射后,ECHO引脚会输出高电平。当ECHO引脚直到检测到超声波信号回来的时,ECHO引脚输出低电平。 这个回响信号的时间表示的是来回经过的时间
//
#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>
#define Trig 0
#define Echo 1
//初始化引脚
void ultraInit(void)
{
pinMode(Echo, INPUT);
pinMode(Trig, OUTPUT);
digitalWrite(Trig,LOW);
}
//测量距离函数
float disMeasure(void)
{
struct timeval tv1;
struct timeval tv2;
long start, stop;
float dis;
//表示发送的10us的一个高电平脉冲
digitalWrite(Trig, HIGH);
delayMicroseconds(10); //发出超声波脉冲
digitalWrite(Trig, LOW);
while(digitalRead(Echo) != 1);
gettimeofday(&tv1, NULL); //获取当前时间 gettimeofday
while(digitalRead(Echo) != 0);
gettimeofday(&tv2, NULL); //获取当前时间
//计算出来的是微秒的时间
start = tv1.tv_sec * 1000000 + tv1.tv_usec; //微秒级的时间
stop = tv2.tv_sec * 1000000 + tv2.tv_usec;
dis = (float)(stop - start) / 1000000 * 34000 / 2; //求出距离
return dis;
}
int main(void)
{
float dis;
if(wiringPiSetup() == -1){ //when initialize wiring failed,print messageto screen
printf("setup wiringPi failed !");
return -1;
}
ultraInit();
while(1){
dis = disMeasure();
printf("distance = %0.2f cm\n",dis); //0.2f表示保留小数点后2位
delay(1000);
}
return 0;
}
struct timeval 结构体
结构体的头文件
#include <sys/time.h>
struct timeval
{
time_t tv_sec; /* Seconds. */
suseconds_t tv_usec; /* Microseconds. */
};
time_t类型,这本质上是一个长整数,表示从1970-01-01 00:00:00到目前计时时间的秒数,如果需要更精确一点的,可以使用timeval精确到毫秒。
tv_sec 表示的是秒
tv_usec 表示的是毫秒
在头文件#include <time.h>
数据类型前面有_ 例如_time_t
时间控制函数
1.void delay (unsigned int howLong)
这个是毫秒级的延时函数。
2.void delayMicroseconds (unsigned int howLong)
微秒级的延时函数
3. unsigned int millis (void)
这个函数返回 一个 从你的程序执行 wiringPiSetup 初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 毫秒数。
返回类型是unsigned int,最大可记录 大约49天的毫秒时长。
4. unsigned int micros (void)
这个函数返回 一个 从你的程序执行 wiringPiSetup 初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 微秒数。
返回类型是unsigned int,最大可记录 大约71分钟的时长。
串口通信
包含的头文件
#include <wiringSerial.h>
/* 修改 cmdline.txt文件 */
>cd /boot/
>sudo vim cmdline.txt
删除【】之间的部分
dwc_otg.lpm_enable=0 console=tty1【 console=serial0,115200】 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
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 重启
打开并初始串口
int serialOpen (char *device, int baud)
device:串口的地址,在Linux中就是设备所在的目录。
串口文件存在于 /dev/ttyAMA0 里面
默认一般是"/dev/ttyAMA0",
baud:波特率
返回:正常返回文件描述符,否则返回-1失败
关闭串口
void serialClose (int fd)
发送一个字节
void serialPutchar (int fd, unsigned char c)
void serialPuts (int fd, unsigned char c)
获取串口缓存字节数
int serialDataAvail (int fd)
返回:串口缓存中已经接收的,可读取的字节数,-1代表错误
读取一个串口缓存字符
int serialGetchar (int fd)
从串口读取一个字节数据返回。
如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1
所以,在读取前,做好通过serialDataAvail判断下。
清空串口缓存的数据
void serialFlush (int fd)
刷新,清空串口缓冲中的所有可用的数据。
例子:
int main()
{
int fd;
int cmd;
fd=serialOpen("/dev/ttyAMA0",9600); //打开设备所在文件 波特率设置9600
if(fd==-1){
printf("打开失败\n");
exit(-1);
}
while(1){
while(serialDataAvail(fd)!=-1){
serialFlush(fd);//刷新缓冲区的值
cmd = serialGetchar(fd);
// printf("cmd = %c\n",cmd);//使用串口打印小助手需要有printf stc=isp 则可有可无
if(cmd == '2'){
serialPuts(fd,"fjsdflsdjfl\r\n");
}
}
// serialPutchar(fd,'c'); //通过串口发射一个字符
// delay(1);
}
return 0;
}
串口换行 \r\n 配合使用换行
语音模块控制灯的打开和关闭
当数据多的时候使用read write函数 和文件读取相同
while(1){
nread = read(fd,cmd,sizeof(cmd));
if(nread>0){
printf("cmd=%s\n",cmd);
if(!strcmp("shou",cmd)){
printf("收到\n");
}
if(!strncmp("open",cmd,4)){
digitalWrite(GPIO_27_B,HIGH);
delay(500);
digitalWrite(GPIO_28_G,HIGH);
delay(500);
digitalWrite(GPIO_29_R,HIGH);
delay(500);
}
if(!strncmp("close",cmd,5)){
digitalWrite(GPIO_27_B,LOW);
delay(500);
digitalWrite(GPIO_28_G,LOW);
delay(500);
digitalWrite(GPIO_29_R,LOW);
delay(500);
}
}else{
printf("读取失败\n");
}
}
超声波测距 以及舵机的使用
舵机的连线接口
舵机的接线
红色是VCC 棕色是GND 橙色是信号线
舵机的使用方法 控制原理
舵机的控制一般需要一个20ms的时基脉冲,该脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分。以180度角度舵机为例,那么对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;
这个代码一运行 就会执行到0°位置
while(1)//turn to 0
{
digitalWrite(15,HIGH);
delayMicroseconds(500);
digitalWrite(15,LOW);
delayMicroseconds(19500);
}
使用舵机进行控制
控制舵机速度的代码
舵机向下移动
int i=180;//表示最大的while循环的次数
int k=0;//表示当前角度值
float x=0;//表示时间us
while(i--){
x=11.11*k;
digitalWrite(sign,HIGH);
delayMicroseconds(500+x);
degitalWrite(sign,LOW);
delayMicroseconds(19500-x);
if(k==angle){
break;//当k执行等于要旋转到的角度后结束
}
k++;
}
舵机向上旋转多少度 要想上旋转90°
首先要确定是在什么角度进行旋转 比如当前的位置在90°的位置 需要把时间进行改变设置成1500
int i=180;//表示最大的while循环的次数
int k=0;//表示当前角度值
float x=0;//表示时间us
while(i--){
x=11.11*k;
digitalWrite(sign,HIGH);
delayMicroseconds(1500-x);
degitalWrite(sign,LOW);
delayMicroseconds(18500+x);
if(k==90){
break;//当k执行等于要旋转到的角度后结束
}
k++;
}
while(1){
dis=disMeasure();
printf("测量的长度是%f\n",dis);
printf("测量1\n");
delayMicroseconds(1000000);//每隔一秒打印一次
if(dis<20){
// 使用上面舵机向上旋转的函数
//再次进行判断 如果距离一直小于20 则进行延时 当距离大于20的时候 使用舵机向下旋转的函数
while(1){
dis=disMeasure();
printf("测量的长度是%f\n",dis);
printf("测量2\n");
if(dis<20){
delayMicroseconds(1000000);
}else {
//使用舵机向下旋转的函数进行关闭
break;
}
}
}else {
//使用舵机向下的函数
//检测长度
while(1){
dis=disMeasure();
printf("测量的长度是%f\n",dis);
printf("测量3\n");
if(dis>20){
delayMicroseconds(1000000);
}else{
//使用舵机向上的函数进行处理
break;
}
}
}
}
使用代码 在最开始的位置进行距离的检测 当距离小于20cm 进入if 里面
执行开盖的指令 开盖完成后进入到