【www.scfx8.com--述职述廉报告】

《 单 片 机 原 理 及 应用》

实 验 指 导 书 (C语言)

XX大学物电学院 微机教研室 XX 2011 前 言 由于单片机具有高可靠性、超小型、低价格、容易产品化等特点,在仪器仪表智能化、实时工业控制、实时数据采集、智能终端、通信设备、导航系统、家用电器等控制应用领域,具有十分广泛的用途。由于目前在国内单片机应用中,MCS-51系列单片机仍然是一种主流单片机,所以本实验指导书为学习MCS-51单片机的学生,配合《单片机原理及应用》课程的,结合本学院自制单片机教学实验板编写了这本实验指导书。

《单片机原理应用及》是一门实践性很强的课程,提高教学质量的一个重要环节是上机实习和训练,无论是学习汇编语言程序设计,还是学习接口电路和外设与计算机的连接,或者软硬兼施地研制单片机应用系统,不通过加强动手是不能获得预期效果的。本实验指导书提供多个实验的指导性材料,有些实验还有一些有一定难度的选做项目,可以根据课时的安排和教学要求进行取舍。为了达到某些实验的目的,书中提供的参考程序与实际应用中的程序会有些差别,所以不一定是最优的。

由于时间紧迫,需要赶课程进度与实验时间的同步,加上编者学识有限,如有不妥之处,欢迎读者批评指正。

实 验 须 知 1. 实验前必须阅读教科书的有关部分和本实验指导书,了解实验目的、内容、步骤,做好实验前的准备工作,编写好实验中要求自编或修改的程序;

完成实验前要求完成的准备工作后方可以上机实验,否则不得上机操作。

2. 各种电源的电压和极性不能接错,严禁带电接线和接插元器件。通电前须经过指导教师检查认可后方能通电。

3. 不准随意拨弄各种与实验无关的旋钮和开关,凡与本次实验无关的任何设备都禁止动用和摸弄,注意安全。

4. 严禁用手触摸实验系统印制电路板和元器件的引脚,防止静电击穿芯片。

5. 实验中若损坏仪器或元器件,应及时向指导教师报告。

6. 在实验室内保持安静和卫生,不得随意走动和喧哗,集中精力完成实验。

7. 实验完成后,关掉电源,及时整理实验台桌面,保持环境整洁。

8. 按规定认真完成实验报告,在规定的时间内缴上实验报告。

9. 凡实验或实验报告未能按规定完成的学员,不能参加本课程的考试或考查。

单片机实验报告格式 实验报告标题 一、实验目的 二、实验内容 实验设计及调试:

(1)实验分析及内容。

(2)实验电路:画出与实验内容有关的简单实验电路。

(3)实验设计及调试步骤:根据内容写出实验程序。调试程序,观察结果。

(4)实验调试过程中所遇到的问题、解决问题的思路和解决的方法。

四、实验后的经验教训。

五、对实验课的建议 目 录 实验一 实验板使用,KEIL C51软件使用 6 实验二 单片机控制LED灯点亮 12 实验三 模拟开关灯 16 实验四 单片机控制数码管实验 21 实验五 中断系统应用实验 25 实验六 LED 数码管的动态驱动 29 实验七 定时器/计数器使用 32 实验八 数字电子钟 36 实验九 矩阵键盘识别实验 37 实验十 自动演奏乐曲 41 实验十一 综合实验 交通信号灯控制器的设计 45 实验十二 教学板自检程序设计 46 实验十三 综合实验:数据采集—火灾报警装置的软硬件设计 47 附录:实验教学板电路原理图 48 实验一 实验板使用,Keil C51软件使用 一、实验目的 1. 熟悉单片机实验板、Keil C51软件使用 二、实验说明 本实验介绍实验板的组成、Keil C51软件使用以及烧录软件的使用。通过该实验学生可以了解单片机编程、调试方法。

三、实验内容及步骤 1.启动PC机,安装好Keil C51软件以及烧录软件,用串口线连接计算机与实验板(USB线提供电源)。

2.打开Keil uVision2仿真软件,首先建立本实验的项目文件,接着建立源程序,编译无误后,全速运行程序。

3.可把源程序编译成可执行文件,用烧录器烧录到89芯片中。

四、Keilc 软件使用说明 1、打开程序:

