【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)

一、OLED屏幕
二、Orangepi的IIC接口
三、wiringPi库示例代码
四、Source insight 初步分析wiringP源码OLED_DEMO
五、设备的映射
六、mmap函数
七、简单OLED屏幕开发及实现

一、OLED屏幕

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第1张图片

二、Orangepi的IIC接口

1) 由 26pin 的原理图可知, Orange Pi Zero 2 可用的 i2c 为 i2c3

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第2张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第3张图片

sudo vim /boot/orangepiEnv.txt

overlays=i2c3

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第4张图片

ls /dev/i2c-*

在这里插入图片描述

2. 启动 linux 系统后, 先确认下 /dev下存在 i2c-3 的设备节点

从命令运行结果能观察到系统支持I2C-3和I2C-5的驱动,而H616的外设我们看到只有一个IIC接口,用的是IIC-3
Linux一切皆文件,每个硬件设备“对应”一个文件,由驱动程序提供映射

cd /dev

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第5张图片

3. 开始测试 i2c, 首先安装 i2c-tools

sudo apt-get install i2c-tools

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第6张图片

4. 列出连接到I2C总线的设备的地址

sudo i2cdetect -y 3

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第7张图片

三、wiringPi库示例代码

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第8张图片

cp wiringOP/examples/oled_demo.c orangeOP/
cd orangeOP/
./build.sh oled_demo.c
sudo ./a.out /dev/i2c-3

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第9张图片

/*
 * Copyright (c) 2015, Vladimir Komendantskiy
 * MIT License
 *
 * SSD1306 demo of block and font drawing.
 */

//
// fixed for OrangePiZero by HypHop
//

#include 
#include 
#include 
#include 
#include 
#include 

#include "oled.h"
#include "font.h"

int oled_demo(struct display_info *disp) {
	int i;
	char buf[100];

	//putstrto(disp, 0, 0, "Spnd spd  2468 rpm");
	//	oled_putstrto(disp, 0, 9+1, "Spnd cur  0.46 A");
	oled_putstrto(disp, 0, 9+1, "Welcome       to");
	disp->font = font1;
	//	oled_putstrto(disp, 0, 18+2, "Spnd tmp    53 C");
	oled_putstrto(disp, 0, 18+2, "----OrangePi----");
	disp->font = font2;
	//	oled_putstrto(disp, 0, 27+3, "DrvX tmp    64 C");
	oled_putstrto(disp, 0, 27+3, "This is 0.96OLED");
	oled_putstrto(disp, 0, 36+4, "");
	oled_putstrto(disp, 0, 45+5, "");
	disp->font = font1;
	//	oled_putstrto(disp, 0, 54, "Total cur  2.36 A");
	oled_putstrto(disp, 0, 54, "*****************");
	oled_send_buffer(disp);

	disp->font = font3;
	for (i=0; i<100; i++) {
		sprintf(buf, "Spnd spd  %d rpm", i);
		oled_putstrto(disp, 0, 0, buf);
		oled_putstrto(disp, 135-i, 36+4, "===");
		oled_putstrto(disp, 100, 0+i/2, ".");
		oled_send_buffer(disp);
	}
	//oled_putpixel(disp, 60, 45);
	//oled_putstr(disp, 1, "hello");

return 0;
}

void show_error(int err, int add) {
	//const gchar* errmsg;
	//errmsg = g_strerror(errno);
	printf("\nERROR: %i, %i\n\n", err, add);
	//printf("\nERROR\n");
}

void show_usage(char *progname) {
	printf("\nUsage:\n%s \n", progname);
}

int main(int argc, char **argv) {
	int e;
	char filename[32];
	struct display_info disp;

	if (argc < 2) {
		show_usage(argv[0]);
		
		return -1;
	}

	memset(&disp, 0, sizeof(disp));
	sprintf(filename, "%s", argv[1]);
	disp.address = OLED_I2C_ADDR;
	disp.font = font2;

	e = oled_open(&disp, filename);

	if (e < 0) {
		show_error(1, e);
	} else {
		e = oled_init(&disp);
	if (e < 0) {
		show_error(2, e);
	} else {
		printf("---------start--------\n");
		if (oled_demo(&disp) < 0)
			show_error(3, 777);
			printf("----------end---------\n");
		}
	}

	return 0;
}

-- VISUAL --                                                                              100       100,2         Bot

四、Source insight 初步分析wiringP源码OLED_DEMO

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第10张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第11张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第12张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第13张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第14张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第15张图片

访问前要先开打设备驱动

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第16张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第17张图片

# 五、设备的映射

mmap 可以用于映射设备文件,这是一种与文件映射相似的操作,但不是映射文件的内容,而是映射设备的内存地址范围。这使得你可以在用户空间直接访问设备的内存,而无需通过标准的读写操作进行通信。

