diff --git a/IMX6ULL/doc_pic/11_SPI/16_使用Framebuffer改造OLED驱动.md b/IMX6ULL/doc_pic/11_SPI/16_使用Framebuffer改造OLED驱动.md new file mode 100644 index 0000000..2f902de --- /dev/null +++ b/IMX6ULL/doc_pic/11_SPI/16_使用Framebuffer改造OLED驱动.md @@ -0,0 +1,68 @@ +# 使用Framebuffer改造OLED驱动 # + +* 源码: + + ![image-20220429174003143](pic/77_src_oled_framebuffer.png) + +## 1. 思路 + +![image-20220429173507474](pic/76_framebuffer_and_oled_gram.png) + +假设OLED的每个像素使用1位数据表示: + +* Linux Framebuffer中byte0对应OLED上第1行的8个像素 +* OLED显存中byte0对应OLED上第1列的8个像素 + + + +为了兼容基于Framebuffer的程序,驱动程序中分配一块Framebuffer,APP直接操作Framebuffer。 + +驱动程序周期性地把Framebuffer中的数据搬移到OLED显存上。 + +怎么搬移? + +发给OLED线程的byte0、1、2、3、4、5、6、7怎么构造出来? + +* 它们来自Framebuffer的byte0、16、32、48、64、80、96、112 +* OLED的byte0,由Framebuffer的这8个字节的bit0组合得到 +* OLED的byte1,由Framebuffer的这8个字节的bit1组合得到 +* OLED的byte2,由Framebuffer的这8个字节的bit2组合得到 +* OLED的byte3,由Framebuffer的这8个字节的bit3组合得到 +* …… + + + + + +## 2. 编程 + +### 2.1 Framebuffer编程 + +分配、设置、注册fb_info结构体。 + +* 分配fb_info +* 设置fb_info + * fb_var + * fb_fix +* 注册fb_info +* 硬件操作 + + + +### 2.2 数据搬移 + +创建内核线程,周期性地把Framebuffer中的数据通过SPI发送给OLED。 + +内核线程 + +* 参考函数:kernel_thread、kthread_create、 kthread_run +* 参考文章:https://blog.csdn.net/qq_37858386/article/details/115573565 + + + +### 2.3 调试 + +配置内核,把下列配置项去掉: + +![image-20220125212414098](pic/78_disable_framebuffer_console.png) + diff --git a/IMX6ULL/doc_pic/11_SPI/16_使用Framebuffer改造OLED驱动.tif b/IMX6ULL/doc_pic/11_SPI/16_使用Framebuffer改造OLED驱动.tif new file mode 100644 index 0000000..cf71165 Binary files /dev/null and b/IMX6ULL/doc_pic/11_SPI/16_使用Framebuffer改造OLED驱动.tif differ diff --git a/IMX6ULL/doc_pic/11_SPI/pic/76_framebuffer_and_oled_gram.png b/IMX6ULL/doc_pic/11_SPI/pic/76_framebuffer_and_oled_gram.png new file mode 100644 index 0000000..3ef1229 Binary files /dev/null and b/IMX6ULL/doc_pic/11_SPI/pic/76_framebuffer_and_oled_gram.png differ diff --git a/IMX6ULL/doc_pic/11_SPI/pic/77_src_oled_framebuffer.png b/IMX6ULL/doc_pic/11_SPI/pic/77_src_oled_framebuffer.png new file mode 100644 index 0000000..7cc2632 Binary files /dev/null and b/IMX6ULL/doc_pic/11_SPI/pic/77_src_oled_framebuffer.png differ diff --git a/IMX6ULL/doc_pic/11_SPI/pic/78_disable_framebuffer_console.png b/IMX6ULL/doc_pic/11_SPI/pic/78_disable_framebuffer_console.png new file mode 100644 index 0000000..86875e7 Binary files /dev/null and b/IMX6ULL/doc_pic/11_SPI/pic/78_disable_framebuffer_console.png differ diff --git a/IMX6ULL/source/11_SPI/09_oled_framebuffer/Makefile b/IMX6ULL/source/11_SPI/09_oled_framebuffer/Makefile new file mode 100644 index 0000000..2b47cb9 --- /dev/null +++ b/IMX6ULL/source/11_SPI/09_oled_framebuffer/Makefile @@ -0,0 +1,22 @@ + +# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR +# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量: +# 2.1 ARCH, 比如: export ARCH=arm64 +# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu- +# 2.3 PATH, 比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin +# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同, +# 请参考各开发板的高级用户使用手册 + +KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88 + +all: + make -C $(KERN_DIR) M=`pwd` modules + $(CROSS_COMPILE)gcc -o spi_oled spi_oled.c + +clean: + make -C $(KERN_DIR) M=`pwd` modules clean + rm -rf modules.order spi_oled + +obj-m += oled_drv.o + + diff --git a/IMX6ULL/source/11_SPI/09_oled_framebuffer/font.h b/IMX6ULL/source/11_SPI/09_oled_framebuffer/font.h new file mode 100644 index 0000000..5698917 --- /dev/null +++ b/IMX6ULL/source/11_SPI/09_oled_framebuffer/font.h @@ -0,0 +1,106 @@ +#ifndef _FONT_H_ +#define _FONT_H_ +const unsigned char oled_asc2_8x16[95][16]= +{ + {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},//016 + {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//117 + {0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},//218 + {0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},//319 + {0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},//420 + {0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},//521 + {0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},//622 + {0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},//723 + {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},//824 + {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},//925 + {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},//A33 + {0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},//B34 + {0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},//C35 + {0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},//D36 + {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},//E37 + {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},//F38 + {0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},//G39 + {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},//H40 + {0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//I41 + {0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},//J42 + {0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},//K43 + {0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},//L44 + {0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},//M45 + {0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},//N46 + {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},//O47 + {0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},//P48 + {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},//Q49 + {0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},//R50 + {0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},//S51 + {0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},//T52 + {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},//U53 + {0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},//V54 + {0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},//W55 + {0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},//X56 + {0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},//Y57 + {0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},//Z58 + {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},//a65 + {0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},//b66 + {0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},//c67 + {0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},//d68 + {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},//e69 + {0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//f70 + {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},//g71 + {0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},//h72 + {0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//i73 + {0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},//j74 + {0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},//k75 + {0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//l76 + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},//m77 + {0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},//n78 + {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},//o79 + {0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},//p80 + {0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},//q81 + {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},//r82 + {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},//s83 + {0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},//t84 + {0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},//u85 + {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},//v86 + {0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},//w87 + {0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},//x88 + {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},//y89 + {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},//z90 + {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 +}; +const unsigned char hz_1616[][32]={ +{0x02,0x00,0x02,0x00,0xE2,0xFF,0x22,0x42,0x22,0x42,0x32,0x42,0x2A,0x42,0x26,0x42,0x22,0x42,0x22,0x42,0x22,0x42,0x22,0x42,0xE2,0xFF,0x02,0x00,0x02,0x00,0x00,0x00},/*"百",0*/ +{0x00,0x00,0xF8,0xFF,0x01,0x00,0x02,0x00,0x00,0x00,0xE2,0x1F,0x22,0x08,0x22,0x08,0x22,0x08,0xE2,0x1F,0x02,0x00,0x02,0x40,0x02,0x80,0xFE,0x7F,0x00,0x00,0x00,0x00},/*"问",1*/ +{0x00,0x00,0xFE,0xFF,0x02,0x10,0x22,0x08,0x42,0x06,0x82,0x01,0x72,0x0E,0x02,0x10,0x22,0x08,0x42,0x06,0x82,0x01,0x72,0x4E,0x02,0x80,0xFE,0x7F,0x00,0x00,0x00,0x00},/*"网",2*/ +}; +#endif diff --git a/IMX6ULL/source/11_SPI/09_oled_framebuffer/oled_drv.c b/IMX6ULL/source/11_SPI/09_oled_framebuffer/oled_drv.c new file mode 100644 index 0000000..27103b8 --- /dev/null +++ b/IMX6ULL/source/11_SPI/09_oled_framebuffer/oled_drv.c @@ -0,0 +1,299 @@ +/* + * Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +#define OLED_IOC_INIT 123 +#define OLED_IOC_SET_POS 124 + +//? 表示命令,为1表示数据 +#define OLED_CMD 0 +#define OLED_DATA 1 + + + +/*-------------------------------------------------------------------------*/ + +static struct spi_device *oled; +static int major; +static struct gpio_desc *dc_gpio; + +static void dc_pin_init(void) +{ + gpiod_direction_output(dc_gpio, 1); +} + +static void oled_set_dc_pin(int val) +{ + gpiod_set_value(dc_gpio, val); +} + +static void spi_write_datas(const unsigned char *buf, int len) +{ + spi_write(oled, buf, len); +} + + +/********************************************************************** + * 函数名称?oled_write_cmd + * 功能描述?oled向特定地址写入数据或者命? * 输入参数:@uc_data :要写入的数据 + @uc_cmd:?则表示写入数据,?表示写入命令 + * 输出参数:无 + * ??值: ? * 修改日期 版本? 修改? 修改内容 + * ----------------------------------------------- + * 2020/03/04 V1.0 芯晓 创建 + ***********************************************************************/ +static void oled_write_cmd_data(unsigned char uc_data,unsigned char uc_cmd) +{ + if(uc_cmd==0) + { + oled_set_dc_pin(0); + } + else + { + oled_set_dc_pin(1);//拉高,表示写入数? } + spi_write_datas(&uc_data, 1);//写入 +} + + +/********************************************************************** + * 函数名称?oled_init + * 功能描述?oled_init的初始化,包括SPI控制器得初始? * 输入参数:无 + * 输出参数?初始化的结果 + * ??值: 成功则返?,否则返?1 + * 修改日期 版本? 修改? 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +static int oled_init(void) +{ + oled_write_cmd_data(0xae,OLED_CMD);//关闭显示 + + oled_write_cmd_data(0x00,OLED_CMD);//设置 lower column address + oled_write_cmd_data(0x10,OLED_CMD);//设置 higher column address + + oled_write_cmd_data(0x40,OLED_CMD);//设置 display start line + + oled_write_cmd_data(0xB0,OLED_CMD);//设置page address + + oled_write_cmd_data(0x81,OLED_CMD);// contract control + oled_write_cmd_data(0x66,OLED_CMD);//128 + + oled_write_cmd_data(0xa1,OLED_CMD);//设置 segment remap + + oled_write_cmd_data(0xa6,OLED_CMD);//normal /reverse + + oled_write_cmd_data(0xa8,OLED_CMD);//multiple ratio + oled_write_cmd_data(0x3f,OLED_CMD);//duty = 1/64 + + oled_write_cmd_data(0xc8,OLED_CMD);//com scan direction + + oled_write_cmd_data(0xd3,OLED_CMD);//set displat offset + oled_write_cmd_data(0x00,OLED_CMD);// + + oled_write_cmd_data(0xd5,OLED_CMD);//set osc division + oled_write_cmd_data(0x80,OLED_CMD);// + + oled_write_cmd_data(0xd9,OLED_CMD);//ser pre-charge period + oled_write_cmd_data(0x1f,OLED_CMD);// + + oled_write_cmd_data(0xda,OLED_CMD);//set com pins + oled_write_cmd_data(0x12,OLED_CMD);// + + oled_write_cmd_data(0xdb,OLED_CMD);//set vcomh + oled_write_cmd_data(0x30,OLED_CMD);// + + oled_write_cmd_data(0x8d,OLED_CMD);//set charge pump disable + oled_write_cmd_data(0x14,OLED_CMD);// + + oled_write_cmd_data(0xaf,OLED_CMD);//set dispkay on + + return 0; +} + +//坐标设置 +/********************************************************************** + * 函数名称?OLED_DIsp_Set_Pos + * 功能描述:设置要显示的位? * 输入参数:@ x :要显示的column address + @y :要显示的page address + * 输出参数?? * ??值: + * 修改日期 版本? 修改? 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +static void OLED_DIsp_Set_Pos(int x, int y) +{ oled_write_cmd_data(0xb0+y,OLED_CMD); + oled_write_cmd_data((x&0x0f),OLED_CMD); + oled_write_cmd_data(((x&0xf0)>>4)|0x10,OLED_CMD); +} + + +static long +spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int x, y; + + /* 根据cmd操作硬件 */ + switch (cmd) + { + case OLED_IOC_INIT: /* init */ + { + dc_pin_init(); + oled_init(); + break; + } + + case OLED_IOC_SET_POS: /* set pos */ + { + x = arg & 0xff; + y = (arg >> 8) & 0xff; + OLED_DIsp_Set_Pos(x, y); + break; + } + + } + + return 0; +} + +static ssize_t +spidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + char *ker_buf; + int err; + + ker_buf = kmalloc(count, GFP_KERNEL); + err = copy_from_user(ker_buf, buf, count); + + oled_set_dc_pin(1);//拉高,表示写入数? spi_write_datas(ker_buf, count); + kfree(ker_buf); + return count; +} + +static const struct file_operations spidev_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .write = spidev_write, + .unlocked_ioctl = spidev_ioctl, +}; + +/*-------------------------------------------------------------------------*/ + +/* The main reason to have this class is to make mdev/udev create the + * /dev/spidevB.C character device nodes exposing our userspace API. + * It also simplifies memory management. + */ + +static struct class *spidev_class; + +static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "100ask,oled" }, + {}, +}; + + +/*-------------------------------------------------------------------------*/ + +static int spidev_probe(struct spi_device *spi) +{ + /* 1. 记录spi_device */ + oled = spi; + + /* 2. 注册字符设备 */ + major = register_chrdev(0, "100ask_oled", &spidev_fops); + spidev_class = class_create(THIS_MODULE, "100ask_oled"); + device_create(spidev_class, NULL, MKDEV(major, 0), NULL, "100ask_oled"); + + /* 3. 获得GPIO引脚 */ + dc_gpio = gpiod_get(&spi->dev, "dc", 0); + + return 0; +} + +static int spidev_remove(struct spi_device *spi) +{ + gpiod_put(dc_gpio); + + /* 反注册字符设?*/ + device_destroy(spidev_class, MKDEV(major, 0)); + class_destroy(spidev_class); + unregister_chrdev(major, "100ask_oled"); + + return 0; +} + +static struct spi_driver spidev_spi_driver = { + .driver = { + .name = "100ask_spi_oled_drv", + .of_match_table = of_match_ptr(spidev_dt_ids), + }, + .probe = spidev_probe, + .remove = spidev_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init spidev_init(void) +{ + int status; + + status = spi_register_driver(&spidev_spi_driver); + if (status < 0) { + } + return status; +} +module_init(spidev_init); + +static void __exit spidev_exit(void) +{ + spi_unregister_driver(&spidev_spi_driver); +} +module_exit(spidev_exit); + +MODULE_LICENSE("GPL"); + diff --git a/IMX6ULL/source/11_SPI/09_oled_framebuffer/spi_oled.c b/IMX6ULL/source/11_SPI/09_oled_framebuffer/spi_oled.c new file mode 100644 index 0000000..98810de --- /dev/null +++ b/IMX6ULL/source/11_SPI/09_oled_framebuffer/spi_oled.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "font.h" + +#define OLED_IOC_INIT 123 +#define OLED_IOC_SET_POS 124 + + +//为0 表示命令,为1表示数据 +#define OLED_CMD 0 +#define OLED_DATA 1 + +static int fd_spidev; +static int dc_pin_num; + + +void OLED_DIsp_Set_Pos(int x, int y); + +void oled_write_datas(const unsigned char *buf, int len) +{ + write(fd_spidev, buf, len); +} + + + +/********************************************************************** + * 函数名称: OLED_DIsp_Clear + * 功能描述: 整个屏幕显示数据清0 + * 输入参数:无 + * 输出参数: 无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_Clear(void) +{ + unsigned char x, y; + char buf[128]; + + memset(buf, 0, 128); + + for (y = 0; y < 8; y++) + { + OLED_DIsp_Set_Pos(0, y); + oled_write_datas(buf, 128); + } +} + +/********************************************************************** + * 函数名称: OLED_DIsp_All + * 功能描述: 整个屏幕显示全部点亮,可以用于检查坏点 + * 输入参数:无 + * 输出参数:无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_All(void) +{ + unsigned char x, y; + char buf[128]; + + memset(buf, 0xff, 128); + + for (y = 0; y < 8; y++) + { + OLED_DIsp_Set_Pos(0, y); + oled_write_datas(buf, 128); + } + + + +} + +//坐标设置 +/********************************************************************** + * 函数名称: OLED_DIsp_Set_Pos + * 功能描述:设置要显示的位置 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + * 输出参数: 无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_Set_Pos(int x, int y) +{ + ioctl(fd_spidev, OLED_IOC_SET_POS, x | (y << 8)); +} +/********************************************************************** + * 函数名称: OLED_DIsp_Char + * 功能描述:在某个位置显示字符 1-9 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + @c :要显示的字符的ascii码 + * 输出参数: 无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 +***********************************************************************/ +void OLED_DIsp_Char(int x, int y, unsigned char c) +{ + int i = 0; + /* 得到字模 */ + const unsigned char *dots = oled_asc2_8x16[c - ' ']; + + /* 发给OLED */ + OLED_DIsp_Set_Pos(x, y); + /* 发出8字节数据 */ + //for (i = 0; i < 8; i++) + // oled_write_cmd_data(dots[i], OLED_DATA); + oled_write_datas(&dots[0], 8); + + OLED_DIsp_Set_Pos(x, y+1); + /* 发出8字节数据 */ + //for (i = 0; i < 8; i++) + //oled_write_cmd_data(dots[i+8], OLED_DATA); + oled_write_datas(&dots[8], 8); +} + + +/********************************************************************** + * 函数名称: OLED_DIsp_String + * 功能描述: 在指定位置显示字符串 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + @str :要显示的字符串 + * 输出参数: 无 + * 返 回 值: 无 + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 +***********************************************************************/ +void OLED_DIsp_String(int x, int y, char *str) +{ + unsigned char j=0; + while (str[j]) + { + OLED_DIsp_Char(x, y, str[j]);//显示单个字符 + x += 8; + if(x > 127) + { + x = 0; + y += 2; + }//移动显示位置 + j++; + } +} +/********************************************************************** + * 函数名称: OLED_DIsp_CHinese + * 功能描述:在指定位置显示汉字 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + @chr :要显示的汉字,三个汉字“百问网”中选择一个 + * 输出参数: 无 + * 返 回 值: 无 + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ + +void OLED_DIsp_CHinese(unsigned char x,unsigned char y,unsigned char no) +{ + unsigned char t,adder=0; + OLED_DIsp_Set_Pos(x,y); + for(t=0;t<16;t++) + {//显示上半截字符 + oled_write_datas(&hz_1616[no][t*2], 1); + adder+=1; + } + OLED_DIsp_Set_Pos(x,y+1); + for(t=0;t<16;t++) + {//显示下半截字符 + oled_write_datas(&hz_1616[no][t*2+1], 1); + adder+=1; + } +} +/********************************************************************** + * 函数名称: OLED_DIsp_Test + * 功能描述: 整个屏幕显示测试 + * 输入参数:无 + * 输出参数: 无 + * 返 回 值: 无 + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_Test(void) +{ + int i; + + OLED_DIsp_String(0, 0, "wiki.100ask.net"); + OLED_DIsp_String(0, 2, "book.100ask.net"); + OLED_DIsp_String(0, 4, "bbs.100ask.net"); + + for(i = 0; i < 3; i++) + { //显示汉字 百问网 + OLED_DIsp_CHinese(32+i*16, 6, i); + } +} + +/* spi_oled /dev/100ask_oled */ +int main(int argc, char **argv) +{ + if (argc != 2) + { + printf("Usage: %s /dev/100ask_oled\n", argv[0]); + return -1; + } + + fd_spidev = open(argv[1], O_RDWR); + if (fd_spidev < 0) { + printf("open %s err\n", argv[1]); + return -1; + } + + + ioctl(fd_spidev, OLED_IOC_INIT); + + OLED_DIsp_Clear(); + + OLED_DIsp_Test(); + + return 0; +} + diff --git a/IMX6ULL/source/11_SPI/09_oled_framebuffer/spi_oled.h b/IMX6ULL/source/11_SPI/09_oled_framebuffer/spi_oled.h new file mode 100644 index 0000000..692b290 --- /dev/null +++ b/IMX6ULL/source/11_SPI/09_oled_framebuffer/spi_oled.h @@ -0,0 +1,17 @@ +#ifndef _OLED_H_ +#define _OLED_H_ + +void oled_write_cmd_data(unsigned char uc_data,unsigned char uc_cmd); +int oled_init(void); +int oled_fill_data(unsigned char fill_Data); +void OLED_DIsp_Clear(void); +void OLED_DIsp_All(void); +void OLED_DIsp_Set_Pos(int x, int y); +void OLED_DIsp_Char(int x, int y, unsigned char c); +void OLED_DIsp_String(int x, int y, char *str); +void OLED_DIsp_CHinese(unsigned char x,unsigned char y,unsigned char no); +void OLED_DIsp_Test(); + + +#endif + diff --git a/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/Makefile b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/Makefile new file mode 100644 index 0000000..2b47cb9 --- /dev/null +++ b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/Makefile @@ -0,0 +1,22 @@ + +# 1. 使用不同的开发板内核时, 一定要修改KERN_DIR +# 2. KERN_DIR中的内核要事先配置、编译, 为了能编译内核, 要先设置下列环境变量: +# 2.1 ARCH, 比如: export ARCH=arm64 +# 2.2 CROSS_COMPILE, 比如: export CROSS_COMPILE=aarch64-linux-gnu- +# 2.3 PATH, 比如: export PATH=$PATH:/home/book/100ask_roc-rk3399-pc/ToolChain-6.3.1/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin +# 注意: 不同的开发板不同的编译器上述3个环境变量不一定相同, +# 请参考各开发板的高级用户使用手册 + +KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88 + +all: + make -C $(KERN_DIR) M=`pwd` modules + $(CROSS_COMPILE)gcc -o spi_oled spi_oled.c + +clean: + make -C $(KERN_DIR) M=`pwd` modules clean + rm -rf modules.order spi_oled + +obj-m += oled_drv.o + + diff --git a/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/font.h b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/font.h new file mode 100644 index 0000000..5698917 --- /dev/null +++ b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/font.h @@ -0,0 +1,106 @@ +#ifndef _FONT_H_ +#define _FONT_H_ +const unsigned char oled_asc2_8x16[95][16]= +{ + {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},//016 + {0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//117 + {0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},//218 + {0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},//319 + {0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},//420 + {0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},//521 + {0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},//622 + {0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},//723 + {0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},//824 + {0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},//925 + {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},//A33 + {0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},//B34 + {0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},//C35 + {0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},//D36 + {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},//E37 + {0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},//F38 + {0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},//G39 + {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},//H40 + {0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//I41 + {0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},//J42 + {0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},//K43 + {0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},//L44 + {0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},//M45 + {0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},//N46 + {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},//O47 + {0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},//P48 + {0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},//Q49 + {0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},//R50 + {0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},//S51 + {0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},//T52 + {0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},//U53 + {0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},//V54 + {0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},//W55 + {0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},//X56 + {0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},//Y57 + {0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},//Z58 + {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},//a65 + {0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},//b66 + {0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},//c67 + {0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},//d68 + {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},//e69 + {0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//f70 + {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},//g71 + {0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},//h72 + {0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//i73 + {0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},//j74 + {0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},//k75 + {0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},//l76 + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},//m77 + {0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},//n78 + {0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},//o79 + {0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},//p80 + {0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},//q81 + {0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},//r82 + {0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},//s83 + {0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},//t84 + {0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},//u85 + {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},//v86 + {0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},//w87 + {0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},//x88 + {0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},//y89 + {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},//z90 + {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 +}; +const unsigned char hz_1616[][32]={ +{0x02,0x00,0x02,0x00,0xE2,0xFF,0x22,0x42,0x22,0x42,0x32,0x42,0x2A,0x42,0x26,0x42,0x22,0x42,0x22,0x42,0x22,0x42,0x22,0x42,0xE2,0xFF,0x02,0x00,0x02,0x00,0x00,0x00},/*"百",0*/ +{0x00,0x00,0xF8,0xFF,0x01,0x00,0x02,0x00,0x00,0x00,0xE2,0x1F,0x22,0x08,0x22,0x08,0x22,0x08,0xE2,0x1F,0x02,0x00,0x02,0x40,0x02,0x80,0xFE,0x7F,0x00,0x00,0x00,0x00},/*"问",1*/ +{0x00,0x00,0xFE,0xFF,0x02,0x10,0x22,0x08,0x42,0x06,0x82,0x01,0x72,0x0E,0x02,0x10,0x22,0x08,0x42,0x06,0x82,0x01,0x72,0x4E,0x02,0x80,0xFE,0x7F,0x00,0x00,0x00,0x00},/*"网",2*/ +}; +#endif diff --git a/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/oled_drv.c b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/oled_drv.c new file mode 100644 index 0000000..27103b8 --- /dev/null +++ b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/oled_drv.c @@ -0,0 +1,299 @@ +/* + * Simple synchronous userspace interface to SPI devices + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * Copyright (C) 2007 David Brownell (simplification, cleanup) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + + +#define OLED_IOC_INIT 123 +#define OLED_IOC_SET_POS 124 + +//? 表示命令,为1表示数据 +#define OLED_CMD 0 +#define OLED_DATA 1 + + + +/*-------------------------------------------------------------------------*/ + +static struct spi_device *oled; +static int major; +static struct gpio_desc *dc_gpio; + +static void dc_pin_init(void) +{ + gpiod_direction_output(dc_gpio, 1); +} + +static void oled_set_dc_pin(int val) +{ + gpiod_set_value(dc_gpio, val); +} + +static void spi_write_datas(const unsigned char *buf, int len) +{ + spi_write(oled, buf, len); +} + + +/********************************************************************** + * 函数名称?oled_write_cmd + * 功能描述?oled向特定地址写入数据或者命? * 输入参数:@uc_data :要写入的数据 + @uc_cmd:?则表示写入数据,?表示写入命令 + * 输出参数:无 + * ??值: ? * 修改日期 版本? 修改? 修改内容 + * ----------------------------------------------- + * 2020/03/04 V1.0 芯晓 创建 + ***********************************************************************/ +static void oled_write_cmd_data(unsigned char uc_data,unsigned char uc_cmd) +{ + if(uc_cmd==0) + { + oled_set_dc_pin(0); + } + else + { + oled_set_dc_pin(1);//拉高,表示写入数? } + spi_write_datas(&uc_data, 1);//写入 +} + + +/********************************************************************** + * 函数名称?oled_init + * 功能描述?oled_init的初始化,包括SPI控制器得初始? * 输入参数:无 + * 输出参数?初始化的结果 + * ??值: 成功则返?,否则返?1 + * 修改日期 版本? 修改? 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +static int oled_init(void) +{ + oled_write_cmd_data(0xae,OLED_CMD);//关闭显示 + + oled_write_cmd_data(0x00,OLED_CMD);//设置 lower column address + oled_write_cmd_data(0x10,OLED_CMD);//设置 higher column address + + oled_write_cmd_data(0x40,OLED_CMD);//设置 display start line + + oled_write_cmd_data(0xB0,OLED_CMD);//设置page address + + oled_write_cmd_data(0x81,OLED_CMD);// contract control + oled_write_cmd_data(0x66,OLED_CMD);//128 + + oled_write_cmd_data(0xa1,OLED_CMD);//设置 segment remap + + oled_write_cmd_data(0xa6,OLED_CMD);//normal /reverse + + oled_write_cmd_data(0xa8,OLED_CMD);//multiple ratio + oled_write_cmd_data(0x3f,OLED_CMD);//duty = 1/64 + + oled_write_cmd_data(0xc8,OLED_CMD);//com scan direction + + oled_write_cmd_data(0xd3,OLED_CMD);//set displat offset + oled_write_cmd_data(0x00,OLED_CMD);// + + oled_write_cmd_data(0xd5,OLED_CMD);//set osc division + oled_write_cmd_data(0x80,OLED_CMD);// + + oled_write_cmd_data(0xd9,OLED_CMD);//ser pre-charge period + oled_write_cmd_data(0x1f,OLED_CMD);// + + oled_write_cmd_data(0xda,OLED_CMD);//set com pins + oled_write_cmd_data(0x12,OLED_CMD);// + + oled_write_cmd_data(0xdb,OLED_CMD);//set vcomh + oled_write_cmd_data(0x30,OLED_CMD);// + + oled_write_cmd_data(0x8d,OLED_CMD);//set charge pump disable + oled_write_cmd_data(0x14,OLED_CMD);// + + oled_write_cmd_data(0xaf,OLED_CMD);//set dispkay on + + return 0; +} + +//坐标设置 +/********************************************************************** + * 函数名称?OLED_DIsp_Set_Pos + * 功能描述:设置要显示的位? * 输入参数:@ x :要显示的column address + @y :要显示的page address + * 输出参数?? * ??值: + * 修改日期 版本? 修改? 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +static void OLED_DIsp_Set_Pos(int x, int y) +{ oled_write_cmd_data(0xb0+y,OLED_CMD); + oled_write_cmd_data((x&0x0f),OLED_CMD); + oled_write_cmd_data(((x&0xf0)>>4)|0x10,OLED_CMD); +} + + +static long +spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int x, y; + + /* 根据cmd操作硬件 */ + switch (cmd) + { + case OLED_IOC_INIT: /* init */ + { + dc_pin_init(); + oled_init(); + break; + } + + case OLED_IOC_SET_POS: /* set pos */ + { + x = arg & 0xff; + y = (arg >> 8) & 0xff; + OLED_DIsp_Set_Pos(x, y); + break; + } + + } + + return 0; +} + +static ssize_t +spidev_write(struct file *filp, const char __user *buf, + size_t count, loff_t *f_pos) +{ + char *ker_buf; + int err; + + ker_buf = kmalloc(count, GFP_KERNEL); + err = copy_from_user(ker_buf, buf, count); + + oled_set_dc_pin(1);//拉高,表示写入数? spi_write_datas(ker_buf, count); + kfree(ker_buf); + return count; +} + +static const struct file_operations spidev_fops = { + .owner = THIS_MODULE, + /* REVISIT switch to aio primitives, so that userspace + * gets more complete API coverage. It'll simplify things + * too, except for the locking. + */ + .write = spidev_write, + .unlocked_ioctl = spidev_ioctl, +}; + +/*-------------------------------------------------------------------------*/ + +/* The main reason to have this class is to make mdev/udev create the + * /dev/spidevB.C character device nodes exposing our userspace API. + * It also simplifies memory management. + */ + +static struct class *spidev_class; + +static const struct of_device_id spidev_dt_ids[] = { + { .compatible = "100ask,oled" }, + {}, +}; + + +/*-------------------------------------------------------------------------*/ + +static int spidev_probe(struct spi_device *spi) +{ + /* 1. 记录spi_device */ + oled = spi; + + /* 2. 注册字符设备 */ + major = register_chrdev(0, "100ask_oled", &spidev_fops); + spidev_class = class_create(THIS_MODULE, "100ask_oled"); + device_create(spidev_class, NULL, MKDEV(major, 0), NULL, "100ask_oled"); + + /* 3. 获得GPIO引脚 */ + dc_gpio = gpiod_get(&spi->dev, "dc", 0); + + return 0; +} + +static int spidev_remove(struct spi_device *spi) +{ + gpiod_put(dc_gpio); + + /* 反注册字符设?*/ + device_destroy(spidev_class, MKDEV(major, 0)); + class_destroy(spidev_class); + unregister_chrdev(major, "100ask_oled"); + + return 0; +} + +static struct spi_driver spidev_spi_driver = { + .driver = { + .name = "100ask_spi_oled_drv", + .of_match_table = of_match_ptr(spidev_dt_ids), + }, + .probe = spidev_probe, + .remove = spidev_remove, + + /* NOTE: suspend/resume methods are not necessary here. + * We don't do anything except pass the requests to/from + * the underlying controller. The refrigerator handles + * most issues; the controller driver handles the rest. + */ +}; + +/*-------------------------------------------------------------------------*/ + +static int __init spidev_init(void) +{ + int status; + + status = spi_register_driver(&spidev_spi_driver); + if (status < 0) { + } + return status; +} +module_init(spidev_init); + +static void __exit spidev_exit(void) +{ + spi_unregister_driver(&spidev_spi_driver); +} +module_exit(spidev_exit); + +MODULE_LICENSE("GPL"); + diff --git a/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/spi_oled.c b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/spi_oled.c new file mode 100644 index 0000000..98810de --- /dev/null +++ b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/spi_oled.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "font.h" + +#define OLED_IOC_INIT 123 +#define OLED_IOC_SET_POS 124 + + +//为0 表示命令,为1表示数据 +#define OLED_CMD 0 +#define OLED_DATA 1 + +static int fd_spidev; +static int dc_pin_num; + + +void OLED_DIsp_Set_Pos(int x, int y); + +void oled_write_datas(const unsigned char *buf, int len) +{ + write(fd_spidev, buf, len); +} + + + +/********************************************************************** + * 函数名称: OLED_DIsp_Clear + * 功能描述: 整个屏幕显示数据清0 + * 输入参数:无 + * 输出参数: 无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_Clear(void) +{ + unsigned char x, y; + char buf[128]; + + memset(buf, 0, 128); + + for (y = 0; y < 8; y++) + { + OLED_DIsp_Set_Pos(0, y); + oled_write_datas(buf, 128); + } +} + +/********************************************************************** + * 函数名称: OLED_DIsp_All + * 功能描述: 整个屏幕显示全部点亮,可以用于检查坏点 + * 输入参数:无 + * 输出参数:无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_All(void) +{ + unsigned char x, y; + char buf[128]; + + memset(buf, 0xff, 128); + + for (y = 0; y < 8; y++) + { + OLED_DIsp_Set_Pos(0, y); + oled_write_datas(buf, 128); + } + + + +} + +//坐标设置 +/********************************************************************** + * 函数名称: OLED_DIsp_Set_Pos + * 功能描述:设置要显示的位置 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + * 输出参数: 无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_Set_Pos(int x, int y) +{ + ioctl(fd_spidev, OLED_IOC_SET_POS, x | (y << 8)); +} +/********************************************************************** + * 函数名称: OLED_DIsp_Char + * 功能描述:在某个位置显示字符 1-9 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + @c :要显示的字符的ascii码 + * 输出参数: 无 + * 返 回 值: + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 +***********************************************************************/ +void OLED_DIsp_Char(int x, int y, unsigned char c) +{ + int i = 0; + /* 得到字模 */ + const unsigned char *dots = oled_asc2_8x16[c - ' ']; + + /* 发给OLED */ + OLED_DIsp_Set_Pos(x, y); + /* 发出8字节数据 */ + //for (i = 0; i < 8; i++) + // oled_write_cmd_data(dots[i], OLED_DATA); + oled_write_datas(&dots[0], 8); + + OLED_DIsp_Set_Pos(x, y+1); + /* 发出8字节数据 */ + //for (i = 0; i < 8; i++) + //oled_write_cmd_data(dots[i+8], OLED_DATA); + oled_write_datas(&dots[8], 8); +} + + +/********************************************************************** + * 函数名称: OLED_DIsp_String + * 功能描述: 在指定位置显示字符串 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + @str :要显示的字符串 + * 输出参数: 无 + * 返 回 值: 无 + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 +***********************************************************************/ +void OLED_DIsp_String(int x, int y, char *str) +{ + unsigned char j=0; + while (str[j]) + { + OLED_DIsp_Char(x, y, str[j]);//显示单个字符 + x += 8; + if(x > 127) + { + x = 0; + y += 2; + }//移动显示位置 + j++; + } +} +/********************************************************************** + * 函数名称: OLED_DIsp_CHinese + * 功能描述:在指定位置显示汉字 + * 输入参数:@ x :要显示的column address + @y :要显示的page address + @chr :要显示的汉字,三个汉字“百问网”中选择一个 + * 输出参数: 无 + * 返 回 值: 无 + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ + +void OLED_DIsp_CHinese(unsigned char x,unsigned char y,unsigned char no) +{ + unsigned char t,adder=0; + OLED_DIsp_Set_Pos(x,y); + for(t=0;t<16;t++) + {//显示上半截字符 + oled_write_datas(&hz_1616[no][t*2], 1); + adder+=1; + } + OLED_DIsp_Set_Pos(x,y+1); + for(t=0;t<16;t++) + {//显示下半截字符 + oled_write_datas(&hz_1616[no][t*2+1], 1); + adder+=1; + } +} +/********************************************************************** + * 函数名称: OLED_DIsp_Test + * 功能描述: 整个屏幕显示测试 + * 输入参数:无 + * 输出参数: 无 + * 返 回 值: 无 + * 修改日期 版本号 修改人 修改内容 + * ----------------------------------------------- + * 2020/03/15 V1.0 芯晓 创建 + ***********************************************************************/ +void OLED_DIsp_Test(void) +{ + int i; + + OLED_DIsp_String(0, 0, "wiki.100ask.net"); + OLED_DIsp_String(0, 2, "book.100ask.net"); + OLED_DIsp_String(0, 4, "bbs.100ask.net"); + + for(i = 0; i < 3; i++) + { //显示汉字 百问网 + OLED_DIsp_CHinese(32+i*16, 6, i); + } +} + +/* spi_oled /dev/100ask_oled */ +int main(int argc, char **argv) +{ + if (argc != 2) + { + printf("Usage: %s /dev/100ask_oled\n", argv[0]); + return -1; + } + + fd_spidev = open(argv[1], O_RDWR); + if (fd_spidev < 0) { + printf("open %s err\n", argv[1]); + return -1; + } + + + ioctl(fd_spidev, OLED_IOC_INIT); + + OLED_DIsp_Clear(); + + OLED_DIsp_Test(); + + return 0; +} + diff --git a/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/spi_oled.h b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/spi_oled.h new file mode 100644 index 0000000..692b290 --- /dev/null +++ b/STM32MP157/source/A7/11_SPI/09_oled_framebuffer/spi_oled.h @@ -0,0 +1,17 @@ +#ifndef _OLED_H_ +#define _OLED_H_ + +void oled_write_cmd_data(unsigned char uc_data,unsigned char uc_cmd); +int oled_init(void); +int oled_fill_data(unsigned char fill_Data); +void OLED_DIsp_Clear(void); +void OLED_DIsp_All(void); +void OLED_DIsp_Set_Pos(int x, int y); +void OLED_DIsp_Char(int x, int y, unsigned char c); +void OLED_DIsp_String(int x, int y, char *str); +void OLED_DIsp_CHinese(unsigned char x,unsigned char y,unsigned char no); +void OLED_DIsp_Test(); + + +#endif +