一、刷机和系统启动
1、TF 卡格式化:
可以使用SD Card Formatter
软件格式化TF
卡
2、镜像烧录:
使用win32diskimager
软件将准备好的镜像烧录到TF
卡中
镜像下载网址🔗点击这里 点击Orange Pi Zero2
官方镜像的ubuntu
镜像,跳转至百度网盘,下载3.0.6
版本:
此镜像可能默认关闭uart5
,需要使用uart5
时配置一下串口uart5
,打开配置文件:
sudo vi /boot/orangepiEnv.txt
加入以下字段,开启uart5
和i2c3
:
overlays=uart5 i2c3
如图所示:
3、登录系统:
利用
MobaXterm
进行串口登录或SSH
方式登录,初次登录应用串口登录或利用USB
转HTML
接入屏幕后登录,默认用户如下:
- 用户名:
orangepi
,密码:orangepi
- 用户名:
root
,密码:orangepi
修改
orangepi
用户密码:sudo passwd orangepi
① 串口登录:
使用TTL 转 USB
模块连接开发板串口(电脑需要安装ch340
驱动),如图所示,然后接入电脑,使用MobaXterm
软件进行串口登录,波特率默认为115200
,MobaXterm
连接上串口后,插入开发板电源线,查看串口打印数据,检验刷机是否成功
② 重启及关机:
- 重启:
sudo reboot
- 关机:
sudo poweroff
③ 网络配置:
- 扫描周围的
WIFI
热点:nmcli dev wifi
- 接入网络:
nmcli dev wifi connect user password xxxxxxxx
// 比如接入用户名为user
的wifi
,密码为xxxxxxxx
- 查看
IP
地址:ip addr show wlan0
或ifconfig
④ SSH 登录开发板:
镜像自带SSH
服务器,只要通过MobaXterm
登陆即可
二、基于官方外设开发
1、wiringPi 外设 SDK 安装:
git clone https://github.com/orangepi-xunlong/wiringOP -b master
// 下载源码cd wiringOP
// 进入文件夹sudo ./build clean
// 清除编译信息sudo ./build
// 编译
或者通过 windows 浏览器打开 https://github.com/orangepi-xunlong/wiringOP,下载压缩包,通过 MobaXterm 把压缩包传到开发板:- 解压:
unzip xxx.zip
cd xxx
sudo ./build
- 验证是否安装成功:
gpio readall
,如下图所示
上述1~26
物理端口,以如图所示方向的引脚对应:
2、C 文件编译:
- 使用
wiringPi
库,编译的时候需要链接:gcc xxx.c -o -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
- 可以制作简单的
shell
脚本便于编译:vi bulid.sh
// 编写 shell 文件- 加入以下代码:
gcc $1 -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt
// $1 为参数- 保存文件后,为 shell 文件添加可执行权限:
chmod +x build.sh
- 运行时 wiringPi 需要访问底层驱动程序,使用超级用户权限运行:
sudo ./a.out
3、基于官方外设的应用开发:
① GPIO 输入输出:
#include <stdio.h>
#include <wiringPi.h>
#include <unistd.h>
#define GPIO1 0
#define GPIO2 2
int main (void)
{
wiringPiSetup(); // 初始化 wiringPi 库
pinMode (GPIO1, OUTPUT); // 设置 IO 口为输出模式
pinMode (GPIO2, INPUT); // 设置 IO 口为输入模式
while(1){
sleep(1); // 延时 1 秒;
// usleep(); 延时微秒
digitalWrite (GPIO1, HIGH); // IO 口输出高电平
sleep(1);
digitalWrite (GPIO1, LOW); // IO 口输出低电平
if(digitalRead(GPIO2)){
// 检测 IO 口电平
printf("high level\n");
}else{
printf("low level\n");
}
}
return 0;
}
② 超声波测距:
时间函数:
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
struct timeval{
time_t tv_sec; /* seconds(秒)*/
suseconds_t tv_usec; /* microseconds(微秒)*/
};
struct timezone{
int tz_minuteswest; /* minutes west of Greenwich (格林威治时间往西方的时差) */
int tz_dsttime; /* type of DST correction (DST 时间的修正方式) */
};
- 获取自
1970-01-01 00:00:00
到调用gettimeofday()
函数所经历的秒数,存放在tv
中,精确到微秒,在超声波测距应用中,我们只关心时间差值- 获取时区信息,存放到
tz
中,不关心时置NULL
例程:
#include <stdio.h>
#include <sys/time.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <unistd.h>
#define Trig 5
#define Echo 7
double getDistance()
{
double dis;
struct timeval start;
struct timeval end;
pinMode(Trig, OUTPUT);
pinMode(Echo, INPUT);
digitalWrite(Trig ,LOW);
usleep(5);
digitalWrite(Trig ,HIGH); /* 向 Trig 口发送 10 微秒 TTL 脉冲 */
usleep(10);
digitalWrite(Trig ,LOW);
while(!digitalRead(Echo)); // 等待 Echo 口高电平
gettimeofday(&start,NULL); // 获取时间
while(digitalRead(Echo)); // 等待 Echo 口低电平
gettimeofday(&end,NULL); // 获取时间
long diffTime = 1000000*(end.tv_sec-start.tv_sec)+(end.tv_usec - start.tv_usec); // 计算时间差值,单位:微秒
dis = (double)diffTime/1000000 * 34000 / 2; // 计算距离,音速为 340 m/s
/*
diffTime/1000000 转化为秒
340(m/s) * 100 转化为厘米每秒(cm/s)
往返为两段路程,需要 /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;
}
③ Linux 定时器:
- 实现定时器,通过
itimerval
结构体配置以及函数setitimer()
产生的信号,系统随之使用signal
信号处理函数来处理产生的定时信号,从而实现定时器
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;
};
struct timeval
{
__time_t tv_sec; /* Seconds. */
__suseconds_t tv_usec; /* Microseconds. */
};
it_interval : |
计时器的初始值,一般基于这个初始值加或减,基于控制函数的参数配置 |
---|---|
it_value : |
当程序运行到此,间隔多久启动定时器 |
tv_sec : |
秒 |
tv_usec |
微秒(μs)(10 -6s) |
int setitimer (__itimer_which_t __which,
const struct itimerval *__restrict __new,
struct itimerval *__restrict __old);
返回值: | 成功返回 0,失败返回 -1 |
---|---|
__which 参数: |
ITIMER_REAL // 数值为 0,计时器的值实时递减,发送的信号是 SIGALRMITIMER_VIRTUAL // 数值为 1,进程执行时递减计时器的值,发送的信号是 SIGVTALRMITIMER_PROF // 数值为 2,进程和系统执行时都递减计时器的值,发送的信号是 SIGPROF |
__new 参数: |
设定定时器相关设置 |
__old 参数: |
保存先前__new 的值,常设为NULL |
- 函数的第一个参数,我们使用
ITIMER_REAL
,那么显然,我们需要捕获对应的信号进行逻辑相关处理,捕获SIGALRM
信号:signal(SIGALRM, signal_handler);
- 该方法一个进程只能创建一个定时器
例程:
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
static int i;
void signal_handler(int signum) // 每隔 2000 * 500 μs,即 1s 打印 "hello\n"
{
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; // 500 微秒
// 定时时间设定完成后,间隔多久启动定时器
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
// 间隔 1 秒启动定时器
// 设定定时方式
if( -1 == setitimer(ITIMER_REAL, &itv, NULL)){
perror("error");
exit(-1);
}
//信号处理
signal(SIGALRM, signal_handler);
while(1);
return 0;
}
④ PWM 输出:
- 输出高电平持续时间为
1.0 ms
,低电平持续时间为19 ms
的PWM
信号,即占空比为5%
,周期为20 ms
,频率为1 / 0.02s = 50 Hz
例程:
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
#define PWM 0
static int i = 0;
void signal_handler(int signum)
{
if(i <= 2){
digitalWrite(PWM, HIGH);
}else{
digitalWrite(PWM, LOW);
}
if(i == 40){
i = 0;
}
i++;
}
int main()
{
struct itimerval itv;
wiringPiSetup();
pinMode(PWM, OUTPUT);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 500; // 定时时间 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;
}
⑤ OLED 显示屏应用——IIC协议:
- 由
Orange Pi Zero 2
的26pin
原理图可知,可用的i2c
为i2c3
- 启动
linux
系统,确认/dev
下存在i2c-3
的设备节点,可以观察到系统支持I2C-3
和I2C-5
的驱动,而H616
的外设只有一个IIC
接口,用的是IIC-3
- 开始测试
IIC
,首先安装i2c-tools
:
sudo apt-get install i2c-tools
- 接好线后,终端输入指令
sudo i2cdetect -y 3
,可以看到终端打印信息,如下图,表明已经通过i2c-3
驱动扫描设备成功
下面基于wiringPi
库中的例程进行开发,路径:.../wiringOP-next/examples/oled_demo.c
,建议阅读熟悉例程代码
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include "oled.h"
#include "font.h"
int oled_demo(struct display_info *disp) {
int i;
char buf[100]