智能家居小项目综述

Tutorial: 电子电路 Category: 嵌入式 Published: 2026-10-08 01:26:37 Views: 1 Likes: 0 Comments: 0

071.9.10 IIC总结

/* ==================== main.c:把 OLED 显示层接入独立 I²C 模块 ====================
 * 迁移要点:OLED 模块不再直接操作 P1.4/P1.5,而是调用 IIC_Start、IIC_Send_Byte、IIC_Recv_Ack、IIC_Stop。
 * 这样显示函数保持不变时,可单独替换/调试底层总线驱动。
 */
#include "reg52.h" /* 引入 8051 寄存器定义。 */
#include <intrins.h>
#include "delay.h"
#include "main.h"
#include "uart.h"
#include "oled.h"  /* 引入 OLED 初始化和显示接口。 */

uchar recv;

void main()
{
//	UART_Init();
	OLED_Init();      /* 配置 SSD1306,并经 IIC 模块将命令发送到 OLED。 */
	OLED_Clear();     /* 清空显示 RAM,建立确定的起始画面。 */

	OLED_ShowCHinese(0+10,0,0);  /* 第 0 个 16×16 汉字从第 0 页、x=10 开始显示。 */
	OLED_ShowCHinese(18+10,0,1); /* 后续字符横向错开 18 列,索引决定从 Hzk 取哪组字模。 */
	OLED_ShowCHinese(36+10,0,2);
	OLED_ShowCHinese(54+10,0,3);
	OLED_ShowCHinese(72+10,0,4);
	OLED_ShowCHinese(90+10,0,5);

OLED_ShowCHinese(18+10,2,6); /* y=2 表示从第 2 页(第 16 行)开始绘制第二行汉字。 */
	OLED_ShowCHinese(36+10,2,7);
	OLED_ShowCHinese(54+10,2,8);
	OLED_ShowCHinese(72+10,2,9);


	while(1)
  {
		//OLED_Clear();
    //OLED_ShowString(6,3,"I am wfeng",16);
		OLED_ShowString(0,6,"STUDY:",12);  /* 在底部第 6 页显示 6×8 ASCII 字符串。 */
		OLED_ShowString(63,6,"LERN:",12);  /* 原样保留课程示例中的 “LERN:” 拼写。 */
		OLED_ShowChar(48,6,'A',16);        /* 单独测试 8×16 字符字模的上下两页写入。 */
		
		OLED_ShowNum(103,6,6,3,16);        /* 以 3 位 16 像素字体显示数字 6,前导空位由函数补空格。 */
		Delay_xms(1000);                   /* 示例画面不改变;此延时只降低循环频率。 */
  }
}


/* ==================== main.h ==================== */
#ifndef _MAIN_H_
#define _MAIN_H_

#include "reg52.h" /* 8051 端口及特殊功能寄存器定义。 */

typedef unsigned char uchar; /* 课程代码中的 8 位无符号类型别名。 */
typedef unsigned int uint;   /* Keil C51 中通常为 16 位无符号整数。 */

extern uchar recv;

sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
sbit BEEP = P1^6;
sbit JDQ1 = P2^0;

sbit IIC_SCL = P1^5; /* 软件 I²C 时钟线;与 OLED 的 SCL 相连。 */
sbit IIC_SDA = P1^4; /* 软件 I²C 数据线;与 OLED 的 SDA 相连。 */

#endif

/* ==================== Delay\delay.c ==================== */
#include "delay.h"
#include <intrins.h>

void Delay_xms(uint xms)	/* 以 11.0592 MHz 为前提的粗略毫秒延时。 */
{
	uchar data i, j;
	while(xms)              /* 每轮消耗约 1 ms,直到请求次数归零。 */
	{
		_nop_();
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
    xms--;		        /* 已完成一个毫秒时间片。 */
	}
}

void Delay5us(void)	//@11.0592MHz
{
}

/* ==================== Delay\delay.h ==================== */
#ifndef _DELAY_H_
#define _DELAY_H_
#include "main.h"

void Delay_xms(uint xms);
void Delay5us(void);

#endif

/* ==================== IIC\iic.c ==================== */
#include "iic.h"
#include "main.h"
#include "delay.h"

void IIC_Start(void) /* I²C 起始条件:SCL 为高电平期间,SDA 由高变低。 */
{
	IIC_SCL = 1; /* 先释放时钟线。 */
	IIC_SDA = 1; /* 空闲总线的两根线均为高。 */
	Delay5us();  /* 保证起始条件的建立时间。 */
	IIC_SDA = 0; /* SCL 高电平时拉低 SDA,形成 START。 */
	Delay5us();
	IIC_SCL = 0; /* 后续数据位在 SCL 低电平阶段准备。 */
}

void IIC_Stop(void) /* I²C 停止条件:SCL 为高电平期间,SDA 由低变高。 */
{
	IIC_SCL = 1; /* 先把时钟恢复为高。 */
	IIC_SDA = 0; /* 确保数据线从低电平开始变化。 */
	Delay5us();
	IIC_SDA = 1; /* SCL 高电平时释放 SDA,形成 STOP。 */
}

