首页 > 范文大全 > 正文

单片机原理与应用考试大纲

开篇:润墨网以专业的文秘视角,为您筛选了一篇单片机原理与应用考试大纲范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!

第一章微型计算机基础

一、考核知识点:

1、计算机的数据表示和数据运算

2、计算机的各种编码

3、计算机的组成及工作过程

二、考核要求:

1、识记计算机的各种编码

2、领会计算机的组成及工作过程

3、简明应用计算机的数据表示和数据运算

第二章51单片机的硬件结构和原理

一、考核知识点:

1、单片机的发展史及各方面的应用

2、51单片机的分类和内部结构

3、单片机的引脚和功能

4、单片机工作的时序

二、考核要求:

1、识记单片机的发展史及各方面的应用

2、识记单片机的引脚和功能

3、领会单片机工作的时序

4、简明应用51单片机的分类和内部结构

第三章51单片机指令系统

一、考核知识点:

1、单片机的寻址方式

2、单片机的指令系统

3、助记符指令和二进制代码指令的异同

二、考核要求:

1、领会助记符指令和二进制代码指令的异同

2、综合应用单片机的寻址方式

3、综合应用单片机的指令系统

第四章汇编语言程序设计

一、考核知识点:

1、伪指令

2、汇编语言设计技巧

3、汇编语言到机器语言的编译过程

二、考核要求:

1、领会伪指令

2、简明应用汇编语言设计技巧

3、综合应用汇编语言到机器语言的编译过程

第五章51单片机的中断系统

一、考核知识点:

1、中断基本概念

2、中断系统的程序编制

3、中断系统的初步应用

二、考核要求:

1、领会中断基本概念

2、简明应用中断系统解决工程问题

3、综合简明应用中断系统的程序编制

第六章51单片机的内部定时器/计数器及串行接口

一、考核知识点:

1、单片机内部定时器/计数器的结构及工作原理

2、定时器/计数器的程序编制

3、定时器/计数器的初步应用

4、串行口的基本概念

5、串行口的程序编制

6、串行口的初步应用

二、考核要求:

1、识记串行口的基本概念

2、领会单片机内部定时器/计数器的结构及工作原理

3、简明应用定时器/计数器解决工程问题

4、简明应用串行口的程序编制

5、简明应用串行口解决工程问题

6、综合应用定时器/计数器的程序编制

第七章单片机的系统扩展与接口技术

一、考核知识点:

1、单片机外部总线的扩展

2、外部存储器的扩展

3、I/O接口的扩展

4、管理功能部件的扩展

5、A/D和D/A接口功能的扩展

二、考核要求:

1、识记单片机外部总线的扩展

2、识记管理功能部件的扩展

3、简明应用A/D和D/A接口功能的扩展

4、综合应用外部存储器的扩展

5、综合应用I/O接口的扩展

第八章单片机应用系统设计

一、考核知识点:

1、单片机应用系统的开发过程

2、单片机开发工具的分类和使用

3、单片机应用系统的软件和硬件调试过程

二、考核要求:

1、识记单片机应用系统的软件和硬件调试过程

2、领会单片机应用系统的开发过程

3、领会单片机开发工具的分类和使用

第九章单片机系统的抗干扰技术

一、考核知识点:

1、单片机干扰源与分类

2、干扰对单片机系统的影响

3、硬件抗干扰技术

4、软件抗干扰技术

5、数字滤波

二、考核要求:

1、识记单片机干扰源与分类

2、识记干扰对单片机系统的影响

3、识记数字滤波

4、简明应用硬件抗干扰技术

5、简明应用软件抗干扰技术

第十章其它单片机简介

一、考核知识点:

1、AT89C系列单片机的特点与性能

2、其它8位单片机的特点与性能

3、16位、32位单片机的特点与性能

二、考核要求:

1、识记其它8位单片机的特点与性能

2、识记16位、32位单片机的特点与性能

3、领会AT89C系列单片机的特点与性能

《单片机原理及应用技术》考试大纲

《单片机原理及应用技术》课程是一门面向应用的专业技术课。单片机原理与应用介绍了单片机的基本知识和单片机技术的应用,其内容与工程实际紧密联系,实用性很强,是一门在理论指导下,偏重于实际应用的课程。本课程具有实用性强、理论和实践结合、软硬件结合等特点。本课程围绕使用较为广泛的MCS-51系列单片机进行学习。本课程已成为理、工科电子类专业的一门基础课程,这是从电子系统设计角度考虑的,它体现了电子系统设计的方法和硬件结构的变化。通过该课程的学习,要求学生掌握80C51单片机的工作原理、编程技术,掌握单片机应用系统的扩展方法和实际应用。因此,以单片机为内核,分析和设计一个简单的计算机应用系统是我们学习本课程要达到的目的。

第一部分考试大纲

1单片机概述

本章为单片机的基本概念。

1.掌握有关单片机的基本概念、单片机的特点、单片机的应用。

2.理解单片机的总体组成。

3.了解单片微型计算机的产生、发展历史、主要品种及系列。

2单片机结构和原理

本章以80C51单片机为例介绍了主要硬件结构和主要功能,着重掌握系统所提供的资源特性及其功能特性。

1.掌握80C51的内部结构。

2.掌握80C51单片机的存储器组成。

3.掌握单片机并行输入/输出端口结构及功能。

4.了解单片机的时序概念和复位工作方式。

5.掌握单片机引脚功能

3指令系统

1.掌握指令与伪指令的正确格式。

2.掌握七种寻址方式的使用及寻址方式的含义。

3.掌握

五类指令的功能和使用,特别是传送指令。

4.理解书中所列例题与习题。

4汇编语言程序设计举例

本章为MCS-51的一些常用伪指令,介绍顺序结构程序设计、分支结构程序设计、循环结构程序设计和子程序的设计。

1.程序设计的基本步骤、各种基本的结构化程序设计方法;读懂较复杂的常用程序。

2.掌握数据传送指令的编写。

3.理解算术运算程序设计。

4.理解数码转换程序设计。

5.理解查表程序设计。

6.理解子程序设计和参数传递。

7.理解逻辑运算程序设计

5中断系统

1.掌握有关中断、中断源、中断优先级等概念。

2.掌握中断响应过程。

3.掌握中断优先级排列。

4.掌握中断允许寄存器IE、中断优先级寄存器IP各位的含义及设置。

5.掌握外部中断的两种触发方式:电平触发、边沿触发。

6定时/计数器

1.掌握定时器/计数器的四种工作方式及有何不同。

2.掌握TMOD和TCON中各位的含义、作用。

4.掌握不同工作方式计数初值与定时时间的关系,即能根据定时时间算出计数初值,完成定时器的初始化编程和简单应用编程。

7串行通信

1.理解有关通信、协议的概念。

2.理解串行口的四种工作方式。

3.掌握SBUF的含义及作用。

4.了解串行口的工作原理。

5.了解SCON中每一位的含义及SMOD位的作用。

6.掌握串行通信总线RS-232C标准、RS-232C电平转换。

7.了解RS-232C与MCS-51的接口。

8系统扩展技术

1.掌握总线、驱动、锁存和译码、地址重叠的概念。

2.掌握程序存储器的扩展:EPROM程序存储器及其扩展方法。

3.掌握数据存储器的扩展:静态存储器SRAM及其扩展方法。

4.掌握简单I/O口的扩展。

5.掌握8255A可编程并行接口:结构、控制字、工作方式、与8255A的接口方法。

9A/D和D/A转换器接口技术

1.掌握DAC0832与单片机的接口方法与编程。

2.掌握ADC0809与单片机的接口方法与编程。

10键盘/显示接口技术

1.掌握LED显示器结构、工作原理和显示方式。

2.掌握键盘接口原理。

3.理解LED显示器与80C51单片机接口。

4.理解键输入程序设计方法。

5.了解行列式键盘与80C51单片机接口。

11、功率接口技术

1.掌握简单开关量接口、光电耦合接口和继电器接口。

2.晶闸管与故态继电器的应用接口。

12、单片机系统设计技术

掌握单片机系统的设计、开发、调试的原则、步骤及方法。

13、实用举例

了解一两个典型的单片机开发应用系统的设计思想和实现方法。

14、新型单片机介绍

了解MCS-51常见8位单片机。

第二部分考试考核改革方案

一、考试考核要求

《单片机技术及应用》选择具有代表性的、使用较为广泛的MCS-51系列单片机进行学习(具体以80C51为例),介绍了80C51单片机的硬件组成、软件编程及一般应用系统组成。通过本课程的学习,要求掌握80C51单片机的系统结构、指令系统、程序设计方法、系统扩展方法、单片机常用接口等应用技术。本课程的教学过程由面授辅导、自学、实验及作业四个环节组成,因此本课程考试考核要求为:

1.作业、实验成绩与期末考试成绩共同评定为课程总成绩。

2.作业、实验占课程总分的60,期末理论考试占总分的40。

为使学生不把注意力仅仅放在期末考试上,培养学生系统学习的能力,加强学生各方面能力的培养,平时、实验课、作业、考试都纳入本课程的成绩评定。平时的成绩包括出勤、课堂提问和随堂测试。期末考试可以选择笔试、口试和进行实际实验、设计等多种形式。

二、平时成绩考核要求及说明

1.每章作业按要求完成后交教师批改,完成作业80为12分(及格);所有作业均完成,且质量较好者,20分(满分)。中间情况酌情给分。

2.每次实验均能按照教师安排进行,实验态度好,至少完成5个实验且实验报告完整,为18分(及格);能基本独立完成6个或以上实验,实验报告完整、无误,实验质量高,30分(满分)。中间情况酌情给分。如果实验有创新的特点,酌情加分。

3.作业与实验的平均分为平时成绩,满分50分。

4.课程设计单独计算成绩,考评方法见其大纲。

三、理论考试说明

1.单片机技术及应用理论考试,采用闭卷笔试形式,考试时间120分钟。

2.期末考试试题根据教学大纲,其范围和难度按照本方案中制订的考试考核内容和要求确定。考试命题覆盖考试大纲要求范围。

3.期末考试试题类型有以下几种:

①填空题;

②选择题;

③判断题;

④简答题

⑤综合应用题。

四、考试考核要求层次

按照教学大纲的要求,理论考试要求分为掌握、理解和了解三个层次。

掌握:

对于本课程的重点内容要求学生达到掌握的程度。即能够全面、深入理解和熟练掌握所学内容,并能够用其分析、初步设计和解答与应用相关的问题,能够举一反三。要求学生掌握的内容也就是考试的主要内容,在考试中所占比例约70。

理解:

对于本课程的一般内容要求学生能够理解。即要求学生能够较好地理解所学内容,并且对所涉及的内容能够进行简单分析和判断。要求学生理解的内容也是考试的内容,在考试中所占比例约25。

了解:

对于本课程的次要内容要求学生能够了解。要求学生了解的内容,一般是指在眼下不必进一步深入和扩展,有些也许需要学生自己今后在工作中进行深入研究。对要求了解的内容,在考试中占较小比例,不超过5。

实验五:按键电路、显示电路实验

一、实验目的:

1.掌握独立式按键电路与矩阵式按键电路的设计方法。

2.掌握数码管显示电路的工作原理

3.掌握源程序编辑软件UltraEdit,编译软件KeilC51、仿真软件Proteus的使用方法

4.掌握硬件仿真器ME-52A的使用方法

二、实验器材:

1.单片机实验板

2.单片机硬件仿真器ME-51A

3.计算机

4.电源

三、实验要求:

1.电路如图5所示,用单片机的P3口所接的四个独立式按键控制p1口流水灯花样的方法;具体表现为:p3.0、P3.1、P3.2、P3.3四个小按键分别实现了四个控制:

(1)跑灯:即P1.0---1.7亮点流动:

(2)流水灯:即P1.0-1.7依次点

亮(3)交叉闪烁:即P0.0,P0.2,P0.4,P0.6和P0.1,P0.3,P0.5,P0.7轮流点亮

(4)停止;在任何状态下按此键程序停止运行.

2.电路如图6所示,用P2口所接的4×4矩阵式键盘作为输入,在P1口所接的数码管上显示出每个按键的0~F序号,键盘的布局如下表所示:

F

E

D

C

B

A

9

8

7

6

5

4

3

2

1

四、实验原理:

1.独立式按键电路显示如图5所示,从图中可看出,判断有无键按下,只要检测P3.0~P3.3相应端口的高低电平即可,若检测有某一端口为低电平,表明该端口有按键按下,经延时消抖后转去执行相应的功能子程序。若为高电平,表明无键按1.独立式按键电路如图5所示,下,继续检测。

示例程序如下:

ORG000H

LJMPSTAR1

ORG0030H

STAR1:MOVP3,#0FFH;置P3口为输入态

JNBP3.0,FUN0;判别P3.0是否有键按下,是,则转FUN0

JNBP3.1,FUN1;判别P3.1是否有键按下,是,则转FUN1

JNBP3.2,FUN2;判别P3.2是否有键按下,是,则转FUN2

JNBP3.3,FUN3;判别P3.3是否有键按下,是,则转FUN3

JNBF0,STAR1;曾经有键按下F0置1

RET

图5

FUN0:LCALLDL10MS;消岸抖动

JBP3.0,STAR1

WAITL0:JNBP3.0,WAITL0;等待键释放

SETBF0

FUN01:LCALLFUN00

LCALLSTAR1

LJMPFUN01

FUN1:LCALLDL10MS;消岸抖动

JBP3.1,STAR1

WAITL1:JNBP3.1,WAITL1;等待键释放

SETBF0

FUN10:LCALLFUN11

LCALLSTAR1

LJMPFUN10

FUN2:LCALLDL10MS;消岸抖动

JBP3.2,STAR1

WAITL2:JNBP3.2,WAITL2;等待键释放

SETBF0

FUN20:LCALLFUN22

LCALLSTAR1

LJMPFUN20

FUN3:LCALLDL10MS;消岸抖动

JBP3.3,STAR1

WAITL3:JNBP3.3,WAITL3;等待键释放

CLRF0

MOVP1,#0FFH;关显示

LJMPSTAR1

FUN00:MOVA,#0FEH;跑灯子程序

FUN000:MOVP1,A

LCALLDL05S

JNBACC.7,OUT

RLA

AJMPFUN000

OUT:RET

FUN11:MOVA,#0FEH;流水灯子程序

FUN111:MOVP1,A

LCALLDL05S

JZOUT

RLA

ANLA,P1

AJMPFUN111

FUN22:MOVA,#0AAH;交叉点亮子程序

MOVP1,A

LCALLDL30S

CPLA

MOVP1,A

LCALLDL30S

RET

;____________;

;延时程序;

;____________;

DL512:MOVR2,#0FFH

LOOP1:DJNZR2,LOOP1

RET

DL10MS:MOVR3,#14H

LOOP2:LCALLDL512

DJNZR3,LOOP2

RET

DL05S:MOVR4,#0AH

LOOP3:LCALLDL10MS

DJNZR4,LOOP3

RET

DL30S:MOVR5,#03H

LOOP4:LCALLDL05S

DJNZR5,LOOP4

RET

END

2.矩阵式按键电路显示如图6所示。采用扫描方式进行按键的识别检测,并将对应按键的键号用查表指令将对应的代码显示在数码管上。

图6

参考程序如下:

ORG0000H

LJMPSTART

ORG0030H

START:MOVSP,#60H;设置堆栈指针

SCAN:MOVR3,#0F7H;置行扫描初值

MOVR1,#00H;到TABLE表中取码的指针

SCAN1:MOVA,R3

MOVP2,A;扫描输出

MOVA,P2;重读P2口状态

MOVR4,A;暂存于R4吕中

SETBC;C=1

MOVR5,#03H;扫描4列初值

L1:RLCA;A中内容循环左移

JNCKEYIN;C=0,有键按下,转消抖

INCR1;取码指针加1

DJNZR5,L1;无键按下,继续检测

MOVA,R3;扫描下一行

SETBC

RRCA

MOVR3,A

JCSCAN1;4行是否扫描完,未完,继续

LJMPSCAN

KEYIN:MOVR7,#10;削除抖动

D2:MOVR6,#248

DJNZR6,$

DJNZR7,D2

D3:MOVA,P2;按键放开否?

XRLA,R4

JZD3

MOVA,R1

MOVDPTR,#TABLE;到TABLE中取码

MOVCA,@A DPTR

MOVP1,A

LJMPSCAN

TABLE:DB0C0H,0F9H,0A4H,0B0H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH

END

DB80H,90H,88H,83H

DB0C6H,0A1H,86H,8EH

END

五、实验步骤:

1.运行UltraEdit-32源程序编辑软件,输入、编辑汇编语言源程序。

2.运行KeiluVision2源程序编译软件,对源程序进行编译,得到目标代码文件。

3.运行Proteus模拟仿真软件,打开已绘制好的仿真电路原理图,进行模拟仿真。

4.把硬件仿真器ME-52A与单片实验板连接好,再用硬件仿真器进行仿真验证。

六、实验分析与总结

1.用仿真系统调试简单程序结构、分支程序结构、循环程序结构、子程序结构和中断结构的关键在于,如何将对程序的分析理解和开发系统提供的基本功能有机地结合起来,其前提条件是必须对源程序的作用、结构特点、运行过程与结果有较全面的认识,并能根据程序运行过程中出现的现象和结果分析并判断产生各种故障现象的原因,再运用排除法逐一检验各种判断是否准确。

2.掌握程序结构特点的基础上,合理选择观测点,通过观察在观测点处参数及路径的变化检验程序运行的结果。

3.高调试程序的效率,应对单片机开发系统所提供的几种程序运行调试方式有

