步进电机实验

Tutorial: 卓越工程师 Category: 嵌入式 Published: 2026-10-23 11:05:29 Views: 0 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 , 宋体 )*/

};

#endif

/* ==================== Step_Motor\step_motor.c ==================== */
#include "step_motor.h"
#include "main.h"

/* 按半步八拍表驱动四相绕组;dir 为 0 时反向索引相位。 */
void step_motor_conctrl(unsigned char step,unsigned char dir)
{
	unsigned char temp=step;
	
	if(dir==0)				/* 逆时针时倒序取相位。 */
		temp=7-step;
	switch(temp)				/* 半步八拍:A→AB→B→BC→C→CD→D→DA。 */
	{
		case 0: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=0;break;
		case 1: IN1_A=1;IN2_B=1;IN3_C=0;IN4_D=0;break;
		case 2: IN1_A=0;IN2_B=1;IN3_C=0;IN4_D=0;break;
		case 3: IN1_A=0;IN2_B=1;IN3_C=1;IN4_D=0;break;
		case 4: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=0;break;
		case 5: IN1_A=0;IN2_B=0;IN3_C=1;IN4_D=1;break;
		case 6: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=1;break;
		case 7: IN1_A=1;IN2_B=0;IN3_C=0;IN4_D=1;break;
		default: IN1_A=0;IN2_B=0;IN3_C=0;IN4_D=0;break; /* 异常相位时释放全部绕组。 */
	}			
}

/* ==================== Step_Motor\step_motor.h ==================== */
#ifndef _STEP_MOTOR_H_
#define _STEP_MOTOR_H_
//#include "main.h"

void step_motor_conctrl(unsigned char step,unsigned char dir);


#endif

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

void Timer0_Init(void)
{
	TMOD &= 0xF0; /* 清 Timer0 模式位,保留 Timer1。 */
	TMOD |=0x01;  /* Timer0 方式 1,16 位定时。 */
	TH0 = 0XFE;   /* 约 0.5 ms 初值高字节。 */
	TL0 = 0X33;   /* 初值低字节。 */
	TF0 = 0;      /* 清溢出标志。 */
	ET0 = 1;      /* 此工程虽未定义中断服务,仍保留模板配置。 */
	EA = 1;
	TR0 = 1;      /* 启动定时器。 */
}