void IIC_Send_Byte(unsigned char IIC_Byte) /* 按最高位优先发送 8 个数据位。 */
{
	char i;
	for(i = 0; i<8; i++)
	{		
		IIC_SDA = IIC_Byte & (0x80 >> i); /* 依次取 bit7 到 bit0;非零值会驱动为高。 */
		IIC_SCL = 1;                      /* 上升沿/高电平阶段让从机采样该位。 */
		Delay5us();
		IIC_SCL = 0;                      /* 回到低电平,准备下一位。 */
		Delay5us();		
	}
}

unsigned char IIC_Recv_Ack(void) /* 读取第 9 个时钟周期的 ACK:0 为应答,1 为未应答。 */
{
	unsigned char ack;
	IIC_SDA = 1; /* 释放 SDA,让从机能够驱动应答位。 */
	IIC_SCL = 1; /* 第 9 个时钟高电平。 */
	Delay5us();
	ack = IIC_SDA; /* 采样从机给出的 ACK/NACK 电平。 */
	IIC_SCL = 0;
	Delay5us();	
	
	return ack;
}

/* ==================== IIC\iic.h ==================== */
#ifndef _IIC_H_
#define _IIC_H_

void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(unsigned char IIC_Byte);
unsigned char IIC_Recv_Ack(void);

#endif

/* ==================== OLED\oled.c:显示层,通过 iic.h 使用总线接口 ==================== */
#include "oled.h"
#include "oledfont.h"  	 
#include "iic.h"   /* 引入独立 I²C 模块的 START、发送、ACK 读取和 STOP 接口。 */

//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;
}
/**********************************************
//I²C 起始信号
**********************************************/
//void IIC_Start()
//{
//	OLED_SCLK_Set() ;
//	OLED_SDIN_Set();
//	OLED_SDIN_Clr();
//	OLED_SCLK_Clr();
//}

/**********************************************
//I²C 停止信号
**********************************************/
//void IIC_Stop()
//{
//  OLED_SCLK_Set() ;
//  //OLED_SCLK_Clr();
//	OLED_SDIN_Clr();
//	OLED_SDIN_Set();
//	
//}

//void IIC_Wait_Ack()
//{
//	OLED_SCLK_Set() ;
//	OLED_SCLK_Clr();
//}
/**********************************************
// I²C 写入一个字节
**********************************************/

//void Write_IIC_Byte(unsigned char IIC_Byte)
//{
//	unsigned char i;
//	unsigned char m,da;
//	da=IIC_Byte;
//	OLED_SCLK_Clr();
//	for(i=0;i<8;i++)		
//	{
//		m=da;
//		//	OLED_SCLK_Clr();
//		m=m&0x80;
//		if(m==0x80)
//		{OLED_SDIN_Set();}
//		else OLED_SDIN_Clr();
//			da=da<<1;
//		OLED_SCLK_Set();
//		OLED_SCLK_Clr();
//	}
//}
/**********************************************
// I²C 写命令
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command) /* 写一个 SSD1306 命令帧;所有物理时序由 IIC 模块完成。 */
{
	IIC_Start();              /* 产生 START,占用 I²C 总线。 */
	IIC_Send_Byte(0x78);      /* SSD1306 地址 0x3C 加写方向位。 */
	IIC_Recv_Ack();           /* 读取应答;原例程未根据返回值处理 NACK,这是后续可完善的错误路径。 */
	IIC_Send_Byte(0x00);      /* 控制字节:后续载荷按命令解释。 */
	IIC_Recv_Ack();           /* 检查控制字节应答。 */
	IIC_Send_Byte(IIC_Command); /* 发送调用者指定的 SSD1306 命令。 */
	IIC_Recv_Ack();           /* 检查命令字节应答。 */
	IIC_Stop();               /* 产生 STOP,释放总线。 */
}
/**********************************************
// I²C 写数据
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data) /* 写一个显示 RAM 数据帧。 */
{
	IIC_Start();              /* 开始本次数据事务。 */
	IIC_Send_Byte(0x78);      /* 选择 SSD1306 并写入。 */
	IIC_Recv_Ack();           /* 读取地址应答。 */
	IIC_Send_Byte(0x40);      /* 控制字节:后续载荷写入 GDDRAM。 */
	IIC_Recv_Ack();           /* 读取控制字节应答。 */
	IIC_Send_Byte(IIC_Data);  /* 写当前页/列指针指向的 8 个纵向像素。 */
	IIC_Recv_Ack();           /* 读取数据应答。 */
	IIC_Stop();               /* 完成本次单字节写入。 */
}