双击程序 2、新建工程:Project → New Project→保存工程→选择CPU(一般选ATMEL公司的AT89S51)

-17- 3、设置工程:右击→Options for ‘Target 1’ →→选择Create HEX (输出HEX文件)。

-18- 4、新建源文件:选File→New→输入、编辑源程序→保存(汇编源程序:文件名.asm;C源程序:文件名.c)

5、为工程添加源文件:在Project出口File页上单击文件组,选择Add Files to Group‘Source Group 1’选项,选择你的源文件和文件类型,然后点击ADD,再点击close。

-19- 6、编译:点击 ,或右击Target 1 →Build Target F7,就可对源程序进行编译。当程序有语法错误时,会在输出窗口(Output Windows)中显示错误信息和警告信息,修改编译成功后会生成 HEX文件。

7、下载、调试:

编译成功后,用在线烧录程序将.HEX文件下载到单片机内部ROM中运行,在运行过程中若发现错误要重新修改程序,并编译后再下载运行。

五、烧录软件的使用 1、打开在线烧录程序 2、选择MCU类型(STC89C51RC)

1、 点击, 打开工程目录下的hex文件 2、 选择端口(一般是COM1) 3、 点击Download烧录程序 4、 打开实验板上的电源(如果烧录的时候出现问题,点击stop) 注意:

5、6 两步骤的顺序不能颠倒!即在点击Download之前要先关掉实验板上的电源。

实验二 单片机控制LED灯点亮 一、实验目的 1.进一步熟悉编程和程序调试 2.学习P1口的使用方法 3.学习延时子程序的编写和使用 二、实验说明 (1)输出控制。

如图1所示 ,当P1 . 0端口输出高电平,即P1.0=1时 ,根据发光二极管的单向导电性 可知,这时发光二极管L1熄灭;

当 P1 .0端口输出低电平,即 P1 .0=0时,发光二极管L 1亮;

我们可以使用SETB P1.0指令使 P 1. 0端口输出高电平 , 使用CLR P1.0指令使 P1 .0 端口输出低电平 。

(2)延时子程序的设计方法 作为单片机的指令的执行时间是很短的,数量达微秒级,因此,如果我们要求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程序是如何设计呢?下面具体介绍其原理:

石英晶体为12MHz,因此,1个机器周期为1微秒 机器周期 微秒 MOV R6,#20 2个机器周期 2 D1: MOV R7,#248 2个机器周期 2×20 DJNZ R7,$ 2个机器周期 2×248×20 DJNZ R6,D1 2个机器周期2×20=4010002 因此,上面的延时程序时间为10.002ms。

由以上可知,当R6=10、R7=248时,延时5ms,R6=20、R7=248时,延时10ms,以此为基本的计时单位。如要求0.2秒=200ms,10ms×R5=200ms,则R5=20,汇编延时子程序如下:

DELAY: MOV R5,#20 D1: MOV R6,#20 D2: MOV R7,#248 DJNZ R7,$ DJNZ R6,D2 DJNZ R5,D1 RET C语言延时子程序如下:

void delay02s(void) //延时0.2秒子程序 { unsigned char i,j,k; for(i=20;i>0;i--) for(j=20;j>0;j--) for(k=248;k>0;k--); } 三、实验步骤及参考例子 实验步骤说明:

本实验需要用到单片机最小应用系统。

用P1口做输出口,程序功能使发光二极管点亮。

1.用串行数据通信线连接计算机与实验板,用USB给实验板提供电源 3.打开Keil uVision2仿真软件,首先建立本实验的项目文件,输入源程序(参考程序1),进行编译,直到编译无误。生成hex文件。

5.通过STC-ISP下载软件,将hex文件下载到实验板内,观察发光二极管显示情况。

参考例子:

(1) 点亮板子上的第一个灯D0 (2) 让第一个灯闪烁 四、参考程序 (一)适用于mini80E实验板 1)

#include void main() { P1=0xfe; } 2)

#include #define uint unsigned int #define uchar unsigned char delay(); void main() { while(1) { P1=0xfe; delay(); P1=0xff; delay(); } } void delay() { uint x,y; for(x=100;x>0;x--) for(y=600;y>0;y--) ; } (二)适用于自制最小系统实验板 (1)

