做网站怎么买断源码,网络营销具有很强的什么特征,wordpress lamp 教程,wordpress 宝塔SPI通信的应用 前言屏幕分类1.3OLED概述驱动芯片框图原理图通信时序显示的方式页地址、列地址初始化指令 程序设计初始化代码初始化写数据与写命令清屏函数 初始化代码字符显示函数 总结 前言
上一篇中介绍了STM32的SPI通信#xff0c;并根据框图和寄存器进行了SPI通信的初始… SPI通信的应用 前言屏幕分类1.3OLED概述驱动芯片框图原理图通信时序显示的方式页地址、列地址初始化指令 程序设计初始化代码初始化写数据与写命令清屏函数 初始化代码字符显示函数 总结 前言
上一篇中介绍了STM32的SPI通信并根据框图和寄存器进行了SPI通信的初始化配置本文继续接着来运用SPI通信来做两个实际的需求一个是常用的LCD屏幕另一个是常用的外部存储器WAQXX。
屏幕分类
作为最常用的人机交互装置在嵌入式系统开发过程中屏幕显示始终是一个绕不开的内容市面上关于屏幕这一块也是卷到飞起各种尺寸各种协议各种规格的都有最常见的有支持串口协议的屏幕例如陶晶驰的串口屏、以及支持modbus协议的各类工控屏幕这类屏幕都是内部集成了一个系统可以使用厂商提供的上位机对屏幕进行编程以及界面设置可以实现更多功能的同时也可以降低开发者的使用难度关于这类屏幕如果还没接触过的小伙伴可以去了解一下这种集成好的屏幕价格相对美好而且功能丰富准备电赛、自己做项目什么的都很方便更重要的是串口屏在以后的工作中会经常遇到关于串口屏我们后面有机会再来介绍本文主要是使用SPI作为底层传输协议来驱动一款1.44寸的LCD屏幕厂家是陶晶驰。 这里有一丢丢小知识需要大家做个了解在嵌入式系统常用的屏幕类型除了上面的按照协议区分还有就是按照其制作工艺来区分在手只因机圈发布会上最近几年高频出现的什么LCDOLED这俩就是不同的屏幕制作工艺二者各有其优缺点LCD屏幕由于使用了背光源这导致它不能显示纯黑色在黑色界面会漏光而OLED是新技术没有背光源从根源上解决了漏光和无法显示纯黑的问题。但是LCD的使用寿命会比OLED好一些同时价格也相对优惠。
1.3OLED概述
这里笔者选用的是中景园的1.3寸OLED来显示的其驱动芯片是SH1106分辨率是128*64默认通信方式就是SPI。 在购买屏幕后商家一般会给一个参考代码大多数时候直接移植过来就可以直接使用了但是这会让开发者对OLED的底层了解较少换了屏幕或者需要特殊显示的时候会一头雾水所以这里笔者带大家来稍稍细致的扒一下OLED的底层驱动代码以及配置流程。
驱动芯片
首先通过上面商家的产品介绍可以知道在这个屏幕内部有一个驱动芯片叫做SH1106也就是说在操作屏幕显示的时候STM32是直接控制这个驱动芯片然后再由驱动芯片去控制屏幕显示的。 既然是驱动外部芯片那么就必须去看看这个芯片的手册了。这个手册可以直接在百度找或者去找商家要或者有需要的可以私信。 首先第一页的产品特点对于软件开发来说特别重要的就是红框框出来的位置一个是告诉开发者最大支持13264的分辨率选用的这个屏幕是12864的然后是下面的关于通信接口的介绍这个驱动芯片支持多种协议。具体选用哪个需要看硬件接法剩下就是一些关于电流电压的硬件参数了如果是自己画板的话是需要去仔细查看的这里笔者用的模块所以就略过了这一部分。
框图
看完了芯片的产品特点接下来再看看芯片的具体驱动框图如下所示上方的输出引脚是SEG0-SEG131与COM0–COM63刚好与上面提到的最大分辨率132*64一一对应这里就是直接控制屏幕各个点位的。 然后是左边的一系列电源以及滤波电路主要作用就是为整个模块供电然后是右侧的CL与CLS是用来选择时钟源的这些我们大致了解就行了最重要的是最下面的用户接口那部分。 需要特别注意的就是这里的用户接口的各个引脚这里面有很多东西都是直接与编程相关的最右边的CS是控制通信时的片选信号然后A0 RD WR这些是在8080或者6800通信时用到的这里不最了解然后是RES是整个屏幕的硬件复位接口需要我们控制然后是IM0-IM2这三个脚是用来选择具体的通信方式的剩下的D0-D7八个数据脚就是和主控进行数据传输用的根据不同的协议会选用不同的引脚。 具体的引脚介绍如下图所示这里重点了解M0-M2、CS、RES、D0、D1的作用。
原理图
根据数据手册的简介就可以绘制硬件的原理图了这里参考中景园的原理图首先为了能够兼容SPI四线和IIC官方在设计原理图时使用了两个电阻来控制BS1的高低电平这里得BS0-BS2也就是前面手册中提到的M0-M2 改变电阻选择拉高BS1就需要使用IIC的通信而拉低BS1就是使用SPI4线的通信方式然后由于CS、D/C也就是上面提到的A0、RES这三个线都需要开发者在编程时进行操作所以也需要外接出来用于控制。
通信时序
搞清楚了硬件的连接后接下来就需要弄清楚软件的具体通讯流程了如下图所示首先通过时序图可以发现当时钟线在高电平的时候数据线的数据是处于平稳期的也就是说高电平时间是用来读取数据的而时钟处于低电平的时候数据处于跳变期也就是此时是写入如数据的时刻而且通过观察时钟线可以看出SCL的空闲电平是高电平且是第二个边沿才开始进行操作所以SH1106的SPI通信使用的是模式3在上一篇中我们提到过模式3和模式0是可以通用也就是说在使用控制器配置过程中可以选用模式三或者模式0。 而当使用IO模拟的时候就需要根据时钟线拉高读取数据时钟线拉低写入数据的时序来进行操作。在写入命令的时候需要将A0拉低DC脚写入数据的时候需要将A0拉高DC脚。
显示的方式
在弄清楚了通信协议的具体方式后接下来还需要进一步了解怎么控制OLED的显示首先整个屏幕是一个12864的矩阵整个矩阵又被分为了八个页其页地址分别是B0-B7每一页都有8128个点阵其写入方式就是每次写入一个八位数据到一页的一列写入后列地址会自动偏移一次继续写入下一列的数据直到这页写完然后才会跳转到下一页继续写。 举个例子假设要在屏幕上显示一个1616的“中”首先需要对中进行取模 取模时是低位在前。 0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, 0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00,/“中”,0*/ 这是取模后的数据 具体的显示过程就是 1.将0x00写入第一页的第一列由于都是0所以没有点亮的位置 2.将0x00写入第一页的第二列 3. …一直写入直到把第一页写完 4. 然后开始写入第二页的数据内容也是一样在第二页第一列写入0x00第二列写入0x00,第三列写入0x0F,直到最后一个“中”字就被显示出来了。 在这里主要要明白整个显示的刷新方式是以页为单位从上到下从左到右进行刷新的每次写入的值就是对应想显示的内容的取模值写入数据的每一位都对应着一个像素点写入值是1时就点亮写入值是0时就熄灭。
更形象的说刷现流程如下图所示一开始是一整个花屏然后屏幕开始由左上方第一页第一列开始刷新以页为单位按照从上到下从左到右的顺序刷新由于手机摄像头的刷新频率和屏幕的刷现频率不一致所以会有频闪有些影响效果。
页地址、列地址
在上面的中字显示介绍中提到了也地址是从B0-B7一共八个每个页占八行。每一次操作OLED屏幕的时钟最少要操作1页 1页8行 页地址不会自己偏移 OLED屏扫描方式 传入数据 同发送数据的函数 对相应的像素点写入1则点亮对相应像素点写入0则熄灭 列地址一个列地址由两个地址控制高位和低位地址 低位地址的基地址0x00 列的低4位数据 高位地址的基地址0x10 列的高4位数据 列的取值返回0~127 在实际显示数据的时候列地址会基于传入的地址进行偏移 列地址会自动偏移每次写入数据的时候只需要写入第一列即可 这样说起来可能不太清晰举个栗子来说吧假设我们对第15列写入数据此时15列对应的十六进制是0x0f那么我们需要写入给芯片的地址就是 低位地址 0000 1111 0x0f; 具体写入的低地址 0x00 列的低4位数据0x000xf0x0f; 高位地址0001 0000 0x10; 高位地址的基地址0x10 列的高4位数据0x100x000x10; 搞清楚对应的列地址计算方式有利于后面找到想要显示的位置。 根据上面的这个流程假设要在第一页的第127(0x7f)列写入数据就需要我们分别写入页地址B0 写入列低地址 0x000x0f 0x0f; 写入列高地址0x100x07 0x17; 根据上面的计算流程可以总结一个OLED屏幕显示的设置显示位置的函数
/************************************************
函数功能OLED设置位置函数
函数名:Oled_Set_Addr
函数形参u8 page,u8 col
函数返回值None
备注
**************************************************/
void Oled_Set_Addr(u8 page,u8 col)
{OLED_Send_Commond(0xb0 page); //页的地址 //列的起始地址 列会自动偏移OLED_Send_Commond(0x00 (col 0x0f)); //列的低地址OLED_Send_Commond(0x10 ((col 0xf0)4)); //列的高地址
}初始化指令
除了上面的行地址和列地址以外在初始化过程中还需要写入很多其他命令这些厂家都会给定对应的指令在芯片手册也有介绍由于数量有点多想要了解的自己去对照看手册哈这里笔者直接给出注释
初始化需要写入的指令
//初始化序列OLED_Send_Commond(0xAE); //关闭显示OLED_Send_Commond(0xD5); //设置时钟分频因子,震荡频率OLED_Send_Commond(80); //[3:0],分频因子;[7:4],震荡频率OLED_Send_Commond(0xA8); //设置驱动路数OLED_Send_Commond(0X3F); //默认0X3F(1/64)OLED_Send_Commond(0xD3); //设置显示偏移OLED_Send_Commond(0X00); //默认为0OLED_Send_Commond(0x40); //设置显示开始行 [5:0],行数.OLED_Send_Commond(0x8D); //电荷泵设置OLED_Send_Commond(0x14); //bit2开启/关闭OLED_Send_Commond(0x20); //设置内存地址模式OLED_Send_Commond(0x02); //[1:0],00列地址模式;01行地址模式;10,页地址模式;默认10;OLED_Send_Commond(0xA1); //段重定义设置,bit0:0,0-0;1,0-127;OLED_Send_Commond(0xC8); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]-COM0;N:驱动路数OLED_Send_Commond(0xDA); //设置COM硬件引脚配置OLED_Send_Commond(0x12); //[5:4]配置OLED_Send_Commond(0x81); //对比度设置OLED_Send_Commond(0xEF); //1~255;默认0X7F (亮度设置,越大越亮)OLED_Send_Commond(0xD9); //设置预充电周期OLED_Send_Commond(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;OLED_Send_Commond(0xDB); //设置VCOMH 电压倍率OLED_Send_Commond(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;OLED_Send_Commond(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)OLED_Send_Commond(0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示OLED_Send_Commond(0xAF); //开启显示
程序设计
关于屏幕的驱动的原理图以及芯片介绍就上面这些接下来就是实际编写代码来实现屏幕的显示。
初始化代码
根据之前的硬件电路可以知道这个屏幕是使用的SPI通信接口来实现显示的这里笔者使用的是学习板几乎所有IO都是可以使用的为了验证上一篇的SPI通信的配置是否正常所以选用了SPI1 也就是PB3、PB4、PB5这三个脚来作为SPI的通信引脚在上一篇SPI控制器的介绍中提到过SPI通信中一般是不用控制器复用的GPIO口的为了方便SPI控制器的CS选用软件管理的方式实际的CS片选脚由编程者根据硬件的连接配置为通用推挽输出来控制即可。 除了SPI通信的三个脚以外还需要对RES、DC进行控制所以还需要配置管脚对它们进行驱动。 具体的引脚使用如下表
OLED管脚STM32F407VECLKPB3(SCK)MOSIPB5(MOSI)RESPB8DCPB6CSPB7
初始化
初始化伪代码
OLED的初始化函数
{1.初始化SPI1的控制器模式三或者模式零主模式、八位数据、 双线单向、软件从器件管理、先发高位。2.初始化控制器OLED的RES、CS、DC的IO口配置为通用推挽输出3.设置空闲电平4.对屏幕进行硬件复位5.写入初始化序列6.清屏
}写数据与写命令
关于初始化函数前面的4步骤都好说第五步的写入初始化序列与第六步的清屏函数还需要进一步进行封装。 根据之前的芯片手册介绍我们知道写入的序列实际上使用命令对于命令的写入OLED是有要求的具体的写入函数如下 /************************************************
函数功能OLED发送命令函数
函数名:OLED_Send_Commond
函数形参u8 cmd
函数返回值None
备注
**************************************************/
void OLED_Send_Commond(u8 cmd)
{OLED_CS_L; //拉低片选OLED_DC_L; //发送命令Spi_Send_Data(cmd);OLED_CS_H; //结束通信
}
/************************************************
函数功能OLED发送数据函数
函数名:OLED_Send_Data
函数形参u8 data
函数返回值None
备注
**************************************************/
void OLED_Send_Data(u8 data)
{OLED_CS_L; //拉低片选OLED_DC_H; //发送数据Spi_Send_Data(data);OLED_CS_H; //结束通信
}
关于写数据和写命令的这两个函数思路很好理解首先需要拉低CS片选然后要通过控制DC脚的高低电平来告诉屏幕此时发送的是数据还是命令然后调用SPI的发送函数进行发送就行了由于OLED是不需要给STM32回数据的所以就没有接收数据这个部分了。发送完成后将片选拉高以便于下次的数据发送。
清屏函数
关于清屏函数就涉及到了屏幕的具体显示了这里也是有一个流程的如下图所示首先需要设置显示的起始位置然后需要给定页地址还要给定列地址。 根据这个流程加上前面对于页地址列地址的介绍可以得出以下的清屏函数
/************************************************
函数功能OLED的清屏函数
函数名:OLED_Clear
函数形参void
函数返回值None
备注
**************************************************/
void OLED_Clear(void)
{u8 i,j;for(i0;i8;i) //页的循环一共是B0-B7八页{OLED_Send_Commond(0xb0i); //页的地址//列的起始地址 列会自动偏移OLED_Send_Commond(0x00); //列的低地址OLED_Send_Commond(0x10); //列的高地址for(j0;j132;j) //列的循环{OLED_Send_Data(0x00);//写入0x00就是全部默认熄灭写入0XFF就是默认全点亮。}}
}初始化代码
补充完上面这三个函数后就可以对OLED进行初始化操作了SPI1的初始化就是上一篇中的SPI控制器的初始化代码。 /*******************************************
*函数名 :OLED_Init
*函数功能 :OLED初始化配置
*函数参数 :无
*函数返回值:无
*函数描述 :
SCK------PB3 //复用输出
MISO-----PB4 //复用输出
MOSI-----PB5 //复用输出RES------PB8 //通用推挽输出
CS-------PB7 //通用推挽输出
DC-------PB6 //通用推挽输出
*********************************************/
void OLED_Init(void)
{/*IO口控制器配置*/
// //端口时钟使能 RCC-AHB1ENR | 11;// PB//OLED_DC PB6GPIOB-MODER ~(312);GPIOB-MODER | 112;GPIOB-OTYPER ~(16);GPIOB-OSPEEDR ~(312);GPIOB-OSPEEDR | 212; //OLED_CS PB7GPIOB-MODER ~(314);GPIOB-MODER | 114;GPIOB-OTYPER ~(17);GPIOB-OSPEEDR ~(314);GPIOB-OSPEEDR | 214; //OLED_RES PB8GPIOB-MODER ~(316);GPIOB-MODER | 116;GPIOB-OTYPER ~(18);GPIOB-OSPEEDR ~(316);GPIOB-OSPEEDR | 216;//初始状态 res1;DC1;CS1GPIOB-ODR |(0X76);//空闲状态为高Spi1_Init();OLED_RES_L;SysTick_Delay_ms(200);OLED_RES_H;//复位//初始化序列OLED_Send_Commond(0xAE); //关闭显示OLED_Send_Commond(0xD5); //设置时钟分频因子,震荡频率OLED_Send_Commond(80); //[3:0],分频因子;[7:4],震荡频率OLED_Send_Commond(0xA8); //设置驱动路数OLED_Send_Commond(0X3F); //默认0X3F(1/64)OLED_Send_Commond(0xD3); //设置显示偏移OLED_Send_Commond(0X00); //默认为0OLED_Send_Commond(0x40); //设置显示开始行 [5:0],行数.OLED_Send_Commond(0x8D); //电荷泵设置OLED_Send_Commond(0x14); //bit2开启/关闭OLED_Send_Commond(0x20); //设置内存地址模式OLED_Send_Commond(0x02); //[1:0],00列地址模式;01行地址模式;10,页地址模式;默认10;OLED_Send_Commond(0xA1); //段重定义设置,bit0:0,0-0;1,0-127;OLED_Send_Commond(0xC8); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]-COM0;N:驱动路数OLED_Send_Commond(0xDA); //设置COM硬件引脚配置OLED_Send_Commond(0x12); //[5:4]配置OLED_Send_Commond(0x81); //对比度设置OLED_Send_Commond(0xEF); //1~255;默认0X7F (亮度设置,越大越亮)OLED_Send_Commond(0xD9); //设置预充电周期OLED_Send_Commond(0xf1); //[3:0],PHASE 1;[7:4],PHASE 2;OLED_Send_Commond(0xDB); //设置VCOMH 电压倍率OLED_Send_Commond(0x30); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;OLED_Send_Commond(0xA4); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)OLED_Send_Commond(0xA6); //设置显示方式;bit0:1,反相显示;0,正常显示OLED_Send_Commond(0xAF); //开启显示//清屏函数OLED_Clear();
}字符显示函数
同样的在理解了显示原理后还可以自己来尝试写一下函数比如说显示英文字符汉字字符串画点画圆画线等等的函数。 首先是字符的显示函数根据上面显示汉字“中”的介绍可以知道要向显示对应的字符首先是要进行取模具体的取模方式应该与我们的显示顺序一致详细的取模方式大家自己去搜索吧CSDN很多大佬都写过详细的介绍。 例如我们这里想要显示一个“A”它占得大小是168也就时需要两页才能显示取模的数据如下0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,/“A”,0*/ /* (8 X 16 , 宋体 )*/ 根据之前的清屏函数稍微修改一下就可以显示出A了具体的代码如下: /************************************************
函数功能OLED设置位置函数
函数名:Oled_Set_Addr
函数形参u8 page,u8 col
函数返回值None
备注
**************************************************/
void Oled_Set_Addr(u8 page,u8 col)
{OLED_Send_Commond(0xb0 page); //页的地址 //列的起始地址 列会自动偏移OLED_Send_Commond(0x00 (col 0x0f)); //列的低地址OLED_Send_Commond(0x10 ((col 0xf0)4)); //列的高地址
}/************************************************
函数功能OLED显示单个英文字符
函数名:Oled_Show_Ch
函数形参u8 page,u8 col 决定字显示在什么位置u8 ch想要显示的字符函数返回值None
备注
**************************************************/
void Oled_Show_Ch(u8 page,u8 col)
{u8 i,j;u8 A_buff[16]{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20};//A的取模16*8的大小for(i0;i2;i) //页的循{Oled_Set_Addr(pagei,col); //设置显示位置for(j0;j8;j) //列的循环{OLED_Send_Data(A_buff[i*8 j]);}}
}
实际的显示效果如下 利用相似的思路还可以显示汉字需要注意的是汉字的一个字的大小是1616是英文字符的2倍。 中(0) 0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, 0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00,/“中”,0*/ /* (16 X 16 , 宋体 )*/
// An highlighted block
/************************************************
函数功能OLED显示单个中文字符
函数名:Oled_Show_Hz
函数形参u8 page,u8 col 决定字显示在什么位置u8 *str 想要显示的汉字函数返回值None
备注
只有添加了字模才能使用
**************************************************/
void Oled_Show_Hz(u8 page,u8 col)
{u8 i,j;u8 CH_buff[32]{0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00,0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00/*中,0*//* (16 X 16 , 宋体 )*/};for(i0;i2;i) //页循环{Oled_Set_Addr(pagei,col); //设置显示位置for(j0;j16;j){OLED_Send_Data(CH_buff[i*16j]);}}
}在搞定了显示的思路后还可以提前对字符和部分汉字进行取模然后直接调用字符串显示进一步封装后代码如下所示 /************************************************
函数功能OLED显示单个英文字符
函数名:Oled_Show_Ch
函数形参u8 page,u8 col 决定字显示在什么位置u8 ch想要显示的字符函数返回值None
备注
**************************************************/
void Oled_Show_Ch(u8 page,u8 col,u8 ch)
{u8 i,j;u8 n0; //表示字符在数组中的位置n ch - ;for(i0;i2;i) //页的循{Oled_Set_Addr(pagei,col); //设置显示位置for(j0;j8;j) //列的循环{OLED_Send_Data(Aciss_8X16[n*16 i*8 j]);}}
}/************************************************
函数功能OLED显示单个中文字符
函数名:Oled_Show_Hz
函数形参u8 page,u8 col 决定字显示在什么位置u8 *str 想要显示的汉字函数返回值None
备注
只有添加了字模才能使用
**************************************************/
void Oled_Show_Hz(u8 page,u8 col,u8 *str)
{u8 i,j;u8 n0; //找到汉字在数组中的位置while(1){if(*strtable[n*2] *(str1)table[n*21]){//此时的N为字在数组中的位置break;}n;}for(i0;i2;i) //页循环{Oled_Set_Addr(pagei,col); //设置显示位置for(j0;j16;j){OLED_Send_Data(Hz_16X16[n*32i*16j]);}}
}/************************************************
函数功能OLED显示字符串
函数名:Oled_Show_Str
函数形参u8 page,u8 col 决定字显示在什么位置u8 *str 待显示的字符串
函数返回值None
备注
可以显示中英结合的字符串
**************************************************/
void Oled_Show_Str(u8 page,u8 col,u8 *str)
{//123云家居while(1){if(*str 0 *str 127) //英文字符{Oled_Show_Ch(page,col,*str); //‘1’str; //显示下一个字符col8;if(col128-8) //遇到屏幕边缘{page2; //换页col0; //列回到起始位置}if(*str\0){break;}}else //中文字符{Oled_Show_Hz(page,col,str); //“云”str2; //汉字是字符的两倍col16;if(col128-16) //遇到屏幕边缘{page2; //换页col0; //列回到起始位置}if(*str\0){break;}}}
}//显示笔画简单
/************************************************
函数功能OLED显示图片
函数名:Oled_Show_Pic
函数形参u8 page,u8 col 页和列显示图片u8 w,u8 h,u8 *pic函数返回值None
备注
可以显示中英结合的字符串自动换行
**************************************************/
void Oled_Show_Pic(u8 page,u8 col,u8 w,u8 h,u8 *pic)
{u8 i,j;for(i0;ih/8;i){Oled_Set_Addr(pagei,col);for(j0;jw;j){OLED_Send_Data(pic[i*wj]);}}
}总结
原本打算一篇就将OLED显示以及W25Qxx烧录字库一起介绍的但是没想到篇幅这么大而且OLED的功能都还没写全先这样吧后面有空再补充吧文中如有不足欢迎批评指正。