目录

LCD1602

LCD1602引脚

LCD1602显示字符

写时序图和读时序图

 写时序图

检测忙标志是否忙

LCD1602初始化

在哪里显示,写入指令(地址)

显示什么字符(写入数据)

DTH11

 DTH11的通讯过程

获取空气中温湿度并发送到串口

DTH11获取空气中温湿度,数据在LCD1602显示 

4针OLED(IIC协议)

IIC协议

IIC特点

IIC构成 

IIC传输数据过程的三种信号

IIC发送一个字节数据

OLED屏

OLED写入指令或数据

OLED的寻址模式(在OLED上哪里显示字符)

OLED初始化

OLED显示一个点

OLED显示一个字母

OLED显示自己的名字

DTH11获取空气中温湿度,在OLED上显示

LCD1602

LCD1602引脚

  • 第 : VSS 为电源地
  • 第 : VDD 接 5V 正电源
  • 第 : VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度
  • 过高时会产生鬼影,使用时可以通过一个 10K 的电位器调整对比度。
  • 第 RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
  • 第 R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W 共 同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信号, 当 RS 为高电平 R/W 为低电平时可以写入数据。
  • 第 端为使能端,当 端由高电平跳变成低电平时,液晶模块执行命令。
  • 第 714 D0D7 为 位双向数据线。
  • 第 15 :背光源正极。
  • 第 16 :背光源负极。

LCD1602显示字符

写时序图和读时序图

读时序图

 写时序图

时序图的参数 

检测忙标志是否忙

  • 液晶显示模块是一个慢显示器件,所以在写入每条指令或数据之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。
  • 由于BF标志位为数据线的D7引脚,我们只关心D7引脚,而且BF标志位为高电平时,LCD1602表示忙,可以利用一个while(BF)循环卡住,然后不断读取数据线的D7引脚,等待LCD1602不忙时,硬件将BF标志位置0。
  • 读取LCD1602的数据,检测忙信号

LCD1602初始化

8bit的LCD1602初始化

  1. 延时 15ms
  2. 写指令 38H(不检测忙信号)
  3. 延时 5ms
  4. 检测忙信号
  5. 写指令 38H:显示模式设置
  6. 写指令 08H:显示关闭
  7. 写指令 01H:显示清屏
  8. 写指令 06H:显示光标移动设置
  9. 写指令 0CH:显示开及光标设置

4bit的LCD1602初始化

  1. 延时 50ms
  2. 发送 0x03(4bit)(rs=0,rw=0)
  3. 延时 4.5ms
  4. 发送 0x03(4bit)(rs=0,rw=0)
  5. 延时 4.5ms
  6. 发送 0x03(4bit)(rs=0,rw=0)
  7. 延时 150μs
  8. 发送 0x02(4bit)(rs=0,rw=0)
  9. 写指令 28H(8bit)
  10. 写指令 0CH(8bit)
  11. 写指令 01H(8bit)
  12. 延时 2ms(8bit)
  13. 写指令 06H(8bit) 

在哪里显示,写入指令(地址)

LCD1602 内部显示地址

由于写入指令或数据的时候,数据线D7恒定为高电平,即如果想要在0x40显示字符,则实际写入的地址为0x40 + 0x80。

写入指令(地址)

显示什么字符(写入数据)

LCD1602 模块字库表

由于字符A的ASCII码为65,即0100 0001,与LCD1602 模块字库表一致,因此在写入字符的时候,直接传入一个'A'即可。

写入数据(地址)

 LCD1602显示一个字符

#include "reg52.h"
#include <intrins.h>
 
#define dataBuf P0
 
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;
 
void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 9;
	j = 244;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay15ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 27;
	j = 226;
	do
	{
		while (--j);
	} while (--i);
}
 
//检测忙信号,读数据线的D7位
void checkBusySignal()
{
	char tmp = 0x80;
	dataBuf = 0x80;
	while(tmp & 0x80){  //当忙标志位(数据位D7)为高电平时,此时模块不能接收命令或者数据
		//根据读时序图,读LCD1602的数据
        RS = 0;
		RW = 1;
		EN = 0;
		_nop_();
		EN = 1;
		_nop_();
		_nop_();
		tmp = dataBuf;  //读八位数据线的数据,当不忙时,硬件会自动将该位置0,当检测到D7为低电平时将退出死循环
		EN = 0;
		_nop_();
	} 
}
 
//写指令
void writeCmd(char cmd)
{
	checkBusySignal();
	RS = 0;  //选择写指令寄存器
	RW = 0;
	EN = 0;
	_nop_();  //该函数为延时函数,延时一微秒
	dataBuf = cmd;  //将指令存入八位数据线中
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}
 
//写数据
void writeData(char myData)
{
	checkBusySignal();
	RS = 1;  //选择写数据寄存器
	RW = 0;
	EN = 0;
	_nop_();  //该函数为延时函数,延时一微秒
	dataBuf = myData;  //将数据存入八位数据线中
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}
 
//LCD1602初始化
void lcd1602Init()
{
	Delay15ms();  //延时 15ms
	writeCmd(0x38);  //写指令 38H(不检测忙信号) 
	Delay5ms();  //延时 5ms
	checkBusySignal();//以后每次写指令,读/写数据操作均需要检测忙信号
	writeCmd(0x38);  //写指令 38H:显示模式设置
	writeCmd(0x08);  //写指令 08H:显示关闭
	writeCmd(0x01);  //写指令 01H:显示清屏
	writeCmd(0x06);  //写指令 06H:显示光标移动设置
	writeCmd(0x0C);  //写指令 0CH:显示开及光标设置
}
 