#include void main (void) { P2=0x00; P2=0x10; P0=0xfe; } (2)

#include void delay(void); void main (void) { P2=0x00; while(1) {P2=0x10; P0=0xfe; delay(); //P2=0x00; P0=0xff; delay(); } } void delay(void) { int x,y; for(x=600;x>0;x--) for(y=100;y>0;y--); } 六、实验内容 请在keil环境下编写以下程序:

1)点亮最后一个LED(或者任意一个LED,或者任意几个LED) 2)让点亮的LED闪烁 3)点亮板子上的D0、D2、D4、D6灯,与D1、D3、D5、D7灯交替闪烁 4)设计出流水灯程序,从D7—D0或从D0-D7 实验三 模拟开关灯 1.实验目的 1.进一步熟悉编程和程序调试 2.学习独立按键的使用方法 2.实验说明 如果系统只需几个按键,可直接采用I/O线构成单个按键电路,各个按键之间相互独立,一根线上的按键状态不会影响其他输入线上的工作状态,又称独立式键盘接口电路。

检测是否有键闭合,如有键闭合,则去除键抖动,判断键号并转入相应的按键处理。编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时,检测松手时就不用加了。

3、参考例子 1)通过四个按键来控制LED灯的显示情况:

S1:D0点亮 S2:D1点亮 S3:D2点亮 S4:D3点亮 4、参考程序 (一)适用于自制实验板 #include #define uint unsigned int #define uchar unsigned char uchar flag; uchar key_down; sbit LED2 = P0^0; sbit LED3 = P0^1; sbit LED4 = P0^2; sbit LED5 = P0^3; /****************************/ void delay(uint k) { uint data i,j; for(i=0;i #define uint unsigned int #define uchar unsigned char uchar flag; /****************************/ void delay(uint k) { uint data i,j; for(i=0;i #define uint unsigned int #define uchar unsigned char uchar flag; uchar key_down; sbit LED2 = P1^0; sbit LED3 = P1^1; sbit LED4 = P1^2; sbit LED5 = P1^3; /****************************/ void delay(uint k) { uint data i,j; for(i=0;i void main(void) { while(1) { P2=0xf7; P0=0x7f; } } 2)

#include #define uint unsigned int #define uchar unsigned char void delay(); void main(void) { while(1) { P2=0xf7; P0=0x66; delay(); P2=0xf6; P0=0x4f; delay(); P2=0xf5; P0=0x5b; delay(); P2=0xf4; P0=0x06; delay(); } } void delay() //延时程序1 { uint x,y; for(x=2;x>0;x--) for(y=112;y>0;y--) ; } (二)自制教学实验板(共阳极数码管)

(1)

#include void main(void) { while(1) { P2=0x08; P0=0x80; } } 2)

#include #define uint unsigned int #define uchar unsigned char void delay(); void main(void) { while(1) { P2=0x08; P0=0x99; delay(); P2=0x04; P0=0xb0; delay(); P2=0x02; P0=0xa4; delay(); P2=0x01; P0=0xf9; delay(); } } void delay() //延时程序1 { uint x,y; for(x=2;x>0;x--) for(y=112;y>0;y--) ; } 五、原理图 六、实验内容 1)用一位数码管循环显示0-9;

2)用数码管显示字母A-F;

3) 交替点亮4个数码管。(例如:开始时在数码显示器的最右边一位上显示1个“0”字,以后每隔0.5秒将“0”字左移1位,直到最左边一位后则停止显示。)

4)结合实验3,实现按键与数字的一一对应。

实验五 中断系统应用实验 一、实验目的 1.掌握外部中断技术的基本使用方法 2.掌握中断处理程序的编写方法 二、实验说明 1.外部中断的初始化设置共有三项内容:中断总允许即EA=1,外部中断允许即EXi=1(i=0或1),中断触发方式设置。中断触发方式设置一般有两种方式:电平触发方式和脉冲(边沿)触发方式,本实验选用后者,其前一次为高电平后一次为低电平时为有效中断请求。因此高电平状态和低电平状态至少维持一个周期,中断请求信号由引脚INT0(P3.2)和INT1(P3.3)引入,本实验由INT0(P3.2)引入。

2.中断控制原理:

中断控制是提供给用户使用的中断控制手段。实际上就是控制一些寄存器,51系列用于此目的的控制寄存器有四个:TCON 、IE 、SCON 及IP。

3.中断响应的过程:

首先中断采样然后中断查询最后中断响应。采样是中断处理的第一步,对于本实验的脉冲方式的中断请求,若在两个相邻周期采样先高电平后低电平则中断请求有效,IE0或IE1置“1”;

否则继续为“0”。所谓查询就是由CPU测试TCON和SCON中各标志位的状态以确定有没有中断请求发生以及是那一个中断请求。中断响应就是对中断请求的接受,是在中断查询之后进行的,当查询到有效的中断请求后就响应一次中断。

4. 8051的中断系统 8051的中断系统包括5个中断源,并提供两个优先级,允许用户对中断源进行独立控制和中断优先级设置.8051支持的5个中断源分别为外部中断0、定时器0溢出中断、外部中断1、定时器1溢出中断和串口中断。

对应的中断号为0、1、2、3、4;

寄存器有4个工作组可以切换,为0-3;C51中,中断服务程序是以中断函数的方式来时实现的。

5.中断函数格式如下:

void 函数名() interrupt 中断号 using 工作组 { 中断服务程序内容;

} 三、参考例子 1) 右边的三个数码管从“000”开始进行加法计数。按动按键时计数暂停,再按继续计数。

四、参考程序 (一)适用于自制教学实验板 #include #define uchar unsigned char #define uint unsigned int sbit P37=P3^7; uchar code table[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uchar code wei[4] = {0x08,0x04,0x02,0x01}; /***************************************************************/ uint cnt; bit flag; /**********************************************/ void init(void) { bit flag=0; //设置标志 EA=1;//开中断 EX0=1; //外部中断0开中断 IT0=1; //外部中断0的触发方式 } /**************************************************/ void delay(uint k) { uint data i,j; for(i=0;i999)cnt=0; for(i=0;i #define uchar unsigned char #define uint unsigned int sbit P37=P3^7; uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uchar code wei[4] = {0xf7,0xf6,0xf5,0xf4}; /***************************************************************/ uint cnt; bit flag; /**********************************************/ void init(void) { bit flag=0; //设置标志 EA=1;//开中断 EX0=1; //外部中断0开中断 IT0=1; //外部中断0的触发方式 } /**************************************************/ void delay(uint k) { uint data i,j; for(i=0;i999)cnt=0; for(i=0;i #define U8 unsigned char U8 tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; U8 scn[] = {0x01,0x02,0x04,0x08};//先点亮左边一个数码管 U8 buf[4] = {0,0,0,0};// 显示缓冲区,开机先显示“0000“ U8 cnt = 0; // 扫描计数 void main(void) { EA = 1; // 允许中断 TMOD = 0x01; // 设定时器 0 为模式 1(16 位) ET0 = 1; // 定时器 0 中断允许 TH0 = 0xee; // 晶振 11.0592MHz,5mS TL0 = 0; TR0 = 1; // 开始计数 while(1); // 死循环,等待中断 } void timeint(void) interrupt 1 // 定时器 0 中断服务程序 { char i; TH0 = 0xee; // 设置定时器时间常数 TL0 = 0; i = cnt // 求应点亮的 LED 号(从左到右依次为 0,1,2,3) P0 = tab[buf[i]]; // 笔划代码送 P0 口 P2 = scn[i]; // 控制扫描码送 P2 口 if(cnt==200) { cnt=0; // 到 1 秒钟,显示的数字加一 for(i=3;i>=0;i--) { buf[i]++; if(buf[i]==10) buf[i]=0;// 加到 10 向前进位 else break; } } cnt++; } (二)mini80e实验板C51参考程序如下:

