51单片机实例学习四 128X64 液晶显示器、PS/2与单片机通信、密码锁

十四.128X64 液晶显示器的基本应用

[实验任务]

利用128X64点阵液晶显示屏显示图片,字符,汉字,画点,实现其基本显示

功能。

[硬件电路图]

[实验原理]

关于液晶显示的原理请用户自行其查找资料,这里只介绍 128X64 点阵液晶

显示屏的具体应用。驱动程序为用户提供了一个应用框架,大家只要直接应用驱

动程序提供的功能将可以了。在编程序前要先用液晶字模提取软件提取字模复制到 hzzi.h 文档,再在主程序里面编写程序。我们使用的液晶没有自带字库,必须提取字模到程序里。5V稳压电源,所以没有点亮液晶的背光。

[C语言源程序]

//注意:以下提供程序并没有包含128X64 液晶显示驱动程序,只有主程序。

#include<reg52.h>

#include<lcd12864.h> //包含128X64 驱动程序

#include<hzzi.H> //包含图片和汉字库

void delay(int x) //延时程序

{

int i,j;

for(i=0;i<600;i++)

for(j=0;j<x;j++);

}

void main(void)

{

unsigned char lie; //定义列

unsigned char hang; //定义行

lcd_init(); //初始化液晶驱动硬件

lcd_clr(); //清屏

while(1)

{

lie=15;//列的值可以是0--127 任意一个

hang=0;//行的值视情况而定

lcd_clr();

Disp_Img(yema);//显示一张128X64 的点阵的图片

delay(200); //延时等待

lcd_clr(); //清屏使残留的点不影响后面的显示

hz_disp(lie+0, hang, da);//在第15 列,第0 行显示汉字'大'

hz_disp(lie+16,hang, jia);//显示汉字'家'

hz_disp(lie+32,hang, yi);//显示汉字'一'

hz_disp(lie+48,hang, qi);//显示汉字'起'

hz_disp(lie+64,hang, lai);//显示汉字'来'

hz_disp(lie+80,hang, xue);//显示汉字'学'

hang=2;//换行 一行有8 个点阵 一列只有一个

hz_disp(lie+24,hang, dan );//显示汉字'单'

hz_disp(lie+40,hang, pian);//显示汉字'片'

hz_disp(lie+56,hang, ji);//显示汉字'机'

hang=4;//换行

hz_disp(lie+0, hang, huan);

hz_disp(lie+16,hang, ying);

hz_disp(lie+32,hang, jia1);

hz_disp(lie+48,hang, ru);

hz_disp(lie+64,hang, qq);

hz_disp(lie+80,hang, qun);

lie=32; hang=7;//换行.换列.

delay(50);

lcd_putchar8x8(lie+0, hang, 1+'0');//显示8X8 字符

delay(50);//延时 达到一个字一个字往外蹦的效果

lcd_putchar8x8(lie+8, hang, 9+'0');delay(50);

lcd_putchar8x8(lie+16,hang, 3+'0');delay(50);

lcd_putchar8x8(lie+24,hang, 0+'0');delay(50);

lcd_putchar8x8(lie+32,hang, 5+'0');delay(50);

lcd_putchar8x8(lie+40,hang, 2+'0');delay(50);

lcd_putchar8x8(lie+48,hang, 5+'0');delay(50);

lcd_putchar8x8(lie+56,hang, 5+'0');

delay(200);//延时显示

lcd_clr();

hang=0;

for(lie=0;lie<128;lie++)

{//画点时 行取值0--64,列取值0--128

set_point(lie,hang);hang++;

if(hang==32){hang=0;}

delay(5);

}

delay(200);

hz_disp128x32(0,0,qian33);//显示128X32 的图片

hz_disp128x32(0,4,dpy);

delay(300);

}

}

除了以上的例子外,还可以显示12X12.32X32.120X2.点阵图形///

///用法和上面的例子差不多,大家实践几次就可以熟练应用了/

---------------------------------------------------------------------------------------------------------------------------------

十五.标准键盘 PS/2与单片机通信

[实验任务]

标准键盘 PS2 向单片机输入数字.字母.字符等,用 128X64 液晶显示器显示

出来。

[硬件电路图]

[实验原理]

键盘通过时钟线和数据线和单片机通信,键盘和系统的相互通信都是采用

11 位格式的串行方式。第 1 位是起始位 0;第 2 到 9 位是 8 位数据位,第 10 位

是奇偶校验位。第11位停止位。时序图如下

[C语言源程序]