/* ==================== 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') //判断字符串结束符,如果识别到‘\0',则跳出while,结束发送
	{
		UART_Send_Byte(*send_str++);	//本质是一个字节一个字节的发送,
		//发送完一个字节,地址+1,等待发送下一个字节,直到检测到字符串结束符为止
	}	
} 

void UART_Init(void)
{
	SCON = 0x50; 	//串口配成工作方式1
	PCON &= 0x7F; //波特率不加倍
	TMOD &= 0x0f;	
	TMOD |= 0x20;	//定时器1,模式二,自动重装初值,串口按照一定速率发数据,需要用的定时器
	TH1 = 0xFD;	
	TL1 = 0xFD; //@11.0592MH时钟,9600比特率定时器初值
	TR1 = 1; //定时器开始运行   
	ES = 1;  //串口中断打开
	EA=1;					//总中断打开
	recv = 0;
}

/* ==================== 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

一、步进电机实验

本实验使用 51 单片机、28BYJ-48 五线四相步进电机和 ULN2003 驱动板。按键 1 切换转向,按键 2 在 1~5 档之间循环调速,OLED 显示方向和速度档位。

1.1 实验演示与接线方式

控制线按代码中的定义连接:IN1→P2.0、IN2→P2.1、IN3→P2.2、IN4→P2.3。驱动板的 + 接 5 V,- 接 GND,电机插头接驱动板五针座。单片机与驱动板必须共地,否则四路控制信号没有共同的电平参考。

28BYJ-48 的线圈电流明显大于普通 GPIO 能安全提供的电流,因此不能把电机线圈直接接到 P2 口。ULN2003 是七路达林顿低端驱动器,本实验只使用其中四路:

51 单片机                      ULN2003 驱动板                  五线四相电机
P2.0 ──> IN1 ──> 达林顿开关1 ──> OUT1 ──> A 相线圈端
P2.1 ──> IN2 ──> 达林顿开关2 ──> OUT2 ──> B 相线圈端
P2.2 ──> IN3 ──> 达林顿开关3 ──> OUT3 ──> C 相线圈端
P2.3 ──> IN4 ──> 达林顿开关4 ──> OUT4 ──> D 相线圈端
 GND ─────────────────────────── GND
 5 V ─────────────────────────── 电机公共端(通常为红线)
                                  COM ──> 5 V(续流二极管公共端)

某路输入为高电平时,对应达林顿管导通,输出端被拉向 GND,电流路径为 5 V→公共端→线圈→ULN2003→GND,该相线圈产生磁场。断开感性线圈时会出现反向感应电压,ULN2003 内置的钳位二极管为电流提供泄放通道,从而保护驱动管和单片机。

驱动板跳帽的具体连接要以板上丝印为准。课程所用模块的跳帽用于接通电机电源公共端,按演示接法需保留;更换其他版本模块时,应先确认跳帽连接的是 VCC/COM 还是独立电机电源,不能只凭外形判断。

若电机电流较大,宜使用独立、稳定的 5 V 电源给驱动板供电,同时让该电源 GND 与单片机 GND 相连。不要假定电脑 USB 或开发板稳压电路可以长期承担任意电机电流。

1.2 原理与代码编写

步进电机不依靠连续变化的模拟电压控制角度,而是按规定顺序给不同线圈通电。每切换一次通电状态,转子磁极就追随定子合成磁场移动一个步距。改变通电顺序可改变方向,改变相邻状态之间的时间间隔可改变速度。

1.2.1 走进电机

28BYJ-48 属于带减速齿轮箱的永磁式步进电机。外部看到的是输出轴,内部电机转子先按小角度步进,再经过齿轮组减速,因此输出轴转得更慢、扭矩更大。不同批次的电机减速比和标称步距可能不同,计算一圈所需脉冲数时应以具体型号参数和实测结果为准,不能把某个固定数值套用到所有 28BYJ-48。

五根线中,一根是四相线圈的公共端,另外四根分别连接 A、B、C、D 相。所谓“四相”指四组可独立受控的绕组,所谓“五线”指四个相端加一个公共端。

flowchart LR
    V[+5 V 公共端] --> A[A 相线圈]
    V --> B[B 相线圈]
    V --> C[C 相线圈]
    V --> D[D 相线圈]
    A --> OA[ULN2003 OUT1]
    B --> OB[ULN2003 OUT2]
    C --> OC[ULN2003 OUT3]
    D --> OD[ULN2003 OUT4]
    OA --> G[GND]
    OB --> G
    OC --> G
    OD --> G

GPIO 输出的是“是否让驱动开关导通”的逻辑量,并不直接给线圈供电。代码中的 1 表示对应 ULN2003 通道导通、该相得电;0 表示该相断电。

1.2.2 五线四相

代码采用八拍半步驱动,即单相通电与双相通电交替:

节拍ABCD通电状态
01000A
11100A+B
20100B
30110B+C
40010C
50011C+D
60001D
71001D+A

相邻两拍只改变一相,合成磁场移动较平滑;相较四拍单相驱动,八拍方式的步距更小。代码顺序执行 0→1→…→7 时朝一个方向转,执行 7→6→…→0 时反转。源码使用 temp = 7 - step 实现倒序。

只给某一状态并不会让电机连续旋转,必须持续循环输出整套节拍。若顺序错误,常见现象是电机抖动、嗡鸣或只锁住不转;若 A、B、C、D 接线整体次序颠倒,则方向会改变。

1.2.3 代码

程序的核心状态量如下:

变量范围作用
dir0 或 1选择正序或倒序输出八拍
step0~7当前节拍编号,每输出一次后递增并取模
speed1~5速度档位,映射为 Delay_xms(6-speed)

因此 1~5 档分别对应约 5、4、3、2、1 ms 的节拍延时。这里控制的是节拍间隔,并不是闭环测得的真实转速:延时越短,给定步频越高;电源能力、负载、齿轮摩擦和电机本体都会影响实际转速。

1.2.3.1 实例操作

主循环先检测按键,再调用 step_motor_conctrl(step++, dir) 输出下一拍,随后用 step %= 8 把节拍限制在 0~7。函数名 conctrl 是工程中沿用的拼写,调用处与声明、定义保持一致即可正常链接;后续自行整理工程时可统一命名为 control。

按键 1 通过 dir = !dir 切换方向;按键 2 通过 speed = speed % 5 + 1 实现 1→2→3→4→5→1 循环。方向突然反转或高档直接启动时,转子可能失步。要求运行更可靠时,应逐级改变节拍间隔,形成加减速斜坡。

OLED 的 I²C 刷新比一次 GPIO 切换慢得多。固定文字可在初始化阶段显示;方向或档位发生变化时再更新对应数字。若在高速主循环中无条件反复刷新 OLED,步进节拍会被拉长且不均匀,电机可能变慢、抖动甚至停转。更稳妥的结构是用定时器产生固定节拍,主循环只处理按键和显示。

停止电机时还有两种取舍:保持最后一拍可以提供保持力,但线圈持续发热、耗电;把 A~D 全部置 0 可以降低功耗,但输出轴不再保持位置。实际项目应根据负载和温升选择。