基于51单片机的智能门禁系统仿真LCD12864显示原理图程序

硬件设计

本电路是由STC89C52 单片机为控制核心,射频卡信息由MFRC522模块读出,通过MCU在LCD12864上显示,通过按键完成密码验证和修改密码的功能。整个门禁系统框图如图3-1所示。
基于51单片机的智能门禁系统仿真LCD12864显示原理图程序_第1张图片
基于51单片机的智能门禁系统仿真LCD12864显示原理图程序_第2张图片

3.1 STC89C52主控模块
3.1.1 STC89C52简介
STC89C52是宏晶科技发行的一款兼容标准MCS-51指令系统,工业80C51产品指令和引脚完全兼容的51单片机。传统的8051系列单片机只有128-256个字节RAM可使用,对于工程量较大的程序设计时往往会不够用。而STC89C52RC系列单片机扩展了256个字节RAM,拓展的容量,在应用中渐渐取代传统单片机被广泛应用。STC89C52还拥有8K字节在线可编程的Flash存储器、支持在线SPI编程、32个双向数据I/O口线、两个16位定时器/计数器和全双工UART串行通道[12]。

3.1.2 STC89C52主要特性
1)与MCS-51 兼容
2)寿命:1000次擦/写
3)据保留时间:10年
4)全静态工作:0Hz-24Hz
5)512M内部RAM
6)32双向数据I/O线
7)两个16位定时器/计数器
8)5个中断源
9)可编程串行通道
10)芯片内自带振荡器和时钟电路[13]

3.1.3 STC89C52管脚说明

图3-2 STC89C52管脚图
VCC:电源电压。
GND:接地。
P0口:P0口为一个8位双向I/O口,内部不提供上拉电阻。连接电路时需外接上拉电阻。P0口缓冲器能接受输出8TTL门电流。当P0口的管脚第一次写入“1”时,被定义为高阻输入。P0能够作为外部程序数据存储器,暂时存储外部输入数据而不需反复输入。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。由于内部上拉的缘故,P1口管脚写入“1”后,其管脚电平被上拉电阻拉高,此时管脚用作输入。P1口被上拉电阻下拉为低电平时,此时管脚作为将输出电流端口用。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收输出4个TTL门电流。由于内部上拉的缘故,当P2口被写“1”时,其管脚电平被上拉电阻拉高,且作为输入。P2口被上拉电阻下拉为低电平时,此时管脚作为将输出电流端口用。在FLASH编程和

校验时,P2口用来接收高八位地址和控制信号。
P3口:P3 口是一个具有内部上拉电阻的8 位双向I/O 口,P3口缓冲器可接收输出4个TTL门电流。对P3口管脚写入“1”时,其管脚电平被上拉电阻拉高,此时可以作为输入口使用。P3口也作为STC89C52的第二功能使用[14]。具体功能如表3-1所示:
表3-1 P3口功能表
端口引脚 第二功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 INT0(外部中断0)
P3.3 INT1(外部中断1)
P3.4 T0(记时器0)
P3.5 T1(记时器1)
P3.6 WR(外部数据存储器写选通)
P3.7 RD(外部数据存储器读选通)

RST:复位输入,高电平有效。当需对器件进行复位时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG: ALE是地址锁存允许信号端,低电平有效。在FLASH编程期间,此引脚用于输入编程脉冲。PORG为编程脉冲的输入端。当ALE/PROG接上低电平的时候,单片机对外部存储器进行数据读取时,用来锁住地址线的低位地址。
/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:当/EA保持低电平时,在此期间数据输入都存入外部程序存储器,不管内部程序存储器是否有空间存储数据。
XTAL1:反向振荡放大器的输入及外部时钟工作电路的输入。
XTAL2:反向振荡放大器的输出及外部时钟工作电路的输出。

3.2.4 LCD12864基本特性
(1)显示分辨率:128×64点
(2)内置128个16×8点阵字符
(3)内部含有繁体、简体中文字库,包括含8192个汉字
(4)低电源电压(VDD:+3.0-+5.5V)
(5)2MHZ时钟频率
(6)显示方式:STN、正显、半透
(7)工作温度: 0℃-+55℃ ,存储温度: -20℃- +60℃
(8)通讯方式:串行、并行
(9)内置转换电路,无需转换电压或外加负压 [17]

部分参考程序:

#include 
#include 
#include "main.h"
#define uchar unsigned char
#define uint  unsigned int

/*LCD12864  端口定义*/
#define LCD_data  P0            //数据口
sbit LCD_RS  =  P3^5;            //寄存器选择输入 
sbit LCD_RW  =  P3^6;            //液晶读/写控制
sbit LCD_EN  =  P3^4;            //液晶使能控制
sbit LCD_PSB =  P3^7;            //串/并方式控制,部分液晶不需要

uchar code dis0[]="  IC卡门禁系统  ";
uchar code dis1[]="1.IC卡输入      ";
uchar code dis2[]="2.密码输入:8位  ";
uchar code dis3[]="3.IC卡登记      ";
uchar code dis4[]="4.密码设置:8位  ";
uchar code dis5[]="成功            ";
uchar code dis6[]="失败            ";


void delay(int ms)	 //延时xms
{
    while(ms--)
	{
      uchar i;
	  for(i=0;i<250;i++)  
	   {
	    _nop_();			   
		_nop_();
		_nop_();
		_nop_();
	   }
	}
}	

