STC90C51驱动LCD1602、LCD12864、OLED

主控芯片(STC90C516RD+PG5151028)介绍

STC90C5116RD芯片引脚图

ROM=64K,RAM=1280字节,40Pin,3个定时器,1个串口,8个中断源(分别是:外部中断0(INTO)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定时器 0中断、定时器 1 中断、定时器 2 中断、串口(UART)中断),所有的中断都具有4个中断优先级

1.LCD1602

1.1.LCD1602简介

1602 液晶也叫 1602 字符型液晶,它能显示 2 行字符信息,每行又能显示 16个字符。它是一种专门用来显示字母、数字、符号的点阵型液晶模块。它是由若干个 5x7 或者 5x10 的点阵字符位组成,每个点阵字符位都可以用显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用。

局部接线图
引脚说明(16引脚):
VSS: 电源地
VDD:电源正极(+5V)
VO:液晶显示偏压信号,用于调整 LCD1602 的显示对比度,一般会外接电位器用以调整偏压信号,注意此脚电压为 0 时可以得到最强的对比度。
RS:数据/命令选择端,当此脚为高电平时,可以对 1602 进行数据字节的传输操作,而为低电平时,则是进行命令字节的传输操作。命令字节,即是用来对 LCD1602 的一些工作方式作设置的字节;数据字节,即使用以在 1602 上显示的字节。值得一提的是,LCD1602 的数据是 8 位的。
RW:读写选择端。当此脚为高电平可对 LCD1602 进行读数据操作,反之进行写数据操作。
E:使能信号,其实是 LCD1602 的数据控制时钟信号,利用该信号的上升沿实现对 LCD1602 的数据传输。
D0-D7:8 位并行数据口,而 51 单片机一组 IO 也是 8 位,使得对 LCD1602的数据读写大为方便。
A:背光源正极
K:背光源负极
在这里插入图片描述
在 LCD1602 内部含有 80 个字节的 DDRAM,它是用来寄存显示字符的。不是所有的地址都可以直接用来显示字符数据,只有第一行中的 00-0F,第二行中的 40-4F 才能显示,其他地址只能用于存储。
LCD1602 操作步骤如下所示: (1)初始化 (2)写命令(RS=L),设置显示坐标 (3)写数据(RS=H)
①当要写指令字,设置 LCD1602 的工作方式时:需要把 RS 置为低电平,RW置为低电平,然后将数据送到数据口 D0~D7,最后 E 引脚一个高脉冲将数据写入。
②当要写入数据字,在 1602 上实现显示时:需要把 RS 置为高电平,RW 置为低电平,然后将数据送到数据口 D0~D7,最后 E 引脚一个高脉冲将数据写入。

硬件连接:
VSS------GND
VDD------5V
RS-------P2.6
RW-------P2.5
E--------P2.7
D0-D7-------P0
VO---------RJ6调节背光

1.2驱动代码

led.h

#ifndef __LCD_H_
#define __LCD_H_/**********************************
包含头文件
**********************************/
#include<reg52.h>//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif#ifndef uint 
#define uint unsigned int
#endif/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c);   //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/	
void LcdWriteData(uchar dat)	;
/*LCD1602初始化子程序*/		
void LcdInit();	
void lcd_clear();
void lcd_show_string(uchar x,uchar y,uchar *str);					  #endif

lcd.c