void OLED_WR_Byte(unsigned dat,unsigned cmd) /* 根据 cmd 将一个字节分流为命令或显示数据。 */
{
	if(cmd) /* OLED_DATA 为 1,走数据帧;OLED_CMD 为 0,走命令帧。 */
	{
    Write_IIC_Data(dat);  /* 数据字节会写入当前 GDDRAM 地址。 */
	}
	else
	{
    Write_IIC_Command(dat); /* 命令字节用于配置地址、显示状态等。 */
	}
}

/********************************************
// 填充整屏图像
********************************************/
void fill_picture(unsigned char fill_Data) /* 用同一字节填满 8 页 × 128 列的整块显示 RAM。 */
{
	unsigned char m,n;
	for(m=0;m<8;m++) /* SSD1306 的 64 行屏幕分为 8 个页。 */
	{
		OLED_WR_Byte(0xb0+m,0);		//设置当前页地址
		OLED_WR_Byte(0x00,0);		//设置列地址低四位
		OLED_WR_Byte(0x10,0);		//设置列地址高四位
		for(n=0;n<128;n++)
		{
			OLED_WR_Byte(fill_Data,1); /* 每个字节控制当前列连续的 8 个纵向像素。 */
		}
	}
}


/***********************延时函数****************************************/
void Delay_50ms(unsigned int Del_50ms)
{
	unsigned int m;
	for(;Del_50ms>0;Del_50ms--)
		for(m=6245;m>0;m--);
}

void Delay_1ms(unsigned int Del_1ms)
{
	unsigned char j;
	while(Del_1ms--)
	{	
		for(j=0;j<123;j++);
	}
}

//坐标设置
void OLED_Set_Pos(unsigned char x, unsigned char y) /* 将后续数据写入定位到列 x、页 y。 */
{ 
	OLED_WR_Byte(0xb0+y,OLED_CMD);              /* 选择 0~7 页。 */
	OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD); /* 写列地址高 4 位。 */
	OLED_WR_Byte((x&0x0f),OLED_CMD);           /* 写列地址低 4 位。 */
}   	  
//开启OLED显示    
void OLED_Display_On(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X14,OLED_CMD);  //开启内部升压电路
	OLED_WR_Byte(0XAF,OLED_CMD);  //开启显示
}
//关闭OLED显示     
void OLED_Display_Off(void)
{
	OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
	OLED_WR_Byte(0X10,OLED_CMD);  //关闭内部升压电路
	OLED_WR_Byte(0XAE,OLED_CMD);  //关闭显示
}		   			 
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!	  
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); 
	} //更新显示
}
void OLED_On(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(1,OLED_DATA); 
	} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示				 
//size:选择字体 16/12 
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size) /* 从字模表取出一个 ASCII 字符并写到屏幕。 */
{      	
	unsigned char c=0,i=0;	
	c=chr-' '; /* 字模表从空格(ASCII 0x20)开始存储,因此先换算下标。 */
	if(x>Max_Column-1)
	{
		x=0;   /* 超出右边界则回到行首。 */
		y=y+2; /* 16 像素字高占两页,换行时页号加 2。 */
	}
	if(Char_Size ==16)
	{
		OLED_Set_Pos(x,y); /* 先写字模上半部分所在页。 */
		for(i=0;i<8;i++)
		OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
		OLED_Set_Pos(x,y+1); /* 再写字模下半部分到下一页。 */
		for(i=0;i<8;i++)
		OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
	}
	else 
	{	
		OLED_Set_Pos(x,y); /* 6×8 字符只占一个页。 */
		for(i=0;i<6;i++)
		OLED_WR_Byte(F6x8[c][i],OLED_DATA);			
	}
}
//m^n函数
u32 oled_pow(u8 m,u8 n) /* 整数幂:供十进制拆位使用。 */
{
	u32 result=1;	 
	while(n--)
	{
	  result*=m; /* 每循环一次多乘一个底数。 */
	}    
	return result;
}				  
//显示2个数字
//x,y :起点坐标	 
//len :数字的位数
//size:字体大小
//mode:模式	0,填充模式;1,叠加模式
//num:数值(0~4294967295);	 		  
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2) /* 按固定宽度显示无符号十进制数。 */
{         	
	u8 t,temp;
	u8 enshow=0;						   
	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+(size2/2)*t,y,' ',size2); /* 隐藏前导零,保持字段对齐。 */
				continue;
			}
			else 
				enshow=1; 		 	 
		}
	 	OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2); /* 将 0~9 转为对应 ASCII 码再显示。 */
	}
} 
//显示一个字符号串
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size) /* 逐字符显示以 '\\0' 结尾的字符串。 */
{
	unsigned char j=0;
	while (chr[j]!='\0')
	{		
		OLED_ShowChar(x,y,chr[j],Char_Size); /* 显示当前字符。 */
		x+=8;                                /* 示例按 8 列步进,适用于 8×16 字体。 */
		if(x>120){x=0;y+=2;}                 /* 即将越界时换到下一字符行。 */
		 j++;
	}
}
//显示汉字
void OLED_ShowCHinese(u8 x,u8 y,u8 no) /* 将第 no 个 16×16 汉字的两组 16 字节字模写入两页。 */
{      			    
	u8 t,adder=0;
	OLED_Set_Pos(x,y); /* 写上半部分。 */
	for(t=0;t<16;t++)
	{
		OLED_WR_Byte(Hzk[2*no][t],OLED_DATA); /* Hzk 每个汉字占两行数组,偶数行是上半部分。 */
		adder+=1;
	}	
	OLED_Set_Pos(x,y+1); /* 写下半部分。 */
	for(t=0;t<16;t++)
	{	
		OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA); /* 奇数行对应同一汉字的下半部分。 */
		adder+=1;
	}					
}
/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]) /* 依页写入一幅位图。 */
{ 	
 unsigned int j=0;
 unsigned char x,y;
  
  if(y1%8==0)
		y=y1/8;      
  else 
		y=y1/8+1;
	for(y=y0;y<y1;y++)
	{
		OLED_Set_Pos(x0,y);
    for(x=x0;x<x1;x++)
	  {      
	    OLED_WR_Byte(BMP[j++],OLED_DATA); /* 位图数据按页、按列连续消费。 */
	  }
	}
} 