void delayNOP()  //延时4us
{ _nop_(); _nop_(); _nop_(); _nop_();}
 /*******************************************************************/
/*                                                                 */
/*因为引脚的定义DB0..DB7是从P1.7...P1.0排列的                                                    */
/*所以顺序需要调换一下                                             */
/*                                                                 */
/*******************************************************************/
  INT8U swapbit(INT8U udata)
{
  INT8U ii,tmp=0;
  for(ii=0;ii<8;ii++)
  {
    tmp<<=1;
    if(udata&0x01)
    {
      tmp|=0x01;
    }
    udata>>=1;
  }
  return tmp;
}

/*******************************************************************/
/*                                                                 */
/*检查LCD忙状态                                                    */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。      */
/*                                                                 */
/*******************************************************************/
bit lcd_busy()
 {                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(LCD_data&0x80);
    LCD_EN = 0;
    return(result); 
 }
/*******************************************************************/
/*                                                                 */
/*写指令数据到LCD                                                  */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             */
/*                                                                 */
/*******************************************************************/
void write_cmd(unsigned char WCLCM,BuysC)
{                          
   unsigned int K=20000;     
   while(lcd_busy() && K--);  //预防没插LCD时候停在这
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_(); 
    LCD_data = swapbit(WCLCM);
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}
/*******************************************************************/
/*                                                                 */
/*写显示数据到LCD                                                  */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。                               */
/*                                                                 */
/*******************************************************************/
void lcd_wdat(unsigned char WDLCM)
{                          
   unsigned int K=20000;     
   while(lcd_busy() && K--);  //预防没插LCD时候停在这
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    LCD_data= swapbit(WDLCM);
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0; 
}
/*******************************************************************/
/*                                                                 */
/*  LCD初始化设定                                                  */
/*                                                                 */
/*******************************************************************/
void lcd_init()
{ 

   LCD_PSB = 1;         //并口方式	,部分液晶不需要
    write_cmd(0x36);      //扩充指令操作
    delay(5);
    write_cmd(0x30);      //基本指令操
	delay(5);
    write_cmd(0x0C);      //显示开,关光标
    delay(5);
    write_cmd(0x01);      //清除LCD的显示内容
    delay(5);
}	  
/*********************************************************/
/*                                                       */
/* 设定显示位置                                          */
/*                                                       */
/*********************************************************/
void lcd_pos(uchar X,uchar Y)
{                          
   uchar  pos;
   if (X==0)
     {X=0x80;}
   else if (X==1)
     {X=0x90;}
   else if (X==2)
     {X=0x88;}
   else if (X==3)
     {X=0x98;}
   pos = X+Y ;  
   write_cmd(pos);     //显示地址
}

/*********************************************************/
/*														 */
/* 显示主程序           							     */
/*                                                       */
/*********************************************************/
void display_all()
 {

    uchar i;          
	   	  
	  lcd_pos(0,0);             //第一行显示数字0~9
	  i = 0;   
      while(dis0[i] != '\0')
       {
         lcd_wdat(dis0[i]);      //显示字母
         i++;
       }
	     
      lcd_pos(1,0);             //第二行显示字母
	  i = 0;   
      while(dis1[i] != '\0')
       {
         lcd_wdat(dis1[i]);      //显示字母
         i++;
       }

 	  lcd_pos(2,0);             //第三行显示文字
	  i = 0;
      while(dis2[i] != '\0')
       {
         lcd_wdat(dis2[i]);     
         i++;
       }

	  lcd_pos(3,0);             //第四行显示广工无线电社
	  i = 0;
      while(dis3[i] != '\0')
       {
         lcd_wdat(dis3[i]);     
         i++;
       }
	  
}

/*********************************************************/
/*														 */
/* 特定字符显示主程序           							     */
/*                                                     

C:
0="  IC卡点台灯    ";
1="1.读卡中....    ";
2="2.登记....      ";
3="成功            ";
4="失败            ";

/*********************************************************/
void display(uchar a,uchar b,uchar c)
 {

      uchar i;          	  
	  lcd_pos(a,b);             //第一行显示数字0~9
	  i = 0; 
	  switch(c)
	  {
	       case 0: 
                while(dis0[i] != '\0')
              {
                lcd_wdat(dis0[i]);      //显示字母
                i++;
              }
			  break;

	  	   case 1: 
               while(dis1[i] != '\0')
              {
                lcd_wdat(dis1[i]);      //显示字母
                i++;
              }
			  break;

			 case 2: 
               while(dis2[i] != '\0')
              {
                lcd_wdat(dis2[i]);      //显示字母
                i++;
              }
			  break;


			  case 3: 
               while(dis3[i] != '\0')
              {
                lcd_wdat(dis3[i]);      //显示字母
                i++;
              }
			  break;	  
			  
			  
	   case 4: 
               while(dis4[i] != '\0')
              {
                lcd_wdat(dis4[i]);      //显示字母
                i++;
              }		 
			  break;	  

	   case 5: 
               while(dis5[i] != '\0')
              {
                lcd_wdat(dis5[i]);      //显示字母
                i++;
              }		 
			  break;
	   case 6: 
               while(dis6[i] != '\0')
              {
                lcd_wdat(dis6[i]);      //显示字母
                i++;
              }		 
			  break; 

			  default :break;
	  }
 }

附:http://www.jh-tec.cn/archives/7319

你可能感兴趣的:(技术分享,单片机,51单片机,stm32)