当前位置:   article > 正文

香橙派KunpengPro测评之使用C语言操控40pin引脚_香橙派 40pin

香橙派 40pin

香橙派KunpengPro测评之使用C语言操控40pin引脚

香橙派KunpengPro介绍

香橙派鲲鹏Pro是一款高性能开发板,搭载4核64位鲲鹏处理器与AI加速器,提供8/16GB LPDDR4X内存及多种存储扩展选项。它配备双HDMI输出、M.2插槽、USB 3.0/Type-C接口等,支持4K视频、高速数据传输及网络连接。预装openEuler操作系统,适合AI研发、云计算、大数据处理等应用场景,凭借其强大的性能与灵活扩展性,成为教育、开发及创新项目的优选平台。
在这里插入图片描述

香橙派实物图

香橙派KunpengPro正面图
在这里插入图片描述
香橙派KunpengPro反面图
在这里插入图片描述
香橙派KunpengPro左侧面图
在这里插入图片描述
香橙派KunpengPro右侧面图
在这里插入图片描述

香橙派登录界面

香橙派KunpengPro的登录界面

在这里插入图片描述

香橙派KunpengPro的原始桌面

在这里插入图片描述

香橙派KunpengPro内安装了VScode等软件

在这里插入图片描述

香橙派KunpengPro的终端

在这里插入图片描述

香橙派硬件参数

OrangePi Kunpeng Pro是一款高性能、高扩展性的单板计算机,专为需要强大AI算力、高速数据处理及多场景应用开发的用户设计,提供了从硬件到软件的全面解决方案。

核心性能

  • 处理器架构:搭载4核64位处理器,集成了专门的AI处理单元,针对人工智能任务优化。
  • AI算力:支持高达8TOPS(Tera Operations Per Second)的AI运算能力,适合机器学习与深度学习应用。
  • 存储扩展:可通过外接eMMC模块扩展存储,支持32GB至256GB不同容量,满足不同存储需求。
  • 内存配置:配备高端的8GB/16GB LPDDR4X内存,确保流畅的数据处理和运行效率。

图形与显示

  • 图形处理:集成高效图形处理器,强化视觉处理与高清输出能力。
  • 视频输出:支持双路4K高清视频输出,适用于多屏展示或高分辨率监控系统。

接口丰富性

  • 外部连接:提供全面的接口选项,包括双HDMI、GPIO、Type-C电源输入、M.2插槽(兼容SATA/NVMe SSD)、TF卡插槽、千兆以太网口、多个USB端口(含USB3.0及USB Type-C 3.0)、Micro USB(具备串口打印调试功能)。
  • 多媒体支持:配备MIPI接口,支持连接摄像头与显示屏,拓展物联网与视觉项目应用。

扩展与兼容性

  • M.2插槽:特别提及的M.2 2280插槽,支持快速SSD,提升系统响应速度与数据传输效率。
  • 电池接口预留:便于移动设备改造或低功耗应用的开发需求。

软件与应用生态

  • 操作系统:兼容openEuler操作系统,为开发者提供稳定且开源的操作环境。
  • 应用场景:广泛适用于AI算法验证、推理应用开发,以及云计算、大数据处理、分布式存储和高性能计算等领域,展现了其作为高性能计算平台的潜力。

香橙派KunpengPro搭建环境

准备的工具有内存32G以上的高速闪迪TF卡、一个读卡器、香橙派KunpengPro镜像、香橙派KunpengPro镜像烧录工具、HDMI显示屏和HDMI转HDMI线或者使用一根Micro数据线进行串口登录。

下载镜像和烧录镜像工具

打开香橙派官网http://www.orangepi.cn/,选择开源硬件中的开发板,选择OrangePi Kunpeng Pro。
在这里插入图片描述
点击下载
在这里插入图片描述
需要下载下面这三个内容
在这里插入图片描述

官方工具下载

官方工具下载下面这几个就够用了。
在这里插入图片描述

烧录镜像

快速格式化TF卡

将TF卡插入读卡器,插到电脑的USB口中,并打开格式化工具SDCardFormatter进行快速格式化。
在这里插入图片描述

烧录香橙派KunpengPro的镜像

选择目标镜像和目标TF卡。
在这里插入图片描述

开始烧录。
在这里插入图片描述
烧录完成后,把TF卡插到香橙派KunpengPro开发板上,并接上Micro数据线,先不接通电源。

香橙派KunpengPro登录

串口登录

接上Micro数据线,在设备管理器查看COM口。
在这里插入图片描述
使用MobaXterm软件建立串口连接。
在这里插入图片描述
串口号选择设备管理器对应的,波特率选择115200。
在这里插入图片描述
流控制选择NONE。
在这里插入图片描述
插上电源,查看登录日志。
在这里插入图片描述
输入账号:openEuler,密码:openEuler进行登录。
在这里插入图片描述

连接WiFi进行SSH登录

sudo nmcli dev wifi,扫描香橙派KunpengPro附近的WiFi。
在这里插入图片描述
sudo nmcli dev wifi connect 用户名 password 密码,连接WiFi。
在这里插入图片描述
ifconfig,查看IP地址。
在这里插入图片描述
建立SSH连接
在这里插入图片描述
输入密码,选择No,就可以SSH登录香橙派KunpengPro了。
在这里插入图片描述

香橙派KunpengPro使用C语言驱动40pin引脚

众所周知,香橙派、树莓派等Linux开发板操控引脚使用最多的方法便是利用wiringPi库,本次测评的香橙派KunpengPro本来也是打算使用wiringOP库进行操控引脚,但是香橙派KunpengPro这块开发板还未适配wiringOP库,所以只能使用其他的方法来操控GPIO口。

方法1:使用system函数调用官方用户手册给出的命令

这个方法不太推荐,有兴趣的小伙伴可以了解一下,必须要以root账户去执行这些操控GPIO口的命令。

gpio_operate -h 命令

gpio_operate -h 命令可以获取 gpio_operate 工具的帮助信息在这里插入图片描述

gpio_operate get_direction gpio_group gpio_pin 命令

gpio_operate get_direction gpio_group gpio_pin 命令用于查询 GPIO 管脚方向。
在这里插入图片描述
value的值是0,该引脚就是输入引脚,value的值是1,该引脚就是输出引脚,
在这里插入图片描述

在这里插入图片描述

gpio_operate set_direction gpio_group gpio_pin direction命令

gpio_operate set_direction gpio_group gpio_pin direction 用于设置 GPIO 管脚方向。
在这里插入图片描述
在这里插入图片描述

gpio_operate get_value gpio_group gpio_pin 命令

gpio_operate get_value gpio_group gpio_pin 命令用于查询 GPIO 管脚值。
在这里插入图片描述
查询到value的值是0,那么引脚电平就是低电平,查询到value的值是1,那么引脚电平就是高电平。
在这里插入图片描述

gpio_operate set_value gpio_group gpio_pin value 命令