//初始化SSD1306					    
void OLED_Init(void) /* 依 SSD1306 初始化顺序配置寻址、扫描方向、供电与显示开关。 */
{ 	
 
	OLED_WR_Byte(0xAE,OLED_CMD);//关闭显示
	OLED_WR_Byte(0x00,OLED_CMD);//设置列地址低四位
	OLED_WR_Byte(0x10,OLED_CMD);//设置列地址高四位
	OLED_WR_Byte(0x40,OLED_CMD);//设置显示起始行  
	OLED_WR_Byte(0xB0,OLED_CMD);//设置页地址
	OLED_WR_Byte(0x81,OLED_CMD); //设置对比度
	OLED_WR_Byte(0xFF,OLED_CMD);//--128   
	OLED_WR_Byte(0xA1,OLED_CMD);//设置段重映射 
	OLED_WR_Byte(0xA6,OLED_CMD);//设置正常显示而非反色显示
	OLED_WR_Byte(0xA8,OLED_CMD);//设置多路复用比(1~64)
	OLED_WR_Byte(0x3F,OLED_CMD);//设置显示占空比
	OLED_WR_Byte(0xC8,OLED_CMD);//设置 COM 扫描方向
	OLED_WR_Byte(0xD3,OLED_CMD);//设置显示偏移
	OLED_WR_Byte(0x00,OLED_CMD);//
	
	OLED_WR_Byte(0xD5,OLED_CMD);//设置振荡器分频
	OLED_WR_Byte(0x80,OLED_CMD);//
	
	OLED_WR_Byte(0xD8,OLED_CMD);//关闭区域彩色模式
	OLED_WR_Byte(0x05,OLED_CMD);//
	
	OLED_WR_Byte(0xD9,OLED_CMD);//设置预充电周期
	OLED_WR_Byte(0xF1,OLED_CMD);//
	
	OLED_WR_Byte(0xDA,OLED_CMD);//设置 COM 引脚硬件配置
	OLED_WR_Byte(0x12,OLED_CMD);//
	
	OLED_WR_Byte(0xDB,OLED_CMD);//设置 VCOMH 电平
	OLED_WR_Byte(0x30,OLED_CMD);//
	
	OLED_WR_Byte(0x8D,OLED_CMD);//配置电荷泵
	OLED_WR_Byte(0x14,OLED_CMD);//
	
	OLED_WR_Byte(0xAF,OLED_CMD);//开启 OLED 面板显示
}  

/* ==================== OLED\oled.h ==================== */
//#include "REG51.h"
#ifndef __OLED_H
#define __OLED_H			  	 
//#include "sys.h"
//#include "stdlib.h"	  
#define  u8 unsigned char 
#define  u32 unsigned int 
#define OLED_CMD  0	/* OLED_WR_Byte 的命令通道标记。 */
#define OLED_DATA 1	/* OLED_WR_Byte 的显示数据通道标记。 */
#define OLED_MODE 0

//sbit OLED_SCL=P1^5;//时钟 D0(SCLK?
//sbit OLED_SDIN=P1^4;//D1(MOSI) 数据

//#define OLED_SCLK_Clr() OLED_SCL=0
//#define OLED_SCLK_Set() OLED_SCL=1

//#define OLED_SDIN_Clr() OLED_SDIN=0
//#define OLED_SDIN_Set() OLED_SDIN=1

//OLED模式设置
//0:4线串行模式
//1:并行8080模式

#define SIZE 16
#define XLevelL		0x02
#define XLevelH		0x10
#define Max_Column	128
#define Max_Row		64
#define	Brightness	0xFF 
#define X_WIDTH 	128
#define Y_WIDTH 	64	    						  
//-----------------OLED端口定义----------------  					   

void delay_ms(unsigned int ms);