#include "lcd.h"/*******************************************************************************
* 函 数 名         : Lcd1602_Delay1ms
* 函数功能		   : 延时函数,延时1ms
* 输    入         : c
* 输    出         : 无
* 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/void Lcd1602_Delay1ms(uint c)   //误差 0us
{uchar a,b;for (; c>0; c--){for (b=199;b>0;b--){for(a=1;a>0;a--);}      }}/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能		   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/void LcdWriteCom(uchar com)	  //写入命令
{LCD1602_E = 0;     //使能LCD1602_RS = 0;	   //选择发送命令LCD1602_RW = 0;	   //选择写入LCD1602_DATAPINS = com;     //放入命令Lcd1602_Delay1ms(1);		//等待数据稳定LCD1602_E = 1;	          //写入时序Lcd1602_Delay1ms(5);	  //保持时间LCD1602_E = 0;
}/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能		   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/		   void LcdWriteData(uchar dat)			//写入数据
{LCD1602_E = 0;	//使能清零LCD1602_RS = 1;	//选择输入数据LCD1602_RW = 0;	//选择写入LCD1602_DATAPINS = dat; //写入数据Lcd1602_Delay1ms(1);LCD1602_E = 1;   //写入时序Lcd1602_Delay1ms(5);   //保持时间LCD1602_E = 0;
}/*******************************************************************************
* 函 数 名       : LcdInit()
* 函数功能		 : 初始化LCD屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/void LcdInit()						  //LCD初始化子程序
{LcdWriteCom(0x38);  //开显示LcdWriteCom(0x0c);  //开显示不显示光标LcdWriteCom(0x06);  //写一个指针加1LcdWriteCom(0x01);  //清屏LcdWriteCom(0x80);  //设置数据指针起点
}/*******************************************************************************
* 函 数 名       : lcd_clear
* 函数功能		 : LCD 清屏
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/void lcd_clear()						  
{LcdWriteCom(0x01);
}/*******************************************************************************
* 函 数 名       : lcd_show_string
* 函数功能		 : LCD 显示字符
* 输    入       : x,y:显示坐标,x=0~15,y=0~1;str:显示字符串
* 输    出       : 无
*******************************************************************************/void lcd_show_string(uchar x,uchar y,uchar *str)						  
{uchar i = 0;if(y>1||x>15)return;//行列参数不对则强制退出if(y<1) //第 1 行显示{while(*str!='\0')//字符串是以'\0'结尾,只要前面有内容就显示{if(i<16-x)//如果字符长度超过第一行显示范围,则在第二行继续显示{LcdWriteCom(0x80+i+x);//第一行显示地址设置}else{LcdWriteCom(0x40+0x80+i+x-16);//第二行显示地址设置}LcdWriteData(*str);//显示内容str++;//指针递增i++;}}else{while(*str!='\0'){if(i<16-x)  //如果字符长度超过第二行显示范围,则在第一行继续显示LcdWriteCom(0x80+0x40+i+x); elseLcdWriteCom(0x80+i+x-16);LcdWriteData(*str);//显示内容str++;//指针递增i++;}}}

main.c

/**************************************************************************************
*		              LCD1602液晶显示实验												  *
实现现象:	具体接线操作请参考视频教程下载程序后插上LCD1602液晶在开发板上,即可显示
注意事项:																				  
***************************************************************************************/#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main(void)
{LcdInit();lcd_clear();lcd_show_string(0,0,"Hello World!");//第一行显示lcd_show_string(0,1,"0123456789");//第二行显示while(1);				
}

1.3显示效果图

在这里插入图片描述

2.LCD12864

2.1LCD12864简介

12864 是以 128 列像素,64 行像素,也就是有 12864 个像素点组成,通常显示一个汉字需要 1616 个像素点,所以 LCD12864 一行最多能显示 8个汉字,最多能显示 4 行。通常显示一个字符需要 8*8 个像素点,所以 LCD12864 一行最多能显示 16 个字符,最多能显示 8 行。

引脚说明(16引脚):
GND:电源地(0V)
VCC:电压输入(+5V)
RS:寄存器选择端,高:读操作 低:写操作
RD:读使能,低电平有效,高电平读失能
WR:读写信号,高:读操作 低:写操作
D0-D7:数据总线
CS:片选信号,低有效
RESET:复位信号,低有效
在这里插入图片描述
从上图可知,LCD12864 能直接显示的地址范围如下:
第一行:0X80-0X87;(一个汉字占用 2 个字节,共 8 个汉字)
第二行:0X90-0X97;
第三行:0X88-0X8F;
第四行:0X98-0X9F;

不带字库的 LCD12864 背面没有芯片,一般为转接板,将 12864 显示屏转接到开发板,所有的显示都需要取模,取模方法和点阵取模一样。内部驱动芯片是 ST7565P,ST7565P 数据手册是液晶屏内核手册,里面有驱动方法和指令和程序有关的数据。

硬件连接:
D0-D7--------P0
CS-----------P3.2
RESET--------P3.3
RS-----------P2.6
RW-----------P2.7
RD-----------P2.5

2.2驱动代码

lcd12864.h

#ifndef __ST7565_H
#define __ST7565_H#include<reg51.h>
#include<intrins.h>//---包含字库头文件
#define CHAR_CODE//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif#ifndef uint 
#define uint unsigned int
#endif//--定时使用的IO口--//
#define DATA_PORT P0
sbit LCD12864_CS   = P3^2;
sbit LCD12864_RSET = P3^3;
sbit LCD12864_RS   = P2^6;
sbit LCD12864_RW   = P2^7;
sbit LCD12864_RD   = P2^5;//--定义全局函数--//
void LcdSt7565_WriteCmd(cmd);
void LcdSt7565_WriteData(dat);
void Lcd12864_Init();
void Lcd12864_ClearScreen(void);
uchar Lcd12864_Write16CnCHAR(uchar x, uchar y, uchar *cn);#endif

lcd12864.c

#include"st7565.h"/*******************************************************************************
* 函 数 名         : LCD12864_WriteCmd
* 函数功能		   : 写入一个命令到12864
* 输    入         : cmd
* 输    出         : 无
*******************************************************************************/void LcdSt7565_WriteCmd(cmd)
{LCD12864_CS = 0;	   //chip select,打开片选LCD12864_RD = 1;	   //disable read,读失能	LCD12864_RS = 0;       //select command,选择命令LCD12864_RW = 0;       //select write,选择写模式_nop_();_nop_();DATA_PORT = cmd; //put command,放置命令_nop_();_nop_();LCD12864_RW = 1;	   //command writing ,写入命令
}/*******************************************************************************
* 函 数 名         : LcdSt7565_WriteData
* 函数功能		   : 写入一个数据到12864
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/void LcdSt7565_WriteData(dat)
{	LCD12864_CS = 0;	   //chip select,打开片选LCD12864_RD = 1;	   //disable read,读失能	LCD12864_RS = 1;       //select data,选择数据LCD12864_RW = 0;       //select write,选择写模式_nop_();_nop_();DATA_PORT = dat;       //put data,放置数据_nop_();_nop_();LCD12864_RW = 1;	   //data writing,写数据 
}/*******************************************************************************
* 函 数 名         : LCD12864_Init
* 函数功能		   : 初始化12864
* 输    入         : 无
* 输    出         : 无
* 说    明         : LCD12864的命令指令可以查看例程文件夹下的《ST7565p数据手册》
*                  * 的第51页的位置。
*******************************************************************************/void Lcd12864_Init()
{uchar i;LCD12864_RSET = 0;for (i=0; i<100; i++);LCD12864_CS = 0;LCD12864_RSET = 1;//----------------Star Initial Sequence-------////------程序初始化设置,具体命令可以看文件夹下---////--软件初始化--//LcdSt7565_WriteCmd(0xE2);  //resetfor (i=0; i<100; i++);	   //延时一下//--表格第8个命令,0xA0段(左右)方向选择正常方向(0xA1为反方向)--//LcdSt7565_WriteCmd(0xA1);  //ADC select segment direction //--表格第15个命令,0xC8普通(上下)方向选择选择反向,0xC0为正常方向--// LcdSt7565_WriteCmd(0xC8);  //Common direction //--表格第9个命令,0xA6为设置字体为黑色,背景为白色---////--0xA7为设置字体为白色,背景为黑色---//LcdSt7565_WriteCmd(0xA6);  //reverse display//--表格第10个命令,0xA4像素正常显示,0xA5像素全开--//LcdSt7565_WriteCmd(0xA4);  //normal display//--表格第11个命令,0xA3偏压为1/7,0xA2偏压为1/9--//LcdSt7565_WriteCmd(0xA2);  //bias set 1/9//--表格第19个命令,这个是个双字节的命令,0xF800选择增压为4X;--////--0xF801,选择增压为5X,其实效果差不多--//	LcdSt7565_WriteCmd(0xF8);  //Boost ratio setLcdSt7565_WriteCmd(0x01);  //x4//--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--////--选择从0x00到0X3F。用来设置背景光对比度。---/LcdSt7565_WriteCmd(0x81);  //V0 a setLcdSt7565_WriteCmd(0x23);//--表格第17个命令,选择调节电阻率--//LcdSt7565_WriteCmd(0x25);  //Ra/Rb set//--表格第16个命令,电源设置。--//LcdSt7565_WriteCmd(0x2F);for (i=0; i<100; i++);//--表格第2个命令,设置显示开始位置--//LcdSt7565_WriteCmd(0x40);  //start line//--表格第1个命令,开启显示--//LcdSt7565_WriteCmd(0xAF);  // display onfor (i=0; i<100; i++);}/*******************************************************************************
* 函 数 名         : LCD12864_ClearScreen
* 函数功能		   : 清屏12864
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/void Lcd12864_ClearScreen(void)
{uchar i, j;for(i=0; i<8; i++){//--表格第3个命令,设置Y的坐标--////--Y轴有64个,一个坐标8位,也就是有8个坐标--////所以一般我们使用的也就是从0xB0到0x07,就够了--//	LcdSt7565_WriteCmd(0xB0+i); //--表格第4个命令,设置X坐标--////--当你的段初始化为0xA1时,X坐标从0x10,0x04到0x18,0x04,一共128位--////--当你的段初始化为0xA0时,X坐标从0x10,0x00到0x18,0x00,一共128位--////--在写入数据之后X坐标的坐标是会自动加1的,我们初始化使用0xA0所以--////--我们的X坐标从0x10,0x00开始---//LcdSt7565_WriteCmd(0x10); LcdSt7565_WriteCmd(0x04);							   //--X轴有128位,就一共刷128次,X坐标会自动加1,所以我们不用再设置坐标--//for(j=0; j<128; j++){LcdSt7565_WriteData(0x00);  //如果设置背景为白色时,清屏选择0XFF}}
}/*******************************************************************************
* 函 数 名         : LCD12864_Write16CnCHAR
* 函数功能		   : 在12864上面书写16X16的汉字
* 输    入         : x, y, cn
* 输    出         : 无
* 说    明		   : 该函数可以直接书写字符串,但是书写是从右到左,所以输入的时
*                  * 侯注意输入。汉字的取模方式请观看文件夹下的《汉字取模软件的
*                  * 使用说明》
*******************************************************************************/#ifdef  CHAR_CODE#include"charcode.h"uchar Lcd12864_Write16CnCHAR(uchar x, uchar y, uchar *cn)
{uchar j, x1, x2, wordNum;//--Y的坐标只能从0到7,大于则直接返回--//if(y > 7){return 0;}//--X的坐标只能从0到128,大于则直接返回--//if(x > 128){return 0;}y += 0xB0;	   //求取Y坐标的值//--设置Y坐标--//LcdSt7565_WriteCmd(y);while ( *cn != '\0')	 //在C语言中字符串结束以‘\0’结尾{	//--设置Y坐标--//LcdSt7565_WriteCmd(y);x1 = (x >> 4) & 0x0F;   //由于X坐标要两句命令,分高低4位,所以这里先取出高4位x2 = x & 0x0F;          //去低四位//--设置X坐标--//LcdSt7565_WriteCmd(0x10 + x1);   //高4位LcdSt7565_WriteCmd(0x04 + x2);	//低4位for (wordNum=0; wordNum<50; wordNum++){//--查询要写的字在字库中的位置--//if ((CN16CHAR[wordNum].Index[0] == *cn)&&(CN16CHAR[wordNum].Index[1] == *(cn+1))){for (j=0; j<32; j++) //写一个字{		if (j == 16)	 //由于16X16用到两个Y坐标,当大于等于16时,切换坐标{//--设置Y坐标--//LcdSt7565_WriteCmd(y + 1);//--设置X坐标--//LcdSt7565_WriteCmd(0x10 + x1);   //高4位LcdSt7565_WriteCmd(0x04 + x2);	//低4位}LcdSt7565_WriteData(CN16CHAR[wordNum].Msk[j]);}x += 16;}//if查到字结束		} //for查字结束	cn += 2;}	//while结束return 1;
}#endif

main.c

#include<reg51.h>
#include"st7565.h"//---声明一个全局变量---//
void Delay10ms(unsigned int c);/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/void main()
{uchar i = 128;Lcd12864_Init();Lcd12864_ClearScreen();while (1){for (i=0; i<2; i += 2){Lcd12864_ClearScreen();//--由于这个函数显示方向正好相反--//Lcd12864_Write16CnCHAR(32, i, "钟时子电气天");Delay10ms(100);}}
}/*******************************************************************************
* 函 数 名         : Delay10ms
* 函数功能		   : 延时函数,延时10ms
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/void Delay10ms(unsigned int c)   //误差 0us
{unsigned char a,b;for(;c>0;c--)for(b=38;b>0;b--)for(a=130;a>0;a--);
}

2.3显示效果图

在这里插入图片描述

3.OLED(IIC)

3.1简介

OLED显示和传统的LCD显示不同,其可以自发光,所以不需要背光灯,这使得OLED显示屏相对于LCD显示屏尺寸更薄,同时显示效果更优。 常用的OLED屏幕有蓝色、黄色、白色等几种。屏的大小为0.96寸,像素点为 128*64,所以我们称为0.96oled屏或者12864屏。电源电压为3.3-5.5V,驱动芯片为SSD1306

硬件连接
GND-------OLED模块电源地
VCC-------OLED模块电源正极(3.3V/5V)
SCL--------IIC总线时钟信号,P0.2
SDA--------IIC总线数据信号,P0.3

3.2代码

oled.h

#ifndef __OLED_H
#define __OLED_H
#include <reg52.h>#define  u8 unsigned char 
#define  u16 unsigned int
#define  u32 unsigned int#define OLED_CMD  0	//写命令
#define OLED_DATA 1	//写数据sbit OLED_SCL=P0^2;//SCL
sbit OLED_SDA=P0^3;//SDA
sbit OLED_RES =P0^4;//RES//-----------------OLED端口定义----------------#define OLED_SCL_Clr() OLED_SCL=0
#define OLED_SCL_Set() OLED_SCL=1#define OLED_SDA_Clr() OLED_SDA=0
#define OLED_SDA_Set() OLED_SDA=1#define OLED_RES_Clr() OLED_RES=0
#define OLED_RES_Set() OLED_RES=1//OLED控制用函数
void delay_ms(unsigned int ms);
void OLED_ColorTurn(u8 i);
void OLED_DisplayTurn(u8 i);
void OLED_WR_Byte(u8 dat,u8 cmd);
void OLED_Set_Pos(u8 x, u8 y);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Clear(void);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey);
u32 oled_pow(u8 m,u8 n);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey);
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 sizey);
void OLED_ShowChinese(u8 x,u8 y,u8 no,u8 sizey);
void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,u8 BMP[]);
void OLED_Init(void);#endif 

oled.c

#include "oled.h"
#include "oledfont.h"  	 //OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127	
//[1]0 1 2 3 ... 127	
//[2]0 1 2 3 ... 127	
//[3]0 1 2 3 ... 127	
//[4]0 1 2 3 ... 127	
//[5]0 1 2 3 ... 127	
//[6]0 1 2 3 ... 127	
//[7]0 1 2 3 ... 127 			   
void delay_ms(unsigned int ms)
{                         unsigned int a;while(ms){a=1800;while(a--);ms--;}return;
}//反显函数
void OLED_ColorTurn(u8 i)
{if(i==0){OLED_WR_Byte(0xA6,OLED_CMD);//正常显示}if(i==1){OLED_WR_Byte(0xA7,OLED_CMD);//反色显示}
}//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{if(i==0){OLED_WR_Byte(0xC8,OLED_CMD);//正常显示OLED_WR_Byte(0xA1,OLED_CMD);}if(i==1){OLED_WR_Byte(0xC0,OLED_CMD);//反转显示OLED_WR_Byte(0xA0,OLED_CMD);}
}//起始信号
void I2C_Start(void)
{OLED_SDA_Set();OLED_SCL_Set();OLED_SDA_Clr();OLED_SCL_Clr();}//结束信号
void I2C_Stop(void)
{OLED_SDA_Clr();OLED_SCL_Set();OLED_SDA_Set();
}//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{OLED_SDA_Set();OLED_SCL_Set();OLED_SCL_Clr();}//写入一个字节
void Send_Byte(u8 dat)
{u8 i;for(i=0;i<8;i++){OLED_SCL_Clr();//将时钟信号设置为低电平if(dat&0x80)//将dat的8位从最高位依次写入{OLED_SDA_Set();}else{OLED_SDA_Clr();}OLED_SCL_Set();OLED_SCL_Clr();dat<<=1;}
}//发送一个字节
//向SSD1306写入一个字节。
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{I2C_Start();Send_Byte(0x78);I2C_WaitAck();if(mode){Send_Byte(0x40);}else{Send_Byte(0x00);}I2C_WaitAck();Send_Byte(dat);I2C_WaitAck();I2C_Stop();
}//坐标设置void OLED_Set_Pos(u8 x, u8 y) 
{ OLED_WR_Byte(0xb0+y,OLED_CMD);OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);OLED_WR_Byte((x&0x0f),OLED_CMD);
}   	  
//开启OLED显示    
void OLED_Display_On(void)
{OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ONOLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示     
void OLED_Display_Off(void)
{OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFFOLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
}		   			 
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
void OLED_Clear(void)  
{  u8 i,n;		    for(i=0;i<8;i++)  {  OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA); } //更新显示
}//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63				 
//sizey:选择字体 6x8  8x16
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 sizey)
{      	u8 c=0,sizex=sizey/2;u16 i=0,size1;if(sizey==8)size1=6;else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2);c=chr-' ';//得到偏移后的值OLED_Set_Pos(x,y);for(i=0;i<size1;i++){if(i%sizex==0&&sizey!=8) OLED_Set_Pos(x,y++);if(sizey==8) OLED_WR_Byte(asc2_0806[c][i],OLED_DATA);//6X8字号else if(sizey==16) OLED_WR_Byte(asc2_1608[c][i],OLED_DATA);//8x16字号
//		else if(sizey==xx) OLED_WR_Byte(asc2_xxxx[c][i],OLED_DATA);//用户添加字号else return;}
}
//m^n函数
u32 oled_pow(u8 m,u8 n)
{u32 result=1;	 while(n--)result*=m;    return result;
}				  
//显示数字
//x,y :起点坐标
//num:要显示的数字
//len :数字的位数
//sizey:字体大小		  
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 sizey)
{         	u8 t,temp,m=0;u8 enshow=0;if(sizey==8)m=2;for(t=0;t<len;t++){temp=(num/oled_pow(10,len-t-1))%10;if(enshow==0&&t<(len-1)){if(temp==0){OLED_ShowChar(x+(sizey/2+m)*t,y,' ',sizey);continue;}else enshow=1;}OLED_ShowChar(x+(sizey/2+m)*t,y,temp+'0',sizey);}
}
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 sizey)
{u8 j=0;while (chr[j]!='\0'){		OLED_ShowChar(x,y,chr[j++],sizey);if(sizey==8)x+=6;else x+=sizey/2;}
}
//显示汉字
void OLED_ShowChinese(u8 x,u8 y,u8 no,u8 sizey)
{u16 i,size1=(sizey/8+((sizey%8)?1:0))*sizey;for(i=0;i<size1;i++){if(i%sizey==0) OLED_Set_Pos(x,y++);if(sizey==16) OLED_WR_Byte(Hzk[no][i],OLED_DATA);//16x16字号
//		else if(sizey==xx) OLED_WR_Byte(xxx[c][i],OLED_DATA);//用户添加字号else return;}				
}//显示图片
//x,y显示坐标
//sizex,sizey,图片长宽
//BMP:要显示的图片
void OLED_DrawBMP(u8 x,u8 y,u8 sizex, u8 sizey,u8 BMP[])
{ 	u16 j=0;u8 i,m;sizey=sizey/8+((sizey%8)?1:0);for(i=0;i<sizey;i++){OLED_Set_Pos(x,i+y);for(m=0;m<sizex;m++){      OLED_WR_Byte(BMP[j++],OLED_DATA);	    	}}
} //初始化				    
void OLED_Init(void)
{OLED_RES_Clr();delay_ms(200);OLED_RES_Set();OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panelOLED_WR_Byte(0x00,OLED_CMD);//---set low column addressOLED_WR_Byte(0x10,OLED_CMD);//---set high column addressOLED_WR_Byte(0x40,OLED_CMD);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control registerOLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current BrightnessOLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常OLED_WR_Byte(0xA6,OLED_CMD);//--set normal displayOLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 dutyOLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)OLED_WR_Byte(0x00,OLED_CMD);//-not offsetOLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequencyOLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/SecOLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge periodOLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configurationOLED_WR_Byte(0x12,OLED_CMD);OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomhOLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect LevelOLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)OLED_WR_Byte(0x02,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disableOLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disableOLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7) OLED_Clear();OLED_WR_Byte(0xAF,OLED_CMD); /*display ON*/ 
}

main.c

#include <reg52.h>
#include "oled.h"int main(void)
{	u8 t=' ';OLED_Init();//初始化OLEDOLED_ColorTurn(0);//0正常显示,1 反色显示OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示while(1) {		OLED_ShowChinese(18,0,0,16);//OLED_ShowChinese(36,0,1,16);//OLED_ShowChinese(54,0,2,16);//OLED_ShowChinese(72,0,3,16);//OLED_ShowChinese(90,0,4,16);//OLED_ShowChinese(108,0,5,16);//OLED_ShowString(20,4,"2024/06/06",16);}
}

3.3显示效果图

在这里插入图片描述

4.下载链接

51驱动LCD

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/23832.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytest构建和测试FastAPI CURD API

文章目录 概述目标FASTAPI 介绍CRUD API 项目设置freezepipreqs 代码介绍run APIpytest测试F&Q1.执行uvicorn app.main:app --host localhost --port 8000 --reload 报错 zsh: /usr/local/bin/uvicorn: bad interpreter2.生成requirement.txt时&#xff0c;pip3 list pipre…

Frida 学习之 messages

目录 一、消息发送 二、环境准备 三、从目标进程中发消息 四、在目标进程中接收消息 五、在目标进程中以阻塞方式接收消息 官方链接&#xff1a;Messages | Frida • A world-class dynamic instrumentation toolkit 参考链接&#xff1a;Frida官方手册 - 消息发送_frida…

C语言 RTC时间(年月日时分秒) 和 时间戳 互相转换

一、介绍 在C语言中&#xff0c;将年月日时分秒转换为时间戳&#xff08;Unix时间戳&#xff0c;即从1970年1月1日00:00:00 UTC到现在的秒数&#xff09;通常需要使用struct tm结构体和timegm或mktime函数。&#xff08;注意&#xff0c;mktime函数假设struct tm是本地时间&…

Python语法详解module4(函数)

目录 一、函数基础1. 函数的概念和作用2. 函数的定义和调用3. 参数传递 二、返回值和文档字符串返回值的概念和用法1. 返回值的概念2. 使用 return 关键字返回值&#xff1a;3. 多个返回值的情况&#xff1a; 文档字符串&#xff08;docstring&#xff09;的作用和使用方法1. 文…

大坝安全监测自动化技术的规范化设计准则

大坝安全监测自动化技术的规范化设计准则 一、施工阶段自动化系统设计要点 在施工阶段&#xff0c;大坝安全监测自动化系统的设计应当涵盖以下几个核心内容&#xff1a; 监测仪器的布局规划及详细的施工图纸设计。 配套土建项目以及防雷设施的施工设计规划。 明确施工过程中的技…

Jenkins工作流程原理

持续集成&#xff1a;自动部署打包发布代码 Jenkins工作流程 项目已经基于Jenkins实现了持续集成&#xff0c;每当我们push代码时&#xff0c;就会触发项目完成自动编译和打包。而需要运行某个微服务时&#xff0c;我们只需要经过两步&#xff1a; 第一步&#xff0c;访问je…

win10下,python3.7安装xlrd和xlwt

win10下&#xff0c;执行import xlwt&#xff0c;结果报错 No module named xlwt。 原因&#xff1a;使用的python没有安装xlwt包。 解决方法&#xff1a; 1&#xff09;打开一个命令窗口&#xff0c;执行&#xff1a;where python&#xff0c;可以看到使用的python路径及版…

2024年SQL Editor趋势

SQL Editor已经超越了仅仅执行查询的传统角色&#xff0c;成为提升生产力、协作和数据管理的综合平台。这一演变反映了QA软件测试人员和开发人员日益增长的需求和复杂需求。让我们深入探讨当前的趋势&#xff0c;强调这些变化如何满足用户的基本需求。 1.增强的协作功能 现代S…

Questflow借助MongoDB Atlas以AI重新定义未来工作方式

MongoDB客户案例导读 Questflow借助MongoDB Atlas赋能AI员工&#xff0c;助力中小型初创企业自动化工作流程&#xff0c;简化数据分析&#xff0c;提升客户体验&#xff0c;推动AI与员工的协作&#xff0c;重新定义未来工作方式。 协作式AI自动化平台 无需编码即可拥有自己的…

动态规划(多重背包问题+二进制优化)

引言 多重背包&#xff0c;相对于01背包来说&#xff0c;多重背包是每个物品会有相应的个数&#xff0c;最多可以选那么多个&#xff0c;因而对于朴素多重背包&#xff0c;需要在01背包的基础上&#xff0c;再加一层物品的循环 朴素多重背包例题 P2347 [NOIP1996 提高组] 砝…

【因果推断python】19_局部平均效应2

目录 局部平均干预效果&#xff1a;后期 对参与度的影响 关键思想 局部平均干预效果&#xff1a;后期 局部平均处理效应明确了我们可以估计因果效应的人群。这也是查看 IV 的另一种方式&#xff0c;它提供了我们可以使用的其他很酷的直觉。在现代 IV 中&#xff0c;我们将工…

Codeforces Round 951 (Div. 2) C、D(构造、线段树)

1979C - Earning on Bets 构造题&#xff1a;观察到k范围很小&#xff0c;首先考虑最终硬币总数可以是多少&#xff0c;我们可以先假设最终的硬币总数为所有k取值的最小公倍数&#xff0c;这样只需要满足每个结果添加1枚硬币即可赚到硬币。 // Problem: C. Earning on Bets //…

《Kubernetes部署篇:基于Kylin V10+ARM64架构CPU+containerd一键离线部署容器版K8S1.26.15高可用集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;企业级K8s集群运维实战 一、部署背景 由于业务系统的特殊性&#xff0c;我们需要针对不同的客户环境部署基于containerd容器版 K8S 1.26.15集群&…

备份和恢复realme智能手机:综合指南

realme自2018年成立至今&#xff0c;一直秉持着“敢于超越”的品牌精神&#xff0c;专注于为全球年轻用户提供性能卓越、设计新颖的高品质手机。对于如何备份和恢复realme手机&#xff0c;本文将介绍多种不同的方法。 第1部分&#xff1a;使用Coolmuster Android Backup Mana…

用 OpenCV 实现图像中水平线检测与校正

前言 在本文中&#xff0c;我们将探讨如何使用 Python 和 OpenCV 库来检测图像中的水平线&#xff0c;并对图像进行旋转校正以使这些线条水平。这种技术可广泛应用于文档扫描、建筑摄影校正以及机器视觉中的各种场景。 环境准备 首先&#xff0c;确保您的环境中安装了 OpenC…

【RAG提升技巧】查询改写HyDE

简介 提高 RAG 推理能力的一个好方法是添加查询理解层 ——在实际查询向量存储之前添加查询转换。以下是四种不同的查询转换&#xff1a; 路由&#xff1a;保留初始查询&#xff0c;同时查明其所属的适当工具子集。然后&#xff0c;将这些工具指定为合适的选项。查询重写&…

随身WIFI修改MAC(bssid)并接收短信

将SIM卡插入随身WiFi卡槽 将随身WIFI插入电脑 打开 http://ufi.icewifi.com &#xff0c;输入设备IMEI &#xff08;或直接扫描设备包装盒上的二维码&#xff09; 点击“确认” 登录到设备主页&#xff08;网址可收藏保存&#xff09; 点击“WIFI配置”按钮&#xff0c;输入想…

C#——枚举类型详情

枚举类型 枚举类型&#xff08;也可以称为“枚举器”&#xff09;由一组具有独立标识符&#xff08;名称&#xff09;的整数类型常量构成&#xff0c;在 C# 中枚举类型不仅可以在类或结构体的内部声明&#xff0c;也可以在类或结构体的外部声明&#xff0c;默认情况下枚举类型…

【Python报错】已解决AttributeError: Nonetype Object Has NoAttribute Group

解决Python报错&#xff1a;AttributeError: ‘list’ object has no attribute ‘get’ 在Python中&#xff0c;AttributeError通常表示你试图访问的对象没有你请求的属性或方法。如果你遇到了AttributeError: list object has no attribute get的错误&#xff0c;这通常意味着…

【NoSQL数据库】Redis——哨兵模式

Redis——哨兵模式 Redis哨兵 Redis——哨兵模式1.什么是哨兵机制&#xff08;Redis Sentinel&#xff09;1.1 哨兵的作用 2.哨兵的运行机制3.故障处理redis常见问题汇总1、redis缓存击穿是什么&#xff1f;如何解决&#xff1f;2、redis缓存穿透是什么&#xff1f;如何解决&am…