OrangePi Zero2 全志H616 开发初探

一、刷机和系统启动

1、TF 卡格式化:

可以使用SD Card Formatter软件格式化TF

2、镜像烧录:

使用win32diskimager软件将准备好的镜像烧录到TF卡中

镜像下载网址🔗点击这里 点击Orange Pi Zero2官方镜像的ubuntu镜像,跳转至百度网盘,下载3.0.6版本:
在这里插入图片描述
此镜像可能默认关闭uart5,需要使用uart5时配置一下串口uart5,打开配置文件:

sudo vi /boot/orangepiEnv.txt

加入以下字段,开启uart5i2c3

overlays=uart5 i2c3

如图所示:

在这里插入图片描述

3、登录系统:

利用MobaXterm进行串口登录或SSH方式登录,初次登录应用串口登录或利用USBHTML接入屏幕后登录,默认用户如下:

  • 用户名:orangepi,密码:orangepi
  • 用户名:root,密码:orangepi

修改orangepi用户密码:sudo passwd orangepi

① 串口登录:

使用TTL 转 USB模块连接开发板串口(电脑需要安装ch340驱动),如图所示,然后接入电脑,使用MobaXterm软件进行串口登录,波特率默认为115200MobaXterm连接上串口后,插入开发板电源线,查看串口打印数据,检验刷机是否成功

在这里插入图片描述
② 重启及关机:

  • 重启:sudo reboot
  • 关机:sudo poweroff

③ 网络配置:

  • 扫描周围的WIFI热点:nmcli dev wifi
  • 接入网络:nmcli dev wifi connect user password xxxxxxxx    // 比如接入用户名为userwifi,密码为xxxxxxxx
  • 查看IP地址:ip addr show wlan0ifconfig

④ 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,计时器的值实时递减,发送的信号是 SIGALRM
ITIMER_VIRTUAL    // 数值为 1,进程执行时递减计时器的值,发送的信号是 SIGVTALRM
ITIMER_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 msPWM信号,即占空比为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 226pin原理图可知,可用的i2ci2c3
  • 启动linux系统,确认/dev下存在i2c-3的设备节点,可以观察到系统支持I2C-3I2C-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]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~莘莘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值