//OLED控制用函数
void OLED_WR_Byte(unsigned dat,unsigned cmd);  
void OLED_Display_On(void);
void OLED_Display_Off(void);	   							   		    
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);	 
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(u8 x,u8 y,u8 no);
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);
void Delay_50ms(unsigned int Del_50ms);
void Delay_1ms(unsigned int Del_1ms);
void fill_picture(unsigned char fill_Data);
void Picture();
void IIC_Start();
void IIC_Stop();
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data);
void Write_IIC_Byte(unsigned char IIC_Byte);
void IIC_Wait_Ack();

#endif

/* ==================== OLED\oledfont.h ==================== */
#ifndef __OLEDFONT_H
#define __OLEDFONT_H 	   
/* OLED 字模资源:各元素是像素点阵数据,按字库索引供显示函数读取。 */
//常用ASCII表
//偏移量32
//ASCII字符集
//偏移量32
//大小:12*6
/************************************6*8的点阵************************************/
const unsigned char code F6x8[][6] =		
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// 空格字符
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// 水平线字符
};
/****************************************8*16的点阵************************************/
const unsigned char code F8X16[]=	  
{
  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
};
unsigned char code Hzk[][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*/

//{0x40,0x40,0x40,0x5F,0x55,0x55,0x55,0x75,0x55,0x55,0x55,0x5F,0x40,0x40,0x40,0x00},
//{0x00,0x40,0x20,0x0F,0x09,0x49,0x89,0x79,0x09,0x09,0x09,0x0F,0x20,0x40,0x00,0x00},/*"景",1*/

//{0x00,0xFE,0x02,0x42,0x4A,0xCA,0x4A,0x4A,0xCA,0x4A,0x4A,0x42,0x02,0xFE,0x00,0x00},
//{0x00,0xFF,0x40,0x50,0x4C,0x43,0x40,0x40,0x4F,0x50,0x50,0x5C,0x40,0xFF,0x00,0x00},/*"园",2*/

//{0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00},
//{0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00},/*"电",3*/

//{0x80,0x82,0x82,0x82,0x82,0x82,0x82,0xE2,0xA2,0x92,0x8A,0x86,0x82,0x80,0x80,0x00},
//{0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"子",4*/

//{0x24,0x24,0xA4,0xFE,0xA3,0x22,0x00,0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00,0x00},
//{0x08,0x06,0x01,0xFF,0x00,0x01,0x04,0x04,0x04,0x04,0x04,0xFF,0x02,0x02,0x02,0x00},/*"科",5*/

//{0x10,0x10,0x10,0xFF,0x10,0x90,0x08,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x08,0x00},
//{0x04,0x44,0x82,0x7F,0x01,0x80,0x80,0x40,0x43,0x2C,0x10,0x28,0x46,0x81,0x80,0x00},/*"技",6*/


// 长(0) 春(1) 理(2) 工(3) 大(4) 学(5) 好(6) 好(7) 学(8) 习(9)

//{0x80,0x80,0x80,0x80,0xFF,0x80,0x80,0xA0,0x90,0x88,0x84,0x82,0x80,0x80,0x80,0x00},
//{0x00,0x00,0x00,0x00,0xFF,0x40,0x21,0x12,0x04,0x08,0x10,0x20,0x20,0x40,0x40,0x00},/*"长",0*/
///* (16 X 16 , 宋体 )*/

//{0x40,0x44,0x54,0x54,0xD4,0x54,0x74,0x5F,0x54,0x54,0xD4,0x54,0x54,0x44,0x40,0x00},
//{0x04,0x04,0x02,0x01,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x01,0x02,0x04,0x04,0x00},/*"春",1*/
///* (16 X 16 , 宋体 )*/

//{0x04,0x84,0x84,0xFC,0x84,0x84,0x00,0xFE,0x92,0x92,0xFE,0x92,0x92,0xFE,0x00,0x00},
//{0x20,0x60,0x20,0x1F,0x10,0x10,0x40,0x44,0x44,0x44,0x7F,0x44,0x44,0x44,0x40,0x00},/*"理",2*/
///* (16 X 16 , 宋体 )*/

//{0x00,0x04,0x04,0x04,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00},
//{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00},/*"工",3*/
///* (16 X 16 , 宋体 )*/

//{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0xFF,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00},
//{0x80,0x80,0x40,0x20,0x10,0x0C,0x03,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00},/*"大",4*/
///* (16 X 16 , 宋体 )*/

//{0x40,0x30,0x11,0x96,0x90,0x90,0x91,0x96,0x90,0x90,0x98,0x14,0x13,0x50,0x30,0x00},
//{0x04,0x04,0x04,0x04,0x04,0x44,0x84,0x7E,0x06,0x05,0x04,0x04,0x04,0x04,0x04,0x00},/*"学",5*/
///* (16 X 16 , 宋体 )*/

//{0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x80,0x82,0x82,0xE2,0x92,0x8A,0x86,0x80,0x00},
//{0x40,0x22,0x15,0x08,0x16,0x61,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00},/*"好",6*/
///* (16 X 16 , 宋体 )*/

//{0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x80,0x82,0x82,0xE2,0x92,0x8A,0x86,0x80,0x00},
//{0x40,0x22,0x15,0x08,0x16,0x61,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00},/*"好",7*/
///* (16 X 16 , 宋体 )*/

//{0x40,0x30,0x11,0x96,0x90,0x90,0x91,0x96,0x90,0x90,0x98,0x14,0x13,0x50,0x30,0x00},
//{0x04,0x04,0x04,0x04,0x04,0x44,0x84,0x7E,0x06,0x05,0x04,0x04,0x04,0x04,0x04,0x00},/*"学",8*/
///* (16 X 16 , 宋体 )*/

//{0x00,0x02,0x02,0x02,0x12,0x22,0xC2,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,0x00},
//{0x00,0x08,0x18,0x08,0x04,0x04,0x04,0x02,0x02,0x41,0x81,0x40,0x3F,0x00,0x00,0x00},/*"习",9*/
///* (16 X 16 , 宋体 )*/

 //温(0) 湿(1) 度(2) 检(3) 测(4) 系(5) 统(6)

//{0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
//{0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00},/*"温",0*/
///* (16 X 16 , 宋体 )*/

//{0x10,0x60,0x02,0x8C,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00},
//{0x04,0x04,0x7E,0x01,0x44,0x48,0x50,0x7F,0x40,0x40,0x7F,0x50,0x48,0x44,0x40,0x00},/*"湿",1*/
///* (16 X 16 , 宋体 )*/

//{0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00},
//{0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00},/*"度",2*/
///* (16 X 16 , 宋体 )*/

//{0x10,0x10,0xD0,0xFF,0x90,0x50,0x20,0x50,0x4C,0x43,0x4C,0x50,0x20,0x40,0x40,0x00},
//{0x04,0x03,0x00,0xFF,0x00,0x41,0x44,0x58,0x41,0x4E,0x60,0x58,0x47,0x40,0x40,0x00},/*"检",3*/
///* (16 X 16 , 宋体 )*/

//{0x10,0x60,0x02,0x8C,0x00,0xFE,0x02,0xF2,0x02,0xFE,0x00,0xF8,0x00,0xFF,0x00,0x00},
//{0x04,0x04,0x7E,0x01,0x80,0x47,0x30,0x0F,0x10,0x27,0x00,0x47,0x80,0x7F,0x00,0x00},/*"测",4*/
///* (16 X 16 , 宋体 )*/

//{0x00,0x00,0x22,0x32,0x2A,0xA6,0xA2,0x62,0x21,0x11,0x09,0x81,0x01,0x00,0x00,0x00},
//{0x00,0x42,0x22,0x13,0x0B,0x42,0x82,0x7E,0x02,0x02,0x0A,0x12,0x23,0x46,0x00,0x00},/*"系",5*/
///* (16 X 16 , 宋体 )*/

//{0x20,0x30,0xAC,0x63,0x30,0x00,0x88,0xC8,0xA8,0x99,0x8E,0x88,0xA8,0xC8,0x88,0x00},
//{0x22,0x67,0x22,0x12,0x12,0x80,0x40,0x30,0x0F,0x00,0x00,0x3F,0x40,0x40,0x71,0x00},/*"统",6*/
///* (16 X 16 , 宋体 )*/

 //智(0) 能(1) 家(2) 居(3) 系(4) 统(5)

{0x10,0x94,0x53,0x32,0x1E,0x32,0x52,0x10,0x00,0x7E,0x42,0x42,0x42,0x7E,0x00,0x00},
{0x00,0x00,0x00,0xFF,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0xFF,0x00,0x00,0x00,0x00},/*"智",0*/
/* (16 X 16 , 宋体 )*/

{0x08,0xCC,0x4A,0x49,0x48,0x4A,0xCC,0x18,0x00,0x7F,0x88,0x88,0x84,0x82,0xE0,0x00},
{0x00,0xFF,0x12,0x12,0x52,0x92,0x7F,0x00,0x00,0x7E,0x88,0x88,0x84,0x82,0xE0,0x00},/*"能",1*/
/* (16 X 16 , 宋体 )*/

{0x10,0x2C,0x24,0x24,0xA4,0xA4,0x65,0xA6,0x24,0x24,0x24,0x24,0xA4,0x34,0x0C,0x00},
{0x40,0x49,0x49,0x29,0x24,0x14,0x52,0x89,0x7F,0x04,0x0A,0x11,0x10,0x20,0x20,0x00},/*"家",2*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xF2,0x92,0x92,0x92,0x9E,0x80,0x80,0x00},
{0x40,0x30,0x0F,0x00,0xFC,0x44,0x44,0x44,0x47,0x44,0x44,0x44,0xFC,0x00,0x00,0x00},/*"居",3*/
/* (16 X 16 , 宋体 )*/

{0x00,0x00,0x22,0x32,0x2A,0xA6,0xA2,0x62,0x21,0x11,0x09,0x81,0x01,0x00,0x00,0x00},
{0x00,0x42,0x22,0x13,0x0B,0x42,0x82,0x7E,0x02,0x02,0x0A,0x12,0x23,0x46,0x00,0x00},/*"系",4*/
/* (16 X 16 , 宋体 )*/

{0x20,0x30,0xAC,0x63,0x30,0x00,0x88,0xC8,0xA8,0x99,0x8E,0x88,0xA8,0xC8,0x88,0x00},
{0x22,0x67,0x22,0x12,0x12,0x80,0x40,0x30,0x0F,0x00,0x00,0x3F,0x40,0x40,0x71,0x00},/*"统",5*/
/* (16 X 16 , 宋体 )*/

};