void main()
{
	char displayAddress = 0x80 + 0x05;  
	char dsiplayData = 'J';  
 
	lcd1602Init();
 
	writeCmd(displayAddress);  //字符显示的地址
	writeData(dsiplayData);  //显示的字符
}



 LCD1602显示一行字符

#include "reg52.h"
#include <intrins.h>
 
#define dataBuf P0
 
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;
 
void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 9;
	j = 244;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay15ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 27;
	j = 226;
	do
	{
		while (--j);
	} while (--i);
}
 
//检测忙信号,读数据线的D7位
void checkBusySignal()
{
	char tmp = 0x80;
	dataBuf = 0x80;
	while(tmp & 0x80){  //当忙标志位(数据位D7)为高电平时,此时模块不能接收命令或者数据
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_();
		EN = 1;
		_nop_();
		_nop_();
		tmp = dataBuf;  //读八位数据线的数据,当不忙时,硬件会自动将该位置0,当检测到D7为低电平时将退出死循环
		EN = 0;
		_nop_();
	} 
}
 
//写指令
void writeCmd(char cmd)
{
	checkBusySignal();
	RS = 0;  //选择写指令寄存器
	RW = 0;
	EN = 0;
	_nop_();  //该函数为延时函数,延时一微秒
	dataBuf = cmd;  //将指令存入八位数据线中
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}
 
//写数据
void writeData(char myData)
{
	checkBusySignal();
	RS = 1;  //选择写数据寄存器
	RW = 0;
	EN = 0;
	_nop_();  //该函数为延时函数,延时一微秒
	dataBuf = myData;  //将数据存入八位数据线中
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}
 
//LCD1602初始化
void lcd1602Init()
{
	Delay15ms();  //延时 15ms
	writeCmd(0x38);  //写指令 38H(不检测忙信号) 
	Delay5ms();  //延时 5ms
	checkBusySignal();//以后每次写指令,读/写数据操作均需要检测忙信号
	writeCmd(0x38);  //写指令 38H:显示模式设置
	writeCmd(0x08);  //写指令 08H:显示关闭
	writeCmd(0x01);  //写指令 01H:显示清屏
	writeCmd(0x06);  //写指令 06H:显示光标移动设置
	writeCmd(0x0C);  //写指令 0CH:显示开及光标设置
}
 
//LCD1602显示一行字符
void lcd1602ShowData(char rows,char columns,char *str)
{
	switch (rows){  //选择行
	case 1:
		writeCmd(0x80 + columns-1);  //选择列
		while(*str != '\0'){
			writeData(*str);  //显示字符
			str++;
		}
		break;
 
	case 2:
		writeCmd(0x80 + 0x40 +columns-1);  //选择列
		while(*str != '\0'){
			writeData(*str);  //显示字符
			str++;
		}
		break;
 
	default:
		break;
	}
}
 
void main()
{
	lcd1602Init();
	lcd1602ShowData(1,1,"jiangxiaoya");
	lcd1602ShowData(2,1,"hao  zi  ge");
}



DTH11

DTH11用来实时检测空气中温湿度,一次完整的数据为40bit,即5个字符

 DTH11的通讯过程

用户发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集, 用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集, 如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。

时序图如下:

 将通讯过程拆分成3个过程,配置DTH11输出数据、输出数据0、输出数据1

  • 配置DTH11输出数据

     
  • 输出数据0

     
  • 输出数据1

获取空气中温湿度并发送到串口

 
#include "reg52.h"
#include <intrins.h>
#include <string.h>
 
sfr AUXR = 0x8e;
 
sbit dht11 = P1^2;
 
char dht11Data[5];
 
void Delay40us()		//@11.0592MHz
{
	unsigned char i;
 
	_nop_();
	i = 15;
	while (--i);
}
 
void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
 
	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
 
void UartInit(void)		//9600bps@11.0592MHz
{
	PCON &= 0x7F;		//波特率不倍速
	SCON = 0x50;		//8位数据,可变波特率
	AUXR &= 0xBF;		//定时器1时钟为Fosc/12,即12T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//清除定时器1模式位
	TMOD |= 0x20;		//设定定时器1为8位自动重装方式
	TL1 = 0xFD;		//设定定时初值
	TH1 = 0xFD;		//设定定时器重装值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
}
 
 
void sendByte(char myData)
{
	SBUF = myData;
	while(!TI);
	TI = 0;
}
 
void sendString(char *str)
{
	while(*str != '\0'){
		sendByte(*str);
		str++;
	}
}
 
//配置DHT11输出数据
void dht11Start()
{
	dht11 =  1;
	dht11 = 0;
	Delay30ms();
	dht11 = 1;
	while(dht11);  //等待自己拉到低电平
	while(!dht11);  //等待自己拉到高电平
	while(dht11);  //等待自己拉到低电平
}
 
//获取DHT11的数据
void obtainDht11Data()
{
	int i,j;
	char tmp;
	char flag;
	dht11Start();  //开始输出数据
	for (i = 0; i < 5; i++){  //总共获取5个字符(40bit)的数据
		for (j = 0; j < 8; j++){  
			//一次获取一个bit数据
			while(!dht11);  //等待自己拉到高电平
			Delay40us();  //高电平时间为27微秒左右表示0,高电平时间为70微秒左右表示1
			
			if(dht11 == 1){  //40微秒后为高电平即输出1
				while(dht11);
				flag = 1;
			}else{  //40微秒后为低电平即输出0
				flag = 0;
			}
			tmp = tmp << 1;  //由于dht11的数据是高位先出,所以用左移的方式
			tmp = tmp | flag;  //(|1成1,|0不变),即对于前面7个bit,flag都为0,不改变tmp的值
		}
		dht11Data[i] = tmp;
	}
	
 
}
 
