当前位置:文档之家› 单片机与12864及红外遥控的主题设计报告

单片机与12864及红外遥控的主题设计报告

单片机主题设计报告

目录

目录 (1)

1设计任务及要求 (1)

2总体设计思路及功能描述 (1)

3 各部分软硬件设计原理及方案详细说明 (6)

3.1 人机接口电路 (6)

3.2单片机与PC机通信电路 (8)

3.3 其他部分电路说明 (8)

3.4 软件模块设计 (9)

3.4.1 LCD初始化 (9)

3.4.2 键盘扫描程序 (11)

3.4.3 显示液晶汉字 (11)

3.4.4 地鼠的随机出现 (12)

5 设计心得体会 (12)

6 附录 (13)

6.1总原理图 (13)

6.2单片机程序代码 (14)

7 参考文献 (27)

正文:

1设计任务及要求

本设计以51系列单片机AT89s52为控制核心,以点阵液晶显示模块、遥控为人机接口,实现了一个打地鼠游戏机。通过本设计,令读者掌握利用单片机开发简单电子产品的基本技能,熟悉原理图绘制、仿真、软件设计、优化以及系统调试的基本方法,为进一步设计开发更为复杂的嵌入式模拟/数字混合系统打下一定的基础。

"打地鼠”又称为“打地鼠”,是一种益智小游戏。其游戏规则比较简单,就是随机产生地鼠,即在12864显示屏相应相应的地鼠图案,规定时间内按相应的键,若按错或者未按键则结束游戏。本作品用红外遥控8个键来模拟锤子,另有一个复位按键控制程序的重启,

游戏界面:采用分辨率为128×64的液晶显示屏

2总体设计思路及功能描述

如图1--1打地鼠主要有一个主程序及相应的一些子程序。主程序的作用是一些初始化工作及相应模块的跳转。该主程序流程图:

有三个主要子程序:打地鼠子程序主要是实现打地鼠动作执行、地鼠的随机产生、得分累计、图像显示、相应的按键解释。而该游戏也融入了音乐的效果,使游戏更具有趣味性,由于课程设计有涉及该方面知识,等。该部分流程图为:

Work0

Work1

Work2

Work3

Work4

Work5

Work6

3 各部分软硬件设计原理及方案详细说明

3.1 人机接口电路

本游戏机游戏界面由液晶显示模块呈现。液晶显示模块中,最主要的就是LCD液晶屏。根据LCD 液晶屏显示内容的不同,液晶显示模块可以分为数显液晶模块、点阵字符液晶模块和点阵图形液晶模块3种。本设计使用点阵图形液晶模块OCM12864。OCM12864液晶显示模块是128×64点阵型液晶显示模块,可显示各种字符及图形,可与CPU直接连接,具有8位标准数据总线、6条控制线及电源线,各引脚的信号说明参见表ChpNum-1。

表ChpNum-1 OCM12864引脚说明

管脚名称

引脚说明

VSS - 逻辑电源地。

VDD - 逻辑电源+5V。

V0 I LCD调整电压,应用时接10K电位器可调端

RS I 数据\指令选择:高电平:数据D0-D7将送入显示RAM;

低电平:数据D0-D7将送入指令寄存器执行。

R/W I 读\写选择:高电平:读数据;低电平:写数据。

E I 读写使能,高电平有效,下降沿锁定数据。

DB0 I/

O

数据输入输出引脚。

DB1 I/

O

数据输入输出引脚。

DB2 I/

O

数据输入输出引脚。

DB3 I/

O

数据输入输出引脚。

DB4 I/

O

数据输入输出引脚。

DB5 I/

O

数据输入输出引脚。

DB6 I/

O

数据输入输出引脚。

DB7 I/

O

数据输入输出引脚。

CS1 I 片选择信号,高电平时选择左半屏。

CS2 I 片选择信号,高电平时选择右半屏。

/RET I 复位信号,低电平有效。

VEE O LCD驱动,负电压输出,对地接10K电位器

LEDA - 背光电源,LED+(5V)。

LEDK - 背光电源,LED-(0V)。

