【全志V821_FoxPi】9-3 Linux IIC驱动SSD1306(0.96寸oled屏幕)
【全志V821_FoxPi】9-3 Linux IIC驱动SSD1306(0.96寸oled屏幕)
- 一、背景
- 二、0.96寸OLED简介
- 2-1 概述
- 2-2 主要技术参数
- 2-3 电气特性
- 三、驱动适配
- 3-1 内核配置
- 3-2 设备树配置
- 3-3 启动测试
- 四、编写自己的应用程序
- 五、显示图片(bmp位图)
- 六、显示图片(png)
- 七、效果展示
一、背景
先前我们在
【全志T113-S3_100ask】13-1 Linux c语言ioctl驱动oled(iic、ssd1306)屏幕
实现了在应用程序通过iic的读写来控制显示OLED屏幕,但是感觉集成度还是不够高,因为涉及到iic的读写,这里使用内核驱动+用户程序(FrameBuffer)来驱动屏幕的显示
二、0.96寸OLED简介
2-1 概述
0.96寸OLED显示屏通常采用SSD1306驱动芯片,支持I2C通信协议,具有高对比度、低功耗、宽视角等特点。适用于嵌入式设备、智能穿戴、便携式仪器等场景。
2-2 主要技术参数
屏幕尺寸:0.96英寸(对角线)
分辨率:128×64像素(常见型号)
驱动芯片:SSD1306(主流型号)
显示颜色:单色(蓝色、白色或黄蓝双色)
可视角度:>160°
对比度:>1000:1
响应时间:<10μs
2-3 电气特性
供电电压:3.3V~5V(兼容主流单片机)
工作电流:约20mA(全亮状态)
待机电流:<1μA(低功耗模式)
通信接口:I2C(默认地址0x3C或0x3D)
I2C时钟频率:标准模式(100kHz)或快速模式(400kHz)
三、驱动适配
3-1 内核配置
在内核里面有SSD1306的驱动,但是在这里我们使用的不是SSD1306这个驱动,那个自带的驱动是使用spi进行的,而且是属于fb_tft框架
在这里我们使用的是SSD1307的驱动
搜索 SSD1307
3-2 设备树配置
在这里我使用的是TWI2,400khz,PD9和PD10
&pio{twi2_pins_default_ts: twi2@0 {pins = "PD9", "PD10";function = "twi2";allwinner,drive = <0>;bias-pull-up;};twi2_pins_sleep_ts: twi2@1 {pins = "PD9", "PD10";function = "gpio_in";};
};
&twi2 {clock-frequency = <400000>;pinctrl-0 = <&twi2_pins_default>;pinctrl-1 = <&twi2_pins_sleep>;pinctrl-names = "default", "sleep";/* For stability and backwards compatibility, we recommend setting 'twi_drv_used' to 1 */twi_drv_used = <0>;status = "okay";ssd1306: oled@3c {compatible = "solomon,ssd1306fb-i2c";reg = <0x3c>; // 你的I2C地址,常见是0x3c或0x3dsolomon,height = <64>; // OLED屏幕高度,常见64像素solomon,width = <128>; // OLED屏幕宽度,常见128像素solomon,page-offset = <0>; // 页偏移,通常0即可// 以下是可选属性,根据你的屏幕硬件特性决定是否添加// solomon,com-lrremap;solomon,com-invdir;// solomon,com-offset = <32>;// solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>;};
};
3-3 启动测试
启动的时候提示SSD1307fb注册到了fb0,理论上来说都是正常的了
root@TinaLinux:~# dmesg | grep fb
[ 0.664124] ssd1307fb 2-003c: fb0: Solomon SSD1307 framebuffer device registered, using 1024 bytes of video memory
四、编写自己的应用程序
在这里将编写一个自己的app,通过写/dev/fb0来控制屏幕的显示
如何编写 自己的app ?
参考 全志在线 - 编写 Hello World
生成以下的文件路径
root@USER-20231008WG:/opt/Tina_V821_V1.2/openwrt/package# tree my_apps/
my_apps/
└── showpng├── Makefile└── src├── Makefile└── main.c2 directories, 3 files
在外围的Makefile写入以下内容,目的是向SDK添加这个软件包
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/package.mkPKG_NAME:=showpng
PKG_RELEASE:=1PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
SRC_CODE_DIR := ./src/define Package/$(PKG_NAME)SECTION:=showpngCATEGORY:=SHOW PNGTITLE:=show png testDEPENDS:=+libpng
endefdefine Package/$(PKG_NAME)/descriptionShow Png
endefdefine Build/Preparemkdir -p $(PKG_BUILD_DIR)$(CP) ./src/* $(PKG_BUILD_DIR)/
endefdefine Package/showpng/install$(INSTALL_DIR) $(1)/usr/bin$(INSTALL_BIN) $(PKG_BUILD_DIR)/showpng $(1)/usr/bin/
endef$(eval $(call BuildPackage,$(PKG_NAME)))
在里面的Makefile写入以下内容,构建编译
CFLAGS = -Wall -O2
LDFLAGS = -lpngTARGET = showpng
OBJ = main.oall: $(TARGET)$(TARGET): $(OBJ)$(CC) $(LDFLAGS) $^ -o $@main.o: main.c$(CC) $(CFLAGS) -c main.cclean:rm -f *.o $(TARGET)
在main.c 写入自己的程序
在SDK make menuconfig 搜索自己的软件包,然后使能它,就能自动编译打包进系统了
五、显示图片(bmp位图)
参考 :v3S 驱动 i2c OLED屏幕
参考:荔枝派 Zero i2c oled使用指南
就是创建一个 128x64 的位图,然后使用字模提取工具,生成一大串的字符数组让屏幕去显示
注意:这里的字节要倒序
可参考程序:
注:Makefile中不需要使用libpng
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>/*seconds: the seconds; mseconds: the micro seconds*/void setTimer(int seconds, int mseconds)
{struct timeval temp;temp.tv_sec = seconds;temp.tv_usec = mseconds;printf("timer1\n");select(0, NULL, NULL, NULL, &temp);printf("timer2\n");return ;
}int main ()
{char lichee[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x06,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x07,0x3C,0x74,0xE0,0x81,0x03,0xE0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x22,0x8C,0x10,0x43,0x04,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x42,0x84,0x10,0x22,0x0C,0xF8,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x03,0x84,0x08,0x22,0x08,0xFC,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x01,0x84,0x18,0x22,0x08,0xFE,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x01,0x84,0x18,0x20,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x04,0x01,0x84,0x08,0x20,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x10,0x04,0x03,0x84,0x18,0x20,0x00,0xFE,0xFF,0x00,0x00,0x00,0x00,0x00,0x08,0x40,0x10,0x04,0x02,0x84,0x10,0x22,0x00,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x0C,0x40,0x18,0x04,0x06,0x84,0x30,0x40,0x04,0xFF,0xFF,0x03,0x00,0x00,0x00,0x00,0x06,0xE0,0x0F,0x1F,0x1C,0xCE,0xC1,0x80,0x03,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xBF,0xFF,0x1F,0x00,0x00,0x00,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xDF,0xFF,0x7F,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC7,0xFF,0xFF,0x00,0x00,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC9,0xFF,0xFF,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xC0,0xFF,0xFF,0x03,0x00,0x00,0xF8,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xFF,0xFF,0x07,0x00,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xC0,0xF7,0xFF,0x0F,0x00,0x00,0xF8,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE3,0xFF,0xFF,0x1F,0x00,0x00,0xF8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xEF,0xFF,0xFF,0x7F,0x00,0x00,0xF8,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFB,0xFF,0xFF,0xFF,0x00,0x00,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0xFC,0x00,0x40,0x30,0x00,0x06,0x04,0x00,0x00,0x80,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0xFE,0x00,0x40,0x10,0x02,0x06,0x04,0xC0,0x00,0x9C,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,0xFF,0x00,0xFE,0xFF,0x07,0x06,0x04,0x80,0xC8,0x81,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x7F,0x00,0x40,0x10,0x00,0x06,0x04,0x80,0x08,0x00,0xFF,0xFF,0xFF,0xFF,0x7F,0x80,0x7F,0x00,0x40,0x13,0x00,0x16,0xCC,0x00,0x08,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x7F,0x00,0x00,0xC3,0xC0,0x3F,0x04,0x00,0x08,0x0E,0xFE,0xFF,0xFF,0xFF,0xFF,0xE3,0x3F,0x00,0x00,0xC1,0x00,0x06,0x04,0x10,0x48,0x00,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0x3F,0x00,0x80,0x41,0x00,0x06,0x04,0x20,0x49,0x00,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x80,0x40,0x00,0x0E,0x44,0x20,0x48,0x30,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x60,0x78,0x00,0x9F,0x61,0x80,0x48,0x08,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x38,0x30,0x00,0x17,0x60,0x80,0x48,0x02,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0x20,0x60,0x00,0x17,0x21,0x80,0x48,0x02,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0xFE,0xFB,0x83,0x06,0x30,0x40,0x48,0x02,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x30,0x23,0x02,0x06,0x12,0x70,0x44,0x04,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0x00,0x30,0x23,0x42,0x06,0x1A,0x60,0x44,0x04,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x10,0x31,0x02,0x06,0x0C,0x40,0x44,0x08,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x00,0x18,0x11,0x03,0x06,0x0E,0x60,0x42,0x18,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x88,0x19,0x03,0x06,0x31,0x60,0xC2,0x30,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xC4,0xCD,0x01,0x86,0xE0,0x61,0x41,0x20,0xE0,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x82,0x01,0x36,0x80,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x9F,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xFF,0xFF,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFC,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};int fp=0;long screensize=0;char *fbp = 0;struct fb_var_screeninfo vinfo;struct fb_fix_screeninfo finfo;fp = open ("/dev/fb0",O_RDWR);if (fp < 0){printf("Error : Can not open framebuffer device/n");exit(1);}if (ioctl(fp,FBIOGET_FSCREENINFO,&finfo)){printf("Error reading fixed information/n");exit(2);}if (ioctl(fp,FBIOGET_VSCREENINFO,&vinfo)){printf("Error reading variable information/n");exit(3);}printf("The mem is :%d\n",finfo.smem_len);printf("The line_length is :%d\n",finfo.line_length);printf("The xres is :%d\n",vinfo.xres);printf("The yres is :%d\n",vinfo.yres);printf("bits_per_pixel is :%d\n",vinfo.bits_per_pixel);screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;printf("screensize: %d\n",screensize);fbp =(char *) mmap (0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,fp,0);if ((int) fbp == -1){printf ("Error: failed to map framebuffer device to memory./n");exit (4);}int i=0;memset(fbp, 0x00, 1024);setTimer(3,0);
// while(1){for(i=0;i<1024;i++){fbp[i]=lichee[i];}//setTimer(3,0);// memset(fbp, 0x00, 1024);// setTimer(3,0);
// }munmap (fbp, screensize);close (fp);
}
六、显示图片(png)
但是我通过png转成bmp,还要生成 char[] 再写进去,太麻烦了,然后就参照以上的程序,实现了一个使用png格式图片就能在oled屏幕上显示出来
可以参照以下程序:Linux 下0.96寸oled(iic)显示png程序
七、效果展示
root@TinaLinux:~# ./showpng a.png
The mem is :1024
The line_length is :16
The xres is :128
The yres is :64
bits_per_pixel is :1
Framebuffer info:Resolution: 128x64Bits Per Pixel: 1Line length: 16Memory length: 1024
screensize: 1024
Loaded PNG: 128x64