//发送数据到串口
void sendDht11Data()
{
	obtainDht11Data();
	sendString("H:");
	//
	sendByte(dht11Data[0]/10 + 0x30);
	sendByte(dht11Data[0]%10 + 0x30);
	sendByte('.');
	sendByte(dht11Data[1]/10 + 0x30);
	sendByte(dht11Data[1]%10 + 0x30);
	sendString("\r\n");
	
	sendString("T:");
	//
	sendByte(dht11Data[2]/10 + 0x30);
	sendByte(dht11Data[2]%10 + 0x30);
	sendByte('.');
	sendByte(dht11Data[3]/10 + 0x30);
	sendByte(dht11Data[3]%10 + 0x30);
	sendString("\r\n");	
}
 
void main()
{
	UartInit();
	//dht11上电后,需要延时1-2s度过不稳定状态
	Delay1000ms();
	Delay1000ms();
	
	//每1s获取空气中的温湿度
	while(1){
		sendDht11Data();
		Delay1000ms();
	}
}
 



DTH11获取空气中温湿度,数据在LCD1602显示 

#include "reg52.h"
#include <intrins.h>
#include <string.h>
 
#define dataBuf P0
 
sfr AUXR = 0x8e;
 
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^2;
sbit dht11 = P1^3;
 
char dht11Data[5];
char temperature[9];
char humidity[9];
 
void Delay40us()		//@11.0592MHz
{
	unsigned char i;
 
	_nop_();
	i = 15;
	while (--i);
}
 
void Delay5ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 9;
	j = 244;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay15ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 27;
	j = 226;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
 
	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
 
//配置DHT11输出数据
void dht11Start()
{
	dht11 =  1;
	dht11 = 0;
	Delay30ms();
	dht11 = 1;
	while(dht11);  //等待自己拉到低电平
	while(!dht11);  //等待自己拉到高电平
	while(dht11);  //等待自己拉到低电平
}
 
//获取DHT11的数据
void obtainDht11Data()
{
	int i,j;
	char tmp;
	char flag;
	dht11Start();  //开始输出数据
	for (i = 0; i < 5; i++){  //总共获取5个字符(40bit)的数据
		for (j = 0; j < 8; j++){  
			//一次获取一个bit数据
			while(!dht11);  //等待自己拉到高电平
			Delay40us();  //高电平时间为27微秒左右表示0,高电平时间为70微秒左右表示1
			
			if(dht11 == 1){  //40微秒后为高电平即输出1
				while(dht11);
				flag = 1;
			}else{  //40微秒后为低电平即输出0
				flag = 0;
			}
			tmp = tmp << 1;  //由于dht11的数据是高位先出,所以用左移的方式
			tmp = tmp | flag;  //(|1成1,|0不变),即对于前面7个bit,flag都为0,不改变tmp的值
		}
		dht11Data[i] = tmp;
	}
	
 
}
 
//发送数据到字符数组,用于LCD1602显示
void sendStrData()
{
	humidity[0] = 'H';
	humidity[1] = ':';
	humidity[2] = dht11Data[0]/10 + 0x30;
	humidity[3] = dht11Data[0]%10 + 0x30;
	humidity[4] = '.';
	humidity[5] = dht11Data[1]/10 + 0x30;
	humidity[6] = dht11Data[1]%10 + 0x30;
	humidity[7] = '%'; 
	humidity[8] = '\0'; 
	temperature[0] = 'T';
	temperature[1] = ':';
	temperature[2] = dht11Data[2]/10 + 0x30;
	temperature[3] = dht11Data[2]%10 + 0x30;
	temperature[4] = '.';
	temperature[5] = dht11Data[3]/10 + 0x30;
	temperature[6] = dht11Data[3]%10 + 0x30;
	temperature[7] = 'C';
	temperature[8] = '\0'; 
}
 
//检测忙信号,读数据线的D7位
void checkBusySignal()
{
	char tmp = 0x80;
	dataBuf = 0x80;
	while(tmp & 0x80){  //当忙标志位(数据位D7)为高电平时,此时模块不能接收命令或者数据
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_();
		EN = 1;
		_nop_();
		_nop_();
		tmp = dataBuf;  //读八位数据线的数据,当不忙时,硬件会自动将该位置0,当检测到D7为低电平时将退出死循环
		EN = 0;
		_nop_();
	} 
}
 
//写指令
void writeCmd(char cmd)
{
	checkBusySignal();
	RS = 0;  //选择写指令寄存器
	RW = 0;
	EN = 0;
	_nop_();  //该函数为延时函数,延时一微秒
	dataBuf = cmd;  //将指令存入八位数据线中
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}
 
//写数据
void writeData(char myData)
{
	checkBusySignal();
	RS = 1;  //选择写数据寄存器
	RW = 0;
	EN = 0;
	_nop_();  //该函数为延时函数,延时一微秒
	dataBuf = myData;  //将数据存入八位数据线中
	EN = 1;
	_nop_();
	_nop_();
	EN = 0;
	_nop_();
}
 