#include #define U8 unsigned char U8 tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; U8 scn[] = {0xf4,0xf5,0xf6,0xf7};//先点亮左边一个数码管 U8 buf[4] = {0,0,0,0};// 显示缓冲区,开机先显示“0000“ U8 cnt = 0; // 扫描计数 void main(void) { EA = 1; // 允许中断 TMOD = 0x01; // 设定时器 0 为模式 1(16 位) ET0 = 1; // 定时器 0 中断允许 TH0 = 0xee; // 晶振 11.0592MHz,5mS TL0 = 0; TR0 = 1; // 开始计数 while(1); // 死循环,等待中断 } void timeint(void) interrupt 1 // 定时器 0 中断服务程序 { char i; TH0 = 0xee; // 设置定时器时间常数 TL0 = 0; i = cnt // 求应点亮的 LED 号(从左到右依次为 0,1,2,3) P0 = tab[buf[i]]; // 笔划代码送 P0 口 P2 = scn[i]; // 控制扫描码送 P2 口 if(cnt==200) { cnt=0; // 到 1 秒钟,显示的数字加一 for(i=3;i>=0;i--) { buf[i]++; if(buf[i]==10) buf[i]=0;// 加到 10 向前进位 else break; } } cnt++; } 五、实验内容 1、每个按键控制一个数码管,按任意一个键,可在相应的数码管上实现数字加1。

2、如何让 4 个 LED 数码管从 0000 开始,每秒钟自动加 1,前两位代表分,后两位代表秒? 实验七 定时器/计数器使用 一、实验目的 1.学习89C51内部定时计数器的使用和编程方法 2.进一步掌握中断处理程序的编写方法 二、实验说明 1、51单片机有。两个16位内部定时器/计数器(T/C,Timer/ Counter)。若是计数内部晶振驱动时钟,则是定时器;

若是计数8051的输入引脚的脉冲信号,则它是计数器。定时器实际上也是工作在计数方式下,只不过对固定频率的脉冲计数。由于脉冲周期固定由计数值可以计算出时间,有定时功能。

定时器有关的寄存器有工作方式寄存器TMOD和控制寄存器TCON。TMOD用于设置定时器/计数器的工作方式0-3,并确定用于定时还是用于计数。TCON主要功能是为定时器在溢出时设定标志位,并控制定时器的运行或停止等。

2、TMOD 1) M1M0工作方式控制位 2) C/T 定时器方式或计数器方式选择位 若C/T=1时, 为计数器方式; C/T = 0时, 为定时器方式。

 3)GATE 定时器/计数器运行门控标志位 当GATE=1时, T/C的启动受双重控制,即要求INT0 (或INT1)引脚为高电平且TR0(或TR1 )置 1 时, 相应的T/C才被选通工作。若GATE=0, T/C的启动仅受TR0 (或 TR1)控制,即置 1, T/C就被选通, 而不管 INT0 (或 INT1)的电平是高还是低。

3、TCON TF0、TF1分别是定时器/计数器T0、 T1 的溢出中断标志位, 加法计数器计满溢出时置1, 申请中断, 在中断响应后自动复 0。TF产生的中断申请是否被接受, 还需要由中断是否开放来决定。TR1、TR0 分别是定时器 /计数器T1、 T0 的运行控制位, 通过软件置 1 后, 定时器 /计数器才开始工作, 在系统复位时被清 0。

4、初始化 1)初始化步骤 在使用51系列单片机的T/C前,应对它进行编程初始化,主要是对TCON和TMOD编程,还需要计算和装载T/C的计数初值。一般完成以下几个步骤:

(1)确定T/C的工作方式——编程TMOD寄存 (2)计算T/C中的计数初值,并装载到TH和TL;

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

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

2)计数初值的计算 (1)定时器的计数初值:

在定时器方式下,T/C是对机器周期脉冲计数的,fOSC=6MHZ,一个机器周期为12/fOSC=2us,则 方式0 13位定时器最大定时间隔=213*2us=16.384ms 方式1 16位定时器最大定时间隔=216*2us=131.072ms 方式2 8位定时器最大定时间隔=28*2us=512us 若T/C工作在定时器方式1时,要求定时1ms,求计数值。如设计数初值为x,则有:

(216-x)*2us=1000us 推出x=216-500 因此,TH,TL可置65 536-500 (2)计数器的计数初值 在计数器方式下:

方式0 13位计数器的满计数值=213=8192 方式1 16位计数器的满计数值=216=65 536 方式2 8位计数器的满计数值=28=256 若T/C工作在计数器方式2时,则要求计数10个脉冲的计数初值,如设计数初值为x。则有 28-x=10 即 x= 28-10 因此,TH=TL=256-10 三、参考例子 1)设单片机晶振频率为 12 MHz,利用定时器在P1.0脚输出周期为 2 ms的方波。