//注意 与第十三个实验128X64液晶显示器的基本应用一样,以下提供程序并没

//有包含128X64 液晶显示驱动程序,只有主程序和PS2 键盘通信的驱动程序。

//请大家到QQ 群:19305255,资源共享里面去下

//以下程序只有单片机接收PS2 键盘程序,没有单片机向PS2 发送命令程序。

//还有键盘数据处理上不是很完善,主要是为用户提供一个参考程序。

//如果把此实验看作是一个系统的话,那么这一个系统就是一个漏洞百出,充满

//Bug 系统。大家在用的时侯可以对它多作改进。

#include<reg52.h>

#include<lcd12864.h>//包含128X64 驱动程序

#include<hzzi.H> //包含图片和汉字库

sbit Key_Data =P2^0;//定义Keyboard 数据端口引脚

sbit Key_CLK=P3^3; //中断端口,时钟线

static unsigned char KeyV=0X00; //键值

static unsigned char BF = 0; //标识是否有字符被收到

static unsigned char IntNum = 0; //中断次数计数

unsigned char lie,hang;//lie 为列值, hang 为行值

bit dx=0; //大小写标志 dx==1 时大写状态

void Keyboard_out(void) interrupt 2//键盘中断处理 键值存储在 KeyV 中

{

if ((IntNum>0) && (IntNum <9))

{

KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位

if (Key_Data==1) //当键盘数据线为1 时

{KeyV = KeyV | 0x80;} //存储一位

}

IntNum++; //中断次数加一(中断一次接收一位数据)

if (IntNum > 10) //中断11 次后数据发送完毕

{

IntNum=0; //当中断11 次后表示一帧数据收完,清变量准备下一次接收

BF = 1; //标识有字符输入完了

EA = 0; //关中断等显示完后再开中

}                     

}

void Decode() //键值处理