gpio_operate set_value gpio_group gpio_pin value 命令用于设置 GPIO 管脚值为高电平或者低电平。
在这里插入图片描述
在这里插入图片描述

方法2:使用我提供的gpioControl.c和gpioControl.h文件

使用这两个文件,只需要调用相应的函数,就可以控制IO口的输入、输出方向,输出高低电平等等功能,而且减少了系统调用,增加了代码的健壮性,话不多说,直接上代码

gpio控制源文件

gpioControl.c

void write_to_file(const char *filename, const char *value)
{
    int fd = open(filename, O_WRONLY);
    if (fd < 0)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    if (write(fd, value, strlen(value)) < 0)
    {
        perror("write");
        exit(EXIT_FAILURE);
    }
    close(fd);
}

void gpio_export(int pin)
{
    char buffer[4];
    snprintf(buffer, sizeof(buffer), "%d", pin);
    write_to_file(GPIO_EXPORT, buffer);
    usleep(100000); // 等待GPIO初始化完成
}

void gpio_unexport(int pin)
{
    char buffer[4];
    snprintf(buffer, sizeof(buffer), "%d", pin);
    write_to_file(GPIO_UNEXPORT, buffer);
}

void gpio_set_direction_in(int pin)
{
    char path[50];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "direction");
    write_to_file(path, "in");
}

void gpio_set_direction_outMode(int pin)
{
    char path[50];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "direction");
    write_to_file(path, "out");
}

void gpio_set_direction_out(int pin, GPIO_Value value)
{
    char path[50];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "direction");
    write_to_file(path, "out");

    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "value");
    write_to_file(path, value == HIGH ? "1" : "0");
}

int gpio_get_value(int pin)
{
    char path[50];
    char value_str[3];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "value");
    int fd = open(path, O_RDONLY);
    if (fd < 0)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    if (read(fd, value_str, sizeof(value_str)) < 0)
    {
        perror("read");
        exit(EXIT_FAILURE);
    }
    close(fd);
    return atoi(value_str);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

gpioControl.h

#ifndef GPIO_CONTROL_H
#define GPIO_CONTROL_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define GPIO_PATH_FORMAT "/sys/class/gpio/gpio%d/%s"
#define GPIO_EXPORT "/sys/class/gpio/export"
#define GPIO_UNEXPORT "/sys/class/gpio/unexport"

typedef enum {
    LOW = 0,
    HIGH = 1
} GPIO_Value;

// 导出GPIO引脚
void gpio_export(int pin);

// 取消导出GPIO引脚
void gpio_unexport(int pin);

// 设置GPIO引脚为输入模式
void gpio_set_direction_in(int pin);

// 设置GPIO引脚为输出模式
void gpio_set_direction_outMode(int pin);

// 设置GPIO引脚为输出模式并设置电平
void gpio_set_direction_out(int pin, GPIO_Value value);

// 读取GPIO引脚的状态
int gpio_get_value(int pin);

#endif // GPIO_CONTROL_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

调用GPIO控制函数控制蜂鸣器发出警报或LED闪烁

利用gpioControl.c和gpioControl.h文件,我们可以轻松的控制IO口输出高低电平或读取输入电平。查看官方用户手册的引脚图,我们发现左边倒数第二根引脚,也就是第37号引脚的GPIO序号是3,所以在代码中,我们使用的引脚序号应该是3而不是37。
在这里插入图片描述
buzzer.c

#include <stdio.h>
#include "gpio_control.h"

int main() {
    int pin = 3;  // 对应第37号引脚

    // 导出GPIO引脚
    gpio_export(pin);

    // 循环控制GPIO高低电平
    for (int i = 0; i < 3; i++) {
        gpio_set_direction_out(pin, HIGH); // 设置为高电平
        sleep(1);                          // 延时1s
        gpio_set_direction_out(pin, LOW);  // 设置为低电平
        sleep(1);                          // 延时1s
    }

    // 取消导出GPIO引脚
    gpio_unexport(pin);

    return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

此时,可以听到蜂鸣器每间接性响动,如果到了这步不能成功的话,大概率是因为你们之前下载了wiringOP这个库,导致引脚映射失败了,建议跟着前面的教程重新刷openEuler的镜像。

驱动OLED屏幕

有了前面操控引脚输出高低电平的方法后,现在只要操控引脚读取电平状态就能软件模拟IIC引脚,从而驱动OLED屏幕。这个使用C语言操控40pin引脚的方法不用安装任何库和配置环境,只需要上述代码就能随意操控IO口,使用左边倒数第四根引脚作为IIC_SCL引脚,即GPIO序号是128,左边倒数第2根作为IIC_SDA引脚,即GPIO序号是3。
oled.c

#include "oled.h"

int pin_scl = 128;
int pin_sda = 3;

/************************************6*8的点阵************************************/
const unsigned F6x8[][6] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp
        0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !
        0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // "
        0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #
        0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
        0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %
        0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &
        0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '
        0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (
        0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )
        0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *
        0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +
        0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,
        0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -
        0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .
        0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /
        0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
        0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1
        0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2
        0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3
        0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4
        0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5
        0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
        0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7
        0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8
        0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9
        0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :
        0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;
        0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <
        0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =
        0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >
        0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?
        0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @
        0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A
        0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B
        0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C
        0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D
        0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E
        0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F
        0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G
        0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H
        0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I
        0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J
        0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K
        0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L
        0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
        0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N
        0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O
        0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P
        0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
        0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R
        0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S
        0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T
        0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U
        0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V
        0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W
        0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X
        0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y
        0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z
        0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [
        0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55
        0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]
        0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^
        0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _
        0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '
        0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a
        0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b
        0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c
        0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d
        0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e
        0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f
        0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g
        0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h
        0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i
        0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j
        0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k
        0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l
        0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m
        0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n
        0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o
        0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p
        0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q
        0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r
        0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s
        0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t
        0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u
        0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v
        0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w
        0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x
        0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y
        0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z
        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, // horiz lines
};

/****************************************8*16的点阵************************************/
unsigned char F8X16[] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
        0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, //! 1
        0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //" 2
        0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3
        0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, //$ 4
        0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, //% 5
        0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, //& 6
        0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //' 7
        0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, //( 8
        0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, //) 9
        0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, //* 10
        0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, //+ 11
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, //, 12
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //- 13
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //. 14
        0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, /// 15
        0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16
        0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17
        0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18
        0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19
        0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20
        0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21
        0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22
        0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23
        0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24
        0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25
        0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, //: 26
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, //; 27
        0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, //< 28
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, //= 29
        0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, //> 30
        0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, //? 31
        0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, //@ 32
        0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33
        0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34
        0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35
        0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36
        0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37
        0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38
        0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39
        0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40
        0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41
        0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42
        0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43
        0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44
        0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45
        0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46
        0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47
        0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48
        0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49
        0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50
        0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51
        0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52
        0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53
        0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54
        0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55
        0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56
        0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57
        0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58
        0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, //[ 59
        0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, //\ 60
        0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, //] 61
        0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //^ 62
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //_ 63
        0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //` 64
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65
        0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66
        0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67
        0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69
        0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71
        0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72
        0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73
        0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74
        0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75
        0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76
        0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77
        0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79
        0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80
        0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81
        0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83
        0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84
        0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85
        0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86
        0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87
        0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88
        0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89
        0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90
        0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, //{ 91
        0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //| 92
        0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, //} 93
        0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //~ 94
};