分析:选用定时器 /计数器T0 作定时器, 输出为P1.0 引脚, 2 ms 的方波可由间隔 1 ms的高低电平相间而成, 因而只要每隔 1 ms对 P1.0 取反一次即可得到这个方波。

机器周期=12÷12MHz= 1 μs 1 ms内T0 需要计数N次: N= 1 ms÷1 μs = 1000 由于计数器向上计数,为得到1000个计数之后的定时器溢出,必须给定时器置初值为:65 536-1000. 2) 在P1.7端接有一个发光二极管,要求利用T/C控制,使LED亮1s,灭1s,周而复始。

分析:要求定时1s,T/C的三种工作方式都不能满足。(为什么?)对于较长时间的定时,应采用符合定时的方法。

l 使T/C0工作在定时器方式1,定时100ms,定时时间到后P1.0反相,即P1.0端输出周期200ms的方波脉冲。另设T/C1工作在计数器方式2,对T1输出的脉冲计数,当计满5次,定时1s时间到,将P1.7端方向,改变灯的状态。

l 采用6MHZ晶振,方式1的最大定时才能达到100多ms。对于100ms,机器周期为12/fOSC=2us,需要计数的次数=100*1000/2=50 000,即初值为65 536-50 000. 方式2满5次溢出中断,初值为256-5. 四、参考程序 (一)适用于自制实验教学板 1)设置周期为2ms的方波 查询方式:

#include sbit P1_0=P1^0; void main() { TMOD=0x01; //T/CO工作在定时器方式1 16位定时器 TR0=1; //启动T/C0 for(;;) //主程序循环 { TH0=(65536-1000)/256; //预置计数初值 TL0=(65536-1000)%256; do { P1_0=!P1_0; //P1.0取反 TF0=0; //软件清TF0 }while(!TF0); //查询等待TF0置位 } } 中断方式:

#include sbit P1_0=P1^0; void timer0(void) interrupt 1 using 1 //T/C中断服务程序入口 { TF0=0; //清楚中断标志位 P1_0=!P1_0; //P1.0取反 TH0=(65536-1000)/256; //计数初值重装载 TL0=(65536-1000)%256; } void main() { TMOD=0x01; //T/CO工作在定时器方式1 P1_0=0; TH0=(65536-1000)/256; //预置计数初值 TL0=(65536-1000)%256; EA=1; //CPU开中断 TF0=0; ET0=1; //T/C0开中断 TR0=1; //启动T/C0开始定时 do {}while(1); } 2) 灯的闪烁,时间间隔为1s(P1.0与P3.5相连,作为定时器1的输入)

#include sbit P1_0=P1^0; sbit P0_7=P0^7; timer0() interrupt 1 using 1 //T/C0中断服务程序入口 { TF0=0; //清楚中断T0标志位 P1_0=!P1_0; //P1.0取反 TH0=(65536-1000)/256; //计数初值重装载 TL0=(65536-1000)%256; } timer1() interrupt 3 using 2 //T/C1中断服务程序入口 { TF1=0; //清楚中断T1标志位 P0_7=!P0_7; //1s到,灯改变状态 } void main() { P2=0x10; //打开LED电源开关 P0_7=1; //置灯初始灭 P1_0=1; //保证第一次方向便开始计数 TMOD=0x61; //T/CO工作在定时器方式1,T/C1工作在计数器方式2 TH0=(65536-10000)/256; //预置计数初值 10毫秒 TL0=(65536-10000)%256; TH1=256-100; TL1=256-100; IP=0X08; //置优先级存储器 EA=1; //CPU开中断 TF0=0; //清除中断T0标志位 TF1=0; //清除中断T1标志位 ET0=1; //T/C0开中断 ET1=1; //T/C1开中断 TR0=1; //启动T/C0开始定时 TR1=1; //启动T/C1 do{} while(1); } (二)适用于MINI80E实验板 (2)P0.7与P3.5相连,作为定时器1的输入 #include sbit P1_0=P1^0; sbit P0_7=P0^7; timer0() interrupt 1 using 1 //T/C0中断服务程序入口 { TF0=0; //清除中断T0标志位 P0_7=!P0_7; //P1.0取反 TH0=(65536-1000)/256; //计数初值重装载 TL0=(65536-1000)%256; } timer1() interrupt 3 using 2 //T/C1中断服务程序入口 { TF1=0; //清除中断T1标志位 P1_0=!P1_0; //1s到,灯改变状态 } void main() { P2=0x10; //打开LED电源开关 P0_7=1; //置灯初始灭 P1_0=1; //保证第一次方向便开始计数 TMOD=0x61; //T/CO工作在定时器方式1,T/C1工作在计数器方式2 TH0=(65536-10000)/256; //预置计数初值 10毫秒 TL0=(65536-10000)%256; TH1=256-100; TL1=256-100; IP=0X08; //置优先级存储器 EA=1; //CPU开中断 TF0=0; //清除中断T0标志位 TF1=0; //清除中断T1标志位 ET0=1; //T/C0开中断 ET1=1; //T/C1开中断 TR0=1; //启动T/C0开始定时 TR1=1; //启动T/C1 do{} while(1); } 五、电路图 六、实验内容 1)利用定时/计数器T1产生定时时钟,由P1口(或P0口)控制8个发光二极管,使8个指示灯依次一个一个闪动,闪动频率为10次/秒(8个灯依次亮一遍为一个周期),循环。