足够的了解并能熟练地运用。例如,在调试过程中,若要观察最终结果,则可选择全速运行调试;若要观察相关指令的运行结果或运行路径的变化过程,则可选择单步运行;若要检查子程序的运行过程,则可选择跟踪运行调试;若要检查循环程序或中断服务程序,则可选择断点运行调试;若要定点检查程序运行到某处的结果时,则可选择快速运行到光标处调试。但实际中究竟选用哪种方法更适宜或哪几种方法结合使用更快捷,将随着分析能力与操作的熟练程度逐步提高。4.程序运行结果是否正确时,应运用单片机开发系统所提供的交互界面,将程序运行过程中程序计数器PC(地址)的变化、各单元(内部RAM和外部RAM)内容的变化、特殊功能寄存器内容的变化、堆栈指针SP内容的变化与程序的理论分析结果相对照。

5.程序和调试程序时,需要多次反复的过程,并非一次就能排除全部故障,特别是单片机应用系统的硬件电路和汇编程序相结合的综合调试就更加复杂,因此,必须通过反复调试,不断修改硬件和软件,直到最终符合设计要求为止。如果在调试中能够根据实验现象预先对产生故障的原因加以判断和分析,并制定出相应的调试方法和步骤,可缩小排除故障的范围,提高调试效率。

七、思考与练习

填空题

1、设X=5AH,Y=36H,则X与Y“或”运算为__7EH_______,X与Y的“异或”运算为___6CH_____。

2、若机器的字长为8位,X=17,Y=35,则X+Y=__110100_____,X-Y=_11101110______(要求结果写出二进制形式)。

3、单片机的复位操作是____高电平______(高电平/低电平),单片机复位后,堆栈指针SP的值是___07h_____。

4、单片机中,常用作地址锁存器的芯片是__74HC373____________,常用作地址译码器芯片是_____74HC138____________。

5、若选择内部程序存储器,应该设置为_____高_______(高电平/低电平),那么,PSEN信号的处理方式为___不用__________________。

6、单片机程序的入口地址是____0000H__________,外部中断1的入口地址是______0013H_________。

7、若采用6MHz的晶体振荡器,则MCS-51单片机的振荡周期为__0.5us_______,机器周期为_____2us__________。

8、扩展芯片的选择方法有两种,它们分别是___线选法_______________和_____译码法__________。

9、单片机的内部RAM区中,可以位寻址的地址范围是____20H~2FH______________,特殊功能寄存器中,可位寻址的地址是___是能被8整除的地址_________________。

10、子程序返回指令是___ret______,中断子程序返回指令是__reti。

11、8051单片机的存储器的最大特点是内部RAM与外部RAM分开编址。

12、8051最多可以有32个并行输入输出口,最少也可以有8个并行口。

13、函数是C语言的基本单位。

14、串行口方式2接收到的第9位数据送SCON寄存器的RB8位中保存。

15、MCS-51内部提供3个可编程的16位定时/计数器,定时器有4种工作方式。

16、一个函数由两部分组成,即说明部分和语句部分。

17、串行口方式3发送的第9位数据要事先写入SCON寄存器的TB8位。

18、利用8155H可以扩展3个并行口,256个RAM单元。

19、C语言中输入和输出操作是由库函数scanf和printf等函数来完成。

二、选择题

1、C语言中最简单的数据类型包括(B)。

A、整型、实型、逻辑型B、整型、实型、字符型

C、整型、字符型、逻辑型D、整型、实型、逻辑型、字符型

2、当MCS-51单片机接有外部存储器,P2口可作为(C)。

A、数据输入口B、数据的输出口

C、准双向输入/输出口D、输出高8位地址

3、下列描述中正确的是(D)。

A、程序就是软件B、软件开发不受计算机系统的限制

C、软件既是逻辑实体,又是物理实体D、软件是程序、数据与相关文档的集合

4、下列计算机语言中,CPU能直接识别的是(D)。

A、自然语言B、高级语言C、汇编语言D、机器语言

5、MCS-5l单片机的堆栈区是设置在(C)中。

A、片内ROM区B、片外ROM区C、片内RAM区D、片外RAM区

6、以下叙述中正确的是(C)。

A、用C语言实现的算法必须要有输入和输出操作

B、用C语言实现的算法可以没有输出但必须要有输入

C、用C程序实现的算法可以没有输入但必须要有输出

D、用C程序实现的算法可以既没有输入也没有输出

7、定时器/计数器工作方式1是(D)。

A、8位计数器结构B、2个8位计数器结构

C、13位计数结构D、16位计数结构

8、C语言提供的合法的数据类型关键字是(B)。

A、DoubleB、shortC、integerD、Char

9、片内RAM的20H~2FH为位寻址区,所包含的位地址是(B)。

A、00H~20HB、00H~7FHC、20H~2FHD、00H~FFH

10、以下能正确定义一维数组的选项是(B)。

A、inta[5]={0,1,2,3,4,5};B、chara[]={0,1,2,3,4,5};

C、chara={’A’,’B’,’C’};D、inta[5]="0123";

11、数据的存储结构是指(D)。

A、存储在外存中的数据B、数据所占的存储空间量

C、数据在计算机中的顺序存储方式D、数据的逻辑结构在计算机中的表示

12、下列关于栈的描述中错误的是(C)。

A、栈是先进后出的先性表B、栈只能顺序存储

C、栈具有记忆作用D、对栈的插入和删除操作中,不需要改变栈底指针

13、在寄存器间接寻址方式中,间址寄存器中存放的数据是(B)。

A、参与操作的数据B、操作数的地址值

C、程序的转换地址D、指令的操作码

14、MCS-51单片机的复位信号是(A)有效。

A、高电平B、低电平C、脉冲D、下降沿

15、为了使模块尽可能独立,要求(B)。

A、模块的内聚程度要尽量高,且各模块间的耦合程度要尽量强

B、模块的内聚程度要尽量高,且各模块间的耦合程度要尽量弱

C、模块的内聚程度要尽量低,且各模块间的耦合程度要尽量弱

D、模块的内聚程度要尽量低,且各模块间的耦合程度要尽量强

16、若MCS-51单片机使用晶振频率为6MHz时,其复位持续时间应该超过(B)。

A、2μsB、4μsC、8μsD、1ms

17、以下选项中可作为C语言合法常量的是(A)

A、-80B、-080C、-8e1.0D、-80.0e

18、能够用紫外光擦除ROM中程序的只读存储器称为(C)。

A、掩膜ROMB、PROMC、EPROMD、EEPROM

19、以下不能定义为用户标识符是(D)。

A、MainB、_0C、_intD、sizeof

20、下选项中,不能作为合法常量的是(B)。//幂不能为小数

A、1.234e04B、1.234e0.4C、1.234e 4D、1.234e0

21、以下叙述中错误的是(C)

A、对于double类型数组,不可以直接用数组名对数组进行整体输入或输出

B、数组名代表的是数组所占存储区的首地址,其值不可改变

C、当程序执行中,数组元素的下标超出所定义的下标范围时,系统将给出“下标越界”的出错信息

D、可以通过赋初值的方式确定数组元素的个数

22、以下与函数fseek(fp,0L,SEEK_SET)有相同作用的是(D)

A、feof(f

p)B、ftell(fp)C、fgetc(fp)D、rewind(fp)

23、存储16×16点阵的一个汉字信息,需要的字节数为(A)

A、32B、64C、128D、256

24、已知1只共阴极LED显示器,其中a笔段为字形代码的最低位,若需显示数字1,则它的字形代码应为(B)。

A、06HB、F9HC、30HD、CFH

25、在C语言中,合法的长整型常数是(A)

A、OLB、4962710C、324562&D、216D

26、以下选项中合法的字符常量是(B)

A、"B"B、’\010’C、68D、D

27、若PSW.4=0,PSW.3=1,要想把寄存器R0的内容入栈,应使用(D)指令。

A、PUSHR0B、PUSH@R0C、PUSH00HD、PUSH08H

28、在片外扩展一片2764程序存储器芯片要(B)地址线。

A、8根B、13根C、16根D、20根

29、设MCS-51单片机晶振频率为12MHz,定时器作计数器使用时,其最高的输入计数频率应为(C)

A、2MHzB、1MHzC、500kHzD、250kHz

30、下列数据字定义的数表中,(A)是错误的。

A、DW“AA”B、DW“A”C、DW“OABC”D、DWOABCH

三、判断题

(√)1、在对某一函数进行多次调用时,系统会对相应的自动变量重新分配存储单元。

(×)2、在C语言的复合语句中,只能包含可执行语句。

(√)3、自动变量属于局部变量。

(×)4、Continue和break都可用来实现循环体的中止。

(√)5、字符常量的长度肯定为1。

(×)6、在MCS-51系统中,一个机器周期等于1.5μs。

(√)7、C语言允许在复合语句内定义自动变量。

(√)8、若一个函数的返回类型为void,则表示其没有返回值。

(×)9、所有定义在主函数之前的函数无需进行声明。

(×)10、定时器与计数器的工作原理均是对输入脉冲进行计数。

(×)11、END表示指令执行到此结束。

(√)12、ADC0809是8位逐次逼近式模/数转换接口。

(√)13、MCS-51的相对转移指令最大负跳距是127B。

(×)14、MCS-51的程序存储器只是用来存放程序的。

(√)15、TMOD中的GATE=1时,表示由两个信号控制定时器的的启停。

(×)16、MCS-51的特殊功能寄存器分布在60H~80H地址范围内。

(×)17、MCS-51系统可以没有复位电路。

(×)18、片内RAM与外部设备统一编址时,需要专门的输入/输出指令。

(√)19、锁存器、三态缓冲寄存器等简单芯片中没有命令寄存和状态寄存等功能。

(√)20、使用8751且=1时,仍可外扩64KB的程序存储器。

四、简答题

1、在使用8051的定时器/计数器前,应对它进行初始化,其步骤是什么?

答:(1)确定T/C的工作方式——编程TMOD寄存器;

(2)计算T/C中的计数初值,并装载到TH和TL;

(3)T/C在中断方式工作时,须开CPU中断和源中断——编程IE寄存器;

(4)启动定时器/计数器——编程TCON中TR1或TR0位。

2、什么是重入函数?重入函数一般什么情况下使用,使用时有哪些需要注意的地方?答:多个函数可以同时使用的函数,称为重入函数。

通常情况下,C51函数不能被递归调用,也不能应用导致递归调用的结构。有此限制是由于函数参数和局部变量是存储在固定的地址单元中。重入函数特性允许你声明一个重入函数。即可以被递归调用的函数。

重入函数可以被递归调用,也可以同时被两个或更多的进程调用。重入函数在实时应用中及中断服务程序代码和非中断程序代码必须共用一个函数的场合中经常用到。

3、8051引脚有多少I/O线?他们和单片机对外的地址总线和数据总线有什么关系?地址总线和数据总线各是几位?

答:8051引脚共有40个引脚,8051的地址总线由P2和P0口提供,P2口是地址总线的高8位,P0口是地址总线的低8位;数据总线由P0口提供;P0口的地址总线和数据总线是分时进行的,P0口的地址总线需要外接地址锁存器完成地址锁存。

地址总线共16位,数据总线是8位。

4、在有串行通信时,定时器/计数器1的作用是什么,怎样确定串行口的波特率?

答:在有串行通信时,定时器/计数器1的作用是串行口发生器。

串行口的波特率根据串行口的工作方式具有不同的计算方式:

方式0的波特率固定为晶体振荡器的十二分之一;

方式1的波特率=2SMOD.(定时器1的溢出率)/32;

方式2波特率=2SMOD.(fosc/64);

方式3波特率同方式1(定时器l作波特率发生器)。

5、如何消除键盘的抖动?怎样设置键盘中的复合键?

答:由于按键是机械开关结构,所以当用手按下其中一个键时,往往会出现所按键在闭合位置和断开位置之间发生跳几下后才会稳定到闭合状态的情况。在释放一个键时,也会出现类似的情况,这就是键的抖动,抖动的持续时间不一,但通常不会大于10ms。

若抖动问题不解决,就会引起对闭合键的多次读入。对于键抖动最方便的解决方法就是当发现有键按下后,不是立即进行扫描,而是延时大约10ms后再进行。由于一个键按下的时间一般会持续上百毫秒,所以延迟10ms后再扫描处理并不迟。

复合键可以仿照计算机复合键的处理方法,通常可以假设一个键具有复合功能,再与其它减的键值组合成复合键。

1、矩阵式键盘的结构与工作原理

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图1所示。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。具体的识别及编程方法如下所述。

2、矩阵式键盘的按键识别方法

确定矩阵式键盘上何键被按下介绍一种“行扫描法”。

行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法,如上图所示键盘,介绍过程如下。

1、判断键盘中有无键按下将全部行线Y0-Y3置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。

2、判断闭合键所在的位置在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

下面给出一个具体的例子:

图仍如上所示。8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。列线P1.0-P1.3分别接有4个上拉电阻到正电源 5V,并把列线P1.0-P1.3设置为输入线,行线P1.4-P.17设置为输出线。4根行线和4根列线形成16个相交点。

1、检测当前是否有键被按下。检测的方法是P1.4-P

1.7输出全“0”,读取P1.0-P1.3的状态,若P1.0-P1.3为全“1”,则无键闭合,否则有键闭合。

2、去除键抖动。当检测到有键按下后,延时一段时间再做下一步的检测判断。

3、若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出:

P1.71110

P1.61101

P1.51011

P1.40111

在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值

4、为了保证键每闭合一次CPU仅作一次处理,必须却除键释放时的抖动。

键盘扫描程序:

从以上分析得到键盘扫描程序的流程图如图2所示。程序如下

SCAN:MOVP1,#0FH

MOVA,P1

ANLA,#0FH

CJNEA,#0FH,NEXT1

SJMPNEXT3

NEXT1:ACALLD20MS

MOVA,#0EFH

NEXT2:MOVR1,A

MOVP1,A

MOVA,P1

ANLA,#0FH

CJNEA,#0FH,KCODE;

MOVA,R1

SETBC

RLCA

JCNEXT2

NEXT3:MOVR0,#00H

RET

KCODE:MOVB,#0FBH

NEXT4:RRCA

INCB

JCNEXT4

MOVA,R1

SWAPA

NEXT5:RRCA

INCB

INCB

INCB

INCB

JCNEXT5

NEXT6:MOVA,P1

ANLA,#0FH

CJNEA,#0FH,NEXT6

MOVR0,#0FFH

RET

键盘处理程序就作这么一个简单的介绍,实际上,键盘、显示处理是很复杂的,它往往占到一个应用程序的大部份代码,可见其重要性,但说到,这种复杂并不来自于单片机的本身,而是来自于操作者的习惯等等问题,因此,在编写键盘处理程序之前,最好先把它从逻辑上理清,然后用适当的算法表示出来,最后再去写代码,这样,才能快速有效地写好代码。

到本课为止,本站教程暂告一个段落!感谢大家的关心和支持!

矩阵按键部分由16个轻触按键按照4行4列排列,连接到JP50端口。将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。确定矩阵式键盘上何键被按下,介绍一种“行扫描法”。行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法.判断键盘中有无键按下:将全部行线置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

下面给出一个具体的例子:

电路图路径:G:\图片\电路图片\xl100097.jpg

8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。列线P1.0-P1.3设置为输入线,行线P1.4-P.17设置为输出线。4根行线和4根列线形成16个相交点。

1.检测当前是否有键被按下。检测的方法是P1.4-P1.7输出全“0”,读取P1.0-P1.3的状态,若P1.0-P1.3为全“1”,则无键闭合,否则有键闭合。

2.去除键抖动。当检测到有键按下后,延时一段时间再做下一步的检测判断。

3.若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出:

P1.71110

P1.61101

P1.51011

P1.40111

在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值。

4.为了保证键每闭合一次CPU仅作一次处理,必须去除键释放时的抖动。

实验目的:通过XL1000的16位矩阵按键,在数码管上分别显示0---9,A,B,C,D,E,F。

接线方法:1用一条8PIN数据排线,把矩阵按键部份的JP50,接到CPU部份的P1口JP44.

2接8位数码管的数据线。将数码管部份的数据口JP5接到CPU部份的P0口JP51.

3接8位数码管的显示位线。将数码管部份的显示位口JP8接到CPU部份的P2口JP52.

参考程序:

;本程序实现扫描按键显示功能.

;分别按16个键盘显示分别显示数字123A456B789C*0#D

;键盘口P1,数码管显示第二位p21,数码管段位p0口

org0000h

ajmpmain

org0030h

main:

movdptr,#tab;将表头放入DPTR

lcallkey;调用键盘扫描程序

movca,@a dptr;查表后将键值送入ACC

movp0,a;将Acc值送入P0口

CLRP2.1;开显示

ljmpmain;返回反复循环显示

KEY:

LCALLKS;调用检测按键子程序

JNZK1;有键按下继续

LCALLDELAY2;无键按调用延时去抖

AJMPKEY;返回继续检测按键

K1:LCALLDELAY2

LCALLDELAY2;有键按下延时去抖动

LCALLKS;再调用检测按键程序

JNZK2;确认有按下进行下一步

AJMPKEY;无键按下返回继续检测

K2:MOVR2,#0EFH;将扫描值送入R2暂存

MOVR4,#00H;将第一列值送入R4暂存

K3:MOVP1,R2;将R2的值送入P1口

L6:JBP1.0,L1;P1.0等于1跳转到L1

MOVA,#00H;将第一行值送入ACC

AJMPLK;跳转到键值处理程序

L1:JBP1.1,L2;P1.1等于1跳转到L2

MOVA,#04H;将第二行的行值送入ACC

AJMPLK;跳转到键值理程序进行键值处理

L2:JBP1.2,L3;P1.2等于1跳转到L3

MOVA,#08H;将第三行的行值送入ACC

AJMPLK;跳转到键值处理程序