void OLED_I2C_Delay(unsigned int t)
{
    usleep(t);
}

void OLED_I2C_Start(void)
{
    gpio_set_direction_outMode(pin_sda);
    OLED_SDA_HIGH; // 发送起始条件的数据信号
    OLED_SCL_HIGH;
    OLED_I2C_Delay(5); // 起始条件建立时间大于4.7us,延时
    OLED_SDA_LOW;      // 发送起始信号
    OLED_I2C_Delay(5); // 起始条件锁定时间大于4μs
    OLED_SCL_LOW;      // 钳住I2C总线,准备发送或接收数据
    OLED_I2C_Delay(5);
}

void OLED_I2C_Stop(void)
{
    gpio_set_direction_outMode(pin_sda);
    OLED_SDA_LOW; // 发送结束条件的数据信号
    OLED_SCL_LOW;
    OLED_I2C_Delay(5);
    OLED_SCL_HIGH;     // 发送结束条件的时钟信号
    OLED_I2C_Delay(5); // 结束条件建立时间大于4μs
    OLED_SDA_HIGH;     // 发送I2C总线结束信号
    OLED_I2C_Delay(5);
}

unsigned char OLED_I2C_Write_Byte(unsigned char writeByte)
{
    unsigned char i;
    gpio_set_direction_outMode(pin_sda);
    OLED_SCL_LOW;
    OLED_I2C_Delay(5);
    for (i = 0; i < 8; i++) // 要传送的数据长度为8位
    {
        if (writeByte & 0x80) // 判断发送位
        {
            OLED_SDA_HIGH;
        }
        else
        {
            OLED_SDA_LOW;
        }
        OLED_I2C_Delay(5);
        OLED_SCL_HIGH;     // 输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
        OLED_I2C_Delay(5); // 保证时钟高电平周期大于4μs
        OLED_SCL_LOW;
        OLED_I2C_Delay(5);
        writeByte <<= 1;
    }
    OLED_I2C_Delay(1);
    OLED_SDA_HIGH; // 8位发送完后释放数据线,准备接收应答位-ZLG
    OLED_I2C_Delay(5);
    OLED_SCL_HIGH; // MCU告知SHT2X数据发送完毕,等待从机的应答信号
    OLED_I2C_Delay(5);
    gpio_set_direction_in(pin_sda);
    /*以下是判断I2C总线接收应到应答信号是ACK还是NACK*/
    if (gpio_get_value(pin_sda) == 1) // SDA为高,收到NACK
    {
        OLED_I2C_Delay(5);
        OLED_SCL_LOW;
        return NACK;
    }
    else // SDA为低,收到ACK
    {
        OLED_I2C_Delay(5);
        OLED_SCL_LOW;
        return ACK;
    }
}

unsigned char OLED_I2C_Read_Byte(unsigned char ackValue)
{
    unsigned char i = 0;
    unsigned char readByte = 0;
    gpio_set_direction_outMode(pin_sda);
    OLED_SCL_LOW; // 置时钟线为低,准备接收数据位
    OLED_I2C_Delay(5);
    OLED_SDA_HIGH; // 释放总线,置数据线为输入方式
    gpio_set_direction_in(pin_sda);
    for (i = 0; i < 8; i++)
    {
        OLED_SCL_HIGH; // SCL高电平期间,采集SDA信号,并作为有效数据 //置时钟线为高使数据线上数据有效
        OLED_I2C_Delay(5);
        readByte <<= 1;                 // 移位
        if (gpio_get_value(pin_sda) == 1) // 采样获取数据
        {
            readByte |= 0x01;
        }
        else
        {
            readByte &= 0xfe;
        }
        OLED_I2C_Delay(5);
        OLED_SCL_LOW; // 下降沿,从机给出下一位值
        OLED_I2C_Delay(5);
    }
    gpio_set_direction_outMode(pin_sda);
    /*以下是I2C总线发送应答信号ACK或者NACK*/
    gpio_set_direction_out(pin_sda,ackValue);
    OLED_I2C_Delay(5);
    OLED_SCL_HIGH;
    OLED_I2C_Delay(5); // 时钟低电平周期大于4μs
    OLED_SCL_LOW;      // 清时钟线,钳住I2C总线以便继续接收
    OLED_I2C_Delay(5);
    return readByte;
}

// OLED写入一条指令
void oledWriteCmd(char writeCmd)
{
    OLED_I2C_Start();
    OLED_I2C_Write_Byte(0x78);
    OLED_I2C_Write_Byte(0x00);
    OLED_I2C_Write_Byte(writeCmd);
    OLED_I2C_Stop();
}

void oledWriteData(char writeData)
{
    OLED_I2C_Start();
    OLED_I2C_Write_Byte(0x78);
    OLED_I2C_Write_Byte(0x40);
    OLED_I2C_Write_Byte(writeData);
    OLED_I2C_Stop();
}

// 更新显存到LCD
void oled_Clear(void)
{
    unsigned char i, n;
    for (i = 0; i < 8; i++)
    {
        oledWriteCmd(0xb0 + i); // 设置页地址(0~7)
        oledWriteCmd(0x00);     // 设置显示位置—列低地址
        oledWriteCmd(0x10);     // 设置显示位置—列高地址
        for (n = 0; n < 130; n++)
        {
            oledWriteData(0);
        }
    }
    OLED_I2C_Delay(500000);
}

// 开启OLED显示
void OLED_Display_On(void)
{
    oledWriteCmd(0X8D); // SET DCDC命令
    oledWriteCmd(0X14); // DCDC ON
    oledWriteCmd(0XAF); // DISPLAY ON
}

// 关闭OLED显示
void OLED_Display_Off(void)
{
    oledWriteCmd(0XAE); // SET DCDC命令
    oledWriteCmd(0X8D); // DCDC OFF
    oledWriteCmd(0X10); // DISPLAY OFF
}

// 设置光标
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
    oledWriteCmd(0xB0 + y);
    oledWriteCmd((x & 0x0f));
    oledWriteCmd(((x & 0xf0) >> 4) | 0x10);
}