#endif

/* ==================== Timer\timer.c ==================== */
#include "timer.h"
#include "reg52.h"

void Timer0_Init(void)
{
	TMOD &= 0xF0; /* 只配置 Timer0,保留串口使用的 Timer1 设置。 */
	TMOD |=0x01;  /* Timer0 方式 1,16 位定时。 */
	TH0 = 0XDC;   /* 约 10 ms 初值高字节。 */
	TL0 = 0X00;   /* 初值低字节。 */
	TF0 = 0;      /* 清 Timer0 溢出标志。 */
	ET0 = 1;      /* 开启 Timer0 中断。 */
	EA = 1;       /* 开启总中断。 */
	TR0 = 1;      /* 启动 Timer0。 */
}

/* ==================== Timer\timer.h ==================== */
#ifndef _TIMER_H_
#define _TIMER_H_
//#include "main.h"

void Timer0_Init(void);

#endif

/* ==================== Uart\uart.c ==================== */
#include "uart.h"
#include "main.h"

//串口发送一个字节
void UART_Send_Byte(uchar send_byte)
{
	SBUF = send_byte; /* 写发送缓冲寄存器,开始发送。 */
	while(!TI);			/* 等待硬件置位发送完成标志。 */
	TI=0;				/* 清标志,准备下一字节。 */
}