L3:JBP1.3,NEXT;P1.3等于1跳转到NEXT处

MOVA,#0cH;将第四行的行值送入ACC

LK:ADDA,R4;行值与列值相加后的键值送入A

PUSHACC;将A中的值送入堆栈暂存

K4:LCALLDELAY2;调用延时去抖动程序

LCALLKS;调用按键检测程序

JNZK4;按键没有松

开继续返回检测POPACC;将堆栈的值送入ACC

RET

NEXT:

INCR4;将列值加一

MOVA,R2;将R2的值送入A

JNBACC.7,KEY;扫描完至KEY处进行下一扫描

RLA;扫描未完将A中的值右移一位进行下一列的扫描

MOVR2,A;将ACC的值送入R2暂存

AJMPK3;跳转到K3继续

KS:MOVP1,#0FH;将P1口高四位置0低四位值1

MOVA,P1;读P1口

XRLA,#0FH;将A中的值与A中的值相异或

RET;子程序返回

DELAY2:;40ms延时去抖动子程序

MOVR5,#08H

L7:MOVR6,#0FAH

L8:DJNZR6,L8

DJNZR5,L7

RET

tab:

db28h,34h,28h,34h,0a9h,60h,20h,7ah,

20h,21h,61h,74h,30h,62h,0a2h,7eh

;0h0hc9878654a321轮流显示键盘因为无法表达*#就用H表示,B用8表示

end

这是我做成功的4X4键盘扫描源程序,P1.0-P1.3做四根列线,P1.4-P1.7做四根行线。

数码管的字型表是按照标准接法做的,按对应的按键数码管显示对应的数字。

以下是源程序:

KEYBUFEQU30H

ORG00H

START:MOVKEYBUF,#2

MOVP2,#00001111B

WAIT:

MOVP1,#0FFH

CLRP1.4

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY1

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY1

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK1

MOVKEYBUF,#0

LJMPDK1

NK1:CJNEA,#0DH,NK2

MOVKEYBUF,#1

LJMPDK1

NK2:CJNEA,#0BH,NK3

MOVKEYBUF,#2

LJMPDK1

NK3:CJNEA,#07H,NK4

MOVKEYBUF,#3

LJMPDK1

NK4:NOP

DK1:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK1A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK1A

NOKEY1:

MOVP1,#0FFH

CLRP1.5

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY2

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY2

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK5

MOVKEYBUF,#4

LJMPDK2

NK5:CJNEA,#0DH,NK6

MOVKEYBUF,#5

LJMPDK2

NK6:CJNEA,#0BH,NK7

MOVKEYBUF,#6

LJMPDK2

NK7:CJNEA,#07H,NK8

MOVKEYBUF,#7

LJMPDK2

NK8:NOP

DK2:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK2A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK2A

NOKEY2:

MOVP1,#0FFH

CLRP1.6

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY3

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY3

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK9

MOVKEYBUF,#8

LJMPDK3

NK9:CJNEA,#0DH,NK10

MOVKEYBUF,#9

LJMPDK3

NK10:CJNEA,#0BH,NK11

MOVKEYBUF,#10

LJMPDK3

NK11:CJNEA,#07H,NK12

MOVKEYBUF,#11

LJMPDK3

NK12:NOP

DK3:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK3A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK3A

NOKEY3:

MOVP1,#0FFH

CLRP1.7

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY4

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY4

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK13

MOVKEYBUF,#12

LJMPDK4

NK13:CJNEA,#0DH,NK14

MOVKEYBUF,#13

LJMPDK4

NK14:CJNEA,#0BH,NK15

MOVKEYBUF,#14

LJMPDK4

NK15:CJNEA,#07H,NK16

MOVKEYBUF,#15

LJMPDK4

NK16:NOP

DK4:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK4A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK4A

NOKEY4:

LJMPWAIT

DELY10MS:

MOVR6,#10

D1:MOVR7,#248

DJNZR7,$

DJNZR6,D1

RET

TABLE:DB0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H;0-9

DB088H,083H,0C6H,0A1H,086H,08EH,089H,0CFH,0C7H,0C8H;A,B,C,D,E,F,H,I,L,N,

END

;P3.1数据采集控制

;P2.6P2.7个位十位显示转换控制

;P1口接8个开关模拟数据

;P1.0-P1.3为个位开关量输入

;P1.4-P1.7为十位开关量输入

;此程序仅供参考

;功能P1口接8个开关输入量4个一组,分别为个位,十位输入

;P0口接一个数码管,依次显示输入量。P3.1控制是否读入

;开关量。P2.6P2.7控制是否显示个位

或十位

ORG100h

LJMPSTAR

STAR:MOVP1,#0FFH

SETBP3.1数据读入标志

MOVR0,#100,循环工作次数

LOOP:JBP3.1,$P3.1低电平时,采集P1口数据开关量处理显示阶段不再应答P3.1

MOVA,P1

PUSHACC

ANLA,#0FH取个位数值

MOVR1,A个位数值保存到R1

POPACC

ANLA,#0F0H

SWAPA高4位转成字节信息

MOVR2,A十位数值保存到R2

MOVDPTR,#TABLED

MOVA,R1

MOVCA,@A DPTR

MOVP0,A

CLRP2.6个位显示

ACALLDELAY500MS

SETBP2.6

MOVA,R2

MOVCA,@A DPTR

MOVP0,A

CLRP2.7十位显示

ACALLDELAY500MS

SETBP2.7

DJNZR0,LOOP

DELAY500MS:延时500毫秒子程略

RET

TABLED:DB0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8hDB80H,90H,88h,83h,0c6h,0a1h,86h,8eh

END

#include

typedefunsignedcharBYTE;

BYTEcodeTABLED[16]={0Xc0,0Xf9,0Xa4,0Xb0,0X99,0X92,0X82,0X0f8,0X80,0X90,0X88,0X83,0Xc6,0Xa1,0X86,0X8e};

BYTEDATled;

sbitP26=P2^6;

sbitP27=P2^7;

sbitP31=P3^1;

intTIME;

voidtimedelay(DTIME)

intDTIME;

{

intI;

for(I=0;I4;

P0=TABLED[TEMP];

P27=0;

timedelay(TIME);

P27=1;

}

}

}

1.实验任务

在8X8 LED点阵上显示柱形,让其先从左到右平滑移动三次,其次从右到左平滑移动三次,再次从上到下平滑移动三次,最后从下到上平滑移动三次,如此循环下去。

2.电路原理图

图4.24.1

3.硬件电路连线

(1).把“单片机系统”区域中的P1端口用8芯排芯连接到“点阵模块”区域中的“DR1-DR8”端口上;

(2).把“单片机系统”区域中的P3端口用8芯排芯连接到“点阵模块”区域中的“DC1-DC8”端口上;

4.程序设计内容

(1).8X8 点阵LED工作原理说明

8X8点阵LED结构如下图所示

图4.24.2

从图4.24.2中可以看出,8X8点阵共需要64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一列置1电平,某一行置0电平,则相应的二极管就亮;因此要实现一根柱形的亮法,如图49所示,对应的一列为一根竖柱,或者对应的一行为一根横柱,因此实现柱的亮的方法如下所述:

一根竖柱:对应的列置1,而行则采用扫描的方法来实现。

一根横柱:对应的行置0,而列则采用扫描的方法来实现。

5.汇编源程序

ORG00H

START:NOP

MOVR3,#3

LOP2:MOVR4,#8

MOVR2,#0

LOP1:MOVP1,#0FFH

MOVDPTR,#TABA

MOVA,R2

MOVCA,@A DPTR

MOVP3,A

INCR2

LCALLDELAY

DJNZR4,LOP1

DJNZR3,LOP2

MOVR3,#3

LOP4:MOVR4,#8

MOVR2,#7

LOP3:MOVP1,#0FFH

MOVDPTR,#TABA

MOVA,R2

MOVCA,@A DPTR

MOVP3,A

DECR2

LCALLDELAY

DJNZR4,LOP3

DJNZR3,LOP4

MOVR3,#3

LOP6:MOVR4,#8

MOVR2,#0

LOP5:MOVP3,#00H

MOVDPTR,#TABB

MOVA,R2

MOVCA,@A DPTR

MOVP1,A

INCR2

LCALLDELAY

DJNZR4,LOP5

DJNZR3,LOP6

MOVR3,#3

LOP8:MOVR4,#8

MOVR2,#7

LOP7:MOVP3,#00H

MOVDPTR,#TABB

MOVA,R2

MOVCA,@A DPTR

MOVP1,A

DECR2

LCALLDELAY

DJNZR4,LOP7

DJNZR3,LOP8

LJMPSTART

DELAY:MOVR5,#10

D2:MOVR6,#20

D1:MOVR7,#248

DJNZR7,$

DJNZR6,D1

DJNZR5,D2

RET

TABA:DB0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH

TABB:DB01H,02H,04H,08H,10H,20H,40H,80H

END

6.C语言源程序

#include0;j--);

}

voidmain(void)

{

unsignedchari,j;

while(1)

{

for(j=0;j<3;j )

//fromlefttoright3time

{

for(i=0;i<8;i )

{

P3=taba[i];

P1=0xff;

delay1();

}

}

for(j=0;j<3;j )

//fromrighttoleft3time

{

for(i=0;i<8;i )

{

P3=taba[7-i];

P1=0xff;

delay1();

}

}

for(j=0;j<3;j )

//fromtoptobottom3time

{

for(i=0;i<8;i )

{

P3=0x00;

P1=tabb[7-i];

delay1();

}

}

for(j=0;j<3;j )

//frombottomtotop3time

{

for(i=0;i<8;i )

{

P3=0x00;

P1=tabb[i];

delay1();

}

}}

}

LED点阵显示实验

一.实验要求

编程实现中英文字符的显示。

二.实验目的

1.了解LED点阵显示的基本原理和实现方法。

2.掌握点阵汉字库的编码和从标准字库中提取汉字编码的方法。

三.实验电路及连线

点阵显示模块WTD3088的(红色)列输入线接至内部LED的阴极端,行输入线接至内部LED的阳极端(若阳极端输入为高电平,阴极端输入低电平,则该LED点亮)。发光点的分布如图22-0所示。

Fig22-0WTD3088LED分布

如图22-1示,本实验模块使用74LS374来控制列输入线的电平值。将74LS374的某输出置0,则对应的LED阴极端被置低。如图22-2示,本实验模块使用74LS273来控制行输入线,并通过9013提供电流驱动。将74LS273的某输出置1,则对应的LED阳极端被置高。每次系统重新开启或总清后,74LS273输出为全0,LED显示被关闭。

通过编程控制各显示点对应LED阳极和阴极端的电平,就可以有效的控制各显示点的亮灭。

Fig22-1LED模块及列扫描电路

Fig22-2行扫描电路

Fig22-3地址译码电路

本实验模块使用4块WTD3088组成16×16点阵,以满足汉字显示的要求。为了方便的控制四个单元,使用了一片74LS139译码,产生四个地址片选信号:CLKR1=CSLED,CLKR2=CSLED 1,用于行控制的两片74LS273;CLKC1=CSLED 2,CLKC2=CSLED 3,用于列控制的两片74LS374。

实验接线:按示例程序,模块的CSLED接51/96地址的8000H。

四.实验说明

使用高亮度LED发光管构成点阵,通过编程控制可以显示中英文字符、图形及视频动态图形。LED显示以其组构方式灵活、亮度高、技术成熟、成本低廉等特点在证券、运动场馆及各种室内/外显示场合得到广泛的应用。

所显示字符的点阵数据可以自行编写(即直接点阵画图),也可从标准字库(如ASC16、HZ16)中提取。后者需要正确掌握字库的编码方法和字符定位的计算。

实验盘片中“字符转换”子目录下提供的Basc16.exe,BHz16.exe可方便的将单个字符的码表从标准字库Asc16,Hzk16中提取出来。具体使用方法是运行上述可执行程序,根据提示输入所需字符(如是汉字还需要先启动dos下的汉字环境,如ucdos,pdos95等)。程序将该字符的码表提取出来,存放在该字符ASC或区位码为文件名称的.dat文件中。用户只需将该文件中内容拷贝、粘贴到自己的程序中即可。但需要注意字节排列顺序、字节中每一位与具体显示点的一一对应关系,必要时还要对码表稍作修改。同一目录下还提供了上述可执行程序的源文件,使用BC3.1编写,供用户参考。

五.实验程序框图

用户应留心其中行扫描的实现及码表的处理。

六.实验程序:

(一)提供LEDA51演示Asc16字符的简单点阵显示。

;________*LED点阵显示示例程序______________________*

;__该程序显示Asc16字符__

;__为了简单起见,程序只显示一个字符__

;__该程序针对T598实验机的模块14__

;____________________________________________________

CSLEDEQU8000H

CSR1EQUCSLED;行1273

CSR2EQUCSLED 1H;行2273

CSC1EQUCSLED 2H;列1374

CSC2EQUCSLED 3H;列2374

ORG0000H

MOVSP,#60H

INIT:MOVA,#0H;关闭行

MOVDPTR,#CSR1

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVX@DPTR,A

MOVA,#0FFH;关闭列

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSC2

MOVX@DPTR,A

D:MOVR5,#00H

MOVR4,#01H;每次为单行扫描

DISP:

MOVA,R5

MOVDPTR,#ASCE;此处设定所要显示的字符

MOVCA,@A DPTR

CPLACC;代码取反,决定显示的阴阳

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVDPTR,#CSR1

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#8H,DISP

MOVA,#0H

MOVX@DPTR,A

MOVR5,#08H

MOVR4,#01H

DISP2:

MOVA,R5

MOVDPTR,#ASCE

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#10H,DISP2

MOVA,#0H

MOVX@DPTR,A

SJMPD

;________延时子程序,协调字符显示速度____________*

DELAY:MOVR7,#1H

DL1:MOVR6,#00H

DL2:DJNZR6,DL2

DJNZR7,DL1

RET

;________字符点阵字库______________*

;ASC16字符编码排列

;0

;1

;|

;|

;14

;15

;高位D7--D0

;请注意编码的排列次序和实际显示点阵分布的关系

ASCA:DB00H,00H,10H,38H,6CH,0C6H,0C6H,0FEH

DB0C6H,0C6H,0C6H,0C6H,00H,00H,00H,00H

ASCE:DB00H,00H,0FEH,66H,62H,68H,78H,68H

DB60H,62H,66H,0FEH,00H,00H,00H,00H

ASCD:DB00H,00H,0F8H,6CH,66H,66H,66H,66H

DB66H,66H,6CH,0F8H,00H,00H,00H,00H

ASCK:DB00H,00H,0E6H,66H,66H,6CH,78H,78H

DB6CH,66H,66H,0E6H,00H,00H,00H,00H

;____________________________________________________

END

(二)LEDHZ51两个示例程序。和Hz16字符的简单点阵显示。

;________*LED点阵显示示例程序______________________*

;__该程序显示hz16字符__

;__为了简单起见,程序只显示一个字符__

;__该程序针对T598实验机的模块14__

;____________________________________________________

CSLEDEQU8000H

CSR1EQUCSLED;行1273

CSR2EQUCSLED 1H;行2273

CSC1EQUCSLED 2H;列1374

CSC2EQUCSLED 3H;列2374ORG0000H

MOVSP,#60H

INIT:MOVA,#0H;关闭LED显示

MOVDPTR,#CSR1

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVX@DPTR,A

MOVA,#0FFH;关闭LED显示

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSC2

MOVX@DPTR,A

D:MOVR5,#00H

MOVR4,#01H

DISP:

MOVA,R5

RLACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVA,R5

RLACC

INCACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSR1

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#8H,DISP

MOVA,#0H

MOVX@DPTR,A

MOVR5,#08H

MOVR4,#01H

DISP2:

MOVA,R5

RLACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVA,R5

RLACC

INCACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#10H,DISP2

MOVA,#0H

MOVX@DPTR,A

SJMPD

;________延时子程序,协调字符显示速度____________*

DELAY:MOVR7,#1H

DL1:MOVR6,#00H

DL2:DJNZR6,DL2

DJNZR7,DL1

RET

;________字符点阵字库______________*

;HZ16字符编码排列

;01

;23

;|

;|

;2829

;3031

;高位D7--D0

HZAI:DB00H,78H,3FH,80H,11H,10H,09H,20H

DB7FH,0FEH,42H,02H,82H,04H,7FH,0F8H

DB04H,00H,07H,0F0H,0AH,20H,09H,40H

DB10H,80H,11H,60H,22H,1CH,0CH,08H

HZDI:DB00H,80H,40H,80H,20H,88H,2FH,0FCH

DB08H,88H,08H,88H,0E8H,88H,2FH,0F8H

DB28H,88H,28H,88H,28H,88H,2FH,0F8H

DB28H,08H,50H,06H,8FH,0FCH,00H,00H

HZKE:DB01H,00H,01H,04H,0FFH,0FEH,01H,00H

DB01H,10H,1FH,0F8H,10H,10H,10H,10H

DB10H,10H,1FH,0F0H,14H,50H,04H,40H

DB04H,40H,08H,42H,10H,42H,60H,3EH

;____________________________________________________

END

基于89C51的计算机可锁定加密键盘设计

摘要:介绍PC键盘和键盘接口的PS/2通信协议,以及用89C51实现可锁定键盘的软件和硬件设计方法。具有安全可靠、容错能力强、可以直接采用标准键盘进行改装、便于实现等优点,并保留标准键盘的全部功能。

关键词:PS/289C51C51键盘

引言