//LCD1602初始化
void lcd1602Init()
{
	Delay15ms();  //延时 15ms
	writeCmd(0x38);  //写指令 38H(不检测忙信号) 
	Delay5ms();  //延时 5ms
	checkBusySignal();//以后每次写指令,读/写数据操作均需要检测忙信号
	writeCmd(0x38);  //写指令 38H:显示模式设置
	writeCmd(0x08);  //写指令 08H:显示关闭
	writeCmd(0x01);  //写指令 01H:显示清屏
	writeCmd(0x06);  //写指令 06H:显示光标移动设置
	writeCmd(0x0C);  //写指令 0CH:显示开及光标设置
}
 
//LCD1602显示一行字符
void lcd1602ShowData(char rows,char columns,char *str)
{
	switch (rows){  //选择行
	case 1:
		writeCmd(0x80 + columns);  //选择列
		while(*str != '\0'){
			writeData(*str);  //显示字符
			str++;
		}
		break;
 
	case 2:
		writeCmd(0x80 + 0x40 +columns);  //选择列
		while(*str != '\0'){
			writeData(*str);  //显示字符
			str++;
		}
		break;
 
	default:
		break;
	}
}
 
void main()
{
	lcd1602Init();
	//dht11上电后,需要延时1-2s度过不稳定状态
	Delay1000ms();
	Delay1000ms();
	
	//每1s获取空气中的温湿度
	while(1){
		obtainDht11Data();  
		sendStrData();
		lcd1602ShowData(2,0,humidity);
		lcd1602ShowData(1,0,temperature);
		Delay1000ms();
	}
}
 



4针OLED(IIC协议)

IIC协议

        IIC全称Inter-Integrated Circuit (集成电路总线),由PHILIPS公司在80年代开发的两线式串行总线,用于连接微控制器及其外围设备。IIC属于半双工同步通信方式。

IIC构成 

        IIC串行总线有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。两条线都接上拉电阻,以确保总线空闲时刻为高电平,其中时钟信号是由主控器件产生。IIC总线支持多设备连接,允许多主机存在,对于并联在一条总线上的每个IIC设备都有唯一的地址(即靠地址来区分每一个IIC设备)。

IIC特点

  • 简单性和有效性:由于接口直接在组件之上,因此IIC总线占用的空间非常小,减少了电路板的空间和芯片管脚的数量,降低了互联成本。总线的长度可高达25英尺,并且能够以10Kbps的最大传输速率支持40个组件
  • 多主控(multimastering):其中任何能够进行发送和接收的设备都可以成为主总线。一个主控能够控制信号的传输和时钟频率。当然,在任何时间点上只能有一个主控。

IIC传输数据过程的三种信号

起始信号:

        当时钟线(SCL)为高平时,数据线(SDA)从高电平跳变到低电平。

时序图

 

终止信号:

        当时钟线(SCL)为高平时,数据线(SDA)从低电平跳变到高电平。

时序图

应答信号:

        主机每发送一个字节(8个bit),就在第9个时钟脉冲期间释放数据线(SDA),由从机反馈一个应答信号。

  • 应答信号(SDA)为低电平时,规定为有效应答位(ACK,简称应答位),表示从机成功地接收了该字节。
  • 应答信号(SDA)为高电平时,规定为非应答位(NACK),一般表示从机接收该字节没有成功。
     

时序图

 

IIC发送一个字节数据

时序图

OLED屏

OLED写入指令或数据

 

OLED的寻址模式(在OLED上哪里显示字符)

OLED显示屏是一个128列*64行的点阵,垂直方向由8个PAGE控制,每个PAGE控制8个点阵。

选择PAGE(在垂直方向的哪个位置显示):

向OLED写入指令0xBx,即b(1011 0xxx),例如选择Page 3时,写入指令0xB3,即b(1011 0011)。 

选择列(在水平方向的哪个位置显示):

向OLED写入指令0x0x和0x1x,即b(0000 xxxx)或b(0001 xxxx),例如选择第1列时,写入指令0x00,即b(0000 0000)和写入指令0x10即b(0001 0000)。 它由第一条指令的低四位和第二条指令的低三位组成七位来控制水平方向的128个点阵,如果选择第64列时,写入指令0x0F,即b(0000 1111)和写入指令0x13即b(0001 0011)。

OLED的三种地址模式

  • 页地址模式
  • 水平地址模式
  • 垂直地址模式

选择寻址模式(在一个PAGE上写满数据后,数据从哪里继续开始): 

向OLED写入指令0x20后,继续写入指令0x0x,即b(0000 00xx),例如选择页寻址时,写入指令0x02,即b(000 0010)。 

OLED初始化

OLED显示一个点

#include "reg52.h"
#include <intrins.h>
 
sbit scl = P1^1;
sbit sda = P1^3; 
 
void Delay5us()		//@11.0592MHz
{
}
 
//IIC起始信号
void IIC_start()
{
	sda = 0;
	scl = 1;
	sda = 1;
	Delay5us();
	sda = 0;
	Delay5us();
	scl = 0;
}
 
//IIC终止信号
void IIC_stop()
{
	scl = 0;
	sda = 0;
	scl = 1;
	Delay5us();
	sda = 1;
	Delay5us();
	sda = 0;
}
 
//IIC的ACK应答信号
char IIC_ack()
{
	char flag;
 
	scl = 0;
	sda = 1;  //在时钟脉冲9期间释放数据线
	Delay5us();  //延时5微秒后,为读取sda数据做准备
 
	scl = 1;  
	Delay5us();  
	flag = sda;  //读取数据线,0为应答
	Delay5us();  
	
	scl = 0;
	Delay5us();
	return flag;
}
 
