文章目录
前期准备:
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//验证指令
如下图,这样就完成了:
vim的设置,修改/etc/vim/vimrc文件,需要用超级用户权限
sudo vim /etc/vim/vimrc
set tabstop=4 设置tab键缩进4个空格
set shiftwidth=4 设置批量对齐时候的tab键空格数为4
shell脚本
shell脚本处理参数,可以通过$?来处理,这里的$1是要编译的文件
vi build.sh
//简易编译的shell脚本:
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
chmod +x build.sh//加权限
蜂鸣器的开发
#include <stdio.h>
#include <wiringPi.h>
#include <unistd.h>
#define BEEP 0
int main()
{
wiringPiSetup();//初始化wiringPi库
pinMode(BEEP,OUTPUT); //设置IO口的输出
while(1){
//sleep(1);
usleep(1000000);
digitalWrite(BEEP,HIGH);//设置IO口输出高电平
usleep(1000000);
digitalWrite(BEEP,LOW);//设置IO口输出低电平,蜂鸣器响
}
return 0;
}
超声波测距
测距原理基本说明
超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度,
计算出模块到前方障碍物的距离
型号:HC-SR04
接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚
怎么让它发波
Trig,给Trig端口至少10us的高电平
怎么知道开始发了
Echo信号,由低电平跳转到高电平,表示开始发送波
怎么知道接收了返回波
Echo,由高电平跳转回低电平,表示波回来了
怎么算时间
Echo引脚维持高电平的时间!
波发出去的那一下,开始启动定时器
波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
怎么算距离
距离=速度(340m/s)*时间/2
时序
时间函数
函数原型
#include<sys/time.h>
int gettimeofday(struct timeval *tv,struct timezone *tz )
gettimeofday()会把目前的时间用tv 结构体返回,当地时区的信息则放到tz所指的结构中测试代码
struct timeval {
long tv_sec;/*秒*/
long tv_usec;/*微妙*/
};
测试代码
#include <stdio.h>
#include <sys/time.h>
//计算程序在当前环境中数数10万次耗时多少
void mydelay()
{
int i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
int main()
{
struct timeval startTime;
struct timeval stopTime;
gettimeofday(&startTime,NULL);
mydelay();
gettimeofday(&stopTime,NULL);
long diffTime = 1000000*(stopTime.tv_sec - startTime.tv_sec)+(stopTime.tv_usec-startTime.tv_usec);
printf("全志H6的Linux数100000耗时:%ldus\n",diffTime);
return 0;
}
代码实现:
#include <stdio.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#define Trig 0
#define Echo 1
double getDistance()
{
double dis;
struct timeval start;
struct timeval stop;
pinMode(Trig,OUTPUT);
pinMode(Echo,INPUT);
//超声波发波
digitalWrite(Trig,LOW);
usleep(5);
digitalWrite(Trig,HIGH);
usleep(10);
digitalWrite(Trig,LOW);
//计算波回来的时间
while(!digitalRead(Echo));
gettimeofday(&start,NULL);
while(digitalRead(Echo));
gettimeofday(&stop,NULL);
long diffTime = 1000000*(stop.tv_sec-start.tv_sec)+(stop.tv_usec - start.tv_usec);
printf("diffTime = %ld\n",diffTime);
//计算波的距离
dis = (double)diffTime/1000000 * 34000 / 2;
return dis;
}
int main()
{
double dis;
if(wiringPiSetup()== -1){
fprintf(stderr,"%s","initWringPi error");
exit(-1);
}
while(1){
dis = getDistance();
printf("dis = %lf\n",dis);
usleep(500000);
}
return 0;
}
SG90舵机开发
舵机基本介绍
如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制用处:垃圾桶项目开盖
用、智能小车的全比例转向、摄像头云台、机械臂等
常见的有0-90°、0-180°、0-360°
怎么控制转角
向黄色信号线“灌入”PWM信号。
PWM波的频率不能太高,50hz,即周期=1/频率=1/50=0.02s,20ms左右数据:
不同的PWM波形对应不同的旋转角度,以20ms为周期,50hz为频率的PWM波
定时器需要定时20ms,关心的单位0.5ms, 20ms = 0.5ms * 40:
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, struct itimerval *__restrict __old)
setitimer()将value指向的结构体设为计时器的当前值,如果ovalue不是NULL,将返回计时器原有值。
which:三种类型
ITIMER_REAL //数值为0,计时器的值实时递减,发送的信号是SIGALRM。
ITIMER_VIRTUAL //数值为1,进程执行时递减计时器的值,发送的信号是SIGVTALRM。
ITIMER_PROF //数值为2,进程和系统执行时都递减计时器的值,发送的信号是SIGPROF。
很明显,这边需要捕获对应的信号进行逻辑相关处理 signal(SIGALRM,signal_handler);
返回说明:
成功执行时,返回0。失败返回-1
测试代码
/*该代码实现的功能是: 1s后开启定时器,然后每隔1s向终端打印hello。*/
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
void signal_handler()
{
i++;
if(i == 2000){
printf("hello\n");
i = 0;
}
}
int main()
{
struct itimerval itv;
//设定定时时间
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(-1 == setitimer(ITIMER_REAL,&itv,NULL)){
perror("error");
exit(-1);
}
//信号处理
signal(SIGALRM,signal_handler);
while(1);
return 0;
}
实现代码
//SG90编程实现:键盘输入不同的值,让舵机转动,软件PWM实现
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <signal.h>
#define SG90Pin 2
int jd = 0;
static int i = 0;
void signal_handler()
{
if(i <= jd){
digitalWrite(SG90Pin, HIGH);
}else{
digitalWrite(SG90Pin, LOW);
}if(i == 40){
i = 0;
}
i++;
}
int main()
{
struct itimerval itv;
wiringPiSetup();
pinMode(SG90Pin, 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(-1 == setitimer(ITIMER_REAL,&itv,NULL)){
perror("error");
exit(-1);
}
//信号处理
signal(SIGALRM,signal_handler);
while(1){
printf("input jd: 1-0 2-45 3-90 4-135 \n"); scanf("%d",&jd);
}
return 0;
}
这种方法需要注意的是,一个进程只能创建一个定时器