目录
一、wiringPi外设SDK安装
第一种:
git clone https : //github.com/orangepi-xunlong/wiringOP // 下载源码
cd wiringOP // 进入文件夹
sudo . / build clean // 清除编译信息
sudo . / build // 编译
第二种:
通过 windows 浏览器打开 https : //github.com/orangepi-xunlong/wiringOP
下载压缩包
把压缩包通过 xterm 传到开发板
解压 unzip xxx . zip
cd xxx
sudo . / build
gpio readall
验证指令: gpio readall
如下方所示,外设库就完成安装了
二、蜂鸣器
例一:给蜂鸣器低电平,一直响
代码如下:blink.c
1 #include <stdio.h>
2 #include <wiringPi.h>
3
4 #define BEEP 0 //设置0脚为蜂鸣器控制引脚
5
6 int main (void)
7 {
8
9 wiringPiSetup () ;//初始化wiringPi库
10 pinMode (BEEP, OUTPUT) ;//设置IO口的输入输出,此处为输出
11 digitalWrite (BEEP, LOW) ; //设置IO口输出低电平,蜂鸣器响
12
13 return 0;
14 }
编译时,要链接库: gcc blink.c -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
可以将编译命令做成build.sh脚本,输入命令chmod +x build.sh给其执行权限
运行时,需使用超级用户权限,sudo ./a.out
例二:蜂鸣器响1s,灭1s
代码如下:
1 #include <stdio.h>
2 #include <wiringPi.h>
3 #include <unistd.h> //sleep的头文件
4
5 #define BEEP 0 //设置0脚为蜂鸣器控制引脚
6
7 int main (void)
8 {
9
10 wiringPiSetup () ;//初始化wiringPi库
11 pinMode (BEEP, OUTPUT) ;//设置IO口的输入输出,此处为输出
12 while(1){
13 sleep(1);
14 digitalWrite (BEEP, LOW) ; //设置IO口输出低电平,蜂鸣器响
15 sleep(1);
16 digitalWrite(BEEP,HIGH);
17 }
18 return 0;
19 }
sleep()是秒级别,usleep()是微秒级别
补充:shell脚本的改进
上述案例中,build.sh中对于XX.c文件的编译是固定的,我们需要把.c文件作为本脚本文件的参数,这样此脚本文件就是通用的了
修改build.sh
$1即为.c文件
echo $0
echo $1
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
编译时:
补充:vim缩进
vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限
sudo vim / etc / vim / vimrc
set tabstop = 4 设置 tab 键缩进 4 个空格
set shiftwidth = 4 设置批量对齐时候的 tab 键空格数为 4
三、超声波测距模块
模块型号:HC-SR04
**接线:**VCC接5V/GND/Trig接0/Echo接1
- 怎么让它发波 --->Trig,给Trig端口至少10us的高电平
- 怎么知道开始发了 --->Echo信号,由低电平跳转到高电平,表示开始发送波
- 怎么知道接收了返回波 --->Echo,由高电平跳转回低电平,表示波回来了
- 怎么算时间--->Echo引脚维持高电平的时间!波发出去的那一下,开始启动定时器。波回来的那一下,我们停止定时器,计算出中间经过多少时间
- 怎么算距离--->距离=速度(340m/s)*时间/2
时序:
时间API
#include<sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz )
gettimeofday() 会把目前的时间用 tv 结构体返回,当地时区的信息则放到 tz 所指的结构中
struct timeval
{
long tv_sec ; /* 秒 */
long tv_usec ; /*微秒 */
};
time.c 获取当前时间与格林尼治时间的差值
1 #include <stdio.h>
2 #include <sys/time.h>
3
4 int main()
5 {
6 struct timeval tv;
7 gettimeofday(&tv,NULL);
8
9 printf("sec=%ld,usec=%ld\n",tv.tv_sec,tv.tv_usec);
10
11 return 0;
12 }
运行结果:
cntTest.c 测试该芯片运行某一程序所需时间(单位:微秒)
1 #include <stdio.h>
2 #include <sys/time.h>
3
4 void cntTest()
5 {
6 int i,j;
7 for(i=0;i<100;i++)
8 for(j=0;j<100;j++);
9 }
10
11 int main()
12 {
13 struct timeval timestart;//开始
14 struct timeval timestop;//结束
15
16 gettimeofday(×tart,NULL);//开始记录时间
17 cntTest();
18 gettimeofday(×top,NULL);//结束记录时间
19
20 long difftime = 1000000*(timestop.tv_sec - timestart.tv_sec)+(timestop.tv_usec - timestart.tv_usec);
21
22 printf("所耗时间为:%ld\n",difftime);
23
24 return 0;
25 }
运行结果:
超声波测距代码:csb.c
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.h>
#define Trig 0
#define Echo 1
double getDistance()
{
double dis;
struct timeval Tstart;
struct timeval Tstop;
pinMode(Trig,OUTPUT);
pinMode(Echo,INPUT);
//Trig有一个不少于10us的高电平
digitalWrite(Trig,LOW);
usleep(5);
digitalWrite(Trig,HIGH);
usleep(10);
digitalWrite(Trig,LOW);
while(!digitalRead(Echo));//Echo由低电平转为高电平,表示开始发送波;如果一直为低电平,0取反为1,死循环
gettimeofday(&Tstart,NULL);
while(digitalRead(Echo));//Echo由高电平转为低电平,波回来了;如果一直为高电平,则1死循环
gettimeofday(&Tstop,NULL);
long difftime = 1000000*(Tstop.tv_sec-Tstart.tv_sec)+(Tstop.tv_usec-Tstart.tv_usec);
dis = (double)difftime/1000000 * 34000/2;
return dis;
}
int main()
{
double dis;
if(wiringPiSetup() == -1){
fprintf(stderr,"%s","initWiringPi error");
exit(-1);
}
while(1){
dis = getDistance();
printf("dis = %lf\n",dis);
usleep(500000);
}
}
运行结果:
四、SG90舵机
如何控制转角:向黄色线灌入PWM信号
PWM波的频率不能太高,一般为50hz,即周期=1/频率=1/50=0.02s=20ms
五、Linux定时器
分析:实现定时器,通过 itimerval 结构体 以及函数 setitimer 产生的信号,系统随之使用 signal 信号处理函数来处理产生的定时信号。从而实现定时器。
先看 itimerval 的结构体
struct itimerval
{
/* Value to put into `it_value' when the timer expires. */
struct timeval it_interval ;
/* Time to the next timer expiration. */
struct timeval it_value ;
};
it_interval :计时器的初始值,一般基于这个初始值来加或者来减,看控制函数的参数配置
it_value :程序跑到这之后,多久启动定时器
struct timeval
{
__time_t tv_sec ; /* Seconds. */
__suseconds_t tv_usec ; /* Microseconds. */
};
int setitimer ( __itimer_which_t __which , const struct itimerval * __restrict __new , s truct itimerval * __restrict __old )
setitimer() 将 value 指向的结构体设为计时器的当前值,如果 value 不是 NULL ,将返回计时器原有值。
which: 三种类型
ITIMER_REAL // 数值为 0 ,计时器的值实时递减,发送的信号是 SIGALRM 。
ITIMER_VIRTUAL // 数值为 1 ,进程执行时递减计时器的值,发送的信号是 SIGVTALRM 。
ITIMER_PROF // 数值为 2 ,进程和系统执行时都递减计时器的值,发送的信号是 SIGPROF 。
很明显,这边需要捕获对应的信号进行逻辑相关处理 signal(SIGALRM,signal_handler);
返回说明:
成功执行时,返回 0 。失败返回 -1
clockTest.c 利用定时器1s打印一次hello
此程序定时器定0.5ms,1s就是2000次0.5ms
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
static int i;
void signal_handler(int signum)
{
i++;
if(i == 2000){
printf("hello\n");
i = 0;
}
}
int main()
{
struct itimerval itv;
//设定开始生效,启动定时器的时间
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
//设定定时时间
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 500;
//设定定时方式
if(setitimer(ITIMER_REAL,&itv,NULL) == -1){
perror("error");
exit(-1);
}
//信号处理
signal(SIGALRM,signal_handler);
while(1);
return 0;
}
sg90.c 用户输入1-5,舵机转动相应的角度
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
#define sg90 1
int jd;
static int i = 0;
void signal_handler(int signum)
{
if(i<=jd){
digitalWrite(sg90,HIGH);
}else{
digitalWrite(sg90,LOW);
}
if(i==40){
i = 0;
}
i++;
}
int main()
{
struct itimerval itv;
jd = 0;
wiringPiSetup();
pinMode(sg90,OUTPUT);
//设定定时时间
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 500;
//设定开始生效,启动定时器的时间
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
//设定定时方式
if(setitimer(ITIMER_REAL,&itv,NULL) == -1){
perror("error");
exit(-1);
}
//信号处理
signal(SIGALRM,signal_handler);
while(1){
printf("input(1-4):1-0度,2-45度,3-90度,4-135度,5-180度\n");
scanf("%d",&jd);
}
return 0;
}