//IIC发送一个字节
void IIC_sendByte(char myData)
{
	int i;
	for ( i = 0; i < 8; i++){
		//发生数据翻转,选择即将发送的是0还是1
		scl = 0;
		sda = myData & 0x80;  //获取需要发送字节的最高位到SDA
		Delay5us();  //数据建立时间
		
		//开始发送数据
		scl = 1;
		Delay5us();  //数据发送时间
		
		scl = 0;  //发送完毕拉低,等待下1bit数据的传输
		Delay5us();
		
		myData = myData << 1;
	}	
}
 
//OLED写入一条指令
void oledWriteCmd(char writeCmd)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x00);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeCmd);
	IIC_ack();
	IIC_stop();
}
 
//OLED写入一个数据
void oledWriteData(char writeData)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x40);  //写入数据,D/C位为1
	IIC_ack();
	IIC_sendByte(writeData);
	IIC_ack();
	IIC_stop();
}
 
//OLCD初始化
void oledInit()
{
	oledWriteCmd(0xAE);
	oledWriteCmd(0x00);
	oledWriteCmd(0x10);
	oledWriteCmd(0x40);
	oledWriteCmd(0xB0);
	oledWriteCmd(0x81);
	oledWriteCmd(0xFF);
	oledWriteCmd(0xA1);
	oledWriteCmd(0xA6);
	oledWriteCmd(0xA8);
	oledWriteCmd(0x3F);
	oledWriteCmd(0xC8);
	oledWriteCmd(0xD3);
	oledWriteCmd(0x00);
	oledWriteCmd(0xD5);
	oledWriteCmd(0x80);
	oledWriteCmd(0xD8);
	oledWriteCmd(0x05);
	oledWriteCmd(0xD9);
	oledWriteCmd(0xF1);
	oledWriteCmd(0xDA);
	oledWriteCmd(0x12);
	oledWriteCmd(0xDB);
	oledWriteCmd(0x30);
	oledWriteCmd(0x8D);
	oledWriteCmd(0x14);
	oledWriteCmd(0xAF);
}
 
void olceClean()
{
	int i,j;
	for(i=0;i<8;i++){
		oledWriteCmd(0xB0 + i);  //选择PAGE
		//选择PAGE的第0列开始显示
		oledWriteCmd(0x00);  
		oledWriteCmd(0x10);
		for(j = 0;j < 128; j++){
			oledWriteData(0);  //写入字符0
		}
	}
}
 
void main()
{
	oledInit();
	olceClean();  //清屏函数
 
	oledWriteCmd(0x20);  //设置内存
	oledWriteCmd(0x02);  //选择页寻址模式
	
	olceClean();  //清屏函数
	
	//选择行,选择第4行
	oledWriteCmd(0xB3);  
 
	//选择列,选择第一列
	oledWriteCmd(0x00);  
	oledWriteCmd(0x10);  
 
	//显示数据
	oledWriteData(0x08);  //显示一个点
 
	//选择第64列
	oledWriteCmd(0x0F);  
	oledWriteCmd(0x13);
 
	//显示一个点
	oledWriteData(0x08);
	
	while(1);
 
}
 


OLED显示一个字母

用取模软件生成自己想要显示的字符

 代码实现

#include "reg52.h"
#include <intrins.h>
 
sbit scl = P1^1;
sbit sda = P1^3; 
 
void Delay5us()		//@11.0592MHz
{
}
 
//IIC起始信号
void IIC_start()
{
	sda = 0;
	scl = 1;
	sda = 1;
	Delay5us();
	sda = 0;
	Delay5us();
	scl = 0;
}
 
//IIC终止信号
void IIC_stop()
{
	scl = 0;
	sda = 0;
	scl = 1;
	Delay5us();
	sda = 1;
	Delay5us();
	sda = 0;
}
 
//IIC的ACK应答信号
char IIC_ack()
{
	char flag;
 
	scl = 0;
	sda = 1;  //在时钟脉冲9期间释放数据线
	Delay5us();  //延时5微秒后,为读取sda数据做准备
 
	scl = 1;  
	Delay5us();  
	flag = sda;  //读取数据线,0为应答
	Delay5us();  
	
	scl = 0;
	Delay5us();
	return flag;
}
 
//IIC发送一个字节
void IIC_sendByte(char myData)
{
	int i;
	for ( i = 0; i < 8; i++){
		//发生数据翻转,选择即将发送的是0还是1
		scl = 0;
		sda = myData & 0x80;  //获取需要发送字节的最高位到SDA
		Delay5us();  //数据建立时间
		
		//开始发送数据
		scl = 1;
		Delay5us();  //数据发送时间
		
		scl = 0;  //发送完毕拉低,等待下1bit数据的传输
		Delay5us();
		
		myData = myData << 1;
	}	
}
 
//OLED写入一条指令
void oledWriteCmd(char writeCmd)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x00);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeCmd);
	IIC_ack();
	IIC_stop();
}
 
//OLED写入一个数据
void oledWriteData(char writeData)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x40);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeData);
	IIC_ack();
	IIC_stop();
}
 
//OLCD初始化
void oledInit()
{
	oledWriteCmd(0xAE);
	oledWriteCmd(0x00);
	oledWriteCmd(0x10);
	oledWriteCmd(0x40);
	oledWriteCmd(0xB0);
	oledWriteCmd(0x81);
	oledWriteCmd(0xFF);
	oledWriteCmd(0xA1);
	oledWriteCmd(0xA6);
	oledWriteCmd(0xA8);
	oledWriteCmd(0x3F);
	oledWriteCmd(0xC8);
	oledWriteCmd(0xD3);
	oledWriteCmd(0x00);
	oledWriteCmd(0xD5);
	oledWriteCmd(0x80);
	oledWriteCmd(0xD8);
	oledWriteCmd(0x05);
	oledWriteCmd(0xD9);
	oledWriteCmd(0xF1);
	oledWriteCmd(0xDA);
	oledWriteCmd(0x12);
	oledWriteCmd(0xDB);
	oledWriteCmd(0x30);
	oledWriteCmd(0x8D);
	oledWriteCmd(0x14);
	oledWriteCmd(0xAF);
}
 