{

unsigned char data TempCyc;

signed char data k;

TempCyc=KeyV;

if(BF==1) //接收完一个有效数据时

{

BF=0; //准备下一次接收

switch ( TempCyc ) //键值与显示字符的对应关系

{ //键值// //对应字符//

case 0x8A: k=0; break; //0 case 0x3C: k=2; break; //2

case 0x2C: k=1; break; //1 case 0x4C: k=3; break; //3

case 0x4A: k=4; break; //4 case 0x88: k=24; break;

case 0x5C: k=5; break; //5 case 0x9A: k=25; break;

case 0x6C: k=6; break; //6 case 0x2A: k=26; break;

case 0x7A: k=7; break; //7 case 0x5A: k=27; break;

case 0x7C: k=8; break; //8 case 0x36: k=28; break;

case 0x8C: k=9; break; //9 case 0x58: k=29; break;

case 0x38: k=10; break; //a case 0x78: k=30; break;

case 0x64: k=11; break; //b case 0x54: k=31; break;

case 0x42: k=12; break; //c case 0x3A: k=32; break;

case 0x46: k=13; break; //d case 0x44: k=33; break;

case 0x48: k=14; break; //e case 0x6A: k=34; break;

case 0x56: k=15; break; //f case 0x34: k=35; break;

case 0x68: k=16; break; //g case 0x98: k=63; break;

case 0x66: k=17; break; //h case 0xAA: k=65; break

case 0x86: k=18; break; //i case 0xF2: k=68; break;

case 0x76: k=19; break; //j case 0x52: k=-16;break; //空

case 0x84: k=20; break; //k case 0xB0: k=101;brea

case 0x96: k=21; break; //l 大小写控制键Caps lock

case 0x74: k=22; break; //m }

case 0x62: k=23; break; //n

if(k==101) {dx=!dx;} //按下大小写控制键时 大小写标志取反

if(k==-16) //空格键按下时

{

lcd_putchar8x8(lie, hang, -16+'0'); //清除光标

lcd_putchar8x8(lie+8, hang, 79+'0');//光标移一位

}

if(dx==0) //小写状态时显示

{

lcd_putchar8x8(lie, hang, k+'0');//小写字符

lcd_putchar8x8(lie+8,                     hang, 79+'0');//光标

}

if(dx==1)//大写状态时显示

{

if(k>9 && k<=35)

{

lcd_putchar8x8(lie, hang, (k+26)+'0');//大写字符

lcd_putchar8x8(lie+8, hang, 79+'0');//光标

}

if(k>=0 && k<=9)

{

lcd_putchar8x8(lie, hang, (k-10)+'0');//数字键对应的符号

lcd_putchar8x8(lie+8, hang, 79+'0');//光标

}

}

if(lie==120) //写满一行

{lie=0;hang=hang+1;//换行

lcd_putchar8x8(lie, hang, 79+'0');}//光标下移

else {lie=lie+8;}

EA=1;

}

}

void delay(int x) //延时程序

{ int i,j;

for(i=0;i<600;i++)

for(j=0;j<x;j++); }

void wlcome() //开机画面和欢迎界面

{

lcd_init(); //初始化液晶驱动硬件 hz_disp(lie+24,hang, shu );//'输'

lcd_clr(); //清屏 hz_disp(lie+40,hang, ru);//'入'

Disp_Img(yema);//显示一张图片 hz_disp(lie+56,hang, xi);//'系'

delay(200); //延时等待 hz_disp(lie+72, hang, tong);//'统'

lie=20; hang=1; delay(200);lcd_clr();

lcd_clr(); lie=8; hang=0;

hz_disp(lie+0, hang, huan);//'欢' hz_disp(lie+16,hang, qing);// '请'

hz_disp(lie+16,hang, ying);//'迎' hz_disp(lie+32,hang, shu);//'输'

hz_disp(lie+32,hang, shi);//'使' hz_disp(lie+48,hang, ru);//'入'

hz_disp(lie+48,hang, yong);//'用' hz_disp(lie+64,hang, zi);//'字'

hz_disp(lie+64,hang, DP);//'DP' hz_disp(lie+80,hang, fu);//'符'

hz_disp(lie+80,hang, Y);//'Y' for(lie=0;lie<128;lie++)//画一条直线

lie=8;hang=4; {set_point(lie,15);}

}

void main()

{                      

wlcome() ; //调用开机画面和欢迎界面子程序

IT1 = 1; //设外部中断1 为下降沿触发

EA = 1; //开总中断

EX1=1; //开中断 1

hang=2; lie=0;//输入的字符从第 2 行 第0 列开始显示

while(1)

{

Decode();

delay(50);

}

}

-------------------------------------------------------------------------------------------------------------------------------------

十六,128X64无字库液晶4X4键盘输入使用(密码锁)

引脚

标号

功能说明 

备注

1

Vss

逻辑负电源输入引脚,0V

2

Vdd

逻辑正电源输入引脚,+5V 

3

Vo

LCD驱动电源输入引脚,大小可调LCD显示对比度

一般接0V

4

RS

数据/指令寄存器选择引脚

RS=“H” :数据D0-D7 与数据寄存器通信

RS=“L” :数据D0-D7 与指令寄存器通信

5

R/W

读/写选择引脚

高电平:读数据

低电平:写数据

若不须要读操

作功能,该引脚

可直接接地

6

E

读写使能引脚

    高电平有效,下降沿锁定数据

7~14

D0~D7

8 位数据线引脚

4 位总线模式

下,D0~D3 引

脚断开

15

A

背光电源输入引脚,+5V

不带背光的模

块无此引脚

16

K

背光电源输入引脚,0V

#include<reg52.h>            

#include<math.h>               

#include<intrins.h>             

#define  uchar unsigned char     

#define  uint  unsigned int

#define  data_IO P2

sbit     rs=P3^0;     //指令和数据寄存器 “1是数据,” “0是指令”

sbit     rw=P3^1;   //读写控制,“1读” “0写”

sbit   e=P3^2;   //片选信号

sbit      p=P2^7;

sbit   deng=P0^0 ; ///响音乐的端口

sbit   md=P0^1;    ///修改密码时的灯

uchar  pwflag;  //密码是否正确的标志位

uchar  count;  //

uchar  gg=0 ;  //只有输入正确的密码才能修改密码

uchar  cs=3 ;  //输入密码的错误次数

uchar m[]={1,2,3,4,5,6}; ///初始密码

static uchar mbuf[6];///输入的密码

 char d[32]={' ','I','M','P','O','R','T',' ','C','I','P','H','E','R',':',' ',

             ' ',' ','_',' ',' ','_','_','_','_','_','_',' ',' ',' ',' ',' '};//输入密码

code  char ks[32]={'C','O','N','G','R','A','T','U','L','A','T','E',' ','Y','O','U',

                       ' ','O','P','E','N','I','N','G',' ',' ','L','O','C','K','!',' '};开锁

code char cw[32]={' ','C','I','P','H','E','R',' ',' ','E','R','R','O','R',' ',' ',

                           '~','~','~','~','~','~','~','~','~','~','~','~','~','~','~','~' };错误    

code char xc[32]={' ',' ','A','M','E','N','D',' ','S','U','C','C','E','E','D',' ',

                  ' ',' ',' ',' ',' ','!','!','!','!','!','!',' ',' ',' ',' ',' '};//修改成功 

code char xg[32]={' ','A','M','E','N','D',' ',' ','C','I','P','H','E','R',':',' ',

                  ' ',' ',' ',' ',' ','_','_','_','_','_','_',' ',' ',' ',' ',' '};///修改密码*/

void yanshi(uint n)///延时函数///

{

 uint i;

  for(i=0;i<n;i++){};

}

void delay(uint n)///延时函数///

{

 uint i,j;

  for(i=0;i<1000;i++)

   {for(j=0;j<n;j++){}}

  

}

void busy() 判断是否忙

{data_IO=0xff;

 rs=0; //写指令        

 rw=1; //表示读状态    // 三个的状态表示 //

 e=1;  //下降延//      // 判忙状态       //

 while(!p);        

// e=0;

}

void xiezl(uchar shuju) /*写指令*/

{

 busy();/*yanshi(6500);*/

 data_IO=shuju;

 rs=0; //写指令       

 rw=0; //表示写状态    // 三个的状态表示 //

 e=1;  //下降延//      // 写指令         //

 e=0;  /      

}

void w_dat(uint n)//写数据//

{

 busy(); /*yanshi(6500) ;*/

  data_IO=n;

   rs=1; //写数据      

   rw=0; //表示写状态    // 三个的状态表示 //

   e=1;  //下降延//      //写数据         //

   e=0;  /      

  // return;

}

void xianshi(uchar js[]) //显示函数///

{

  uchar h,v;

  xiezl(0x01); //清屏显示

  yanshi(2000) ;

  xiezl(0x80); // DDRAM地址的设置

 for(h=0;h<16;h++)

   {w_dat(js[h]);  ///n表示有写几位数据

   yanshi(100) ;

   }

   xiezl(0xc0);//换行

 for(v=(16);v<32;v++)

   {w_dat(js[v]);  ///n表示有写几位数据

   yanshi(100) ;

   }

}

void chushihua(void)///*液晶模块初始化*/

 { uchar i;

   rs=0; //写指令    

   rw=0; //表示写状态

   e=0;  //使能

   for(i=0;i<3;i++)

   {

    xiezl(0x38);  //功能设置,8位,一行显示,5*7点阵

    yanshi(1000);

   }

    xiezl(0x38); //两行显示

    xiezl(0x0f); //显示开关控制位

    xiezl(0x18); //移位控制,光标和显示一起左移 

    xiezl(0x06); //设置输入模式

    xiezl(0x01); //清屏显示

    xiezl(0x80); // DDRAM地址的设置

    }

bit pwcmp(void)

{

       bit flag;

       uchar i;

       for (i=0;i<6;i++)

       {

              if (m[i]==mbuf[i])   flag = 1;   //*密码正确*/

              else  {  flag = 0;  i=6; } //*密码错误*/

       }

       return(flag);

}

void gb(void)/转移光标

{  uchar c;

   xiezl(0xc0);//换行

   yanshi(3000) ;

   for(c=0;c<5;c++)

   {w_dat(' ');///n表示有写几位数据

    yanshi(2000) ;

   }

}

uchar getkey(void)///得到键值

{ uchar h,l,k;

  while(P1!=0x0f)

  {

   h=P1&0x0f;

   P1=0xf0;

   l=P1&0xf0;

   k=h|l;

   return(k);

  }

}

void diaoyong(uchar i)///调用各键的函数//输入密码

{  uchar lq;

         switch(i)

           {

          case 0x7e: if (count<6) { mbuf[count]=1; count++;  w_dat('*');} break;  // 01111110       1

          case 0xbe: if (count<6) { mbuf[count]=2; count++;  w_dat('*');}break;  // 10111110          2

          case 0xde: if (count<6) { mbuf[count]=3; count++;  w_dat('*');} break;  // 11011110          3

          case 0xee: if (count<6) { mbuf[count]=4; count++;  w_dat('*');} break;  // 11101110          4

          case 0x7d: if (count<6) { mbuf[count]=5; count++;  w_dat('*');} break;  // 01111101          5

          case 0xbd: if (count<6) { mbuf[count]=6; count++;  w_dat('*');} break; // 10111101             6

          case 0xdd: if (count<6) { mbuf[count]=7; count++;  w_dat('*');} break;  // 11011101         7

          case 0xed: if (count<6) { mbuf[count]=8; count++;  w_dat('*');} break;  // 11101101         8

          case 0x7b: if (count<6) { mbuf[count]=9; count++;  w_dat('*');} break;  // 01111011          9

          case 0xbb: if (count<6) { mbuf[count]=0; count++;  w_dat('*');}break;  // 10111011         0

          case 0xdb:   if (count==6) { pwflag = pwcmp();}   else  pwflag = 0;// 只有输入6个密码后按确认键才作密码比较

                                if(pwflag) {deng=0; xianshi(ks);gg=1; }   else { cs--;deng=1; xianshi(cw); delay(200); xianshi(d);gb();count = 0; }

                                 break;  // 11011011             a     

          case 0xeb:  count = 0;deng=1; xianshi(d);  gb();gg=0; /*取消键*/

                             break;  // 11101011       b  

          case 0x77: if(gg==1){ count=0;xianshi(xg); gb();} //修该密码

                             break;  // 01110111        c

         

                case 0xb7: if((count==6)&&(gg==1)) { count=0;for (lq=0;lq<6;lq++){ m[lq]=mbuf[lq]; yanshi(10000);} md=0; xianshi(xc); delay(200);md=1; xianshi(d);yanshi(2000);gb();yanshi(200);gg=0;}//保存密码

                             break;  // 10110111       d

          /*case 0xd7: sr[jm]='e'; break;  // 11010111              e

            case 0xe7: sr[jm]='f'; break;  // 11100111              f    */

          default: break;

          }

      

}

void main(void)

{uchar key;

chushihua();

xianshi(d);  //显示函数

gb();       //移光标到第二行第六位

while(cs)

{

  P1=0x0f;

  if(P1!=0x0f) 

 {

   yanshi(20);

   key=getkey();

   diaoyong(key);

   yanshi(20000);

}

}while(1);

}

------------------------------------------------------------------------------------------------------------------------------------------------------------

十七、串口下载线

十八步进电机控制程序:

原理图参考:单片机控制实训书44页

#include<reg52.h>  

#define uchar unsigned char

uchar a,b;

int k;

uchar zdzt=0x0c;

uchar zsgw=0x02;

uchar zsdw=0x00;

uchar yxsj=0x11;

uchar zs=20;

uchar zsscgw=0x1f;

uchar zsscdw=0x00;

void key(void);

void delay();

void delays();

code uchar tab[13]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39};

