Orangepi Zero2 基于官方外设开发(一)

目录

一、wiringPi外设SDK安装

二、蜂鸣器

补充:shell脚本的改进

补充:vim缩进

三、超声波测距模块

四、SG90舵机

五、Linux定时器


一、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(&timestart,NULL);//开始记录时间
 17     cntTest();
 18     gettimeofday(&timestop,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;
}
相关推荐
库库的里昂3 分钟前
Linux系统Docker部署开源在线协作笔记Trilium Notes与远程访问详细教程
linux·运维·docker·开源
在下不上天14 分钟前
flume-将日志采集到hdfs
大数据·linux·运维·hadoop·hdfs·flume
stone519530 分钟前
鸿蒙系统ubuntu开发环境搭建
c语言·ubuntu·华为·嵌入式·harmonyos
Mango00000041 分钟前
香港站群服务器有助于提升网站在搜索引擎中的排名
运维·服务器·搜索引擎
嚯——哈哈43 分钟前
筑起数字堡垒:解析AWS高防盾(Shield)的全面防护能力
服务器·微服务·云计算·aws
humors2211 小时前
阿里云ECS服务器监控报警配置
运维·服务器·安全·阿里云·云计算
杨江1 小时前
ThingsBoard安装测试
服务器·数据库
mit6.8241 小时前
[Redis#3] 通用命令 | 数据类型 | 内部编码 | 单线程 | 快的原因
linux·redis·分布式
愿天垂怜1 小时前
【C++】C++11引入的新特性(1)
java·c语言·数据结构·c++·算法·rust·哈希算法
文弱书生6561 小时前
TIM输入捕获
stm32·单片机·嵌入式硬件