void olceClean()
{
	int i,j;
	for(i=0;i<8;i++){
		oledWriteCmd(0xB0 + i);  //选择PAGE
		//选择PAGE的第0列开始显示
		oledWriteCmd(0x00);  
		oledWriteCmd(0x10);
		for(j = 0;j < 128; j++){
			oledWriteData(0);  //写入字符0
		}
	}
}
 
char J1[8] = {0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00};
char J2[8] = {0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00};
 
void main()
{
	int i;
	oledInit();
	olceClean();  //清屏函数
 
	oledWriteCmd(0x20);  //设置内存
	oledWriteCmd(0x02);  //选择页寻址模式
	
	olceClean();  //清屏函数
	
	//选择行,选择第4行
	oledWriteCmd(0xB3);  
 
	//选择列,选择第64列
	oledWriteCmd(0x0F);  
	oledWriteCmd(0x13);
 
	//显示数据,显示J的上
	for ( i = 0; i < 8; i++){
		oledWriteData(J1[i]);
	} 
 
	//选择行,选择第5行
	oledWriteCmd(0xB4);  
 
	//选择第64列
	oledWriteCmd(0x0F);  
	oledWriteCmd(0x13);
 
	//显示数据,显示J的下
	for ( i = 0; i < 8; i++){
		oledWriteData(J2[i]);
	} 
	
	while(1);
 
}
 



OLED显示自己的名字

#include "reg52.h"
#include <intrins.h>
 
sbit scl = P1^1;
sbit sda = P1^3; 
 
void Delay5us()		//@11.0592MHz
{
}
 
//IIC起始信号
void IIC_start()
{
	sda = 0;
	scl = 1;
	sda = 1;
	Delay5us();
	sda = 0;
	Delay5us();
	scl = 0;
}
 
//IIC终止信号
void IIC_stop()
{
	scl = 0;
	sda = 0;
	scl = 1;
	Delay5us();
	sda = 1;
	Delay5us();
	sda = 0;
}
 
//IIC的ACK应答信号
char IIC_ack()
{
	char flag;
 
	scl = 0;
	sda = 1;  //在时钟脉冲9期间释放数据线
	Delay5us();  //延时5微秒后,为读取sda数据做准备
 
	scl = 1;  
	Delay5us();  
	flag = sda;  //读取数据线,0为应答
	Delay5us();  
	
	scl = 0;
	Delay5us();
	return flag;
}
 
//IIC发送一个字节
void IIC_sendByte(char myData)
{
	int i;
	for ( i = 0; i < 8; i++){
		//发生数据翻转,选择即将发送的是0还是1
		scl = 0;
		sda = myData & 0x80;  //获取需要发送字节的最高位到SDA
		Delay5us();  //数据建立时间
		
		//开始发送数据
		scl = 1;
		Delay5us();  //数据发送时间
		
		scl = 0;  //发送完毕拉低,等待下1bit数据的传输
		Delay5us();
		
		myData = myData << 1;
	}	
}
 
//OLED写入一条指令
void oledWriteCmd(char writeCmd)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x00);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeCmd);
	IIC_ack();
	IIC_stop();
}
 
//OLED写入一个数据
void oledWriteData(char writeData)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x40);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeData);
	IIC_ack();
	IIC_stop();
}
 
//OLCD初始化
void oledInit()
{
	oledWriteCmd(0xAE);
	oledWriteCmd(0x00);
	oledWriteCmd(0x10);
	oledWriteCmd(0x40);
	oledWriteCmd(0xB0);
	oledWriteCmd(0x81);
	oledWriteCmd(0xFF);
	oledWriteCmd(0xA1);
	oledWriteCmd(0xA6);
	oledWriteCmd(0xA8);
	oledWriteCmd(0x3F);
	oledWriteCmd(0xC8);
	oledWriteCmd(0xD3);
	oledWriteCmd(0x00);
	oledWriteCmd(0xD5);
	oledWriteCmd(0x80);
	oledWriteCmd(0xD8);
	oledWriteCmd(0x05);
	oledWriteCmd(0xD9);
	oledWriteCmd(0xF1);
	oledWriteCmd(0xDA);
	oledWriteCmd(0x12);
	oledWriteCmd(0xDB);
	oledWriteCmd(0x30);
	oledWriteCmd(0x8D);
	oledWriteCmd(0x14);
	oledWriteCmd(0xAF);
}
 
void olceClean()
{
	int i,j;
	for(i=0;i<8;i++){
		oledWriteCmd(0xB0 + i);  //选择PAGE
		//选择PAGE的第0列开始显示
		oledWriteCmd(0x00);  
		oledWriteCmd(0x10);
		for(j = 0;j < 128; j++){
			oledWriteData(0);  //写入字符0
		}
	}
}
 
code char Hao1[16] = {0x10,0x60,0x02,0x8C,0x20,0x90,0x8E,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0x80,0x00};
code char Hao2[16] = {0x04,0x04,0x7E,0x01,0x00,0x00,0xFC,0x44,0x44,0x44,0x44,0x44,0xFC,0x00,0x00,0x00};
 