在智能仪器、自动控制等领域,已大量使用嵌入式PC,如Advantech公司的PC/104、AMD公司的DIMM-PC等。为适应开放式、模块化的要求,嵌入式PC具有标准的PC接口,如VGA显示器控制接口、以太网接口、RS232接口、PC/AT键盘接口等。所以,可以用标准的PC键盘对嵌入式PC进行操作与控制。键盘在输入指令之后,可能很长一段时间不用。为计算机安全和防止误触发,需要将键盘锁定,还要对某些键采取屏蔽措施,但是PC标准键盘不能满足这些要求。本文介绍一种用89C51设计实现的可锁定加密PC/AT键盘。

1键盘功能及工作原理

PC键盘功能主要有按键识别、去抖、重键处理、发送扫描码、自动重发、接收键盘命令、处理命令等。键盘有编码键盘和非编码键盘。编码键盘程序设计简单,但硬件电路复杂,价格较高;非编码键盘用软件来实现识别键、编码转换、去抖等功能,硬件电路简单,价格便宜。现代微机系统中广泛采用非编码键盘。PC键盘多采用18行×8列的二维矩阵行列结构。采用行扫描法识别按下的按键。

2PS/2协议

PS/2协议是外设与主机之间通信的一种同步双向串行协议。在该协议中主机拥有较高的优先级,在一定条件下可以终止外设正在进行的发送过程。PS/2协议采用的传送数据帧的格式为:1位起始位(0)、8位数据位、1位奇偶校验位、1位停止位(1)。数据发送时低位在前,高位在后。外设每收到主机发来的1帧数据,都要紧随该帧的停止位发送一个握手位ACK(0)应答主机。然后,外设还要发1帧应答数据(0xF0),表示外设已经完整地接收到了主机的命令;而主机则不需发送握手位,也不需要发送应答帧。

2.1键盘到PC键盘接口的通信

当时钟线和数据线均为高电平时,允许键盘发送数据,系统将接收数据;当时钟线被拉为低电平时,表明系统禁止数据传输。图1给出了发送时序,包含1个低电平触发的起始位、8位数据位、1个奇校验位和1个高电平的结束位。

2.2PC系统到键盘的通信协议

若时钟线出现高电平,数据线出现低电平,表明系统请求发送,键盘准备产生同步时钟脉冲串,并接收数据。包含了1个低电平触发的起始位、8位数据位、1个奇校验位、1个应答位、1个高电平的结束位。图2为时序图。

(1)键盘命令及执行过程

①FFH:复位键盘。系统通过此软件复位命令使键盘进入程序复位和内部自测试,称为基本保证测试(BAT)。复位键盘的过程如下:

a.键盘收到FFH后立即回送ACK(FAH)作答;

b.键盘接口收到ACK后,将键盘时钟和数据线置为高电平;

c.键盘检测到此状态后开始BAT操作;

d.如果BAT正确完成,键盘发送AAH以表示结束,

否则以FDH(或其它任何值)表示诊断有误。

②FEH:重新发送。当系统检测

到从键盘送来的任何传输错误时,它便向键盘发送FEH命令。键盘接收到此命令后,将重新送出原来的内容。③FDH~F7H:空操作(保留未用)。

④F6H:设置缺省值。此命令使键盘所有条件复位到电源接通时的缺省状态,键盘继续扫描。

⑤F5H:设置缺省值和停止键盘。此命令使键盘所有条件复位到电源接通时的缺省状态,并停止键盘扫描,等待下一个键盘命令。

⑥F4H:启动键盘。键盘接收到此命令后,用ACK(FAH)作答,清除输出缓冲器,并启动键盘开始扫描。

⑦F3H:设置拍发速率和延时参数。每当按下任一键时,键盘以拍发速率连续送出键的接通码,直到键被释放为止。延时参数是指按下一键后,键盘输出的响应时间。

系统缺省设置:拍发速率=10个/s±20,延时=500ms±20。

当要改变设置时可以使用F3H命令,并后跟一个字节的参数。参数定义如表1所列。

表1

D7

D6D5

D4D3

D2D1D0

C

B

A

计算拍发速率和响应延时的公式如下:

拍发速率=1/[(8 A)×2B×0.00417](1/s)

响应延时=(1 C)×250(ms)

注:缺省的延时参数值为2CH。

此命令的执行过程如下:

a.键盘收到F3H命令后,用FAH予以响应,并停止

扫描和等待随后的参数;

b.键盘若收到随后的设置参数,用另一个ACK响

应,并按其参数设置新的拍发速率和响应延时,

之后重新开始扫描(若键盘原来是开放的);

c.键盘若收到FAH命令,但无随后的设置参数,则

键盘结束命令设置,并保持原来的拍发速率和响

应延时,停止扫描。

⑧F2H,F1,EFH:保留未用。

⑨F0H:设置键盘扫描码命令。此命令用于设置键盘的扫描码,后跟参数指定三种扫描码的哪一种。键盘复位时,默认扫描码是第二种。

⑩EEH:回送命令。此命令用于辅助诊断,要求键盘接收到EEH时也要回送EEH予以响应。若键盘原来是开放的,则继续扫描。

EDH:置位/复位LED指示器。键盘右上角有三个LED指示器,分别反映Caps、Num和Scroll三个键的锁定情况。参数字节如表2所列。

表2

D7D3

D2

D1

D0

保留

1=激励CapsLED

1=激励NumLED

1=激励ScrollLED

此命令执行过程与F3H相似。若命令后跟参数,则按参数设定LED状态并继续扫描。若仅有命令无参数,则不改变LED原状态,并停止扫描。

(2)键盘响应

键盘在下列四种情况下都会向键盘接口发送数据。

①按下任一键,键盘以拍发速率向接口发送键盘接通扫描码。

②释放所按下的键,键盘发送断开扫描码。

③系统向键盘发送键盘命令后,键盘回送应答。

④当用户按键速度超出键盘所能容纳的最大键个数时,键盘做出响应。

后三种情况称为键盘响应。响应字节有7个,定义如下。

①FEH:重新发送响应。当键盘收到一个无效的键盘命令,或者检测到奇偶错的键盘命令时,键盘回送响应字节为FEH,要求系统重发键盘命令。

②FAH:正常应答。对任何一个有效的键盘命令,键盘回送FAH予以响应。

③00H:超限应答。当用户按键速度超出键盘所能容纳的最大键符个数时(16个字节的缓冲器),键盘发送00H。

④FDH:诊断故障应答。键盘接受软件复位命令,执行自测试过程中。若检测到故障,则以FDH应答。此时,键盘停止扫描并等待下一个键盘命令。

⑤AAH:诊断正常应答。键盘在软件复位过程中,正常完成BAT测试,以AAH应答。

⑥FEH:回响命令的应答,对键盘FEH命令的应答。

⑦F0H:断开扫描码前缀,键盘对键符按下后释放的应答,第一个字节为F0H,第二个字节为接通扫描码(有几个键例外)。

3硬件设计

PC系列键盘采用18行×8列的矩阵行列结构。89C51单片机有4个8位I/O端口,因此可以采用P0、P2口再加上P3口的2个(P3.6和P3.7)作为行扫描线。P1口作为列输入线(如果用P0口作列输入线,必须加上拉电阻)。采用P3.0、P3.1作为数据线和时钟线与PC系统进行通信,用P3.2、P3.4、P3.5控制键盘上的3个指示灯。硬件原理如图3所示。

键盘与计算机通过一个五芯(PS/2接口为六芯)插座相接,4个有效引脚的定义分别是电源(VCC)、地(GND)、串行时钟线(SCK)、串行数据线(SIO)。

4软件设计

①消抖及重键处理:通过软件上延时程序来消除抖动;采用后按键优先处理,即多键同时按下时,只重复发送最后按下键的扫描码。

②程序包括键盘扫描子程序、发送键码子程序、发送数据子程序、接收命令子程序、定时器1中断服务程序、主程序等。键盘扫描子程序用于扫描键状态,将被按键的位置号存入缓冲器中;发送键码子程序用于将缓冲区键的接通码或断开码发送给计算机键盘接口或者存在键盘密码缓冲区中;发送数据子程序用于将数据发给计算机键盘接口;接收命令子程序用于接收计算机键盘接口发来的键盘命令;定时器1中断服务子程序用于给程序中的延时提供标准时钟,并具有软件看门狗功能,防止软件出现死机现象;主程序用于系统初始化,子程序调度,锁定状态的显示等。

图6发送缓冲区键码子程序流程图

图4~6是主要软件模块的流程图。单片机源程序见本刊网络补充版(.com)。

5结论

本文介绍的PC/AT键盘具有结构简单、设计灵活、安全可靠的特点,可用于标准PC和嵌入式PC。本键盘可以在标准的键盘基础上进行改造,只需换掉原来的控制芯片即可,可节省设计成本。

单片机C51编程几个有用的模块(1)

KeilC51常用功能模块使用说明

说明

本文档包括单片机系统中常用到的时钟中断、通讯及键盘扫描等模块(见所附源程序)的说明。这些模块使用前后台系统模型。为达到最大的灵活性,需要在用户工程中定义config.h文件,在其中定义各模块可选参数的设置,而不是直接更改源代码。

这些可选内容大部分为宏定义,如果不定义宏相应的功能在编译时被屏蔽,不会增加代码长度。具体可选内容见各模块中的说明。

在Config.h文件中还要包含一个单片机硬件的资源头文件。

各模块使用了定义在Common.h中的一些数据类型。如:BIT(bit)BYTE(unsignedchar)等,具体请参见源程序。

时钟模块

在单片机软件设计中,时钟是重要资源,为了充分利用时钟资源,故设计本时钟模块。本模块使用定时器0,在完成用户指定功能的同时,还能够自动处理一些其它模块中与时钟相关的信息。

时钟模块由声明文件Timer.h以及实现文件Timer.c组成。

用户应该在Config.h中定义宏TIMER_RELOAD来设定定时器0的重装载初值。推荐的定时器0的中断时间大于1毫秒。

在程序的初始化阶段调用时钟模块的初始化函数InitTimerModule()之后,就可以使用时钟模块所以支持的各种功能。具体描述如下:

延时:当用户需要进行一定时间的延时时,可以通过调用Delay()来进行,参数为时钟中断的次数。如时钟中断周期为1ms,想进行100ms的延时,则可以调用Delay(100)。

注意:

如果延时的绝对时间小于时钟中断的周期,则不能够用本方法做到延时。

定时:当程序中需要使用定时功能时,如等待某外部事件,如果在一定时间内发生则继续执行,如果在这段时间内发生,则认为出现错误,转向错误处理机制。

在此推荐一种编程模式,但用户可以用自己认为更合理的方式处理此类问题。

这里简单说明一下关于阻塞式函数及非阻塞式函数。简单说,阻塞式函数就是当检测完成条件,如

果不能够完成则等待,如:

voidCheckSomething()

{

//gbitSuccessFlagisaglobalvariable

while(gbitSuccessFlag==FALSE)

{

//donothingbutwaiting

}

}

可以看到,当bitSuccessFlag没有被设置为TRUE时,函数保持等待状态不返回,这样就是阻塞式的函数。

另外一种情况:

BITCheckSomething()

{

if(gbitSuccessFlag==TRUE)

{

//…

returnTRUE;

}

returnFALSE;

}

在这里,如果所检测的事件有没有完成,函数进行检测之后,立刻返回,通过返回值报告完成情况,如果没有完成,则等待调用者分配再次执行的机会。这样的函数就是非阻塞函数。

在应用定时功能时,首先要将检测函数定义成非阻塞函数。如上面的第二个版本的CheckSomething。

然后下面模式:

BITbitDone=FALSE;

ResetClock();//cleartimerinterrupttimescounter

while(GetClock()

{

if(CheckSomething()==TRUE)

{

bitDone=TRUE;

break;

}

}

if(bitDone==FALSE)

{

//processtimeout

}或者简单写成:

BITbitDone=FALSE;

ResetClock();

while(GetClock()=(z))

当然,用户也可以将IsPackageHeader和IsPackageTailer定义成为函数,通过BIT类型的返回值来向调用者提供与相应宏相同的信息。

另一种办法需要在Config.h文件中定义宏SCOMM_ComplexPackageFormat。(需要注意的是,不能够同时定义SCOMM_SimplePackageFormat和SCOMM_ComplexPackageFormat宏,否则会造成严重的不可预见性错误。

这时需要提供回调函数QueryPackageFormat,原形如下:

BYTEQueryPackageFormat(BYTEbyData,BYTEbyCount,BYTEbyParam);

函数中三个参数的含义与使用简单数据包格式时判断数据包尾的宏的参数相同。

函数通过返回值来通知作为调用者的接收函数对接收到的数据如何处理,但目前这种方法仅为需要处理复杂数据包格式时的一种可选方法,但不推荐。用户如果想使用这种方法可以自己更改接收函数中相应的

#ifdefSCOM_ComplexPackageFormat

#endif//SCOMM_ComplexPackageFormat

预编译指令之间的内容。

例如指定QueryPackageFormat的返回值的含义:

0:继续找数据包头或继续找数据包尾。

1:找到数据包头。

2:找到数据包尾。

3:数据包出错,需要抛弃。

然后更改源代码来实现上面的协议。

注意:当用户需要使用字符串的时候,可以利用简单的包装函数将字符串转换为字节数组。所以没有必要提供专用的字符串处理函数。

键盘扫描模块

键盘扫描模块有两种工作方式,一种为自动的由时钟模块调用,另一种是由程序员自行调用。

1)由时钟模块自动调用的方式

将时钟模块实现文件(Timer.h)及键盘扫描模块的实现文件(KBScan。c)包含进工程,在Config.h文件中添加TIMER_KBSCANDELAY宏。时钟模块自动对时钟中断进行计数,当达到TIMER_KBSCANDELAY宏所定义的值后,自动调用键盘扫描模块中的函数KBScanProcess()进行键盘扫描,也就是说,这个宏的值可以决定按键消抖动的时间。

用户应该提供两个回调函数OnKBScan()及OnKeysPressed()。在函数OnKBScan中进行键盘扫描,并返回扫描码。扫描码的类型缺省为BYTE,当键盘规模较大时,BYTE不能够完全包含键盘信息时,可在Config.h文件中重定义宏KBvalue,如下:

#defineKBvalueWORD

这样,就可以使用16位的键盘扫描码,如果此时还达不到要求,可以将键盘扫描码定义成一个结构,但这样做将会增加代码量及消耗更多的RAM资源,故不推荐。

扫描模块调用OnKBScan取得扫描码,并调用用户可以重定义的宏IsNoKeyPressed来判断是否有键按下,缺省的IsNoKeyPressed实现如下:

#defineIsNoKeyPressed(x)((x)==0x00)

即认为OnKBScan返回0扫描码时为没有键按下,如果扫描函数返回其它非零扫描码做为无键按下的扫描码时,可以在Config.h文件中重定义IsNoKeyPressed宏的实现。

8位键盘扫描码(缺省值)时,相应的扫描函数为:

BYTEOnKBScan()

当扫描模块经过软件消抖动之后,发现有键按下,就会调用另一个回调函数OnKeysPressed。函数的声明应该如下:

voidOnKeyPressed(BYTEbyKBvalue,BYTEbyState)

其中中的参数byKBvalue的类型为BYTE,此为缺省值,如果使用其它类型的扫描码,就将此参数变为相应类型。这个值由OnKBScan返回。另一个参数byState在通常情况下为零。但当用户在Config.h中定义宏KBSCAN_BRUSTCOUNT,同时键盘上的某键被按住不放时,扫描模块对它自己的调用(注意这里和TIMER_KBSCANDELAY宏不同,TIMER_KBSCANDELAY是时钟中断足够的次数后调用扫描模块,而KBSCAN_BRUSHCOUNT为扫描模块自身的被调用次数)进行计数,当达到KBSCAN_BRUSTCOUNT时,扫描模块调用OnKeysPressed,此时第一个参数的含义不变,而byState变成1,同时计数器复位,又经过一段时间后,用值为3的byState调用OnKeysPressed。这样就可以很方便的实现多功能键或者检测某键的长时间被按下。

2)由用户自行调用

由用户自行在程序中调用扫描模块,而不是由时钟中断自行调用。其它与方式1相同。

注意:

1)函数KBScanProcess为非阻塞函数,它将在很快的时间内返回,等待再次分配给它执行的机会。

2)函数KBScanProcess是在时钟中断外部运行的,它的过程可以被任何中断打断,但不影响系统运行。

3)byState的最大值为250,之后被复位为零。

应用举例

现在来举例说明上述几个模块的使用方法。

硬件环境描述:

为了控制一盏灯,需要单片机提供一个做控制功能的开关量,这里不描述外部接口电路,只说明当单片机的P10脚为高电平时,灯灭,当P10脚为低电平时,灯亮。

可以通过计算机由串口发送命令来控制,或通过一个按键(pus

hbutton不是自锁式的按键)来手动控制(按键接在P11脚上,当键没有按下时,P11电平为高,键按下时,引脚电平被接低),当使用按键手动控制的时候,需要给计算机发送通知。

设定串口通讯指令如下:

数据包由0xff做包头,4个字节长,第二个字节为命令代码,第三个字节为数据,最后一个字节为校验位。

命令和数据代码有如下组合:

(计算机发给单片机)

0x100x01:计算机控制灯亮。(数据位是非零值即可)

0x100x00:计算机控制灯灭。

(单片机发给计算机)

0x110x01:单片机正常执行控制指令,返回。(数据位是非零值即可)

0x110x00:单片机不能够正常执行控制指令,或控制指令错(不明含义的数据包或校验错等)。

0x120x01:手动控制灯亮。(数据位是非零值即可)

0x120x00:手动控制灯灭。建立工程:

在硬盘上建立文件夹Projects,在Projects下建立Common文件夹及Example文件夹。将各模块的头文件及实现文件拷贝到Common文件夹下(推荐使用这样的文件组织结构,其它工程也可以建立在Projects下,各工程共享Common文件夹中的代码)。

