嵌入式控制系统中,常常会遇到需要显示控制状态的控制场合,这种场景下往往不需要显示花里胡哨的窗口或者层级菜单,只需要显示一些控制过程参数或者变化不大的界面,此时可以使用一些小巧的OLED模块来实现上述控制效果。本文介绍常用的0.96″的OLED模块的控制原理和驱动程序,文末可获取完整的示例代码。
本文用到的OLED模块如下图所示:
它有四个引脚:VCC、GND、SCL、SDA。功能如下表所示:
引脚名 | 功能 |
---|---|
VCC | 供电电源引脚,一般选用3.3V直流电源 |
GND | 共地引脚 |
SCL | i i c iic iic 总线中的时钟线 |
SDA | i i c iic iic 总线中的数据线 |
和单片机相连时有以下需要注意的地方:
控制器与该模块控制的时候,单片机通过 i i c iic iic总线在指定的寄存器地址写数据,从而达到在指定的位置显示像素点的目的。
i i c iic iic是一种串行同步通讯总线协议,中文名为内置集成电路总线,由Philips公司开发的两线式总线协议,用于连接微控制器及其外围设备。 i i c iic iic总线简单而有效,占用的PCB(印制电路板)空间很小,芯片引脚数量少,设计成本低。 i i c iic iic总线支持多主控(Multi-Mastering)模式,任何能够进行发送和接收的设备都可以成为主设备。主控能够控制数据的传输和时钟频率,在任意时刻只能有一个Master设备。
组成 i i c iic iic总线的两个信号为数据线SDA和时钟SCL。为了避免总线信号的混乱,要求各设备连接到总线的输出端必须是开漏输出或集电极开路输出的结构。总线空闲时,上拉电阻使SDA和SCL线都保持高电平。根据开漏输出或集电极开路输出信号的“线与”逻辑, i i c iic iic总线上任意器件输出低电平都会使相应总线上的信号线变低。物理层上还规定了 i i c iic iic总线采用的是TTL电平。
i i c iic iic设备上的串行数据线SDA接口电路是双向的,输出电路用于向总线上发送数据,输入电路用于接收总线上的数据。同样地,串行时钟线SCL也是双向的,作为控制总线数据传送的主机要通过SCL输出电路发送时钟信号,并检测总线上SCL上的电平以决定什么时候发下一个时钟脉冲电平;作为接收主机命令的从设备需按总线上SCL的信号发送或接收SDA上的信号,它也可以向SCL线发出低电平信号以延长总线时钟信号周期。当SCL稳定在高电平时,SDA由高到低的变化将产生一个开始位,而由低到高的变化则产生一个停止位,如下图所示:
开始位和停止位都由 i i c iic iic主设备产生。在选择从设备时,如果从设备采用7位地址,则主设备在发起传输过程前,需先发送1字节的地址信息,前7位为设备地址,最后1位为读写标志。之后,每次传输的数据也是1字节,从MSB开始传输。每个字节传完后,在SCL的第9个上升沿到来之前,接收方应该发出1个ACK位。SCL上的时钟脉冲由 i i c iic iic主控方发出,在第8个时钟周期之后,主控方应该释放SDA, i i c iic iic总线的时序如下图所示:
通讯拓扑上,如果是点对点通信,那么发送方是Master,两个通讯节点轮流作为Master发送数据。如果是多对多通讯,仍是按照这种机制传输数据。
//引脚分配
sbit LCD_SCL=P0^7; //时钟 D0(SCLK)
sbit LCD_SDA=P0^6; //D1(MOSI) 数据
sbit LCD_RST=P0^5; //复位
sbit LCD_DC =P0^4; //数据/命令控制
//驱动API
void LCD_DLY_ms(unsigned int ms);
void LCD_WrDat(unsigned char dat);
void LCD_WrCmd(unsigned char cmd);
void LCD_Setxy(unsigned char x, unsigned char y);
void LCD_Fill(unsigned char bmp_dat);
void LCD_CLS(void);
void LCD_Init1(void);
void LCD_6x8(unsigned char x, y,unsigned char ch[]);
void LCD_Cler_6x8(unsigned char x,y,n);
void showNum(unsigned char x,unsigned char y,unsigned char num);
#define OLED_SCL PBout(8)
#define OLED_SDA PBout(9)
#define high 1
#define low 0
#define X_WIDTH 128
#define Y_WIDTH 64
#define Brightness 196 //0~255设置亮度
void IIC_Start(void);// -- 开启I2C总线
void IIC_Stop(void);// -- 关闭I2C总线
void Write_IIC_Byte(unsigned char IIC_Byte);// -- 通过I2C总线写一个byte的数据
void OLED_WrDat(unsigned char dat);// -- 向OLED屏写数据
void OLED_WrCmd(unsigned char cmd);// -- 向OLED屏写命令
void OLED_Set_Pos(unsigned char x, unsigned char y);// -- 设置显示坐标
void OLED_Fill(unsigned char bmp_dat);// -- 全屏显示(显示BMP图片时才会用到此功能)
void OLED_CLS(void);// -- 复位/清屏
void OLED_ON(void);
void OLED_OFF(void);
void OLED_Init(void);// -- OLED屏初始化程序,此函数应在操作屏幕之前最先调用
void OLED_P6x8Str(unsigned char x,unsigned char y,unsigned char ch[],unsigned char against);// -- 6x8点整,用于显示ASCII码的最小阵列,不太清晰
void OLED_P8x16Str(unsigned char x,unsigned char y,unsigned char ch[],unsigned char against);// -- 8x16点整,用于显示ASCII码,非常清晰
void OLED_Show6x8(unsigned char x,unsigned char y,unsigned int N,unsigned char against);
void OLED_Show8x16(unsigned char x,unsigned char y,unsigned int N,unsigned char against);
void OLED_Show16x16(unsigned char x,unsigned char y,unsigned int N,unsigned char against);// -- 16x16点整,用于显示汉字的最小阵列,可设置各种字体、加粗、倾斜、下划线等
void Oled_Printf_U16(unsigned char x,unsigned char y,unsigned int num,unsigned char TextSize);
void Oled_Printf_Float(unsigned char x,unsigned char y,float num,unsigned char TextSize);
本文对应的完整驱动程序已经开源至微信公众号“24K纯学渣”上,回复"OLED4"即可获取。