code char Zi1[16] = {0x80,0x82,0x82,0x82,0x82,0x82,0x82,0xE2,0xA2,0x92,0x8A,0x86,0x82,0x80,0x80,0x00};
code char Zi2[16] = {0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 
code char Ge1[16] = {0x00,0x02,0x02,0x7A,0x4A,0x4A,0x4A,0x4A,0x7A,0x02,0x02,0x7E,0x02,0x02,0x00,0x00};
code char Ge2[16] = {0x01,0x01,0x01,0x3D,0x25,0x25,0x25,0x25,0x3D,0x41,0x81,0x7F,0x01,0x01,0x01,0x00};
 
void main()
{
	int i;
	oledInit();
	olceClean();  //清屏函数
 
	oledWriteCmd(0x20);  //设置内存
	oledWriteCmd(0x02);  //选择页寻址模式
	
	olceClean();  //清屏函数
	
	//选择行,选择第3行
	oledWriteCmd(0xB2);  
 
	//选择列,选择第64列
	oledWriteCmd(0x0F);  
	oledWriteCmd(0x13);
 
	//显示数据,显示浩的上
	for ( i = 0; i < 16; i++){
		oledWriteData(Hao1[i]);
	} 
 
	//显示数据,显示子的上
	for ( i = 0; i < 16; i++){
		oledWriteData(Zi1[i]);
	} 
 
	//显示数据,显示哥的上
	for ( i = 0; i < 16; i++){
		oledWriteData(Ge1[i]);
	} 
 
	//选择行,选择4行
	oledWriteCmd(0xB3);  
 
	//选择第64列
	oledWriteCmd(0x0F);  
	oledWriteCmd(0x13);
 
	//显示数据,显示浩的下
	for ( i = 0; i < 16; i++){
		oledWriteData(Hao2[i]);
	} 
	
	//显示数据,显示子的下
	for ( i = 0; i < 16; i++){
		oledWriteData(Zi2[i]);
	}
 
	//显示数据,显示哥的下
	for ( i = 0; i < 16; i++){
		oledWriteData(Ge2[i]);
	}
 
	while(1);
 
}
 




DTH11获取空气中温湿度,在OLED上显示

#include "reg52.h"
#include <intrins.h>
#include <string.h>
 
sfr AUXR = 0x8e;
 
sbit scl = P1^1;
sbit sda = P1^2;
sbit dht11 = P1^3; 
 
char dht11Data[5];
char temperature[9];
char humidity[9];
 
void Delay5us()		//@11.0592MHz
{
}
 
void Delay40us()		//@11.0592MHz
{
	unsigned char i;
 
	_nop_();
	i = 15;
	while (--i);
}
 
void Delay30ms()		//@11.0592MHz
{
	unsigned char i, j;
 
	i = 54;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}
 
void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;
 
	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
 
//配置DHT11输出数据
void dht11Start()
{
	dht11 =  1;
	dht11 = 0;
	Delay30ms();
	dht11 = 1;
	while(dht11);  //等待自己拉到低电平
	while(!dht11);  //等待自己拉到高电平
	while(dht11);  //等待自己拉到低电平
}
 
//获取DHT11的数据
void obtainDht11Data()
{
	int i,j;
	char tmp;
	char flag;
	dht11Start();  //开始输出数据
	for (i = 0; i < 5; i++){  //总共获取5个字符(40bit)的数据
		for (j = 0; j < 8; j++){  
			//一次获取一个bit数据
			while(!dht11);  //等待自己拉到高电平
			Delay40us();  //高电平时间为27微秒左右表示0,高电平时间为70微秒左右表示1
			
			if(dht11 == 1){  //40微秒后为高电平即输出1
				while(dht11);
				flag = 1;
			}else{  //40微秒后为低电平即输出0
				flag = 0;
			}
			tmp = tmp << 1;  //由于dht11的数据是高位先出,所以用左移的方式
			tmp = tmp | flag;  //(|1成1,|0不变),即对于前面7个bit,flag都为0,不改变tmp的值
		}
		dht11Data[i] = tmp;
	}
}
 
//发送数据到字符数组,用于LCD1602显示
void sendStrData()
{
	humidity[0] = 'H';
	humidity[1] = ':';
	humidity[2] = dht11Data[0]/10 + 0x30;
	humidity[3] = dht11Data[0]%10 + 0x30;
	humidity[4] = '.';
	humidity[5] = dht11Data[1]/10 + 0x30;
	humidity[6] = dht11Data[1]%10 + 0x30;
	humidity[7] = '%'; 
	humidity[8] = '\0'; 
	temperature[0] = 'T';
	temperature[1] = ':';
	temperature[2] = dht11Data[2]/10 + 0x30;
	temperature[3] = dht11Data[2]%10 + 0x30;
	temperature[4] = '.';
	temperature[5] = dht11Data[3]/10 + 0x30;
	temperature[6] = dht11Data[3]%10 + 0x30;
	temperature[7] = 'C';
	temperature[8] = '\0'; 
}
 
//IIC起始信号
void IIC_start()
{
	sda = 0;
	scl = 1;
	sda = 1;
	Delay5us();
	sda = 0;
	Delay5us();
	scl = 0;
}
 
//IIC终止信号
void IIC_stop()
{
	scl = 0;
	sda = 0;
	scl = 1;
	Delay5us();
	sda = 1;
	Delay5us();
	sda = 0;
}
 
//IIC的ACK应答信号
char IIC_ack()
{
	char flag;
 
	scl = 0;
	sda = 1;  //在时钟脉冲9期间释放数据线
	Delay5us();  //延时5微秒后,为读取sda数据做准备
 
	scl = 1;  
	Delay5us();  
	flag = sda;  //读取数据线,0为应答
	Delay5us();  
	
	scl = 0;
	Delay5us();
	return flag;
}
 
//IIC发送一个字节
void IIC_sendByte(char myData)
{
	int i;
	for ( i = 0; i < 8; i++){
		//发生数据翻转,选择即将发送的是0还是1
		scl = 0;
		sda = myData & 0x80;  //获取需要发送字节的最高位到SDA
		Delay5us();  //数据建立时间
		
		//开始发送数据
		scl = 1;
		Delay5us();  //数据发送时间
		
		scl = 0;  //发送完毕拉低,等待下1bit数据的传输
		Delay5us();
		
		myData = myData << 1;
	}	
}
 
//OLED写入一条指令
void oledWriteCmd(char writeCmd)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x00);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeCmd);
	IIC_ack();
	IIC_stop();
}
 