实验八 数字电子钟 一、实验目的 进一步熟悉定时/计数器的使用。

二、实验内容 在实验板上编写程序,实现电子钟功能。时间显示格式为 HH.MM,中间的小数点每秒钟闪烁一次。用两个按键控制分和小时的调整,每按一次分或者小时加1。

三、实验说明 前面实验钟 LED 数码管的笔划代码均不含小数点(h 位为 1,小数点不亮),为了让第 2 个 LED 的小数点在每一秒的前半秒亮,后半秒灭,应在定时器的中断子程序中,判断当前时间为前半秒,而且动态扫描到第 2 个 LED 时,将其笔划代码取出,和 0xDF 相与后再写入 P0 口。

实验九 矩阵键盘识别实验 一、实验目的 1.掌握矩阵键盘的检测原理 二、实验说明 1、矩阵式键盘中,行、列线分别连接到按键开关的两端,行线通过上拉电阻接到+5V上。当无键按下时,行线处于高电平状态;

当有键按下时,行、列线将导通,此时,行线电平将由与此行线相连的列线电平决定。这一点是识别矩阵按键是否被按下的关键。然而,矩阵键盘中的行线、列线和多个键相连,各按键按下与否均影响该键所在行线和列线的电平,各按键间将相互影响,因此,必须将行线、列线信号配合起来作适当处理,才能确定闭合键的位置。

扫描方式是利用CPU完成其他工作的空余调用键盘扫描子程序来响应键盘输入的要求。在执行键功能程序时,CPU不再响应键输入要求,直到CPU重新扫描键盘为止。键盘扫描程序一般应包括以下内容:

(1)判别有无键按下。

(2)键盘扫描取得闭合键的行、列值。

(3)用计算法或查表法得到键值。

(4)判断闭合键是否释放,如没释放则继续等待。

(5)将闭合键键号保存,同时转去执行该闭合键的功能。

三、参考例子 1)按矩阵键盘上面的key0---key15,在第一个数码管上分别显示0-9,A-F。

四、参考程序 1)矩阵键盘(适用于MINI80E板)