//串口发送字符串
void UART_Send_Str(uchar *send_str)
{	
	while(*send_str != '\0') /* 遍历至 C 字符串结束符。 */
	{
		UART_Send_Byte(*send_str++); /* 逐字节发送并移动指针。 */
	}	
} 

void UART_Init(void)
{
	SCON = 0x50; 	/* 串口方式 1,允许接收。 */
	PCON &= 0x7F; /* 不启用波特率倍速。 */
	TMOD &= 0x0f;	/* 保留 Timer0 的低四位。 */
	TMOD |= 0x20;	/* Timer1 方式 2:8 位自动重装作波特率发生器。 */
//		PS=1;
//	PT0=0;
	TH1 = 0xFD;		/* 11.0592 MHz 下 9600 bps 的重装值。 */
	TL1 = 0xFD;
	TR1 = 1;			/* 启动 Timer1。 */
	ES = 1;				/* 使能串口中断。 */
	EA=1;					/* 确保总中断已打开。 */

}

/* ==================== Uart\uart.h ==================== */
#ifndef _UART_H_
#define _UART_H_
#include "main.h"

void UART_Send_Byte(uchar send_byte);
void UART_Send_Str(uchar *send_str);
void UART_Init(void);

#endif

一、简单智能家居小项目

本项目把 DHT11 温湿度采集、光照检测、OLED 显示、直流电机 PWM 调速和蓝牙串口控制整合到同一套 51 单片机程序中。重点不是增加新外设,而是练习多模块接线、引脚分配、定时任务和通信协议之间的协同。

1.1 项目功能介绍

功能代码中的接口作用
DHT11P1.2读取温度和湿度;该引脚也与板载 LED3 复用
光照数字量SUN=P3.7根据光敏模块输出控制 LED4
自动照明LED4=P1.3源码中由光照输入控制
蓝牙照明LED2=P1.1接收 0x01/0x02 后开灯或关灯
风扇 PWMPWM=P1.0接收 0x03/0x04 后提高或降低档位
OLEDSCL=P1.4、SDA=P1.5显示温度、湿度和档位
蓝牙串口RXD=P3.0、TXD=P3.1接收控制字节并回传温湿度

这张表也说明了一个综合项目必须先做“引脚资源表”:同一 GPIO 不能在同一时刻承担互相冲突的功能。源码中光敏自动控制的是 LED4(P1.3),蓝牙控制的是 LED2(P1.1),而 P1.0 专门输出风扇 PWM。

硬件可按下列数据流理解:

flowchart LR
    DHT[DHT11 温湿度] --> MCU[STC89C52]
    SUN[光敏模块] --> MCU
    APP[手机蓝牙助手] <-->|UART 字节| BT[蓝牙串口模块]
    BT <--> MCU
    MCU --> OLED[OLED 显示]
    MCU --> LED[LED2 / LED4]
    MCU --> PWM[PWM]
    PWM --> DRIVER[电机驱动级]
    DRIVER --> FAN[直流风扇]