// 屏幕初始化函数
void oled_Init(void)
{
    // 导出GPIO引脚
    gpio_export(pin_scl);
    gpio_export(pin_sda);

    gpio_set_direction_out(pin_scl, HIGH);
    gpio_set_direction_out(pin_sda, HIGH);

    oledWriteCmd(0xAE); // 关闭显示
    oledWriteCmd(0x00); // 设置时钟分频因子,震荡频率
    oledWriteCmd(0x10); //[3:0],分频因子;[7:4],震荡频率
    oledWriteCmd(0x40); // 设置驱动路数
    oledWriteCmd(0xB0); // 默认0X3F(1/64)

    oledWriteCmd(0x81); // 默认为0
    oledWriteCmd(0xFF); // 设置显示开始行 [5:0],行数.

    oledWriteCmd(0xA1); // 电荷泵设置
    oledWriteCmd(0xA6); // bit2,开启/关闭

    oledWriteCmd(0xA8); // 设置内存地址模式
    oledWriteCmd(0x3F); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;

    oledWriteCmd(0xC8); // 段重定义设置,bit0:0,0->0;1,0->127;

    oledWriteCmd(0xD3); // 设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
    oledWriteCmd(0x00); // 设置COM硬件引脚配置

    oledWriteCmd(0xD5); //[5:4]配置
    oledWriteCmd(0x80); // 对比度设置

    oledWriteCmd(0xD9); // 1~255;默认0X7F (亮度设置,越大越亮)
    oledWriteCmd(0xF1); // 设置预充电周期

    oledWriteCmd(0xDA); //[3:0],PHASE 1;[7:4],PHASE 2;
    oledWriteCmd(0x12); // 设置VCOMH 电压倍率

    oledWriteCmd(0xDB); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc
    oledWriteCmd(0x40); // 全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)

    oledWriteCmd(0x8D); // 设置显示方式;bit0:1,反相显示;0,正常显示
    oledWriteCmd(0x14); // 开启显示
    oledWriteCmd(0xAF); // 开启显示 OLED_Clear();
    OLED_Set_Pos(0, 0);

    oled_Clear();
}

void oled_DeInit(void)
{
    gpio_unexport(pin_scl);
    gpio_unexport(pin_sda);
}

// 在指定位置显示一个字符,包括部分字符
// x:0~127
// y:0~63
// mode:0,反白显示;1,正常显示
// size:选择字体 16/12
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr)
{
    unsigned char c = 0, i = 0;
    c = chr - ' ';
    if (x > Max_Column)
    {
        x = 0;
        y = y + 2;
    }
    if (SIZE == 16) // ×Ö·û´óСÈç¹ûΪ16 =8 *16
    {
        OLED_Set_Pos(x, y); // ´Óx,y¿ªÊ¼»­µã
        for (i = 0; i < 8; i++)
        {
            oledWriteData(F8X16[c * 16 + i]);
        }
        OLED_Set_Pos(x, y + 1); // ´Óx,y¿ªÊ¼»­µã
        for (i = 0; i < 8; i++)
        {
            oledWriteData(F8X16[c * 16 + i + 8]);
        }
    }
    else // 6 =6*8
    {
        OLED_Set_Pos(x, y);

        for (i = 0; i < 6; i++)
            oledWriteData(F6x8[c][i]);
    }
}

// 显示字符串
// x,y:起点坐标
// size:字体大小
//*p:字符串起始地址
void oled_ShowString(unsigned char x, unsigned char y, const unsigned char *chr)
{

    unsigned char j = 0;
    while (chr[j] != '\0')
    {

        OLED_ShowChar(x, y, chr[j]);
        x += 8;
        if (x >= 128)
        {
            x = 0;
            y += 2;
        }
        j++;
    }
}

void main()
{
    oled_Init();
    oled_ShowString(0,0,"jiangxiaoya");
    oled_DeInit();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492

oled.h

#ifndef OLED_H
#define OLED_H

#include <stdio.h>
#include "gpio_control.h"

#define SIZE 16           // 字符大小
#define Max_Column 128    // 最大列数

#define OLED_IIC_ADDRESS 0x3C

#define ACK 0  // 应答信号
#define NACK 1 // 非应答信号

#define OLED_SCL_HIGH gpio_set_direction_out(pin_scl, HIGH)
#define OLED_SCL_LOW  gpio_set_direction_out(pin_scl, LOW)
#define OLED_SDA_HIGH gpio_set_direction_out(pin_sda, HIGH)
#define OLED_SDA_LOW  gpio_set_direction_out(pin_sda, LOW)

void oled_Init(void);
void oled_DeInit(void);
void oled_Clear(void);
void oled_ShowString(unsigned char x, unsigned char y, const unsigned char *chr);

#endif // OLED_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

显示效果如下图:在这里插入图片描述
它会有一个清屏函数,动图如下,清屏效果可能有点慢,动态图如下。

香橙派KunpengPro配置开机自启动使用OLED屏幕显示IP地址

写一个自动获取IP的程序

文件列表

程序文件列表如下:
clear.c:主要是清除引脚的使用,后面会将clear.c单独gcc编译成可执行文件clear,编译成功后可以将clear.c删掉了。
oled.c、oled.h
server.c、server.h
mainPro.c、mainPro.h

gpio_control.c和gpio_control.h

gpio_control.h

#ifndef GPIO_CONTROL_H
#define GPIO_CONTROL_H

#define GPIO_PATH_FORMAT "/sys/class/gpio/gpio%d/%s"
#define GPIO_EXPORT "/sys/class/gpio/export"
#define GPIO_UNEXPORT "/sys/class/gpio/unexport"

typedef enum {
    LOW = 0,
    HIGH = 1
} GPIO_Value;

// 导出GPIO引脚
void gpio_export(int pin);

// 取消导出GPIO引脚
void gpio_unexport(int pin);

// 设置GPIO引脚为输入模式
void gpio_set_direction_in(int pin);

// 设置GPIO引脚为输出模式
void gpio_set_direction_outMode(int pin);

// 设置GPIO引脚为输出模式并设置电平
void gpio_set_direction_out(int pin, GPIO_Value value);

// 读取GPIO引脚的状态
int gpio_get_value(int pin);

#endif // GPIO_CONTROL_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

gpio_control.c

#include "mainPro.h"

void write_to_file(const char *filename, const char *value)
{
    int fd = open(filename, O_WRONLY);
    if (fd < 0)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    if (write(fd, value, strlen(value)) < 0)
    {
        perror("write");
        exit(EXIT_FAILURE);
    }
    close(fd);
}

void gpio_export(int pin)
{
    char buffer[4];
    snprintf(buffer, sizeof(buffer), "%d", pin);
    write_to_file(GPIO_EXPORT, buffer);
    usleep(100000); // 等待GPIO初始化完成
}

void gpio_unexport(int pin)
{
    char buffer[4];
    snprintf(buffer, sizeof(buffer), "%d", pin);
    write_to_file(GPIO_UNEXPORT, buffer);
}

void gpio_set_direction_in(int pin)
{
    char path[50];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "direction");
    write_to_file(path, "in");
}

void gpio_set_direction_outMode(int pin)
{
    char path[50];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "direction");
    write_to_file(path, "out");
}

void gpio_set_direction_out(int pin, GPIO_Value value)
{
    char path[50];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "direction");
    write_to_file(path, "out");

    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "value");
    write_to_file(path, value == HIGH ? "1" : "0");
}