单片机与液晶显示器的连接电路如图ChpNum-1所示,片选信号CS1与CS2接P2.4和P2.3引脚,RS、R/W、E分别接引脚P2.2、P2.1、P2.0。VEE驱动负电压输出,而V0接10K电位器,对LCD 亮度进行调节。51单片机的P0口为了实现准3态,采用了OC输出,也就是集电极悬空输出。这种电路结构,只有下拉能力,高电平输出没有电流。在高电平时表现为高阻态,加上拉电阻,就会失去高阻态,变成 1、0 两态。因此在P0口与OCM12864的I/O口之间接上10K的排阻。

游戏音效由蜂鸣器实现,接法如图ChpNum-1所示。由于单片机输出脚的驱动电流有限,我们用单片机P2.5脚输出信号控制PNP三极管S8550的通断,当P2.5输出高电平时,三极管截止,当P2.5输出低电平时,三极管导通。因此,通过在P2.5脚输出不同频率的方波信号,可使得蜂鸣器发出不同频率的声音。

蜂鸣器电路图:

B1

BE LL VCC

R15

100

BE EP(P1.5)

蜂鸣器

本次设计按键部分采用的是红外遥控器,其原理是: 一体化红外线接收器是一种集红外线接收和放大于一体,不需要任何外接元件,就能完成从红外线接收到输出与TTL电平信号兼容的所有工作,而体积和普通的塑封三极管大小一样,它适合于各种红外线遥控和红外线数据传输。红外接收头将38K载波信号过虑,得到与发射代码反向接收代码解码的关键是如何识别“0”和“1”,从位的定义我们可以发现“0”,“1”均以0.56ms的低电平开始,不同的是高电平的宽度不同,“0”为

0.56ms,“1”为1.68ms,所以必须根据高电平的宽度区别“0”和“1”。如果从0.56ms 低电平过后,开始延时,0.56ms 以后,若读到的电平为低,说明该位“0”,反之则为“1”,为了可靠起见,延时必须比0.56ms 长些,但又不能超过1.12ms,否则如果该位为“0”,读到的已是下一位的高电平,因此取(1.12ms+0.56ms )/2=0.84ms 最为可靠,一般取0.84ms 左右均可。 红外接收模块电路:

P 3.2/C S 1

红外接收

Te

3.2单片机与PC 机通信电路

中央控制器CPU

3.3 其他部分电路说明

显示电路、复位和时钟电路比较简单,具体连接请参见电路原理总图。

SK

上拉电阻

复位电路

502

供电部分采用7805将输入9~12V电压转换为5V输出,输入输出端接220uF电解电容,使整流后的脉动直流电压变成相对比较稳定的直流电压。由于大容量的电解电容一般具有一定的电感,对高频及脉冲干扰信号不能有效地滤除,所以两端并联一只容量为0.1uF的电容,以滤除高频及脉冲干扰。

复位电路含有上电复位和按键复位功能,按键复位用于游戏结束后游戏的重新启动。系统插电瞬间电源通过10K电阻给10uF电容充电电平,充电电流在10K电阻上产生压降,于是电阻上端产生一个维持几百毫秒的高电平输入到RESET对单片机进行复位,电容充电满后经过电阻电流为0,复位失效。类似地,当开关按下时,强制产生一个高电平对单片机进行复位。

时钟电路使用12MHz的晶振,晶振的两引脚处接入两个22pF的瓷片电容来削减谐波对电路稳定性的影响。

3.4 软件模块设计

3.4.1 LCD初始化

在对LCD进行初始化时,先要检查读忙碌标志位,当BF为1表示内部操作正在进行,0表示允许指令操作。具体指令说明如下:

显示开/关设置

引脚

R

/W

R

S

D

B7

D

B6

D

B5

D

B4

D

B3

D

B2

D

B1

D

B0

电平L L L L H H H H H H

/L

功能:设置屏幕显示开/关。DB0=H,开显示;DB0=L,关显示。不影响显示RAM(DD RAM)中的内容。

设置显示起始行

引R R D D D D D D D D

脚/W S B7 B6 B5 B4 B3 B2 B1 B0

L L H H 行地址(0~63)