启动KeilC的IDE,在Example下建立新工程,将各模块的实现文件包含进工程。

在Example文件夹下建立Output文件夹,更改工程设置,将Output作为输出文件和List文件的输出文件夹(推荐使用这样的结构,当保存工程文件时,可以简单的删除Output文件夹中的内容而不会误删有用的工程文件)。

建立工程配置头文件Config.h及工程主文件Example.c,并将Exmaple.c文件加入工程。

输入代码:

代码的具体编写过程略。下面是最后的Config.h文件及Example.c文件。

//

//file:onfig.h

//

#ifndef_CONFIG_H_

#define_CONFIG_H_

#include//使用AT89C52做控制

#include“../Common/Common.h”//使用自定义的数据类型

#defineTIMER_RELOAD922//11.0592MHz晶振,1ms中断周期

#defineTIMER_KBSCANDELAY40//40ms重检测按键状态,即40ms消抖

#defineSCOMM_AsyncInterface//使用异步通讯服务

#defineIsPackageHeader(x)((x)==0xff)//判断包头是不是0xff

#defineIsPackageTailer(x,y,z)((y)<=(z))//判断包的长度是不是足够

#endif//_CONFIG_H_

//

//file:xample.c

//

#include

#include“../Common/Common.h”

#include“../Common/Timer.h”

#include“../Common/Scomm.h”

#include“../Common/KBScan.h”

BITgbitLampState=1;//灯的状态,缺省为off

staticvoidInitialize()

{

InitTimerModule();//初始化时钟模块

InitSCommModule(0xfd,TRUE);//初始化通讯模块,11.0592MHz晶振,

//波特率为19200

EA=1;//开中断

}

voidmain()

{

Initialize();//初始化

while(TRUE)//主循环

{

ImpTimerService();//实现时钟中断服务,如键盘扫描

AsyncRecePackage(4);//接收4个字节长的数据包

}

}

//在中断外部响应时钟中断事件

voidOnTimerEvent()

{

//donothing

}

//控制外部灯

staticvoidTriggerLamp(BITbEnable)

{

P10=~bEnable;//需要反相控制

}

//键扫描回调函数

BYTEKBScan()

{

BITb;

P11=1;//读之前拉高引脚电平

b=P11;//读入引脚状态

return~b;//数据反相做扫描码

}

//计算校验和

staticBYTECalcCheckSum(BYTE*pbyBuf,BYTEbyLen)