#include #define uchar unsigned char #define uint unsigned int uchar code DIS_SEG7[16]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar code DIS_BIT[8]={0xf7,0xf6,0xf5,0xf4,0xf3,0xf2,0xf1,0xf0}; uchar code SKEY[16]={13,14,15,0,9,10,11,12,5,6,7,8,1,2,3,4}; uchar code act[4]={0xf7,0xfb,0xfd,0xfe}; //======================== void delay(uint k) { uint data i,j; for(i=0;i>4; in=in|0xf0; for(j=0;j #define uchar unsigned char #define uint unsigned int uchar code DIS_SEG7[8]={0xc0,0xf9,0xa4,0xb0,0x99, 0x92,0x82,0xf8}; uchar code DIS_BIT[4]={0x08,0x04,0x02,0x01}; uchar code SKEY[8]={4,5,6,7,0,1,2,3}; uchar code act[4]={0xf7,0xfb,0xfd,0xfe}; //======================== void delay(uint k) { uint data i,j; for(i=0;i>4; in=in|0xf0; for(j=0;j #define U8 unsigned char sbit SPK=P1^2; sbit P3_2=P3^2; code unsigned int cyc[]={1800,1600,1440,1351,1200,1079,960};//音阶 1-7 的半周期数 code U8 tone[]={13,15,16,16,15,16,13,12,12,13,15,16,16,15,16,13,13, 13,15,16, 16,15,16,13,12,12,15,13,12,13,12,11,12,6,6,12,15,13,12,6,6,15,13,12,13,12,11, 12,6,5,6,0xff};// 乐曲《康定情歌》的简谱表 code U8 time[]={8,8,8,4,4,8,8,12,4,8,8,8,4,4,8,16,8,8,8,8,4,4,8,8,12,4,8,8,4,4, 4,4,8,24,8,24,8,24,8,16,8,8,8,4,4,4,4,8,16,8,32};// 节拍表 U8 H0,L0,cnt; void cntint0(void) interrupt 1 // 定时器 0 中断用于产生音阶方波 { TH0=H0; TL0=L0; SPK=~SPK; // P1.2 是音乐信号输出脚,P1.2 反相,产生方波 } void cntint1(void) interrupt 3 // 定时器 1 中断用于产生节拍延时 { cnt++; // 计数初值为 0,所以不用赋值 } void main(void) { U8 i,a,t; unsigned int b; next:TMOD=0x11; EA=1; ET0=1; ET1=1; cnt=0; TR1=1; i=0; while(1) { t=tone[i]; // 读音调 if(t==0xff) break; // 0xff 是结束符 if(t!=0) // 0 是休止符 { b=cyc[t%10-1]; // 根据基本音阶,求出半周期数 if(t20) b=b/2; // 若是高八度音阶,半周期数减半 H0=(65536-b)/256; // 根据半周期数,计算 T0 初值的高字节和低字节 L0=(65536-b)%256; TR0=1; // 启动定时器 0 发音 } cnt=0; a=time[i]; // 读节拍 while(a>cnt); TR0=0; i++; for(b=0;b #define U8 unsigned char sbit P2_5=P2^5; sbit P3_2=P3^2; code unsigned int cyc[]={1800,1600,1440,1351,1200,1079,960};//音阶 1-7 的半周期数 code U8 tone[]={13,15,16,16,15,16,13,12,12,13,15,16,16,15,16,13,13, 13,15,16, 16,15,16,13,12,12,15,13,12,13,12,11,12,6,6,12,15,13,12,6,6,15,13,12,13,12,11, 12,6,5,6,0xff};// 乐曲《康定情歌》的简谱表 code U8 time[]={8,8,8,4,4,8,8,12,4,8,8,8,4,4,8,16,8,8,8,8,4,4,8,8,12,4,8,8,4,4, 4,4,8,24,8,24,8,24,8,16,8,8,8,4,4,4,4,8,16,8,32};// 节拍表 U8 H0,L0,cnt; void cntint0(void) interrupt 1 // 定时器 0 中断用于产生音阶方波 { TH0=H0; TL0=L0; P2_5=~P2_5; // P2.5 是音乐信号输出脚,P2.5 反相,产生方波 } void cntint1(void) interrupt 3 // 定时器 1 中断用于产生节拍延时 { cnt++; // 计数初值为 0,所以不用赋值 } void main(void) { U8 i,a,t; unsigned int b; next:TMOD=0x11; EA=1; ET0=1; ET1=1; cnt=0; TR1=1; i=0; while(1) { t=tone[i]; // 读音调 if(t==0xff) break; // 0xff 是结束符 if(t!=0) // 0 是休止符 { b=cyc[t%10-1]; // 根据基本音阶,求出半周期数 if(t20) b=b/2; // 若是高八度音阶,半周期数减半 H0=(65536-b)/256; // 根据半周期数,计算 T0 初值的高字节和低字节 L0=(65536-b)%256; TR0=1; // 启动定时器 0 发音 } cnt=0; a=time[i]; // 读节拍 while(a>cnt); TR0=0; i++; for(b=0;b 下载《单片机原理及应用》实验指导书(C语言)word格式文档 下载《单片机原理及应用》实验指导书(C语言).doc 将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。 点此处下载文档

文档为doc格式

本文来源:http://www.scfx8.com/shuzhibaogao/71837.html