一.平台介绍
OrangePi开发板不仅仅是一款消费品,同时也是给任何想用技术来进行创作创新的人设计的。它是一款简单、有趣、实用的工具,你可以用它去打造你身边的世界。
特性
- CPU 全志H616四核64位1.5GHz高性能Cortex-A53处理器
- GPU MaliG31MP2 SupportsOpenGLES1.0/2.0/3.2、OpenCL2.0
- 运行内存 1GBDDR3(与GPU共享)
- 存储 TF卡插槽_课程配套硬件16G,测试128G可支持、2MBSPIFlash
- WIFI+蓝牙 AW859A芯片、支持IEEE802.11a/b/g/n/ac、BT5.0
- 视频输出 MicroHDMI20a
- 电源 USBTypeC接口输入
- 外设 带有I2Cx1、SPIx1、UARTx1以及多个GPIO口
- 电源指示灯和状态指示灯
二.基于官方外设开发
2.1 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,结果如下方所示:
2.2基本IO口应用——蜂鸣器开发
-
代码:
#include <stdio.h> #include <wiringPi.h> #include <unistd.h> #define BEEP 0 //设置针脚0为蜂鸣器的控制引脚 int main (void) {wiringPiSetup () ;//初始化wiringPi库ipinMode (BEEP, OUTPUT) ;//设置IO口的输入输出,输出while(1){//sleep(1);usleep(100000);digitalWrite (BEEP, HIGH) ; //设置IO口输出低电平,蜂鸣器响//sleep(1);usleep(100000);digitalWrite (BEEP, LOW) ; //设置IO口输出低电平,蜂鸣器响}return 0; }
-
简单编译shell脚本来gcc编译函数
./build beep.c gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt shell脚本处理参数,可以通过$?来处理,这里的$1是要编译的文件
2.3超声波测距
-
测距原理基本说明
超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度, 计算出模块到前方障碍物的距离。
-
超声波模块HC-SR04
!
-
时序
-
时间函数
gettimeofday
是一个在 Unix 及类 Unix 系统(如 Linux)中广泛使用的系统调用,它的目的是获取当前系统的日期和时间,精确到微秒级别。这个函数允许程序获取自1970年1月1日以来的秒数(即Unix时间戳)以及额外的微秒部分。这对于需要高精度时间测量的应用特别有用,例如在性能测试、计时、实时系统或是任何需要精确时间管理的场景。#include <sys/time.h>int gettimeofday(struct timeval *tv, struct timezone *tz); //结构体: struct timeval {long tv_sec;/*秒*/long tv_usec;/*微妙*/ }; struct timezone (在某些系统中可能已弃用或不推荐使用)结构包含了时区信息,但在大多数现代应用中,传递 NULL 给 tz 参数是常见的做法,因为时区处理现在更倾向于使用其他方法,如 localtime_r 或 gmtime_r 函数配合 struct tm。
-
测试代码:
//计算程序在当前环境中数数10万次耗时多少 #include <sys/time.h> #include <stdio.h> //int gettimeofday(struct timeval *tv,struct timezone *tz ) void mydelay() {int i,j;for(i=0;i<100;i++){for(j=0;j<1000;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 <sys/time.h> #include <wiringPi.h> #include <stdlib.h> #include <unistd.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);/*above init CSB*/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; }
2.4SG90舵机开发
-
舵机基本介绍
如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等常见的有0-90°、0-180°、0-360°。
-
角度控制
向黄色信号线“灌入”PWM信号。
PWM波的频率不能太高,50hz,即周期=1/频率=1/50=0.02s,20ms左右数据:不同的PWM波形对应不同的旋转角度,以20ms为周期,50hz为频率的PWM波。
0.5ms的高电平,19.5ms的低电平,角度为0°;1ms的高电平,19ms的低电平,角度为45°;1.5ms的高电平,18.5ms的低电平,角度为90°;以此类推。
-
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:通过传递定时器类型(which)、指向 itimerval 结构体的指针,以及一个之前 itimerval 的地址(可选,用于获取先前的定时器设置)来调用 setitimer。
setitimer
支持三种类型的间隔定时器:- ITIMER_REAL:这是最常用的类型,它按照实际流逝的时间来计时,即使进程处于睡眠状态也会继续计时。当定时器到期时,会给进程发送
SIGALRM
信号。 - ITIMER_VIRTUAL:这种定时器测量的是进程在用户模式下消耗的CPU时间。当进程因为系统调用等原因进入内核模式时,该定时器会暂停计时。到期时发送
SIGVTALRM
信号。 - ITIMER_PROF:类似于 ITIMER_VIRTUAL,但是它不仅计算用户模式下的时间,也包括内核模式下消耗的时间(即总的CPU时间)。到期时发送
SIGPROF
信号。
- ITIMER_REAL:这是最常用的类型,它按照实际流逝的时间来计时,即使进程处于睡眠状态也会继续计时。当定时器到期时,会给进程发送
-
定时示例代码
/*该代码实现的功能是: 1s后开启定时器,然后每隔1s向终端打印hello。*/ #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_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> Orangepi Zero2 全志H616开发学习文档 猿学社 #include <stdlib.h> #include <signal.h> #include <wiringPi.h> #define SG90Pin 5 int jd; static int i = 0; void signal_handler(int signum) {if(i <= jd){digitalWrite(SG90Pin, HIGH);}else{digitalWrite(SG90Pin, LOW);}if(i == 40){i = 0;}i++;} int main() {struct itimerval itv;jd = 0;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; }