int gpio_get_value(int pin)
{
    char path[50];
    char value_str[3];
    snprintf(path, sizeof(path), GPIO_PATH_FORMAT, pin, "value");
    int fd = open(path, O_RDONLY);
    if (fd < 0)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    if (read(fd, value_str, sizeof(value_str)) < 0)
    {
        perror("read");
        exit(EXIT_FAILURE);
    }
    close(fd);
    return atoi(value_str);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

clear.c和可执行文件clear

clear.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define GPIO_PATH_FORMAT "/sys/class/gpio/gpio%d/%s"
#define GPIO_EXPORT "/sys/class/gpio/export"
#define GPIO_UNEXPORT "/sys/class/gpio/unexport"

void write_to_file(const char *filename, const char *value)
{
    int fd = open(filename, O_WRONLY);
    if (fd < 0)
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    if (write(fd, value, strlen(value)) < 0)
    {
        perror("write");
        exit(EXIT_FAILURE);
    }
    close(fd);
}

void gpio_unexport(int pin)
{
    char buffer[4];
    snprintf(buffer, sizeof(buffer), "%d", pin);
    write_to_file(GPIO_UNEXPORT, buffer);
}

void main()
{
    gpio_unexport(3);
    gpio_unexport(128);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

clear可执行文件
在这里插入图片描述

oled.c和oled.h

oled.h

#ifndef OLED_H
#define OLED_H

#define SIZE 16           // 字符大小
#define Max_Column 128    // 最大列数

#define OLED_IIC_ADDRESS 0x3C

#define ACK 0  // 应答信号
#define NACK 1 // 非应答信号

#define OLED_SCL_HIGH gpio_set_direction_out(pin_scl, HIGH)
#define OLED_SCL_LOW  gpio_set_direction_out(pin_scl, LOW)
#define OLED_SDA_HIGH gpio_set_direction_out(pin_sda, HIGH)
#define OLED_SDA_LOW  gpio_set_direction_out(pin_sda, LOW)

void oled_Init(void);
void oled_DeInit(void);
void oled_Clear(void);
void oled_ShowString(unsigned char x, unsigned char y, const unsigned char *chr);

#endif // OLED_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

oled.c

#include "mainPro.h"

int pin_scl = 128;
int pin_sda = 3;

/************************************6*8的点阵************************************/
const unsigned F6x8[][6] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp
        0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // !
        0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // "
        0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // #
        0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
        0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // %
        0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // &
        0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // '
        0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // (
        0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // )
        0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // *
        0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // +
        0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // ,
        0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // -
        0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // .
        0x00, 0x20, 0x10, 0x08, 0x04, 0x02, // /
        0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
        0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, // 1
        0x00, 0x42, 0x61, 0x51, 0x49, 0x46, // 2
        0x00, 0x21, 0x41, 0x45, 0x4B, 0x31, // 3
        0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, // 4
        0x00, 0x27, 0x45, 0x45, 0x45, 0x39, // 5
        0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
        0x00, 0x01, 0x71, 0x09, 0x05, 0x03, // 7
        0x00, 0x36, 0x49, 0x49, 0x49, 0x36, // 8
        0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, // 9
        0x00, 0x00, 0x36, 0x36, 0x00, 0x00, // :
        0x00, 0x00, 0x56, 0x36, 0x00, 0x00, // ;
        0x00, 0x08, 0x14, 0x22, 0x41, 0x00, // <
        0x00, 0x14, 0x14, 0x14, 0x14, 0x14, // =
        0x00, 0x00, 0x41, 0x22, 0x14, 0x08, // >
        0x00, 0x02, 0x01, 0x51, 0x09, 0x06, // ?
        0x00, 0x32, 0x49, 0x59, 0x51, 0x3E, // @
        0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C, // A
        0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, // B
        0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, // C
        0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, // D
        0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, // E
        0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, // F
        0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A, // G
        0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, // H
        0x00, 0x00, 0x41, 0x7F, 0x41, 0x00, // I
        0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, // J
        0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, // K
        0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, // L
        0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
        0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, // N
        0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, // O
        0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, // P
        0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
        0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, // R
        0x00, 0x46, 0x49, 0x49, 0x49, 0x31, // S
        0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, // T
        0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, // U
        0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, // V
        0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, // W
        0x00, 0x63, 0x14, 0x08, 0x14, 0x63, // X
        0x00, 0x07, 0x08, 0x70, 0x08, 0x07, // Y
        0x00, 0x61, 0x51, 0x49, 0x45, 0x43, // Z
        0x00, 0x00, 0x7F, 0x41, 0x41, 0x00, // [
        0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55, // 55
        0x00, 0x00, 0x41, 0x41, 0x7F, 0x00, // ]
        0x00, 0x04, 0x02, 0x01, 0x02, 0x04, // ^
        0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // _
        0x00, 0x00, 0x01, 0x02, 0x04, 0x00, // '
        0x00, 0x20, 0x54, 0x54, 0x54, 0x78, // a
        0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, // b
        0x00, 0x38, 0x44, 0x44, 0x44, 0x20, // c
        0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, // d
        0x00, 0x38, 0x54, 0x54, 0x54, 0x18, // e
        0x00, 0x08, 0x7E, 0x09, 0x01, 0x02, // f
        0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g
        0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, // h
        0x00, 0x00, 0x44, 0x7D, 0x40, 0x00, // i
        0x00, 0x40, 0x80, 0x84, 0x7D, 0x00, // j
        0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, // k
        0x00, 0x00, 0x41, 0x7F, 0x40, 0x00, // l
        0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, // m
        0x00, 0x7C, 0x08, 0x04, 0x04, 0x78, // n
        0x00, 0x38, 0x44, 0x44, 0x44, 0x38, // o
        0x00, 0xFC, 0x24, 0x24, 0x24, 0x18, // p
        0x00, 0x18, 0x24, 0x24, 0x18, 0xFC, // q
        0x00, 0x7C, 0x08, 0x04, 0x04, 0x08, // r
        0x00, 0x48, 0x54, 0x54, 0x54, 0x20, // s
        0x00, 0x04, 0x3F, 0x44, 0x40, 0x20, // t
        0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C, // u
        0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, // v
        0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, // w
        0x00, 0x44, 0x28, 0x10, 0x28, 0x44, // x
        0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C, // y
        0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, // z
        0x14, 0x14, 0x14, 0x14, 0x14, 0x14, // horiz lines
};

/****************************************8*16的点阵************************************/
unsigned char F8X16[] =
    {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0
        0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00, //! 1
        0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //" 2
        0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00, // # 3
        0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00, //$ 4
        0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00, //% 5
        0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10, //& 6
        0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //' 7
        0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00, //( 8
        0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00, //) 9
        0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00, //* 10
        0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00, //+ 11
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, //, 12
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, //- 13
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, //. 14
        0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00, /// 15
        0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00, // 0 16
        0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // 1 17
        0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00, // 2 18
        0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // 3 19
        0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00, // 4 20
        0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00, // 5 21
        0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // 6 22
        0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // 7 23
        0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00, // 8 24
        0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00, // 9 25
        0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, //: 26
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00, //; 27
        0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, //< 28
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, //= 29
        0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, //> 30
        0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00, //? 31
        0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00, //@ 32
        0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20, // A 33
        0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00, // B 34
        0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00, // C 35
        0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // D 36
        0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00, // E 37
        0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, // F 38
        0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00, // G 39
        0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20, // H 40
        0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // I 41
        0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00, // J 42
        0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00, // K 43
        0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00, // L 44
        0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00, // M 45
        0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00, // N 46
        0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00, // O 47
        0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00, // P 48
        0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00, // Q 49
        0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20, // R 50
        0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00, // S 51
        0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // T 52
        0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // U 53
        0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00, // V 54
        0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00, // W 55
        0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20, // X 56
        0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00, // Y 57
        0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00, // Z 58
        0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00, //[ 59
        0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00, //\ 60
        0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00, //] 61
        0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //^ 62
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //_ 63
        0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //` 64
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20, // a 65
        0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00, // b 66
        0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00, // c 67
        0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20, // d 68
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00, // e 69
        0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // f 70
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00, // g 71
        0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // h 72
        0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // i 73
        0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, // j 74
        0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00, // k 75
        0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00, // l 76
        0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F, // m 77
        0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20, // n 78
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, // o 79
        0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00, // p 80
        0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80, // q 81
        0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00, // r 82
        0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00, // s 83
        0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00, // t 84
        0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20, // u 85
        0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00, // v 86
        0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00, // w 87
        0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00, // x 88
        0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00, // y 89
        0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00, // z 90
        0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40, //{ 91
        0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, //| 92
        0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00, //} 93
        0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //~ 94
};

void OLED_I2C_Delay(unsigned int t)
{
    usleep(t);
}

void OLED_I2C_Start(void)
{
    gpio_set_direction_outMode(pin_sda);
    OLED_SDA_HIGH; // 发送起始条件的数据信号
    OLED_SCL_HIGH;
    OLED_I2C_Delay(5); // 起始条件建立时间大于4.7us,延时
    OLED_SDA_LOW;      // 发送起始信号
    OLED_I2C_Delay(5); // 起始条件锁定时间大于4μs
    OLED_SCL_LOW;      // 钳住I2C总线,准备发送或接收数据
    OLED_I2C_Delay(5);
}

void OLED_I2C_Stop(void)
{
    gpio_set_direction_outMode(pin_sda);
    OLED_SDA_LOW; // 发送结束条件的数据信号
    OLED_SCL_LOW;
    OLED_I2C_Delay(5);
    OLED_SCL_HIGH;     // 发送结束条件的时钟信号
    OLED_I2C_Delay(5); // 结束条件建立时间大于4μs
    OLED_SDA_HIGH;     // 发送I2C总线结束信号
    OLED_I2C_Delay(5);
}

unsigned char OLED_I2C_Write_Byte(unsigned char writeByte)
{
    unsigned char i;
    gpio_set_direction_outMode(pin_sda);
    OLED_SCL_LOW;
    OLED_I2C_Delay(5);
    for (i = 0; i < 8; i++) // 要传送的数据长度为8位
    {
        if (writeByte & 0x80) // 判断发送位
        {
            OLED_SDA_HIGH;
        }
        else
        {
            OLED_SDA_LOW;
        }
        OLED_I2C_Delay(5);
        OLED_SCL_HIGH;     // 输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
        OLED_I2C_Delay(5); // 保证时钟高电平周期大于4μs
        OLED_SCL_LOW;
        OLED_I2C_Delay(5);
        writeByte <<= 1;
    }
    OLED_I2C_Delay(1);
    OLED_SDA_HIGH; // 8位发送完后释放数据线,准备接收应答位-ZLG
    OLED_I2C_Delay(5);
    OLED_SCL_HIGH; // MCU告知SHT2X数据发送完毕,等待从机的应答信号
    OLED_I2C_Delay(5);
    gpio_set_direction_in(pin_sda);
    /*以下是判断I2C总线接收应到应答信号是ACK还是NACK*/
    if (gpio_get_value(pin_sda) == 1) // SDA为高,收到NACK
    {
        OLED_I2C_Delay(5);
        OLED_SCL_LOW;
        return NACK;
    }
    else // SDA为低,收到ACK
    {
        OLED_I2C_Delay(5);
        OLED_SCL_LOW;
        return ACK;
    }
}

unsigned char OLED_I2C_Read_Byte(unsigned char ackValue)
{
    unsigned char i = 0;
    unsigned char readByte = 0;
    gpio_set_direction_outMode(pin_sda);
    OLED_SCL_LOW; // 置时钟线为低,准备接收数据位
    OLED_I2C_Delay(5);
    OLED_SDA_HIGH; // 释放总线,置数据线为输入方式
    gpio_set_direction_in(pin_sda);
    for (i = 0; i < 8; i++)
    {
        OLED_SCL_HIGH; // SCL高电平期间,采集SDA信号,并作为有效数据 //置时钟线为高使数据线上数据有效
        OLED_I2C_Delay(5);
        readByte <<= 1;                 // 移位
        if (gpio_get_value(pin_sda) == 1) // 采样获取数据
        {
            readByte |= 0x01;
        }
        else
        {
            readByte &= 0xfe;
        }
        OLED_I2C_Delay(5);
        OLED_SCL_LOW; // 下降沿,从机给出下一位值
        OLED_I2C_Delay(5);
    }
    gpio_set_direction_outMode(pin_sda);
    /*以下是I2C总线发送应答信号ACK或者NACK*/
    gpio_set_direction_out(pin_sda,ackValue);
    OLED_I2C_Delay(5);
    OLED_SCL_HIGH;
    OLED_I2C_Delay(5); // 时钟低电平周期大于4μs
    OLED_SCL_LOW;      // 清时钟线,钳住I2C总线以便继续接收
    OLED_I2C_Delay(5);
    return readByte;
}

// OLED写入一条指令
void oledWriteCmd(char writeCmd)
{
    OLED_I2C_Start();
    OLED_I2C_Write_Byte(0x78);
    OLED_I2C_Write_Byte(0x00);
    OLED_I2C_Write_Byte(writeCmd);
    OLED_I2C_Stop();
}

void oledWriteData(char writeData)
{
    OLED_I2C_Start();
    OLED_I2C_Write_Byte(0x78);
    OLED_I2C_Write_Byte(0x40);
    OLED_I2C_Write_Byte(writeData);
    OLED_I2C_Stop();
}

// 更新显存到LCD
void oled_Clear(void)
{
    unsigned char i, n;
    for (i = 0; i < 8; i++)
    {
        oledWriteCmd(0xb0 + i); // 设置页地址(0~7)
        oledWriteCmd(0x00);     // 设置显示位置—列低地址
        oledWriteCmd(0x10);     // 设置显示位置—列高地址
        for (n = 0; n < 130; n++)
        {
            oledWriteData(0);
        }
    }
    OLED_I2C_Delay(500000);
}

// 开启OLED显示
void OLED_Display_On(void)
{
    oledWriteCmd(0X8D); // SET DCDC命令
    oledWriteCmd(0X14); // DCDC ON
    oledWriteCmd(0XAF); // DISPLAY ON
}

// 关闭OLED显示
void OLED_Display_Off(void)
{
    oledWriteCmd(0XAE); // SET DCDC命令
    oledWriteCmd(0X8D); // DCDC OFF
    oledWriteCmd(0X10); // DISPLAY OFF
}

// 设置光标
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
    oledWriteCmd(0xB0 + y);
    oledWriteCmd((x & 0x0f));
    oledWriteCmd(((x & 0xf0) >> 4) | 0x10);
}