设备映射通常用于以下场景:

  1. 直接内存访问(DMA)设备:一些硬件设备(如图形卡、网络适配器)允许通过DMA将数据传输到设备的内存。mmap 可用于映射这些设备内存,以便应用程序可以直接读写设备内存,而不必通过内核交互。

  2. 共享内存:设备映射允许多个进程或线程在用户空间共享设备内存。这对于高性能计算、数据传输和共享大量数据的应用程序非常有用。

  3. 加速硬件:一些硬件设备,如GPU,可以通过 mmap 实现与应用程序的高性能通信,以加速计算和数据处理。

以下是一个示例,演示如何使用 mmap 映射设备文件:

#include 
#include 
#include 
#include 
#include 

int main() {
    int fd = open("/dev/my_device", O_RDWR); // 打开设备文件,这里示意性地使用了"/dev/my_device"
    if (fd == -1) {
        perror("open");
        return 1;
    }

    size_t length = 4096; // 映射的长度,根据设备的需求设置
    void *map = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    
    if (map == MAP_FAILED) {
        perror("mmap");
        return 1;
    }

    // 使用指针 map 来访问设备内存
    // ...

    close(fd); // 关闭设备文件
    munmap(map, length); // 取消映射

    return 0;
}

在这个示例中,我们打开了一个设备文件(/dev/my_device 是一个示例设备文件路径),将设备内存映射到用户空间,然后可以使用 map 指针来访问设备内存。请注意,这个示例是简化的,实际应用中需要根据设备的特性和需求来使用 mmap
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第18张图片

六、mmap函数

mmap 是一个UNIX和类UNIX操作系统上的系统调用,用于在进程的地址空间中映射文件或设备。这个系统调用通常用于实现内存映射文件和共享内存的操作。

mmap 的原型如下:

#include 

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

参数说明:

  • addr:指定映射区域的起始地址,通常设置为 NULL,让操作系统自动选择。
  • length:指定映射的长度,以字节为单位。
  • prot:指定映射区域的保护权限,如 PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)等。
  • flags:指定映射区域的标志,如 MAP_SHARED(共享映射)、MAP_PRIVATE(私有映射)等。
  • fd:指定要映射的文件的文件描述符。如果不是映射文件,可以设置为 -1
  • offset:指定文件中的偏移,通常设置为 0

mmap 函数允许你将文件或设备的内容映射到进程的地址空间中,使得进程可以通过内存操作来访问文件的内容,而不必直接读写文件。这有助于提高访问速度和简化文件操作。

示例用法:

#include 
#include 
#include 
#include 

int main() {
    int fd = open("example.txt", O_RDONLY);
    if (fd == -1) {
        perror("open");
        return 1;
    }

    off_t file_size = lseek(fd, 0, SEEK_END);
    void *map = mmap(NULL, file_size, PROT_READ, MAP_SHARED, fd, 0);

    if (map == MAP_FAILED) {
        perror("mmap");
        return 1;
    }

    // 现在可以通过指针 map 访问文件的内容
    printf("File content: %s\n", (char *)map);

    close(fd);
    munmap(map, file_size);

    return 0;
}

上述示例打开一个名为 “example.txt” 的文件,将其内容映射到内存中,然后通过指针 map 访问文件的内容。最后,使用 munmap 函数取消映射并关闭文件描述符。这是 mmap 的一个简单示例,它可用于更复杂的应用,如共享内存、内存映射数据库等。

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第19张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第20张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第21张图片
【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第22张图片

七、简单OLED屏幕开发及实现

#include 
#include 
#include 
#include 
#include 
#include 
 
#include "oled.h"
#include "font.h"
 
int oled_show(struct display_info *disp)
{ 
	int i; 
	char buf[100];
 
	oled_putstrto(disp, 0, 9+1, "Welcome to"); 
	disp->font = font1; 
	oled_putstrto(disp, 0, 18+2, " ---OrangePi--- "); 
	disp->font = font2; 
	oled_putstrto(disp, 0, 27+3, "DALI NIANGAO"); 
	disp->font = font3; 
 
	oled_send_buffer(disp); 
	
	return 0; 
}
 
void show_error(int err, int add) 
{ 
	printf("\nERROR: %i, %i\n\n", err, add); 
}
 
void show_usage(char *progname) 
{ 
	printf("\nUsage:\n%s \n", progname); 
}
 
int main(int argc, char **argv) 
{ 
	int e; 
	char filename[32]; 
	struct display_info disp; 
 
	if (argc < 2) { 
		show_usage(argv[0]); 
		return -1; 
	}
 
	memset(&disp, 0, sizeof(disp)); 
	sprintf(filename, "%s", argv[1]); 
	disp.address = OLED_I2C_ADDR; 
	disp.font = font2; 
 
	e = oled_open(&disp, filename); 
	e = oled_init(&disp); 
 
	oled_show(&disp); 
 
	return 0; 
}
vim my_oled_demo.c
./build.sh my_oled_demo.c
sudo ./a.out /dev/i2c-3

【Orangepi Zero2 全志H616】驱动OLED屏应用-IIC协议、设备的映射(mmap)_第23张图片

你可能感兴趣的:(全志H616,linux,ubuntu,驱动开发,Source,insight,IIC)