功能:执行该命令后,所设置的行将显示在屏幕的第一行。显示起始行是由Z地址计数器控制的,该命令自动将A0-A5位地址送入Z地址计数器,起始地址可以是0-63范围内任意一行。Z地址计数器具有循环计数功能,用于显示行扫描同步,当扫描完一行后自动加一。

设置页地址

引脚

R

/W

R

S

D

B7

D

B6

D

B5

D

B4

D

B3

D

B2

D

B1

D

B0

电平L L H L H H H 页地址(0~

7)

功能:执行本指令后,下面的读写操作将在指定页内,直到重新设置。页地址就是DD RAM 的行地址,页地址存储在X地址计数器中,A2-A0可表示8页,读写数据对页地址没有影响,除本指令可改变页地址外,复位信号(RST)可把页地址计数器内容清零。

设置列地址

引脚

R

/W

R

S

D

B7

D

B6

D

B5

D

B4

D

B3

D

B2

D

B1

D

B0

L L L H 列地址(0~63)

功能: DD RAM 的列地址存储在Y地址计数器中,读写数据对列地址有影响,在对DD RAM进行读写操作后,Y地址自动加1。

状态检测

引脚

R

/W

R

S

D

B7

D

B6

DB

5

D

B4

D

B3

D

B2

D

B1

D

B0

电平H L B

F

L ON

/OFF

R

ST

L L L L

功能:读忙信号标志位(BF)、复位标志位(RST)以及显示状态位(ON/OFF)。 BF=H:内部正在执行操作;BF=L:空闲状态。RST=H:正处于复位初始化状态;RST=L:正常状态。ON/OFF=H:表示显示关闭;ON/OFF=L:表示显示开。

写显示数据

引脚

R

/W

R

S

D

B7

D

B6

D

B5

D

B4

D

B3

D

B2

D

B1

D

B0

电平L H D

7

D

6

D

5

D

4

D

3

D

2

D

1

D

功能:写数据到DD RAM,DD RAM是存储图形显示数据的,写指令执行后Y地址计数器自动加1。D7-D0位数据为1表示显示,数据为0表示不显示。写数据到DD RAM前,要先执行“设置页地址”及“设置列地址”命令。

读显示数据

引脚

R

/W

R

S

D

B7

D

B6

D

B5

D

B4

D

B3

D

B2

D

B1

D

B0

电平H H D

7

D

6

D

5

D

4

D

3

D

2

D

1

D

功能:从DD RAM读数据,读指令执行后Y地址计数器自动加1。从DD RAM读数据前要先执行“设置页地址” 及“设置列地址”命令.

LCD初始化时,根据指令格式,先进行读忙碌检查。当BF为低电平时,设置显示起始行为第一行,A0~A5位为0,然后设置屏幕显示为开,具体做法见参考代码。

3.4.2 键盘扫描程序

键盘扫描通过红外接收头来检测,与P3.2(中断输入)引脚相连。程序初始化时将IT0置0,表示外部中断使用电平触发方式,低电平可引起中断。任何键的按下均会使P3.2电平为低,进入中断服务程序。中断服务程序先将P2口数据取出,根据按键解释子程序来模拟使用哪个锤子来打小地鼠。

3.4.3 显示液晶汉字

液晶显示器的数据线是8位的,显示数据是逐字节输入的。每字节输入数据对应到一列的8个像素点(8行)。自然地,64行像素点分成8页,每8行为一页。向液晶显示器写入显示数据时均要先设置写入的页号和列号(而不是具体某一个像素点的坐标),然后写入一个字节的数据。如表ChpNum-2所示,液晶显示模块中的DDRAM是存储图形显示数据的,LCD显示的数据与DDRAM中的数据一一对应(一位DDRAM对应一个像素,数据为1表显示该点,为0不显示)。汉字在液晶中占用16*16像素点,即两页16列。把汉字的点阵数据写到液晶的DDRAM中时。先载入第一页的16列(字节),再载第2页的16列。详细过程见参考代码。

表ChpNum-2 DDRAM地址映像

Y 地址

0 1 2 ……………………

6

1

6

2

6

