STC90C51驱动LCD1602、LCD12864、OLED

news2024/12/25 0:27:33

主控芯片(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);  //写一个指针加1
	LcdWriteCom(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); 
            else
               LcdWriteCom(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);  //reset
	for (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 set
	LcdSt7565_WriteCmd(0x01);  //x4
	
	//--表格第18个命令,这个是个双字节命令,高字节为0X81,低字节可以--//
	//--选择从0x00到0X3F。用来设置背景光对比度。---/
	LcdSt7565_WriteCmd(0x81);  //V0 a set
	LcdSt7565_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 on
	for (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 ON
	OLED_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 OFF
	OLED_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 panel
	OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
	OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
	OLED_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 register
	OLED_WR_Byte(0xCF,OLED_CMD); // Set SEG Output Current Brightness
	OLED_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 display
	OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
	OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
	OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset	Shift Mapping RAM Counter (0x00~0x3F)
	OLED_WR_Byte(0x00,OLED_CMD);//-not offset
	OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
	OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
	OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
	OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
	OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
	OLED_WR_Byte(0x12,OLED_CMD);
	OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
	OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
	OLED_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/disable
	OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
	OLED_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();//初始化OLED
	OLED_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.coloradmin.cn/o/1793682.html

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

相关文章

线性dp+数论分块,1561D1 - Up the Strip

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1561D1 - Up the Strip (simplified version) 二、解题报告 1、思路分析 一眼dp 写出dp方程&#xff1a; 前者维护前缀和即可O(1)转移 后者呢&#xff1f;——整除分块数论分块问题-CSDN博客 简单叙述下…

Mongodb的数据库简介、docker部署、操作语句以及java应用

Mongodb的数据库简介、docker部署、操作语句以及java应用 本文主要介绍了mongodb的基础概念和特点&#xff0c;以及基于docker的mongodb部署方法&#xff0c;最后介绍了mongodb的常用数据库操作语句&#xff08;增删改查等&#xff09;以及java下的常用语句。 一、基础概念 …

Technart电动螺丝刀TN101控制器维修

Technart电动螺丝刀以其高效、稳定和精确的扭矩控制而闻名。然而&#xff0c;即使优质的产品&#xff0c;在长时间的使用下&#xff0c;也可能会出现TECHNART电动螺母扳手控制器故障。 常见故障及维修方法 1. 控制器不工作 症状&#xff1a;电动螺丝刀无法启动&#xff0c;或启…

sql注入-布尔盲注

布尔盲注&#xff08;Boolean Blind SQL Injection&#xff09;是一种SQL注入攻击技术&#xff0c;用于在无法直接获得查询结果的情况下推断数据库信息&#xff1b;它通过发送不同的SQL查询来观察应用程序的响应&#xff0c;进而判断查询的真假&#xff0c;并逐步推断出有用的信…

数据库与数据库管理系统 MySQL的安装 SQL语言学习:DDL、DML

day51 数据库 数据库&#xff08;database&#xff09;就是一个存储数据的仓库。为了方便数据的存储和管理&#xff0c;它将数据按照特定的规律存储在磁盘上。 通过数据库管理系统&#xff0c;可以有效地组织和管理存储在数据库中的数据&#xff0c;如数据库管理系统MySQL 数据…

HSC Mailinspector loader.php 任意文件读取漏洞复现(CVE-2024-34470)

0x01 产品简介 HSC Mailinspector是一款远程电子邮件检查工具&#xff0c;支持POP3/IMAP4协议。它允许用户远程扫描最新邮件&#xff0c;并进行浏览、垃圾邮件排除、编辑、删除等操作&#xff0c;无需实际登录邮箱。 0x02 漏洞概述 由于HSC Mailinspector /public/loader.ph…

XM平台的交易模式模式是什么?

外汇交易平台的盈利模式主要分为两种&#xff1a;有交易员平台和无交易员平台。 有交易员平台&#xff0c;也称为做市商平台&#xff0c;为客户提供交易市场&#xff0c;并在需要时与客户持相反方向的交易&#xff0c;从中赚取利润。交易者看到的买入卖出价可能与实际价格不同&…

activiti用法随记

案例&#xff1a; 摘抄于官网&#xff0c;假设我们有如下流程&#xff1a; 流程对应的bpmn文件如下&#xff1a; <definitions xmlns:activiti"http://activiti.org/bpmn" xmlns:bpmndi"http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc&quo…

Java--方法的定义和调用

1.Java的方法类似于其他语言的函数&#xff0c;是一段用来用来完成特定功能的代码片段&#xff0c;一般情况下&#xff0c;定义一个方法包含以下语法&#xff1a; 1.方法包含一个方法头和方法体&#xff0c;。下面是一个方法的所有部分&#xff1a; 1.修饰符&#xff1a;修饰符…

重生奇迹mu战士技能石头在哪打

战士技能石头是靠打怪物&#xff0c;从它们身上掉下来而获得的&#xff0c;战士的技能石头分几种&#xff0c;每种都分布在不同的地方&#xff1a; 1、袭风刺技能石头可以到沙漠之地&#xff0c;通过打尖嘴猪获得。 2、雷霆裂闪技能石头可以到沙漠之地通过打黑暗大师或者破坏…

如何防止线上事故?从一次流水号重复引发的故障说起

最近我负责的系统出了一次生产事故&#xff0c;这次事故竟然是因为流水号重复导致的。今天来给大家分享一下。 1.问题背景 这个流水号的使用场景是上游系统调用下游接口时传入一个唯一 ID&#xff0c;流水号这个参数在联调或定位问题时很方便。 我们系统中的流水号是一个 32…

React权限管理系统实现

目录 一、需求 二、逻辑 三、实现 &#xff08;一&#xff09;代码 &#xff08;二&#xff09;解释 1. 获取权限对照数组 (queryReferencePermissionsInfo) 2. 获取处理对照数组 (queryDisposePermissionsInfo) 3. 获取权限映射表信息并处理 (queryPermissionsInfo) 4…

awdawdawd

c语言中的小小白-CSDN博客c语言中的小小白关注算法,c,c语言,贪心算法,链表,mysql,动态规划,后端,线性回归,数据结构,排序算法领域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 给大家分享一句我很喜欢我话&#xff1a; 知不足而奋进&#xff0c;望远山而前行&am…

2024-06-05-记一次cnvd渗透

前言&#xff1a;挖src挖郁闷了&#xff0c;闲来无事选择挖一个cnvd来练练手&#xff0c;本次的漏洞都没啥难度&#xff0c;企查查资产过了5000万 说一下cnvd证书的下放标准 对于中危及中危以上通用型漏洞&#xff08;CVSS2.0基准评分超过4.0分&#xff09;&#xff0c;以及涉…

eclipse添加maven插件

打开eclipse菜单 Help/Install New SoftwareWork with下拉菜单选择 2022-03 - https://download.eclipse.org/releases/2022-03‘type filter text’搜索框中输入 maven选择 M2E - Maven Integration for Eclipse一路next安装&#xff0c;重启eclipseImport项目时&#xff0c;就…

国外视频流量密码!我想要好好的,不要废掉我——早读(逆天打工人爬取热门微信文章解读)

耐心点好吗&#xff1f; 引言Python 代码第一篇 洞见 废掉一个人最隐蔽的方式&#xff1a;陷于底层习惯第二篇 视频信息差结尾 引言 戒骄戒躁 昨天晚上在沙发上睡着了 原因是身体不想睡 神想睡 于是身体躺在沙发上 神就睡着 早上早早就起来 差一点感冒 不过身体在冷水浴 还有呼…

Mac下载Homebrew

通过command空格搜索终端打开 直接输入 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" 然后输入电脑密码 然后直接回车等待安装完成 注意⚠️&#xff1a;如果出现报错/opt/homebrew/bin is not in your PATH…

LW-DETR:实时目标检测的Transformer, Apache-2.0 开源可商用,实验超 YOLOv8

LW-DETR&#xff1a;实时目标检测的Transformer&#xff0c; Apache-2.0 开源可商用&#xff0c;实验超 YOLOv8 LW-DETR 架构实例化高效训练高效推理 目的与解法拆解ViT编码器和DETR解码器多级特征图聚合变形交叉注意力窗口注意力和全局注意力 论文&#xff1a;https://arxiv.o…

Vue3实战笔记(57)—一键换肤:在Vuetify中打造个性化主题切换体验

文章目录 前言一键换肤总结 前言 在当今追求极致用户体验的时代&#xff0c;为应用程序提供个性化的主题切换功能已经成为提升用户满意度和留存率的关键因素之一。Vuetify&#xff0c;作为基于Vue.js的流行前端框架&#xff0c;以其丰富的组件库和高度可定制性&#xff0c;为开…

数字影像产业园的三大赋能:科技、创新与无限可能

数字影像产业园作为文创产业的重要载体&#xff0c;以科技为核心驱动力&#xff0c;不断推动产业的技术革新和升级。 园区内汇聚了最前沿的数字技术资源&#xff0c;高清摄影设备、虚拟现实技术、人工智能应用等尖端科技在这里得到广泛应用&#xff0c;不仅提升了生产效率&…