// 屏幕初始化函数
void oled_Init(void)
{
    // 导出GPIO引脚
    gpio_export(pin_scl);
    gpio_export(pin_sda);

    gpio_set_direction_out(pin_scl, HIGH);
    gpio_set_direction_out(pin_sda, HIGH);

    oledWriteCmd(0xAE); // 关闭显示
    oledWriteCmd(0x00); // 设置时钟分频因子,震荡频率
    oledWriteCmd(0x10); //[3:0],分频因子;[7:4],震荡频率
    oledWriteCmd(0x40); // 设置驱动路数
    oledWriteCmd(0xB0); // 默认0X3F(1/64)

    oledWriteCmd(0x81); // 默认为0
    oledWriteCmd(0xFF); // 设置显示开始行 [5:0],行数.

    oledWriteCmd(0xA1); // 电荷泵设置
    oledWriteCmd(0xA6); // bit2,开启/关闭

    oledWriteCmd(0xA8); // 设置内存地址模式
    oledWriteCmd(0x3F); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;

    oledWriteCmd(0xC8); // 段重定义设置,bit0:0,0->0;1,0->127;

    oledWriteCmd(0xD3); // 设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数
    oledWriteCmd(0x00); // 设置COM硬件引脚配置

    oledWriteCmd(0xD5); //[5:4]配置
    oledWriteCmd(0x80); // 对比度设置

    oledWriteCmd(0xD9); // 1~255;默认0X7F (亮度设置,越大越亮)
    oledWriteCmd(0xF1); // 设置预充电周期

    oledWriteCmd(0xDA); //[3:0],PHASE 1;[7:4],PHASE 2;
    oledWriteCmd(0x12); // 设置VCOMH 电压倍率

    oledWriteCmd(0xDB); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc
    oledWriteCmd(0x40); // 全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)

    oledWriteCmd(0x8D); // 设置显示方式;bit0:1,反相显示;0,正常显示
    oledWriteCmd(0x14); // 开启显示
    oledWriteCmd(0xAF); // 开启显示 OLED_Clear();
    OLED_Set_Pos(0, 0);

    oled_Clear();
}