电机也不能由 GPIO 直接供电,应通过三极管或电机驱动模块放大电流,并为感性负载配置续流保护。蓝牙模块、传感器、驱动板和单片机必须共地;模块供电电压与串口逻辑电平应按器件规格确认。

1.2 项目代码分析

初始化依次完成串口、OLED、DHT11、定时器和显示内容设置。主循环承担低实时性任务,定时器中断产生 PWM,串口中断只接收控制字节:

上电
 ├─ 初始化 UART / OLED / DHT11 / Timer0
 ├─ 显示固定标题
 └─ while(1)
     ├─ 光照输入 → LED4
     ├─ 到达采样时刻 → 读取 DHT11 → 显示并回传
     └─ 显示风扇档位

Timer0 每 10 ms 中断
 ├─ 计数满 300 次 → 置温湿度采样标志(约 3 s)
 └─ 软件 PWM 计数 → 控制 P1.0

UART 中断
 └─ 收到 0x01~0x04 → 控制 LED2 或风扇档位

Timer0 每 10 ms 进入一次中断,tim_count 累计到 300 才置位,因此理想周期约为:

$T_{DHT}=300\times10\text{ ms}=3000\text{ ms}=3\text{ s}$

源码注释中的 1000 ms 与实际计数不一致,应按 3 s 理解。DHT11 不适合高频连续读取,用标志位降低采样频率是正确方向。

软件 PWM 使用 pwm_count 在 0~9 之间循环。计数小于 level 时输出高电平,否则输出低电平,所以占空比约为:

$D=\frac{level}{10}\times100%$

level=0~10 分别对应约 0%、10%、20%……100%。当 level=10 时,pwm_count 的 0~9 始终小于 10,所以输出保持高电平,即满占空比。

串口接收中断取得 SBUF 后,用 switch 解释一个字节:0x01 开 LED2、0x02 关 LED2、0x03 增大风扇档位、0x04 减小档位。手机助手必须选择 HEX 发送;输入 01 表示字节 0x01,若按文本发送字符 1,得到的是 ASCII 0x31,程序不会进入对应分支。

中断和主循环共同访问的标志或档位变量,在严格的嵌入式 C 工程中宜声明为 volatile,防止编译器把主循环中的读取长期缓存。中断服务函数应尽量短,只记录事件;OLED 刷新、DHT11 时序读取和长串口发送应放在主循环中执行。

项目源码还有两个值得注意的细节:

  • DHT11 组装第一个数据字节前,应先把 data_byte 清零,否则左移和按位或会读取不确定初值;每进入一次等待电平的超时循环前,也应把 count 清零,避免低电平位累计上一次计数而被误判为超时。
  • OLED 的动态数字只需在数据或档位变化时刷新,无条件反复发送 I²C 数据会占用主循环时间。

1.3 实验演示

实验时先观察 OLED 的温湿度是否周期更新,再遮挡或照射光敏模块,确认 LED4 随模块数字输出变化。很多光敏数字模块的比较器输出为低电平有效,源码的逻辑是 SUN==0 时令 LED4=1;而板载 LED 若低电平点亮,此时实际表现为熄灭。判断“亮时开灯还是暗时开灯”必须同时结合传感器输出极性和 LED 有效电平,必要时交换 0/1 分支。

手机端连接蓝牙模块后建立四个按钮,并设置为 HEX 发送:

控制字节动作
01LED2 点亮
02LED2 熄灭
03风扇档位加 1,最高为 10
04风扇档位减 1,最低为 0

若某一模块单独正常、组合后异常,应按“电源→共地→引脚冲突→中断时长→协议字节”的顺序检查。电机启动造成复位或温湿度数据跳变,通常优先检查供电压降、地线回路和电机干扰,而不是先怀疑业务代码。

1.4 VS Code介绍

VS Code 是通用源代码编辑器,适合浏览整个工程、跨文件搜索、安装 C 语言扩展和 AI 辅助插件。它本身不是 51 单片机编译器,也不会自动替代 Keil 的 C51 工具链;课程中主要用它阅读和整理 .c/.h 文件,实际编译、链接和烧录仍使用已经配置好的嵌入式工具链。

1.5 VS Code功能介绍

安装时可按需要勾选“添加到 PATH”“将‘通过 Code 打开’添加到文件和目录上下文菜单”等选项。打开完整工程文件夹后,左侧资源管理器能显示 main.c、各驱动目录和头文件;全局搜索可追踪函数声明、定义和调用位置。

初学者阅读综合项目时,可先从 main.c 的初始化和主循环开始,再沿 #include 与函数调用进入 DHT11、OLED、UART、Timer 等模块。不要只看单个文件,否则容易忽略宏定义的引脚、定时器初始化参数以及中断服务函数。