3

X地

DB0

∫ PAGE0

DB7

X=0

DB0

∫ PAGE1

DB7

X=1

DB0

∫ PAGE6

DB7

X=7

DB0

∫ PAGE7

DB7

3.4.4 地鼠的随机出现

地鼠的出现是一种随机行为,所以必须做一个随机数,而且地鼠出现的位置不能超出规定的游戏界面。这里使用程序中的定时计数器的低八位TL0的数值,由于TL0不断变化,不同的时间点数值不同,TL0%33来表示我们之前定义的显示区数组。

5 设计心得体会

我们这次的课程设计的方案是通过OCM-12864-1液晶显示屏显示。我们的硬件电路比较简单,只要单片机最小系统加一红外遥控,所以我们还加入了程序下载模块。通过这次主题设计,使我对C语言的基本使用更加熟练,同时也增加我对C语言模块化程序设计的一些认识。在调试过程中通过和同学的交流,也增加了合作的技巧。通过查阅资料也学到了一些课本上没有的知识,拓宽了自己的知识面,增加了学习C语言的信心。平时我也做了很多实验,写了很多小程序。很多子程序都是固定的,直接调用就可以了,只要改一下参数就可以。这大大方便了我们的设计。为我们节省了横多时间。这次主题报告的设计让我受益匪浅,无论从知识上还是其他个方面。通过课程设计能够理论联系实际

的学习,开阔了我们的眼界,也提高了单片机知识的理解水平。在这次主题报告设计中又让我体会到了合作与团结的力量,当我遇到问题,我就会和同组同学讨论或者是同学之间相互帮助。团结就是力量,无论在现在的学习中还是在以后的工作中,团结都是至关重要的,有了团结就会有更多的理念、更多的思维、更多的情感。

单片机是一门很重要的课程。最后感谢白老师对我们上课时对我们的精心引导和帮助,同时

也感谢同学对我们的帮助。

6 附录

6.1总原理图

复位电路

P 3.2/C S 1

红外接收

Tex

502

6.2单片机程序代码

/*******************************************************************************

●描述:

●12864标准字库液晶演示数据p0,控制p2 *

********************************************************************************/

#include

#include

#include"vadef.h"

#include"music1.h"

#include "hwyk.h"

/*****************************************************************

定时器初始化

******************************************************************/

void inti0()

{ TMOD=0X11;

TH1=0XEC;

TL1=0X78;

TR1=1;

EA=1;

ET0=1;

PT0=1;

//ET2=1; //定时器2中断用于红外控制

TR0=0;

TH2=0X00; //装载初值

TL2=0X06;

TR2=1;

}

/********************************************************* * * 主函数* * *********************************************************/

void main()

{

inti0();

delay(100); //上电,等待稳定

lcd_init(); //初始化LCD

while(1)

{ while(!TF1);

TF1=0;

TH1=0XEC;

TL1=0X78;

t1s++;

if(irok) //如果接收好了进行红外处理

{

Ircordpro();

{key=IRcord[2];

irpro_ok=0;

}

irok=0;

}

switch(sta)

{ case 0:work0();break;

case 1:work1();break;

case 2:work2();break;

case 3:work3();break; //游戏设置模块

case 4:work4();break; //倒计时播放音乐进入游戏模块

case 5:work5();break; //显示游戏结束界面

default:break;

}

}

}

void work0()

{ lcd_pos(1,0); //设置显示位置为第一行

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

{lcd_wdat(DIS1[i]);}

lcd_pos(2,0); //设置显示位置为第二行

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

{lcd_wdat(DIS2[i]);}

lcd_pos(3,0); //设置显示位置为第三行

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

{lcd_wdat(DIS3[i]);}

lcd_pos(4,0); //设置显示位置为第四行

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

{lcd_wdat(DIS4[i]);}

if(t1s==400)

{ t1s=0;

lcdflag();

clr_screen(); //清屏

sta=1;

}

}

/************************************************************/ void work1() //进入游戏界面