code uchar zssc[2]={0x1f,0x00};

main()

{

while(1)

{key();

if(zdzt==0x0c)

P1=0xff;

else if(zdzt==0x0a)

{P1=yxsj;

deleys();

yxsj=yxsj<<1|yxsj>>7;

}

else if(zdzt==0x0b)

{P1=yxsj;

delays();

yxsj=yxsj<<7|yxsj>>1;

}

}

}

void key(void)

{

if(!(P2&0x01))

{delay();

while(!(P2&0x01))

zdzt=0x0a;

}

else if(!(P2&0x02))

{

delay();

while(!(P2&0x02))

zdzt=0x0b;

}

else if(!(P2&0x04))

{

delay();

while(!(P2&0x04))

zdzt=0x0c;

}

}

void delay()

{

for(k=0;k<1200;k++);

}

void delays()

{

a=zssc[0];

while(a--)

{b=zssc[1];

while(b--);

}

}

#include<reg52.h>   /*闪烁灯*/

int k;

void delay()

{

for(k=0;k<2000;k++);

}

main()

{

while(1)

{

P1=0x01;

delay();

P1=0x04;

delay();

P1=0x02;

delay();

}

}

#include<reg52.h>  

#define uchar unsigned char

code uchar zz[]={0x08,0x01,0x04,0x02};

code uchar fz[]={0x08,0x02,0x04,0x01};

sbit start=P3^0;

sbit stop=P3^2;

void delay(uchar a)

{

uchar b,c;

for(b=0;b<a;b++)

for(c=0;c<100;c++);

}

void run(uchar a)

{

uchar b,c;

for(b=0;b<6;b++)

for(c=0;c<4;c++);

{if(a==1) P1=zz[c];

else P1=fz[c];

delay(0x10);

}

}

in0()interrupt0 using 1

{P1=0xff;

while(start);

void main(void)

{IE=0x81;

while(start);

while(1)

{

uchar a=4;

uchar b=3;

while(a--)

run(1);

while(b--)

run(2);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜航一直在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值