{

BYTEby,bySum=0;

for(by=0;by

return0–bySum;

}

//接收到键盘消息回调函数

voidOnKeyPressed(BYTEbyvalue,BYTEbyState)

{

BYTEby[4];

if(byState==0)

{

switch(byvalue)

{

case0x01:

gbitLampState=~gbitLampState;//灯状态取反

TriggerLamp(gbitLampState);//执行控制

by[0]=0xff;//构造数据包

by[1]=0x12;

by[2]=(BYTE)gbitLampState;

by[3]=CalcCheckSum(by,3);//求校验和

SendPackage(by,4);//发送数据包

break;

//处理其它扫描码

default:

break;

}

}

//接收到数据包回调函数

voidOnRecePackage(BYTE*pbyBuf,BYTEbyBufLen)

{

BYTEby[4];

by[0]=0xff;

by[1]=0x11;

if(byBufLen!=4||pbyBuf[3]!=CalcCheckSum(pbyBuf,3))

{

by[2]=0;

by[3]=CalcCheckSum(by,3);

SendPackage(by,4);//处理长度或校验和不正确

}

switch(pbyBuf[1])

{

case0x10:

gbitLampState=(BIT)pbyBuf[2];

TriggerLamp(gbitLampState);

by[2]=1;

by[3]=CalcCheckSum(by,3);

SendPackage(by,4);//发送成功执行通知

break;

default://不知道的命令

by[2]=0;

by[3]=CalcCheckSum(by,3);

SendPackage(by,4);//发送没有成功执行通知

break;

}

}

4.课程设计单独计算成绩,考评方法见其大纲。

三、理论考试说明

1.单片机技术及应用理论考试,采用闭卷笔试形式,考试时间120分钟。

2.期末考试试题根据教学大纲,其范围和难度按照本方案中制订的考试考核内容和要求确定。考试命题覆盖考试大纲要求范围。

3.期末考试试题类型有以下几种:

①填空题;

②选择题;

③判断题;

④简答题⑤综合应用题。

四、考试考核要求层次

按照教学大纲的要求,理论考试要求分为掌握、理解和了解三个层次。

掌握:

对于本课程的重点内容要求学生达到掌握的程度。即能够全面、深入理解和熟练掌握所学内容,并能够用其分析、初步设计和解答与应用相关的问题,能够举一反三。要求学生掌握的内容也就是考试的主要内容,在考试中所占比例约70。

理解:

对于本课程的一般内容要求学生能够理解。即要求学生能够较好地理解所学内容,并且对所涉及的内容能够进行简单分析和判断。要求学生理解的内容也是考试的内容,在考试中所占比例约25。

了解:

对于本课程的次要内容要求学生能够了解。要求学生了解的内容,一般是指在眼下不必进一步深入和扩展,有些也许需要学生自己今后在工作中进行深入研究。对要求了解的内容,在考试中占较小比例,不超过5。实验五:按键电路、显示电路实验一、实验目的:1.掌握独立式按键电路与矩阵式按键电路的设计方法。2.掌握数码管显示电路的工作原理3.掌握源程序编辑软件UltraEdit,编译软件KeilC51、仿真软件Proteus的使用方法4.掌握硬件仿真器ME-52A的使用方法二、实验器材:1.单片机实验板2.单片机硬件仿真器ME-51A3.计算机4.电源三、实验要求:1.电路如图5所示,用单片机的P3口所接的四个独立式按键控制p1口流水灯花样的方法;具体表现为:p3.0、P3.1、P3.2、P3.3四个小按键分别实现了四个控制:(1)跑灯:即P1.0---1.7亮点流动:(2)流水灯:即P1.0-1.7依次点亮(3)交叉闪烁:即P0.0,P0.2,P0.4,P0.6和P0.1,P0.3,P0.5,P0.7轮流点亮(4)停止;在任何状态下按此键程序停止运行.2.电路如图6所示,用P2口所接的4×4矩阵式键盘作为输入,在P1口所接的数码管上显示出每个按键的0~F序号,键盘的布局如下表所示:FEDCBA9876543210四、实验原理:1.独立式按键电路显示如图5所示,从图中可看出,判断有无键按下,只要检测P3.0~P3.3相应端口的高低电平即可,若检测有某一端口为低电平,表明该端口有按键按下,经延时消抖后转去执行相应的功能子程序。若为高电平,表明无键按1.独立式按键电路如图5所示,下,继续检测。示例程序如下:ORG000HLJMPSTAR1ORG0030HSTAR1:MOVP3,#0FFH;置P3口为输入态JNBP3.0,FUN0;判别P3.0是否有键按下,是,则转FUN0JNBP3.1,FUN1;判别P3.1是否有键按下,是,则转FUN1JNBP3.2,FUN2;判别P3.2是否有键按下,是,则转FUN2JNBP3.3,FUN3;判别P3.3是否有键按下,是,则转FUN3JNBF0,STAR1;曾经有键按下F0置1RET图5FUN0:LCALLDL10MS;消岸抖动JBP3.0,STAR1WAITL0:JNBP3.0,WAITL0;等待键释放SETBF0FUN01:LCALLFUN00LCALLSTAR1LJMPFUN01FUN1:LCALLDL10MS;消岸抖动JBP3.1,STAR1WAITL1:JNBP3.1,WAITL1;等待键释放SETBF0FUN10:LCALLFUN11LCALLSTAR1LJMPFUN10FUN2:LCALLDL10MS;消岸抖动JBP3.2,STAR1WAITL2:JNBP3.2,WAITL2;等待键释放SETBF0FUN20:LCALLFUN22LCALLSTAR1LJMPFUN20FUN3:LCALLDL10MS;消岸抖动JBP3.3,STAR1WAITL3:JNBP3.3,WAITL3;等待键释放CLRF0MOVP1,#0FFH;关显示LJMPSTAR1FUN00:MOVA,#0FEH;跑灯子程序FUN000:MOVP1,ALCALLDL05SJNBACC.7,OUTRLAAJMPFUN000OUT:RETFUN11:MOVA,#0FEH;流水灯子程序FUN111:MOVP1,ALCALLDL05SJZOUTRLAANLA,P1AJMPFUN111FUN22:MOVA,#0AAH;交叉点亮子程序MOVP1,ALCALLDL30SCPLAMOVP1,ALCALLDL30SRET;____________;;延时程序;;____________;DL512:MOVR2,#0FFHLOOP1:DJNZR2,LOOP1RETDL10MS:MOVR3,#14HLOOP2:LCALLDL512DJNZR3,LOOP2RETDL05S:MOVR4,#0AHLOOP3:LCALLDL10MSDJNZR4,LOOP3RETDL30S:MOVR5,#03HLOOP4:LCALLDL05SDJNZR5,LOOP4RETEND2.矩阵式按键电路显示如图6所示。采用扫描方式进行按键的识别检测,并将对应按键的键号用查表指令将对应的代码显示在数码管上。图6参考程序如下:ORG0000HLJMPSTARTORG0030HSTART:MOVSP,#60H;设置堆栈指针SCAN:MOVR3,#0F7H;置行扫描初值MOVR1,#00H;到TABLE表中取码的指针SCAN1:MOVA,R3MOVP2,A;扫描输出MOVA,P2;重读P2口状态MOVR4,A;暂存于R4吕中SETBC;C=1MOVR5,#03H;扫描4列初值L1:RLCA;A中内容循环左移JNCKEYIN;C=0,有键按下,转消抖INCR1;取码指针加1DJNZR5,L1;无键按下,继续检测MOVA,R3;扫描下一行SETBCRRCAMOVR3,AJCSCAN1;4行是否扫描完,未完,继续LJMPSCANKEYIN:MOVR7,#10;削除抖动D2:MOVR6,#248DJNZR6,$DJNZR7,D2D3:MOVA,P2;按键放开否?XRLA,R4JZD3MOVA,R1MOVDPTR,#TABLE;到TABLE中取码MOVCA,@A DPTRMOVP1,ALJMPSCANTABLE:DB0C0H,0F9H,0A4H,0B0H,80H,90H,88H,83H,0C6H,0A1H,86H,8EHENDDB80H,90H,88H,83HDB0C6H,0A1H,86H,8EHEND五、实验步骤:1.运行UltraEdit-32源程序编辑软件,输入、编辑汇编语言源程序。2.运行KeiluVision2源程序编译软件,对源程序进行编译,得到目标代码文件。3.运行Proteus模拟仿真软件,打开已绘制好的仿真电路原理图,进行模拟 仿真。4.把硬件仿真器ME-52A与单片实验板连接好,再用硬件仿真器进行仿真验证。六、实验分析与总结1.用仿真系统调试简单程序结构、分支程序结构、循环程序结构、子程序结构和中断结构的关键在于,如何将对程序的分析理解和开发系统提供的基本功能有机地结合起来,其前提条件是必须对源程序的作用、结构特点、运行过程与结果有较全面的认识,并能根据程序运行过程中出现的现象和结果分析并判断产生各种故障现象的原因,再运用排除法逐一检验各种判断是否准确。2.掌握程序结构特点的基础上,合理选择观测点,通过观察在观测点处参数及路径的变化检验程序运行的结果。3.高调试程序的效率,应对单片机开发系统所提供的几种程序运行调试方式有足够的了解并能熟练地运用。例如,在调试过程中,若要观察最终结果,则可选择全速运行调试;若要观察相关指令的运行结果或运行路径的变化过程,则可选择单步运行;若要检查子程序的运行过程,则可选择跟踪运行调试;若要检查循环程序或中断服务程序,则可选择断点运行调试;若要定点检查程序运行到某处的结果时,则可选择快速运行到光标处调试。但实际中究竟选用哪种方法更适宜或哪几种方法结合使用更快捷,将随着分析能力与操作的熟练程度逐步提高。4.程序运行结果是否正确时,应运用单片机开发系统所提供的交互界面,将程序运行过程中程序计数器PC(地址)的变化、各单元(内部RAM和外部RAM)内容的变化、特殊功能寄存器内容的变化、堆栈指针SP内容的变化与程序的理论分析结果相对照。5.程序和调试程序时,需要多次反复的过程,并非一次就能排除全部故障,特别是单片机应用系统的硬件电路和汇编程序相结合的综合调试就更加复杂,因此,必须通过反复调试,不断修改硬件和软件,直到最终符合设计要求为止。如果在调试中能够根据实验现象预先对产生故障的原因加以判断和分析,并制定出相应的调试方法和步骤,可缩小排除故障的范围,提高调试效率。七、思考与练习填空题

1、设X=5AH,Y=36H,则X与Y“或”运算为__7EH_______,X与Y的“异或”运算为___6CH_____。

2、若机器的字长为8位,X=17,Y=35,则X+Y=__110100_____,X-Y=_11101110______(要求结果写出二进制形式)。

3、单片机的复位操作是____高电平______(高电平/低电平),单片机复位后,堆栈指针SP的值是___07h_____。

4、单片机中,常用作地址锁存器的芯片是__74HC373____________,常用作地址译码器芯片是_____74HC138____________。

5、若选择内部程序存储器,应该设置为_____高_______(高电平/低电平),那么,PSEN信号的处理方式为___不用__________________。

6、单片机程序的入口地址是____0000H__________,外部中断1的入口地址是______0013H_________。

7、若采用6MHz的晶体振荡器,则MCS-51单片机的振荡周期为__0.5us_______,机器周期为_____2us__________。

8、扩展芯片的选择方法有两种,它们分别是___线选法_______________和_____译码法__________。

9、单片机的内部RAM区中,可以位寻址的地址范围是____20H~2FH______________,特殊功能寄存器中,可位寻址的地址是___是能被8整除的地址_________________。

10、子程序返回指令是___ret______,中断子程序返回指令是__reti。

11、8051单片机的存储器的最大特点是内部RAM与外部RAM分开编址。

12、8051最多可以有32个并行输入输出口,最少也可以有8个并行口。

13、函数是C语言的基本单位。

14、串行口方式2接收到的第9位数据送SCON寄存器的RB8位中保存。

15、MCS-51内部提供3个可编程的16位定时/计数器,定时器有4种工作方式。

16、一个函数由两部分组成,即说明部分和语句部分。

17、串行口方式3发送的第9位数据要事先写入SCON寄存器的TB8位。

18、利用8155H可以扩展3个并行口,256个RAM单元。

19、C语言中输入和输出操作是由库函数scanf和printf等函数来完成。

二、选择题

1、C语言中最简单的数据类型包括(B)。

A、整型、实型、逻辑型B、整型、实型、字符型

C、整型、字符型、逻辑型D、整型、实型、逻辑型、字符型

2、当MCS-51单片机接有外部存储器,P2口可作为(C)。

A、数据输入口B、数据的输出口

C、准双向输入/输出口D、输出高8位地址

3、下列描述中正确的是(D)。

A、程序就是软件B、软件开发不受计算机系统的限制

C、软件既是逻辑实体,又是物理实体D、软件是程序、数据与相关文档的集合

4、下列计算机语言中,CPU能直接识别的是(D)。

A、自然语言B、高级语言C、汇编语言D、机器语言

5、MCS-5l单片机的堆栈区是设置在(C)中。

A、片内ROM区B、片外ROM区C、片内RAM区D、片外RAM区

6、以下叙述中正确的是(C)。

A、用C语言实现的算法必须要有输入和输出操作

B、用C语言实现的算法可以没有输出但必须要有输入

C、用C程序实现的算法可以没有输入但必须要有输出

D、用C程序实现的算法可以既没有输入也没有输出

7、定时器/计数器工作方式1是(D)。

A、8位计数器结构B、2个8位计数器结构

C、13位计数结构D、16位计数结构

8、C语言提供的合法的数据类型关键字是(B)。

A、DoubleB、shortC、integerD、Char

9、片内RAM的20H~2FH为位寻址区,所包含的位地址是(B)。

A、00H~20HB、00H~7FHC、20H~2FHD、00H~FFH

10、以下能正确定义一维数组的选项是(B)。

A、inta[5]={0,1,2,3,4,5};B、chara[]={0,1,2,3,4,5};

C、chara={’A’,’B’,’C’};D、inta[5]="0123";

11、数据的存储结构是指(D)。

A、存储在外存中的数据B、数据所占的存储空间量

C、数据在计算机中的顺序存储方式D、数据的逻辑结构在计算机中的表示

12、下列关于栈的描述中错误的是(C)。

A、栈是先进后出的先性表B、栈只能顺序存储

C、栈具有记忆作用D、对栈的插入和删除操作中,不需要改变栈底指针

13、在寄存器间接寻址方式中,间址寄存器中存放的数据是(B)。

A、参与操作的数据B、操作数的地址值

C、程序的转换地址D、指令的操作码

14、MCS-51单片机的复位信号是(A)有效。

A、高电平B、低电平C、脉冲D、下降沿

15、为了使模块尽可能独立,要求(B)。

A、模块的内聚程度要尽量高,且各模块间的耦合程度要尽量强

B、模块的内聚程度要尽量高,且各模块间的耦合程度要尽量弱

C、模块的内聚程度要尽量低,且各模块间的耦合程度要尽量弱

D、模块的内聚程度要尽量低,且各模块间的耦合程度要尽量强

16、若MCS-51单片机使用晶振频率为6MHz时,其复位持续时间应该超过(B)。

A、2μsB、4μsC、8μsD、1ms

17、以下选项中可作为C语言合法常量的是(A)

A、-80B、-080C、-8e1.0D、-80.0e

18、能够用紫外光擦除ROM中程序的只读存储器称为(C)。

A、掩膜ROMB、PROMC、EPROMD、EEPROM

19、以下不能定义为用户标识符是(D)。

A、MainB、_0C、_intD、sizeof

20、下选项中,不能作为合法常量的是(B)。//幂不能为小数

A、1.234e04B、1.234e0.4C、1.234e 4D、1.234e0

21、以下叙述中错误的是(C)

A、对于double类型数组,不可以直接用数组名对数组进行整体输入或输出

B、数组名代表的是数组所占存储区的首地址,其值不可改变

C、当程序执行中,数组元素的下标超出所定义的下标范围时,系统将给出“下标越界”的出错信息

D、可以通过赋初值的方式确定数组元素的个数

22、以下与函数fseek(fp,0L,SEEK_SET)有相同作用的是(D)

A、feof(fp)B、ftell(fp)C、fgetc(fp)D、rewind(fp)

23、存储16×16点阵的一个汉字信息,需要的字节数为(A)

A、32B、64C、128D、256

24、已知1只共阴极LED显示器,其中a笔段为字形代码的最低位,若需显示数字1,则它的字形代码应为(B)。

A、06HB、F9HC、30HD、CFH

25、在C语言中,合法的长整型常数是(A)

A、OLB、4962710C、324562&D、216D

26、以下选项中合法的字符常量是(B)

A、"B"B、’\010’C、68D、D

27、若PSW.4=0,PSW.3=1,要想把寄存器R0的内容入栈,应使用(D)指令。

A、PUSHR0B、PUSH@R0C、PUSH00HD、PUSH08H

28、在片外扩展一片2764程序存储器芯片要(B)地址线。

A、8根B、13根C、16根D、20根

29、设MCS-51单片机晶振频率为12MHz,定时器作计数器使用时,其最高的输入计数频率应为(C)

A、2MHzB、1MHzC、500kHzD、250kHz

30、下列数据字定义的数表中,(A)是错误的。

A、DW“AA”B、DW“A”C、DW“OABC”D、DWOABCH

三、判断题

(√)1、在对某一函数进行多次调用时,系统会对相应的自动变量重新分配存储单元。

(×)2、在C语言的复合语句中,只能包含可执行语句。

(√)3、自动变量属于局部变量。

(×)4、Continue和break都可用来实现循环体的中止。

(√)5、字符常量的长度肯定为1。

(×)6、在MCS-51系统中,一个机器周期等于1.5μs。

(√)7、C语言允许在复合语句内定义自动变量。

(√)8、若一个函数的返回类型为void,则表示其没有返回值。

(×)9、所有定义在主函数之前的函数无需进行声明。

(×)10、定时器与计数器的工作原理均是对输入脉冲进行计数。

(×)11、END表示指令执行到此结束。

(√)12、ADC0809是8位逐次逼近式模/数转换接口。

(√)13、MCS-51的相对转移指令最大负跳距是127B。

(×)14、MCS-51的程序存储器只是用来存放程序的。

(√)15、TMOD中的GATE=1时,表示由两个信号控制定时器的的启停。

(×)16、MCS-51的特殊功能寄存器分布在60H~80H地址范围内。

(×)17、MCS-51系统可以没有复位电路。

(×)18、片内RAM与外部设备统一编址时,需要专门的输入/输出指令。

(√)19、锁存器、三态缓冲寄存器等简单芯片中没有命令寄存和状态寄存等功能。

(√)20、使用8751且=1时,仍可外扩64KB的程序存储器。

四、简答题

1、在使用8051的定时器/计数器前,应对它进行初始化,其步骤是什么?

答:(1)确定T/C的工作方式——编程TMOD寄存器;

(2)计算T/C中的计数初值,并装载到TH和TL;

(3)T/C在中断方式工作时,须开CPU中断和源中断——编程IE寄存器;

(4)启动定时器/计数器——编程TCON中TR1或TR0位。

2、什么是重入函数?重入函数一般什么情况下使用,使用时有哪些需要注意的地方?

答:多个函数可以同时使用的函数,称为重入函数。

通常情况下,C51函数不能被递归调用,也不能应用导致递归调用的结构。有此限制是由于函数参数和局部变量是存储在固定的地址单元中。重入函数特性允许你声明一个重入函数。即可以被递归调用的函数。

重入函数可以被递归调用,也可以同时被两个或更多的进程调用。重入函数在实时应用中及中断服务程序代码和非中断程序代码必须共用一个函数的场合中经常用到。

3、8051引脚有多少I/O线?他们和单片机对外的地址总线和数据总线有什么关系?地址总线和数据总线各是几位?

答:8051引脚共有40个引脚,8051的地址总线由P2和P0口提供,P2口是地址总线的高8位,P0口是地址总线的低8位;数据总线由P0口提供;P0口的地址总线和数据总线是分时进行的,P0口的地址总线需要外接地址锁存器完成地址锁存。

地址总线共16位,数据总线是8位。

4、在有串行通信时,定时器/计数器1的作用是什么,怎样确定串行口的波特率?

答:在有串行通信时,定时器/计数器1的作用是串行口发生器。

串行口的波特率根据串行口的工作方式具有不同的计算方式:

方式0的波特率固定为晶体振荡器的十二分之一;

方式1的波特率=2SMOD.(定时器1的溢出率)/32;

方式2波特率=2SMOD.(fosc/64);

方式3波特率同方式1(定时器l作波特率发生器)。

5、如何消除键盘的抖动?怎样设置键盘中的复合键?

答:由于按键是机械开关结构,所以当用手按下其中一个键时,往往会出现所按键在闭合位置和断开位置之间发生跳几下后才会稳定到闭合状态的情况。在释放一个键时,也会出现类似的情况,这就是键的抖动,抖动的持续时间不一,但通常不会大于10ms。

若抖动问题不解决,就会引起对闭合键的多次读入。对于键抖动最方便的解决方法就是当发现有键按下后,不是立即进行扫描,而是延时大约10ms后再进行。由于一个键按下的时间一般会持续上百毫秒,所以延迟10ms后再扫描处理并不迟。

复合键可以仿照计算机复合键的处理方法,通常可以假设一个键具有复合功能,再与其它减的键值组合成复合键。1、矩阵式键盘的结构与工作原理

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图1所示。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。具体的识别及编程方法如下所述。

2、矩阵式键盘的按键识别方法

确定矩阵式键盘上何键被按下介绍一种“行扫描法”。

行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法,如上图所示键盘,介绍过程如下。

1、判断键盘中有无键按下将全部行线Y0-Y3置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。

2、判断闭合键所在的位置在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为 高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。

下面给出一个具体的例子:

图仍如上所示。8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。列线P1.0-P1.3分别接有4个上拉电阻到正电源 5V,并把列线P1.0-P1.3设置为输入线,行线P1.4-P.17设置为输出线。4根行线和4根列线形成16个相交点。

1、检测当前是否有键被按下。检测的方法是P1.4-P1.7输出全“0”,读取P1.0-P1.3的状态,若P1.0-P1.3为全“1”,则无键闭合,否则有键闭合。

2、去除键抖动。当检测到有键按下后,延时一段时间再做下一步的检测判断。

3、若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出:

P1.71110

P1.61101

P1.51011

P1.40111

在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值

4、为了保证键每闭合一次CPU仅作一次处理,必须却除键释放时的抖动。

键盘扫描程序:

从以上分析得到键盘扫描程序的流程图如图2所示。程序如下

SCAN:MOVP1,#0FH

MOVA,P1

ANLA,#0FH

CJNEA,#0FH,NEXT1

SJMPNEXT3

NEXT1:ACALLD20MS

MOVA,#0EFH

NEXT2:MOVR1,A

MOVP1,A

MOVA,P1

ANLA,#0FH

CJNEA,#0FH,KCODE;

MOVA,R1

SETBC

RLCA

JCNEXT2

NEXT3:MOVR0,#00H

RET

KCODE:MOVB,#0FBH

NEXT4:RRCA

INCB

JCNEXT4

MOVA,R1

SWAPA

NEXT5:RRCA

INCB

INCB

INCB

INCB

JCNEXT5

NEXT6:MOVA,P1

ANLA,#0FH

CJNEA,#0FH,NEXT6

MOVR0,#0FFH

RET

键盘处理程序就作这么一个简单的介绍,实际上,键盘、显示处理是很复杂的,它往往占到一个应用程序的大部份代码,可见其重要性,但说到,这种复杂并不来自于单片机的本身,而是来自于操作者的习惯等等问题,因此,在编写键盘处理程序之前,最好先把它从逻辑上理清,然后用适当的算法表示出来,最后再去写代码,这样,才能快速有效地写好代码。

到本课为止,本站教程暂告一个段落!感谢大家的关心和支持!矩阵按键部分由16个轻触按键按照4行4列排列,连接到JP50端口。将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。确定矩阵式键盘上何键被按下,介绍一种“行扫描法”。行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法.判断键盘中有无键按下:将全部行线置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。若所有列线均为高电平,则键盘中无键按下。判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。下面给出一个具体的例子:电路图路径:G:\图片\电路图片\xl100097.jpg8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。列线P1.0-P1.3设置为输入线,行线P1.4-P.17设置为输出线。4根行线和4根列线形成16个相交点。1.检测当前是否有键被按下。检测的方法是P1.4-P1.7输出全“0”,读取P1.0-P1.3的状态,若P1.0-P1.3为全“1”,则无键闭合,否则有键闭合。2.去除键抖动。当检测到有键按下后,延时一段时间再做下一步的检测判断。3.若有键被按下,应识别出是哪一个键闭合。方法是对键盘的行线进行扫描。P1.4-P1.7按下述4种组合依次输出:P1.71110P1.61101P1.51011P1.40111在每组行输出时读取P1.0-P1.3,若全为“1”,则表示为“0”这一行没有键闭合,否则有键闭合。由此得到闭合键的行值和列值,然后可采用计算法或查表法将闭合键的行值和列值转换成所定义的键值。4.为了保证键每闭合一次CPU仅作一次处理,必须去除键释放时的抖动。实验目的:通过XL1000的16位矩阵按键,在数码管上分别显示0---9,A,B,C,D,E,F。接线方法:1用一条8PIN数据排线,把矩阵按键部份的JP50,接到CPU部份的P1口JP44.2接8位数码管的数据线。将数码管部份的数据口JP5接到CPU部份的P0口JP51.3接8位数码管的显示位线。将数码管部份的显示位口JP8接到CPU部份的P2口JP52.参考程序:;本程序实现扫描按键显示功能.;分别按16个键盘显示分别显示数字123A456B789C*0#D;键盘口P1,数码管显示第二位p21,数码管段位p0口org0000hajmpmainorg0030hmain:movdptr,#tab;将表头放入DPTRlcallkey;调用键盘扫描程序movca,@a dptr;查表后将键值送入ACCmovp0,a;将Acc值送入P0口CLRP2.1;开显示ljmpmain;返回反复循环显示KEY:LCALLKS;调用检测按键子程序JNZK1;有键按下继续LCALLDELAY2;无键按调用延时去抖AJMPKEY;返回继续检测按键K1:LCALLDELAY2LCALLDELAY2;有键按下延时去抖动LCALLKS;再调用检测按键程序JNZK2;确认有按下进行下一步AJMPKEY;无键按下返回继续检测K2:MOVR2,#0EFH;将扫描值送入R2暂存MOVR4,#00H;将第一列值送入R4暂存K3:MOVP1,R2;将R2的值送入P1口L6:JBP1.0,L1;P1.0等于1跳转到L1MOVA,#00H;将第一行值送入ACCAJMPLK;跳转到键值处理程序L1:JBP1.1,L2;P1.1等于1跳转到L2MOVA,#04H;将第二行的行值送入ACCAJMPLK;跳转到键值理程序进行键值处理L2:JBP1.2,L3;P1.2等于1跳转到L3MOVA,#08H;将第三行的行值送入ACCAJMPLK;跳转到键值处理程序L3:JBP1.3,NEXT;P1.3等于1跳转到NEXT处MOVA,#0cH;将第四行的行值送入ACCLK:ADDA,R4;行值与列值相加后的键值送入APUSHACC;将A中的值送入堆栈暂存K4:LCALLDELAY2;调用延时去抖动程序LCALL KS;调用按键检测程序JNZK4;按键没有松开继续返回检测POPACC;将堆栈的值送入ACCRETNEXT:INCR4;将列值加一MOVA,R2;将R2的值送入AJNBACC.7,KEY;扫描完至KEY处进行下一扫描RLA;扫描未完将A中的值右移一位进行下一列的扫描MOVR2,A;将ACC的值送入R2暂存AJMPK3;跳转到K3继续KS:MOVP1,#0FH;将P1口高四位置0低四位值1MOVA,P1;读P1口XRLA,#0FH;将A中的值与A中的值相异或RET;子程序返回DELAY2:;40ms延时去抖动子程序MOVR5,#08HL7:MOVR6,#0FAHL8:DJNZR6,L8DJNZR5,L7RETtab:db28h,34h,28h,34h,0a9h,60h,20h,7ah,20h,21h,61h,74h,30h,62h,0a2h,7eh;0h0hc9878654a321轮流显示键盘因为无法表达*#就用H表示,B用8表示end这是我做成功的4X4键盘扫描源程序,P1.0-P1.3做四根列线,P1.4-P1.7做四根行线。

数码管的字型表是按照标准接法做的,按对应的按键数码管显示对应的数字。

以下是源程序:

KEYBUFEQU30H

ORG00H

START:MOVKEYBUF,#2

MOVP2,#00001111B

WAIT:

MOVP1,#0FFH

CLRP1.4

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY1

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY1

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK1

MOVKEYBUF,#0

LJMPDK1

NK1:CJNEA,#0DH,NK2

MOVKEYBUF,#1

LJMPDK1

NK2:CJNEA,#0BH,NK3

MOVKEYBUF,#2

LJMPDK1

NK3:CJNEA,#07H,NK4

MOVKEYBUF,#3

LJMPDK1

NK4:NOP

DK1:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK1A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK1A

NOKEY1:

MOVP1,#0FFH

CLRP1.5

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY2

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY2

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK5

MOVKEYBUF,#4

LJMPDK2

NK5:CJNEA,#0DH,NK6

MOVKEYBUF,#5

LJMPDK2

NK6:CJNEA,#0BH,NK7

MOVKEYBUF,#6

LJMPDK2

NK7:CJNEA,#07H,NK8

MOVKEYBUF,#7

LJMPDK2

NK8:NOP

DK2:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK2A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK2A

NOKEY2:

MOVP1,#0FFH

CLRP1.6

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY3

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY3

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK9

MOVKEYBUF,#8

LJMPDK3

NK9:CJNEA,#0DH,NK10

MOVKEYBUF,#9

LJMPDK3

NK10:CJNEA,#0BH,NK11

MOVKEYBUF,#10

LJMPDK3

NK11:CJNEA,#07H,NK12

MOVKEYBUF,#11

LJMPDK3

NK12:NOP

DK3:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK3A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK3A

NOKEY3:

MOVP1,#0FFH

CLRP1.7

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY4

LCALLDELY10MS

MOVA,P1

ANLA,#0FH

XRLA,#0FH

JZNOKEY4

MOVA,P1

ANLA,#0FH

CJNEA,#0EH,NK13

MOVKEYBUF,#12

LJMPDK4

NK13:CJNEA,#0DH,NK14

MOVKEYBUF,#13

LJMPDK4

NK14:CJNEA,#0BH,NK15

MOVKEYBUF,#14

LJMPDK4

NK15:CJNEA,#07H,NK16

MOVKEYBUF,#15

LJMPDK4

NK16:NOP

DK4:

MOVA,KEYBUF

MOVDPTR,#TABLE

MOVCA,@A DPTR

MOVP0,A

DK4A:MOVA,P1

ANLA,#0FH

XRLA,#0FH

JNZDK4A

NOKEY4:

LJMPWAIT

DELY10MS:

MOVR6,#10

D1:MOVR7,#248

DJNZR7,$

DJNZR6,D1

RET

TABLE:DB0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H;0-9

DB088H,083H,0C6H,0A1H,086H,08EH,089H,0CFH,0C7H,0C8H;A,B,C,D,E,F,H,I,L,N,

END;P3.1数据采集控制

;P2.6P2.7个位十位显示转换控制

;P1口接8个开关模拟数据

;P1.0-P1.3为个位开关量输入

;P1.4-P1.7为十位开关量输入

;此程序仅供参考

;功能P1口接8个开关输入量4个一组,分别为个位,十位输入

;P0口接一个数码管,依次显示输入量。P3.1控制是否读入

;开关量。P2.6P2.7控制是否显示个位或十位

ORG100h

LJMPSTAR

STAR:MOVP1,#0FFH

SETBP3.1数据读入标志

MOVR0,#100,循环工作次数

LOOP:JBP3.1,$P3.1低电平时,采集P1口数据开关量处理显示阶段不再应答P3.1

MOVA,P1

PUSHACC

ANLA,#0FH取个位数值

MOVR1,A个位数值保存到R1

POPACC

ANLA,#0F0H

SWAPA高4位转成字节信息

MOVR2,A十位数值保存到R2

MOVDPTR,#TABLED

MOVA,R1

MOVCA,@A DPTR

MOVP0,A

CLRP2.6个位显示

ACALLDELAY500MS

SETBP2.6

MOVA,R2

MOVCA,@A DPTR

MOVP0,A

CLRP2.7十位显示

ACALLDELAY500MS

SETBP2.7

DJNZR0,LOOP

DELAY500MS:延时500毫秒子程略

RET

TABLED:DB0c0h,0f9h,0a4h,0b0h,99h,92h,82h,0f8h

DB80H,90H,88h,83h,0c6h,0a1h,86h,8eh

END#include

typedefunsignedcharBYTE;

BYTEcodeTABLED[16]={0Xc0,0Xf9,0Xa4,0Xb0,0X99,0X92,0X82,0X0f8,0X80,0X90,0X88,0X83,0Xc6,0Xa1,0X86,0X8e};

BYTEDATled;

sbitP26=P2^6;

sbitP27=P2^7;

sbitP31=P3^1;

intTIME;

voidtimedelay(DTIME)

intDTIME;

{

intI;

for(I=0;I<=DTIME;I );

}

voidmain()

{

intTEMP;

P26=1;

P27=1;

P31=1;

P1=0xFF;

TIME=1000;

while(1){

while(P31==0){

DATled=P1;

TEMP=DATled&0x0f4;

P0=TABLED[TEMP];

P27=0;

timedelay(TIME);

P27=1;

}

}

}1.实验任务在8X8 LED点阵上显示柱形,让其先从左到右平滑移动三次,其次从右到左平滑移动三次,再次从上到下平滑移动三次,最后从下到上平滑移动三次,如此循环下去。2.电路原理图图4.24.13.硬件电路连线(1).把“单片机系统”区域中的P1端口用8芯排芯连接到“点阵模块”区域中的“DR1-DR8”端口上;(2).把“单片机系统”区域中的P3端口用8芯排芯连接到“点阵模块”区域中的“DC1-DC8”端口上;4.程序设计内容(1).8X8 点阵LED工作原理说明8X8点阵LED结构如下图所示图4.24.2从图4.24.2中可以看出,8X8点阵共需要64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一列置1电平,某一行置0电平,则相应的二极管就亮;因此要实现一根柱形的亮法,如图49所示,对应的一列为一根竖柱,或者对应的一行为一根横柱,因此实现柱的亮的方法如下所述:一根竖柱:对应的列置1,而行则采用扫描的方法来实现。一根横柱:对应的行置0,而列则采用扫描的方法来实现。5.汇编源程序

ORG00H

START:NOP

MOVR3,#3

LOP2:MOVR4,#8

MOVR2,#0

LOP1:MOVP1,#0FFH

MOVDPTR,#TABA

MOVA,R2

MOVCA,@A DPTR

MOVP3,A

INCR2

LCALLDELAY

DJNZR4,LOP1

DJNZR3,LOP2

MOVR3,#3

LOP4:MOVR4,#8

MOVR2,#7

LOP3:MOVP1,#0FFH

MOVDPTR,#TABA

MOVA,R2

MOVCA,@A DPTR

MOVP3,A

DECR2

LCALLDELAY

DJNZR4,LOP3

DJNZR3,LOP4

MOVR3,#3

LOP6:MOVR4,#8

MOVR2,#0

LOP5:MOVP3,#00H

MOVDPTR,#TABB

MOVA,R2

MOVCA,@A DPTR

MOVP1,A

INCR2

LCALLDELAY

DJNZR4,LOP5

DJNZR3,LOP6

MOVR3,#3

LOP8:MOVR4,#8

MOVR2,#7

LOP7:MOVP3,#00H

MOVDPTR,#TABB

MOVA,R2

MOVCA,@A DPTR

MOVP1,A

DECR2

LCALLDELAY

DJNZR4,LOP7

DJNZR3,LOP8

LJMPSTART

DELAY:MOVR5,#10

D2:MOVR6,#20

D1:MOVR7,#248

DJNZR7,$

DJNZR6,D1

DJNZR5,D2

RET

TABA:DB0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH

TABB:DB01H,02H,04H,08H,10H,20H,40H,80H

END

6.C语言源程序

#include

unsignedcharcodetaba[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f0;j--);

}

voidmain(void)

{

unsignedchari,j;

while(1)

{

for(j=0;j<3;j )

//fromlefttoright3time

{

for(i=0;i<8;i )

{

P3=taba[i];

P1=0xff;

delay1();

}

}

for(j=0;j<3;j )

//fromrighttoleft3time

{

for(i=0;i<8;i )

{

P3=taba[7-i];

P1=0xff;

delay1();

}

}

for(j=0;j<3;j )

//fromtoptobottom3time

{

for(i=0;i<8;i )

{

P3=0x00;

P1=tabb[7-i];

delay1();

}

}

for(j=0;j<3;j )

//frombottomtotop3time

{

for(i=0;i<8;i )

{

P3=0x00;

P1=tabb[i];

delay1();

}

}

}

}LED点阵显示实验一.实验要求

编程实现中英文字符的显示。

二.实验目的

1.了解LED点阵显示的基本原理和实现方法。

2.掌握点阵汉字库的编码和从标准字库中提取汉字编码的方法。

三.实验电路及连线

点阵显示模块WTD3088的(红色)列输入线接至内部LED的阴极端,行输入线接至内部LED的阳极端(若阳极端输入为高电平,阴极端输入低电平,则该LED点亮)。发光点的分布如图22-0所示。

Fig22-0WTD3088LED分布

如图22-1示,本实验模块使用74LS374来控制列输入线的电平值。将74LS374的某输出置0,则对应的LED阴极端被置低。如图22-2示,本实验模块使用74LS273来控制行输入线,并通过9013提供电流驱动。将74LS273的某输出置1,则对应的LED阳极端被置高。每次系统重新开启或总清后,74LS273输出为全0,LED显示被关闭。

通过编程控制各显示点对应LED阳极和阴极端的电平,就可以有效的控制各显示点的亮灭。

Fig22-1LED模块及列扫描电路Fig22-2行扫描电路

Fig22-3地址译码电路

本实验模块使用4块WTD3088组成16×16点阵,以满足汉字显示的要求。为了方便的控制四个单元,使用了一片74LS139译码,产生四个地址片选信号:CLKR1=CSLED,CLKR2=CSLED 1,用于行控制的两片74LS273;CLKC1=CSLED 2,CLKC2=CSLED 3,用于列控制的两片74LS374。

实验接线:按示例程序,模块的CSLED接51/96地址的8000H。

四.实验说明

使用高亮度LED发光管构成点阵,通过编程控制可以显示中英文字符、图形及视频动态图形。LED显示以其组构方式灵活、亮度高、技术成熟、成本低廉等特点在证券、运动场馆及各种室内/外显示场合得到广泛的应用。

所显示字符的点阵数据可以自行编写(即直接点阵画图),也可从标准字库(如ASC16、HZ16)中提取。后者需要正确掌握字库的编码方法和字符定位的计算。

实验盘片中“字符转换”子目录下提供的Basc16.exe,BHz16.exe可方便的将单个字符的码表从标准字库Asc16,Hzk16中提取出来。具体使用方法是运行上述可执行程序,根据提示输入所需字符(如是汉字还需要先启动dos下的汉字环境,如ucdos,pdos95等)。程序将该字符的码表提取出来,存放在该字符ASC或区位码为文件名称的.dat文件中。用户只需将该文件中内容拷贝、粘贴到自己的程序中即可。但需要注意字节排列顺序、字节中每一位与具体显示点的一一对应关系,必要时还要对码表稍作修改。同一目录下还提供了上述可执行程序的源文件,使用BC3.1编写,供用户参考。

五.实验程序框图

用户应留心其中行扫描的实现及码表的处理。

六.实验程序:(一)提供LEDA51演示Asc16字符的简单点阵显示。

;________*LED点阵显示示例程序______________________*

;__该程序显示Asc16字符__

;__为了简单起见,程序只显示一个字符__

;__该程序针对T598实验机的模块14__

;____________________________________________________

CSLEDEQU8000H

CSR1EQUCSLED;行1273

CSR2EQUCSLED 1H;行2273

CSC1EQUCSLED 2H;列1374

CSC2EQUCSLED 3H;列2374

ORG0000H

MOVSP,#60H

INIT:MOVA,#0H;关闭行

MOVDPTR,#CSR1

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVX@DPTR,A

MOVA,#0FFH;关闭列

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSC2

MOVX@DPTR,A

D:MOVR5,#00H

MOVR4,#01H;每次为单行扫描

DISP:

MOVA,R5

MOVDPTR,#ASCE;此处设定所要显示的字符

MOVCA,@A DPTR

CPLACC;代码取反,决定显示的阴阳

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVDPTR,#CSR1

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#8H,DISP

MOVA,#0H

MOVX@DPTR,A

MOVR5,#08H

MOVR4,#01H

DISP2:

MOVA,R5

MOVDPTR,#ASCE

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#10H,DISP2

MOVA,#0H

MOVX@DPTR,A

SJMPD

;________延时子程序,协调字符显示速度____________*

DELAY:MOVR7,#1H

DL1:MOVR6,#00H

DL2:DJNZR6,DL2

DJNZR7,DL1

RET

;________字符点阵字库______________*

;ASC16字符编码排列

;0

;1

;|

;|

;14

;15

;高位D7--D0

;请注意编码的排列次序和实际显示点阵分布的关系

ASCA:DB00H,00H,10H,38H,6CH,0C6H,0C6H,0FEH

DB0C6H,0C6H,0C6H,0C6H,00H,00H,00H,00H

ASCE:DB00H,00H,0FEH,66H,62H,68H,78H,68H

DB60H,62H,66H,0FEH,00H,00H,00H,00H

ASCD:DB00H,00H,0F8H,6CH,66H,66H,66H,66H

DB66H,66H,6CH,0F8H,00H,00H,00H,00H

ASCK:DB00H,00H,0E6H,66H,66H,6CH,78H,78H

DB6CH,66H,66H,0E6H,00H,00H,00H,00H

;____________________________________________________

END

(二)LEDHZ51两个示例程序。和Hz16字符的简单点阵显示。

;________*LED点阵显示示例程序______________________*

;__该程序显示hz16字符__

;__为了简单起见,程序只显示一个字符__

;__该程序针对T598实验机的模块14__

;____________________________________________________

CSLEDEQU8000H

CSR1EQUCSLED;行1273

CSR2EQUCSLED 1H;行2273

CSC1EQU CSLED 2H;列1374

CSC2EQUCSLED 3H;列2374

ORG0000H

MOVSP,#60H

INIT:MOVA,#0H;关闭LED显示

MOVDPTR,#CSR1

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVX@DPTR,A

MOVA,#0FFH;关闭LED显示

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSC2

MOVX@DPTR,A

D:MOVR5,#00H

MOVR4,#01H

DISP:

MOVA,R5

RLACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVA,R5

RLACC

INCACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSR1

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#8H,DISP

MOVA,#0H

MOVX@DPTR,A

MOVR5,#08H

MOVR4,#01H

DISP2:

MOVA,R5

RLACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC2

MOVX@DPTR,A

MOVA,R5

RLACC

INCACC

MOVDPTR,#HZAI

MOVCA,@A DPTR

CPLACC

MOVDPTR,#CSC1

MOVX@DPTR,A

MOVDPTR,#CSR2

MOVA,R4

MOVX@DPTR,A

RLACC

MOVR4,ACC

INCR5

LCALLDELAY

CJNER5,#10H,DISP2

MOVA,#0H

MOVX@DPTR,A

SJMPD

;________延时子程序,协调字符显示速度____________*

DELAY:MOVR7,#1H

DL1:MOVR6,#00H

DL2:DJNZR6,DL2

DJNZR7,DL1

RET

;________字符点阵字库______________*

;HZ16字符编码排列

;01

;23

;|

;|

;2829

;3031

;高位D7--D0

HZAI:DB00H,78H,3FH,80H,11H,10H,09H,20H

DB7FH,0FEH,42H,02H,82H,04H,7FH,0F8H

DB04H,00H,07H,0F0H,0AH,20H,09H,40H

DB10H,80H,11H,60H,22H,1CH,0CH,08H

HZDI:DB00H,80H,40H,80H,20H,88H,2FH,0FCH

DB08H,88H,08H,88H,0E8H,88H,2FH,0F8H

DB28H,88H,28H,88H,28H,88H,2FH,0F8H

DB28H,08H,50H,06H,8FH,0FCH,00H,00H

HZKE:DB01H,00H,01H,04H,0FFH,0FEH,01H,00H

DB01H,10H,1FH,0F8H,10H,10H,10H,10H

DB10H,10H,1FH,0F0H,14H,50H,04H,40H

DB04H,40H,08H,42H,10H,42H,60H,3EH

;____________________________________________________

END基于89C51的计算机可锁定加密键盘设计摘要:介绍PC键盘和键盘接口的PS/2通信协议,以及用89C51实现可锁定键盘的软件和硬件设计方法。具有安全可靠、容错能力强、可以直接采用标准键盘进行改装、便于实现等优点,并保留标准键盘的全部功能。关键词:PS/289C51C51键盘引言

在智能仪器、自动控制等领域,已大量使用嵌入式PC,如Advantech公司的PC/104、AMD公司的DIMM-PC等。为适应开放式、模块化的要求,嵌入式PC具有标准的PC接口,如VGA显示器控制接口、以太网接口、RS232接口、PC/AT键盘接口等。所以,可以用标准的PC键盘对嵌入式PC进行操作与控制。键盘在输入指令之后,可能很长一段时间不用。为计算机安全和防止误触发,需要将键盘锁定,还要对某些键采取屏蔽措施,但是PC标准键盘不能满足这些要求。本文介绍一种用89C51设计实现的可锁定加密PC/AT键盘。

1键盘功能及工作原理

PC键盘功能主要有按键识别、去抖、重键处理、发送扫描码、自动重发、接收键盘命令、处理命令等。键盘有编码键盘和非编码键盘。编码键盘程序设计简单,但硬件电路复杂,价格较高;非编码键盘用软件来实现识别键、编码转换、去抖等功能,硬件电路简单,价格便宜。现代微机系统中广泛采用非编码键盘。PC键盘多采用18行×8列的二维矩阵行列结构。采用行扫描法识别按下的按键。2PS/2协议

PS/2协议是外设与主机之间通信的一种同步双向串行协议。在该协议中主机拥有较高的优先级,在一定条件下可以终止外设正在进行的发送过程。PS/2协议采用的传送数据帧的格式为:1位起始位(0)、8位数据位、1位奇偶校验位、1位停止位(1)。数据发送时低位在前,高位在后。外设每收到主机发来的1帧数据,都要紧随该帧的停止位发送一个握手位ACK(0)应答主机。然后,外设还要发1帧应答数据(0xF0),表示外设已经完整地接收到了主机的命令;而主机则不需发送握手位,也不需要发送应答帧。

2.1键盘到PC键盘接口的通信

当时钟线和数据线均为高电平时,允许键盘发送数据,系统将接收数据;当时钟线被拉为低电平时,表明系统禁止数据传输。图1给出了发送时序,包含1个低电平触发的起始位、8位数据位、1个奇校验位和1个高电平的结束位。2.2PC系统到键盘的通信协议

若时钟线出现高电平,数据线出现低电平,表明系统请求发送,键盘准备产生同步时钟脉冲串,并接收数据。包含了1个低电平触发的起始位、8位数据位、1个奇校验位、1个应答位、1个高电平的结束位。图2为时序图。(1)键盘命令及执行过程①FFH:复位键盘。系统通过此软件复位命令使键盘进入程序复位和内部自测试,称为基本保证测试(BAT)。复位键盘的过程如下:a.键盘收到FFH后立即回送ACK(FAH)作答;b.键盘接口收到ACK后,将键盘时钟和数据线置为高电平;c.键盘检测到此状态后开始BAT操作;d.如果BAT正确完成,键盘发送AAH以表示结束,

否则以FDH(或其它任何值)表示诊断有误。②FEH:重新发送。当系统检测到从键盘送来的任何传输错误时,它便向键盘发送FEH命令。键盘接收到此命令后,将重新送出原来的内容。③FDH~F7H:空操作(保留未用)。④F6H:设置缺省值。此命令使键盘所有条件复位到电源接通时的缺省状态,键盘继续扫描。⑤F5H:设置缺省值和停止键盘。此命令使键盘所有条件复位到电源接通时的缺省状态,并停止键盘扫描,等待下一个键盘命令。⑥F4H:启动键盘。键盘接收到此命令后,用ACK(FAH)作答,清除输出缓冲器,并启动键盘开始扫描。⑦F3H:设置拍发速率和延时参数。每当按下任 一键时,键盘以拍发速率连续送出键的接通码,直到键被释放为止。延时参数是指按下一键后,键盘输出的响应时间。

系统缺省设置:拍发速率=10个/s±20,延时=500ms±20。

当要改变设置时可以使用F3H命令,并后跟一个字节的参数。参数定义如表1所列。

表1D7D6D5D4D3D2D1D00CBA

计算拍发速率和响应延时的公式如下:

拍发速率=1/[(8 A)×2B×0.00417](1/s)

响应延时=(1 C)×250(ms)注:缺省的延时参数值为2CH。此命令的执行过程如下:a.键盘收到F3H命令后,用FAH予以响应,并停止扫描和等待随后的参数;b.键盘若收到随后的设置参数,用另一个ACK响应,并按其参数设置新的拍发速率和响应延时,之后重新开始扫描(若键盘原来是开放的);c.键盘若收到FAH命令,但无随后的设置参数,则键盘结束命令设置,并保持原来的拍发速率和响应延时,停止扫描。⑧F2H,F1,EFH:保留未用。⑨F0H:设置键盘扫描码命令。此命令用于设置键盘的扫描码,后跟参数指定三种扫描码的哪一种。键盘复位时,默认扫描码是第二种。⑩EEH:回送命令。此命令用于辅助诊断,要求键盘接收到EEH时也要回送EEH予以响应。若键盘原来是开放的,则继续扫描。EDH:置位/复位LED指示器。键盘右上角有三个LED指示器,分别反映Caps、Num和Scroll三个键的锁定情况。参数字节如表2所列。

表2D7D3D2D1D0保留1=激励CapsLED1=激励NumLED1=激励ScrollLED

此命令执行过程与F3H相似。若命令后跟参数,则按参数设定LED状态并继续扫描。若仅有命令无参数,则不改变LED原状态,并停止扫描。(2)键盘响应键盘在下列四种情况下都会向键盘接口发送数据。①按下任一键,键盘以拍发速率向接口发送键盘接通扫描码。②释放所按下的键,键盘发送断开扫描码。③系统向键盘发送键盘命令后,键盘回送应答。④当用户按键速度超出键盘所能容纳的最大键个数时,键盘做出响应。后三种情况称为键盘响应。响应字节有7个,定义如下。

①FEH:重新发送响应。当键盘收到一个无效的键盘命令,或者检测到奇偶错的键盘命令时,键盘回送响应字节为FEH,要求系统重发键盘命令。②FAH:正常应答。对任何一个有效的键盘命令,键盘回送FAH予以响应。③00H:超限应答。当用户按键速度超出键盘所能容纳的最大键符个数时(16个字节的缓冲器),键盘发送00H。④FDH:诊断故障应答。键盘接受软件复位命令,执行自测试过程中。若检测到故障,则以FDH应答。此时,键盘停止扫描并等待下一个键盘命令。⑤AAH:诊断正常应答。键盘在软件复位过程中,正常完成BAT测试,以AAH应答。⑥FEH:回响命令的应答,对键盘FEH命令的应答。⑦F0H:断开扫描码前缀,键盘对键符按下后释放的应答,第一个字节为F0H,第二个字节为接通扫描码(有几个键例外)。3硬件设计

PC系列键盘采用18行×8列的矩阵行列结构。89C51单片机有4个8位I/O端口,因此可以采用P0、P2口再加上P3口的2个(P3.6和P3.7)作为行扫描线。P1口作为列输入线(如果用P0口作列输入线,必须加上拉电阻)。采用P3.0、P3.1作为数据线和时钟线与PC系统进行通信,用P3.2、P3.4、P3.5控制键盘上的3个指示灯。硬件原理如图3所示。

键盘与计算机通过一个五芯(PS/2接口为六芯)插座相接,4个有效引脚的定义分别是电源(VCC)、地(GND)、串行时钟线(SCK)、串行数据线(SIO)。

4软件设计①消抖及重键处理:通过软件上延时程序来消除抖动;采用后按键优先处理,即多键同时按下时,只重复发送最后按下键的扫描码。②程序包括键盘扫描子程序、发送键码子程序、发送数据子程序、接收命令子程序、定时器1中断服务程序、主程序等。键盘扫描子程序用于扫描键状态,将被按键的位置号存入缓冲器中;发送键码子程序用于将缓冲区键的接通码或断开码发送给计算机键盘接口或者存在键盘密码缓冲区中;发送数据子程序用于将数据发给计算机键盘接口;接收命令子程序用于接收计算机键盘接口发来的键盘命令;定时器1中断服务子程序用于给程序中的延时提供标准时钟,并具有软件看门狗功能,防止软件出现死机现象;主程序用于系统初始化,子程序调度,锁定状态的显示等。

图6发送缓冲区键码子程序流程图

图4~6是主要软件模块的流程图。单片机源程序见本刊网络补充版(.com)。

5结论

本文介绍的PC/AT键盘具有结构简单、设计灵活、安全可靠的特点,可用于标准PC和嵌入式PC。本键盘可以在标准的键盘基础上进行改造,只需换掉原来的控制芯片即可,可节省设计成本。单片机C51编程几个有用的模块(1)KeilC51常用功能模块使用说明

说明

本文档包括单片机系统中常用到的时钟中断、通讯及键盘扫描等模块(见所附源程序)的说明。这些模块使用前后台系统模型。为达到最大的灵活性,需要在用户工程中定义config.h文件,在其中定义各模块可选参数的设置,而不是直接更改源代码。

这些可选内容大部分为宏定义,如果不定义宏相应的功能在编译时被屏蔽,不会增加代码长度。具体可选内容见各模块中的说明。

在Config.h文件中还要包含一个单片机硬件的资源头文件。

各模块使用了定义在Common.h中的一些数据类型。如:BIT(bit)BYTE(unsignedchar)等,具体请参见源程序。

时钟模块

在单片机软件设计中,时钟是重要资源,为了充分利用时钟资源,故设计本时钟模块。本模块使用定时器0,在完成用户指定功能的同时,还能够自动处理一些其它模块中与时钟相关的信息。

时钟模块由声明文件Timer.h以及实现文件Timer.c组成。

用户应该在Config.h中定义宏TIMER_RELOAD来设定定时器0的重装载初值。推荐的定时器0的中断时间大于1毫秒。

在程序的初始化阶段调用时钟模块的初始化函数InitTimerModule()之后,就可以使用时钟模块所以支持的各种功能。具体描述如下:

延时:当用户需要进行一定时间的延时时,可以通过调用Delay()来进行,参数为时钟中断的次数。如时钟中断周期为1ms,想进行100ms的延时,则可以调用Delay(100)。

注意:

如果延时的绝对时间小于时钟中断的周期,则不能够用本方法做到延时。

定时:当程序中需要使用定时功能时,如等待某外部事件,如果在一定时间内发生则继续执行,如果在这段时间内发生,则认为出现错误,转向错误处理机制。

在此推荐一种编程模式,但用户可以用自己认为更合理的方式处理此类问题。

这里简单说明一下关于阻塞式函数及非阻塞式函数。简单说,阻塞式函数就是当检测完成条件,如果不能够完成则等待,如:

voidCheckSomething()

{

//gbitSuccessFlagisaglobalvariable

while(gbitSuccessFlag==FALSE)

{

//donothingbutwaiting

}

}

可以看到,当bitSuccessFlag没有被设置为TRUE时,函数保持等待状态不返回,这样就是阻塞式的函数。

另外一种情况:

BITCheckSomething()

{

if(gbitSuccessFlag==TRUE)

{

//…

returnTRUE;

}

returnFALSE;

}

在这里,如果所检测的事件有没有完成,函数进行检测之后,立刻返回, 通过返回值报告完成情况,如果没有完成,则等待调用者分配再次执行的机会。这样的函数就是非阻塞函数。

在应用定时功能时,首先要将检测函数定义成非阻塞函数。如上面的第二个版本的CheckSomething。

然后下面模式:

BITbitDone=FALSE;

ResetClock();//cleartimerinterrupttimescounter

while(GetClock()

{

if(CheckSomething()==TRUE)

{

bitDone=TRUE;

break;

}

}

if(bitDone==FALSE)

{

//processtimeout

}

或者简单写成:

BITbitDone=FALSE;

ResetClock();

while(GetClock()=(z))

当然,用户也可以将IsPackageHeader和IsPackageTailer定义成为函数,通过BIT类型的返回值来向调用者提供与相应宏相同的信息。

另一种办法需要在Config.h文件中定义宏SCOMM_ComplexPackageFormat。(需要注意的是,不能够同时定义SCOMM_SimplePackageFormat和SCOMM_ComplexPackageFormat宏,否则会造成严重的不可预见性错误。

这时需要提供回调函数QueryPackageFormat,原形如下:

BYTEQueryPackageFormat(BYTEbyData,BYTEbyCount,BYTEbyParam);

函数中三个参数的含义与使用简单数据包格式时判断数据包尾的宏的参数相同。

函数通过返回值来通知作为调用者的接收函数对接收到的数据如何处理,但目前这种方法仅为需要处理复杂数据包格式时的一种可选方法,但不推荐。用户如果想使用这种方法可以自己更改接收函数中相应的

#ifdefSCOM_ComplexPackageFormat

#endif//SCOMM_ComplexPackageFormat

预编译指令之间的内容。

例如指定QueryPackageFormat的返回值的含义:

0:继续找数据包头或继续找数据包尾。

1:找到数据包头。

2:找到数据包尾。

3:数据包出错,需要抛弃。

然后更改源代码来实现上面的协议。

注意:当用户需要使用字符串的时候,可以利用简单的包装函数将字符串转换为字节数组。所以没有必要提供专用的字符串处理函数。

键盘扫描模块

键盘扫描模块有两种工作方式,一种为自动的由时钟模块调用,另一种是由程序员自行调用。

1)由时钟模块自动调用的方式

将时钟模块实现文件(Timer.h)及键盘扫描模块的实现文件(KBScan。c)包含进工程,在Config.h文件中添加TIMER_KBSCANDELAY宏。时钟模块自动对时钟中断进行计数,当达到TIMER_KBSCANDELAY宏所定义的值后,自动调用键盘扫描模块中的函数KBScanProcess()进行键盘扫描,也就是说,这个宏的值可以决定按键消抖动的时间。

用户应该提供两个回调函数OnKBScan()及OnKeysPressed()。在函数OnKBScan中进行键盘扫描,并返回扫描码。扫描码的类型缺省为BYTE,当键盘规模较大时,BYTE不能够完全包含键盘信息时,可在Config.h文件中重定义宏KBvalue,如下:

#defineKBvalueWORD

这样,就可以使用16位的键盘扫描码,如果此时还达不到要求,可以将键盘扫描码定义成一个结构,但这样做将会增加代码量及消耗更多的RAM资源,故不推荐。

扫描模块调用OnKBScan取得扫描码,并调用用户可以重定义的宏IsNoKeyPressed来判断是否有键按下,缺省的IsNoKeyPressed实现如下:

#defineIsNoKeyPressed(x)((x)==0x00)

即认为OnKBScan返回0扫描码时为没有键按下,如果扫描函数返回其它非零扫描码做为无键按下的扫描码时,可以在Config.h文件中重定义IsNoKeyPressed宏的实现。

8位键盘扫描码(缺省值)时,相应的扫描函数为:

BYTEOnKBScan()

当扫描模块经过软件消抖动之后,发现有键按下,就会调用另一个回调函数OnKeysPressed。函数的声明应该如下:

voidOnKeyPressed(BYTEbyKBvalue,BYTEbyState)

其中中的参数byKBvalue的类型为BYTE,此为缺省值,如果使用其它类型的扫描码,就将此参数变为相应类型。这个值由OnKBScan返回。另一个参数byState在通常情况下为零。但当用户在Config.h中定义宏KBSCAN_BRUSTCOUNT,同时键盘上的某键被按住不放时,扫描模块对它自己的调用(注意这里和TIMER_KBSCANDELAY宏不同,TIMER_KBSCANDELAY是时钟中断足够的次数后调用扫描模块,而KBSCAN_BRUSHCOUNT为扫描模块自身的被调用次数)进行计数,当达到KBSCAN_BRUSTCOUNT时,扫描模块调用OnKeysPressed,此时第一个参数的含义不变,而byState变成1,同时计数器复位,又经过一段时间后,用值为3的byState调用OnKeysPressed。这样就可以很方便的实现多功能键或者检测某键的长时间被按下。

2)由用户自行调用

由用户自行在程序中调用扫描模块,而不是由时钟中断自行调用。其它与方式1相同。

注意:

1)函数KBScanProcess为非阻塞函数,它将在很快的时间内返回,等待再次分配给它执行的机会。