{ lcd_pos(1,0); //设置显示位置为第一行

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

{lcd_wdat(DIS11[i]);}

lcd_pos(2,0); //设置显示位置为第二行

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

{lcd_wdat(DIS22[i]);}

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

{lcd_wdat(DIS33[i]);}

song(TwoMouse);

}

/************************************************************/

void work2() //游戏模块

{ if(!dispflag)

{photodisplay(Photo1);

dispflag=1;

}

if(ts++==400)

{sta=3;

ts=0;

dispflag=0;

clr_screen();

}

}

/****************************************************************/ void work3() //游戏初始化模块

{

levsel(void);

}

/******************************************************************/ void work4()

{ uchar i;

lcd_pos(2,0); //设置显示位置为第2行

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

{lcd_wdat(lcdtime[i]);}

lcd_wcmd(0x88); //设置显示位置为第三行

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

{lcd_wdat(0x04);}

if(ts++==200)

{

ts=0;

if(lcdtime[10]!=0)

{ lcdtime[10]-=1;

if(lcdtime[9]==0&&lcdtime[10]==0)

sta=6;

}

else

{lcdtime[9]=0;

lcdtime[10]=9;

}

}

/************************************************************/

void work5()

{ if(!dispflag)

{photodisplay(Photo2);

dispflag=1;

}

if(ts++==400)

{sta=3;

ts=0;

dispflag=0;

clr_screen();

}

}

/************************************************************/

void work6() //游戏主体

{ swap(void);

}

/*******************************************************************/ void swap(void) //打地鼠子程序

{

if(time==count)

{

photodisplay(disp[s][]);

dispflag=1;

if(s<12)

s++;

else

s=0;

}

checkkey();

if((keynum1==seq[s])&(keynum1!=0)) //按对键出现下一个地鼠

{ score[9]+=h;

time=count;

gamenum++;

keynum1=0;

if(gamenum>=gamenum1)

{ level+=1;

gamenum=0;

}

}

else //按错键马上结束

{ sta=5;

}

}

void levsel(void) //根据关卡来选择得分和转换速度

{

lcd_pos(1,0); //设置显示位置为第一行

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

{lcd_wdat(game1[i]);}

lcd_pos(2,0); //设置显示位置为第二行

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

{lcd_wdat(game2[i]);}

lcd_pos(1,0); //设置显示位置为第一行

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

{lcd_wdat(levels[i]);} //游戏设置if(key==0x01){key=0;level++;levels[10]+=1;if(level==6){level=0;levels[10]=0;}}

switch(level)

{case 1: { gamenum1=10;count=100;h=1;}

case 2: { gamenum1=20;count=200;h=2;}

case 3: { gamenum1=30;count=300;h=3;}

case 4: { gamenum1=40;count=400;h=4;}

case 5: { gamenum1=50;count=500;h=5;}

default:break;

}

}

/******************按键解释函数***********************************/

void checkkey(void) //按键解释

{

switch(key)

{case 0x01: key=0;keynum1=1;break;

case 0x02: key=0;keynum1=2;break;

case 0x03: key=0;keynum1=3;break;

case 0x04: key=0;keynum1=4;break;

case 0x05: key=0;keynum1=5;break;

case 0x06: key=0;keynum1=6;break;

case 0x07: key=0;keynum1=7;break;

case 0x08: key=0;keynum1=8;break;

default:break;

}

}

/*******************************************************************/

/* */

/* 延时函数*/

/* */

/*******************************************************************/

void delay(int ms)

{

{

uchar i;

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

{

_nop_();

_nop_();

_nop_();

_nop_();

}

}

}

/*******************************************************************/ /* */ /* 延时函数*/ /* */ /*******************************************************************/ void delay1(int ms)

{

while(ms--)

{

uchar y;

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

}

}

/*******************************************************************/ /* */ /*检查LCD忙状态*/ /*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。*/ /* */ /*******************************************************************/ bit lcd_busy()

{

bit result;

LCD_RS = 0;

LCD_RW = 1;

LCD_EN = 1;

delayNOP();

result = (bit)(P0&0x80);

LCD_EN = 0;

return(result);

}

/*******************************************************************/ /* */ /*写指令数据到LCD */

相关主题
文本预览
相关文档 最新文档