//OLED写入一个数据
void oledWriteData(char writeData)
{
	IIC_start();
	IIC_sendByte(0x78);  //选择一个OLED屏,写模式
	IIC_ack();
	IIC_sendByte(0x40);  //写入命令,D/C位为0
	IIC_ack();
	IIC_sendByte(writeData);
	IIC_ack();
	IIC_stop();
}
 
//OLCD初始化
void oledInit()
{
	oledWriteCmd(0xAE);
	oledWriteCmd(0x00);
	oledWriteCmd(0x10);
	oledWriteCmd(0x40);
	oledWriteCmd(0xB0);
	oledWriteCmd(0x81);
	oledWriteCmd(0xFF);
	oledWriteCmd(0xA1);
	oledWriteCmd(0xA6);
	oledWriteCmd(0xA8);
	oledWriteCmd(0x3F);
	oledWriteCmd(0xC8);
	oledWriteCmd(0xD3);
	oledWriteCmd(0x00);
	oledWriteCmd(0xD5);
	oledWriteCmd(0x80);
	oledWriteCmd(0xD8);
	oledWriteCmd(0x05);
	oledWriteCmd(0xD9);
	oledWriteCmd(0xF1);
	oledWriteCmd(0xDA);
	oledWriteCmd(0x12);
	oledWriteCmd(0xDB);
	oledWriteCmd(0x30);
	oledWriteCmd(0x8D);
	oledWriteCmd(0x14);
	oledWriteCmd(0xAF);
}
 
void olceClean()
{
	int i,j;
	for(i=0;i<8;i++){
		oledWriteCmd(0xB0 + i);  //选择PAGE
		//选择PAGE的第0列开始显示
		oledWriteCmd(0x00);  
		oledWriteCmd(0x10);
		for(j = 0;j < 128; j++){
			oledWriteData(0);  //写入字符0
		}
	}
}
 
//OLED的字符构造点阵
const unsigned char code oledFont[]=
{
  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,//0 16
  0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
  0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
  0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
  0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
  0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
  0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
  0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
  0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
  0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
  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,//A 33
  0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
  0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
  0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
  0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
  0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
  0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
  0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
  0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
  0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
  0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
  0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
  0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
  0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
  0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
  0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
  0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
  0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
  0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
  0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
  0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
  0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
  0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
  0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
  0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
  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,//a 65
  0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
  0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
  0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
  0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
  0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
  0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
  0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
  0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
  0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
  0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
  0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
  0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
  0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
  0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
  0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
  0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
  0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
  0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
  0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
  0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
  0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
  0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
  0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
  0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
  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
};
 
//OLED显示一个字符
void oledShowByte(char rows,char columns,char oledByte)
{ 
	unsigned int i;
 
	//显示字符的上半部分
	oledWriteCmd(0xb0+(rows*2-2));  //选择行
	//选择列                        
	oledWriteCmd(0x00+(columns&0x0f));                          
	oledWriteCmd(0x10+(columns>>4));      
	//显示数据                       
	for(i=((oledByte-32)*16);i<((oledByte-32)*16+8);i++){
		oledWriteData(oledFont[i]);                            
	}
 
 	//显示字符的上半部分
	oledWriteCmd(0xb0+(rows*2-1));  //选择行  
	//选择列                    
	oledWriteCmd(0x00+(columns&0x0f));                          
	oledWriteCmd(0x10+(columns>>4)); 
	//显示数据                           
	for(i=((oledByte-32)*16+8);i<((oledByte-32)*16+8+8);i++){
		oledWriteData(oledFont[i]);                            
	}       
}
 
//OLED显示一个字符串
void oledShowString(char rows,char columns,char *str)
{
	while(*str != '\0'){
		oledShowByte(rows,columns,*str);
		str++;
		columns += 8;   
	}       
}
 
void main()
{
	oledInit();
	olceClean();  //清屏函数
 
	oledWriteCmd(0x20);  //设置内存
	oledWriteCmd(0x02);  //选择页寻址模式
 
	while(1){
		obtainDht11Data();  //获取空气中的温湿度
		sendStrData();  //将温湿度存储到字符数组中,用于OLED显示
		olceClean();  //清屏函数
		oledShowString(1,5,temperature);  //OLED显示温度
		oledShowString(2,5,humidity);  //OLED显示湿度
		oledShowString(3,5,"haozige");  //OLED显示湿度
		oledShowString(4,5,"jiangxiaoya");  //OLED显示湿度
 
		Delay1000ms();
	}
 
}