void oled_DeInit(void)
{
    gpio_unexport(pin_scl);
    gpio_unexport(pin_sda);
}

// 在指定位置显示一个字符,包括部分字符
// x:0~127
// y:0~63
// mode:0,反白显示;1,正常显示
// size:选择字体 16/12
void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char chr)
{
    unsigned char c = 0, i = 0;
    c = chr - ' ';
    if (x > Max_Column)
    {
        x = 0;
        y = y + 2;
    }
    if (SIZE == 16) // ×Ö·û´óСÈç¹ûΪ16 =8 *16
    {
        OLED_Set_Pos(x, y); // ´Óx,y¿ªÊ¼»­µã
        for (i = 0; i < 8; i++)
        {
            oledWriteData(F8X16[c * 16 + i]);
        }
        OLED_Set_Pos(x, y + 1); // ´Óx,y¿ªÊ¼»­µã
        for (i = 0; i < 8; i++)
        {
            oledWriteData(F8X16[c * 16 + i + 8]);
        }
    }
    else // 6 =6*8
    {
        OLED_Set_Pos(x, y);

        for (i = 0; i < 6; i++)
            oledWriteData(F6x8[c][i]);
    }
}

// 显示字符串
// x,y:起点坐标
// size:字体大小
//*p:字符串起始地址
void oled_ShowString(unsigned char x, unsigned char y, const unsigned char *chr)
{

    unsigned char j = 0;
    while (chr[j] != '\0')
    {

        OLED_ShowChar(x, y, chr[j]);
        x += 8;
        if (x >= 128)
        {
            x = 0;
            y += 2;
        }
        j++;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485

server.c和server.h

server.h

#ifndef SERVER_H
#define SERVER_H

#define MAX_MATCHES 10                          // 正则表达式匹配次数
#define IP_REGEX "([0-9]{1,3}\\.){3}[0-9]{1,3}" // 正则表达式,匹配xxx.xxx.xxx.xxx

#define BUF_SIZE 128  // readBuffer和writeBuffer的大小

#define SERVER_PORT "8006"

void *server_pthread(void *arg);

#endif /* SERVER_H */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

server.c

#include "mainPro.h"

int server_Fd = 0;

char IP_ADDRESS[24] = {'\0'};

void get_ip_address()
{
    // 调用终端执行ifconfig命令
    char tmpBuf[1024] = {'\0'};
    FILE *fp = popen("ifconfig wlan0", "r");
    int readCnt = fread(tmpBuf, 1, 1024, fp);
    pclose(fp);

    regex_t regex;                   // 正则表达式结构体,用来存储编译后的正则表达式
    regmatch_t matches[MAX_MATCHES]; // 匹配结果数组,用来存储匹配到的结果
    int ret;

    ret = regcomp(&regex, IP_REGEX, REG_EXTENDED); // 编译正则表达式,REG_EXTENDED使用扩展正则表达式模式
    if (ret != 0)
    {
        fprintf(stderr, "Failed to compile regex\n");
        return;
    }

    ret = regexec(&regex, tmpBuf, MAX_MATCHES, matches, 0); // 目标字符串匹配正则表达式,MAX_MATCHES为匹配的最大次数
    if (ret != 0)
    {
        fprintf(stderr, "No IP address found\n");
        regfree(&regex);
        return;
    }

    char *ip_address = malloc(16);
    if (ip_address == NULL)
    {
        fprintf(stderr, "Failed to allocate memory\n");
        regfree(&regex); // 释放编译的正则表达式结构体
        return;
    }
    memset(ip_address, '\0', 16);
    int len = matches[0].rm_eo - matches[0].rm_so;
    strncpy(ip_address, tmpBuf + matches[0].rm_so, len);

    // Free the regex
    regfree(&regex); // 释放编译的正则表达式结构体
    // oled_Clear();
    // oled_ShowString(0 + 2, 0, ip_address);  // 第一行
    // oled_ShowString(0 + 2, 6, SERVER_PORT); // 最后一行
    memset(IP_ADDRESS,0,24);
    strncpy(IP_ADDRESS,ip_address,16);
}

void *server_SendData_pthread(void *arg)
{
    int connectFd = *((int *)arg);
    char writeBuf[BUF_SIZE] = "Hello Orange KunPengPro";

    while (1)
    {
        write(connectFd, writeBuf, strlen(writeBuf));
        usleep(3000000); // 延时1000ms
    }

    return NULL;
}

void *server_clientConnect_pthread(void *arg)
{
    int connectFd = *((int *)arg);
    char readBuf[BUF_SIZE];
    int readSize;

    pthread_t server_SendData_tid;
    if (pthread_create(&server_SendData_tid, NULL, server_SendData_pthread, arg) != 0)
    {
        perror("pthread_create");
    }

    while (1)
    {
        memset(readBuf, '\0', sizeof(readBuf));
        readSize = read(connectFd, readBuf, sizeof(readBuf));
        if (readSize < 0)
        {
            perror("read");
            break;
        }
        else if (readSize == 0)
        {
            printf("Client disconnected\n");
            break;
        }
        else
        {
            printf("Message from client: %s\n", readBuf);
        }
    }

    pthread_cancel(server_SendData_tid);

    close(connectFd);
    free(arg);
    return NULL;
}

int serverInit()
{
    get_ip_address();
    server_Fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_Fd < 0)
    {
        perror("socket");
        return -1;
    }
    struct sockaddr_in my_net;
    memset(&my_net, 0, sizeof(struct sockaddr_in));
    my_net.sin_family = AF_INET;
    my_net.sin_port = htons(atoi(SERVER_PORT));
    inet_aton(IP_ADDRESS, &my_net.sin_addr);
    if (bind(server_Fd, (struct sockaddr *)&my_net, sizeof(struct sockaddr_in)) < 0)
    {
        perror("bind");
        return -1;
    }
    if (listen(server_Fd, 15) < 0)
    {
        perror("listen");
        return -1;
    }
    return 0;
}

void *server_pthread(void *arg)
{
    int connectFd = 0;
    struct sockaddr_in msg_addr;
    int tmp = 0;
    int size = sizeof(struct sockaddr_in);

    serverInit();
    printf("OrangeKunPengPro_IP:%s,OrangeKunPengPro_Port:%s\n", IP_ADDRESS, SERVER_PORT);
    oled_ShowString(0, 0, IP_ADDRESS);
    oled_ShowString(0, 6, SERVER_PORT);
    while (1)
    {
        memset(&msg_addr, 0, sizeof(struct sockaddr_in));
        connectFd = accept(server_Fd, (struct sockaddr *)&msg_addr, &size);
        if (connectFd < 0)
        {
            perror("accept");
        }
        tmp++;
        printf("Got connection %d from %s\n", tmp, inet_ntoa(msg_addr.sin_addr));

        int *connectFd_ptr = (int *)malloc(sizeof(int));
        *connectFd_ptr = connectFd;

        pthread_t server_clientConnect_tid;
        if (pthread_create(&server_clientConnect_tid, NULL, server_clientConnect_pthread, connectFd_ptr) != 0)
        {
            perror("pthread_create");
            free(connectFd_ptr);
        }

        pthread_detach(server_clientConnect_tid);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169

mainPro.c和mainPro.h

mainPro.h

#ifndef MAINPRO_H
#define MAINPRO_H

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <regex.h>

#include "gpio_control.h"
#include "oled.h"
#include "server.h"

#endif /* MAINPRO_H */
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

mainPro.c

#include "mainPro.h"

int main(int argc, char *argv[])
{
    system("sudo /home/openEuler/GPIO_CONTROL/clear");
    oled_Init();

    pthread_t server_tid;
    if (pthread_create(&server_tid, NULL, server_pthread, NULL) != 0)
    {
        perror("pthread_create");
    }

    pthread_join(server_tid, NULL);

    oled_ShowString(0,0,"jiangxiaoya");

    oled_DeInit();

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

与QT上位机的交互

因为架设了Socket服务端,因此,我们可以通过网络调试助手或者QT上位机来与香橙派KunpengPro进行网络通信。
在这里插入图片描述

创建一个开机自启动服务

创建一个开机自启动服务,该服务连上网后才会执行。
在这里插入图片描述

创建一个自启动服务文件

sudo vi /etc/systemd/system/haozige.service,haozige是文件名,可以自行修改,内容填下面的,记得使用root权限,如果有报错,把中文注释删掉。

[Unit]
Description=Haozige #这里是这个服务的描述,可以不用管
After=network.target #连上网才启动服务
[Service]
User=root #用户名
ExecStart=/home/openEuler/GPIO_CONTROL/haozige #可执行文件的路径,就是你gcc编译出来的可执行文件
Restart=on-failure #服务失败后选择重启操作
StandardOutput=journal #服务的标准输出流,选择日志,可以用journalctl -u haozige.service -e命令查看
[Install]
WantedBy=multi-user.target
在这里插入图片描述

重新加载 systemd 配置并启用服务

sudo systemctl daemon-reload
sudo systemctl restart haozige.service

查看服务是否成功开启

sudo systemctl status haozige.service,这里发现服务开启失败了。
在这里插入图片描述

重新启动服务,并查看服务状态

sudo systemctl start haozige.service,重新启动服务,sudo systemctl status haozige.service重新查看服务状态。
在这里插入图片描述
此时已经成功开启服务了,我们可以使用sudo reboot命令重启香橙派KunpengPro开发板,查看开机显示IP效果。
在这里插入图片描述

体验总结

作为一名即将毕业的嵌入式爱好者,最近有幸参与了香橙派KunpengPro开发板的亲身体验,香橙派KunpengPro最吸引我的地方在于它那颗强大的“心脏”——4核64位处理器+AI处理器,搭配上8GB或16GB的大内存,运行速度快得起飞,即便是同时运行多个编程环境或者开发工具也不在话下。而且,它那AI处理能力,8TOPS的算力也算得上是性能怪兽。无论是图像识别的小实验,还是语音助手的复杂demo,都能轻松驾驭。

我平时的主要研究方向就是水下智能机器人、智能家居、智能鸡舍、智能小车等智能系统,期间用的开发板在OpenCV的折磨下,都发烫的厉害,从而造成系统卡顿以及程序因温度过高而崩溃,香橙派KunpengPro搭配了良好的散热套装,在这几天的体验下来,明显感觉到香橙派KunpengPro在程序运行期间的流畅性,而且板子温度也不高,以后有机会可以用来开发出各种各样的智能系统。

总的来说,香橙派KunpengPro就像是我数字生活里的瑞士军刀,功能多样又实用,无论是日常的学习探索,还是突发的创新灵感,它都能完美匹配,让我的技术之旅更加多彩多姿。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/775813
推荐阅读
相关标签
  

闽ICP备14008679号