2)函数KBScanProcess是在时钟中断外部运行的,它的过程可以被任何中断打断,但不影响系统运行。

3)byState的最大值为250,之后被复位为零。应用举例

现在来举例说明上述几个模块的使用方法。

硬件环境描述:

为了控制一盏灯,需要单片机提供一个做控制功能的开关量,这里不描述外部接口电路,只说明当单片机的P10脚为高电平时,灯灭,当P10脚为低电平时,灯亮。

可以通过计算机由串口发送命令来控制,或通过一个按键(pushbutton不是自锁式的按键)来手动控制(按键接在P11脚上,当键没有按下时,P11电平为高,键按下时,引脚电平被接低),当使用按键手动控制的时候,需要给计算机发送通知。

设定串口通讯指令如下:

数据包由0xff做包头,4个字节长,第二个字节为命令代码,第三个字节为数据,最后一个字节为校验位。

命令和数据代码有如下组合:

(计算机发给单片机)

0x100x01:计算机控制灯亮。(数据位是非零值即可)

0x100x00:计算机控制灯灭。

(单片机发给计算机)

0x110x01:单片机正常执行控制指令,返回。(数据位是非零值即可)

0x110x00:单片机不能够正常执行控制指令,或控制指令错(不明含义的数据包或校验错等)。

0x120x01:手动控制灯亮。(数据位是非零值即可)

0x120x00:手动控制灯灭。

建立工程:

在硬盘上建立文件夹Projects,在Projects下建立Common文件夹及Example文件夹。将各模块的头文件及实现文件拷贝到Common文件夹下(推荐使用这样的文件组织结构,其它工程也可以建立在Projects下,各工程共享Common文件夹中的代码)。

启动KeilC的IDE,在Example下建立新工程,将各模块的实现文件包含进工程。

在Example文件夹下建立Output文件夹,更改工程设置,将Output作为输出文件和List文件的输出文件夹(推荐使用这样的结构, 当保存工程文件时,可以简单的删除Output文件夹中的内容而不会误删有用的工程文件)。

建立工程配置头文件Config.h及工程主文件Example.c,并将Exmaple.c文件加入工程。

输入代码:

代码的具体编写过程略。下面是最后的Config.h文件及Example.c文件。

//

//file:onfig.h

//

#ifndef_CONFIG_H_

#define_CONFIG_H_

#include//使用AT89C52做控制

#include“../Common/Common.h”//使用自定义的数据类型

#defineTIMER_RELOAD922//11.0592MHz晶振,1ms中断周期

#defineTIMER_KBSCANDELAY40//40ms重检测按键状态,即40ms消抖

#defineSCOMM_AsyncInterface//使用异步通讯服务

#defineIsPackageHeader(x)((x)==0xff)//判断包头是不是0xff

#defineIsPackageTailer(x,y,z)((y)<=(z))//判断包的长度是不是足够

#endif//_CONFIG_H_

//

//file:xample.c

//

#include

#include“../Common/Common.h”

#include“../Common/Timer.h”

#include“../Common/Scomm.h”

#include“../Common/KBScan.h”

BITgbitLampState=1;//灯的状态,缺省为off

staticvoidInitialize()

{

InitTimerModule();//初始化时钟模块

InitSCommModule(0xfd,TRUE);//初始化通讯模块,11.0592MHz晶振,

//波特率为19200

EA=1;//开中断

}

voidmain()

{

Initialize();//初始化

while(TRUE)//主循环

{

ImpTimerService();//实现时钟中断服务,如键盘扫描

AsyncRecePackage(4);//接收4个字节长的数据包

}

}

//在中断外部响应时钟中断事件

voidOnTimerEvent()

{

//donothing

}

//控制外部灯

staticvoidTriggerLamp(BITbEnable)

{

P10=~bEnable;//需要反相控制

}

//键扫描回调函数

BYTEKBScan()

{

BITb;

P11=1;//读之前拉高引脚电平

b=P11;//读入引脚状态

return~b;//数据反相做扫描码

}

//计算校验和

staticBYTECalcCheckSum(BYTE*pbyBuf,BYTEbyLen)

{

BYTEby,bySum=0;

for(by=0;by

return0–bySum;

}

//接收到键盘消息回调函数

voidOnKeyPressed(BYTEbyvalue,BYTEbyState)

{

BYTEby[4];

if(byState==0)

{

switch(byvalue)

{

case0x01:

gbitLampState=~gbitLampState;//灯状态取反

TriggerLamp(gbitLampState);//执行控制

by[0]=0xff;//构造数据包

by[1]=0x12;

by[2]=(BYTE)gbitLampState;

by[3]=CalcCheckSum(by,3);//求校验和

SendPackage(by,4);//发送数据包

break;

//处理其它扫描码

default:

break;

}

}

//接收到数据包回调函数

voidOnRecePackage(BYTE*pbyBuf,BYTEbyBufLen)

{

BYTEby[4];

by[0]=0xff;

by[1]=0x11;

if(byBufLen!=4||pbyBuf[3]!=CalcCheckSum(pbyBuf,3))

{

by[2]=0;

by[3]=CalcCheckSum(by,3);

SendPackage(by,4);//处理长度或校验和不正确

}

switch(pbyBuf[1])

{

case0x10:

gbitLampState=(BIT)pbyBuf[2];

TriggerLamp(gbitLampState);

by[2]=1;

by[3]=CalcCheckSum(by,3);

SendPackage(by,4);//发送成功执行通知

break;

default://不知道的命令

by[2]=0;

by[3]=CalcCheckSum(by,3);

SendPackage(by,4);//发送没有成功执行通知

break;

}

}电话情思很…想很想,给你打个电话,问问远方的朋友,现在还好吗,顺便问问你的…爸爸妈妈,电话能否把我……的问候转达。很…想很想,给你打个电话,也想和你悄悄…说些知心话,一遍一遍拨…着电话号码,电话响着无人回……答。…………窗外的月光,慢慢的坠下,带不走我对你的牵…挂,夜幕中的留影,飘飘荡荡,能否把我问候转达,窗外的月光,慢慢的坠下,带不走我对你的牵挂,夜幕中的留影,飘飘荡荡,能否把我问候转达。很想很想,给你打个电话,也想和你悄悄说些知心话,一遍一遍拨着电话号码,电话响着无人回答。窗外的月光,慢慢的坠……下,带不走我对你的牵挂,夜幕中的留影,飘飘荡荡,能否把我问候转达!!。窗外的月光,慢慢的坠下,带不走我对你的牵挂,夜幕中的留影,飘飘荡荡,能否把我问候转达窗外的月光,慢慢的坠下,带不走我对你的牵挂,夜幕中的留影,飘飘荡荡,能否把我问候转达能…否…把…我…问…候…转……达………!!