单片机原理与接口技术实验指导书.docx
《单片机原理与接口技术实验指导书.docx》由会员分享,可在线阅读,更多相关《单片机原理与接口技术实验指导书.docx(41页珍藏版)》请在冰豆网上搜索。
单片机原理与接口技术实验指导书
MCS51单片机原理
实验指导书
付浩编
淮阴师范学院物理与电子电气工程学院
2009.9
实验要求
51单片机集成开发环境MedWinV2.39简介
STC单片机下载软件STC-ISP的使用
实验二用一位数码管循环显示数字0~9
实验三LED数码管的动态驱动
实验四用单片机自动演奏乐曲
实验五电子钟
实验六单片机与PC机的串行通信
实验七I2C串行flash存储器的读写
实验要求
1、实验前预习实验内容,理解实验原理。
2、按规定时间进入实验室,登记领取实验板和连接线,按操作程序将实验板连接到PC机上,开始实验。
2、实验完毕请指导老师确认后,按操作程序拆除实验板,将连接线收拾好,与实验板一起归还指导老师,方可离开实验室。
3、按时撰写并上交实验报告。
实验报告格式为:
(1)实验目的,
(2)实验内容,(3)源代码及流程图,(4)结果记录及分析,(5)思考题,(6)体会及设想。
注意:
实验板与PC机连接时一定要先连接串行通信电缆,然后再将其电源线插入USB接口;拆除时先断开其电源,再断开串行通信电缆。
否则极易损坏PC机的串口。
最好先关闭微机电源,再连接或拆除实验板。
实验板原理图
51单片机集成开发环境MedWinV2.39简介
1.安装
从网站免费下载MedWinV2.39集成开发环境安装程序压缩包,将其释放后,按照默认路径安装到C:
\Manley\PmedWin文件夹。
2.设置
(1)每次启动MedWin会出现对话框,询问使用仿真器还是模拟仿真,应点击[模拟仿真]按钮。
(2)设置仿真器点击[设置]—[设置仿真器]命令,选择时钟频率为12兆赫兹。
(3)设置工作目录MedWin集成开发环境默认的工作目录为C:
\MedWin\PMedWin,建议根据需要建立自己的工作目录。
注意:
不得使用长文件名或长目录名!
(4)设置编译器将C语言编译器C51(文件夹)拷贝到C:
\MedWin文件夹下,点击[设置]—[设置编译工具]命令,打开“设置编译工具”对话框,使用汇编语言时选择第一行,使用C语言时选择第二行,如下图所示。
3.使用
(1)新建项目点击[项目管理]—[新建项目]命令,输入项目名称,点击[确定]按钮,出现“添加项目文件”对话框,输入源代码文件名,如T1.C(或T1.ASM),单击[打开]按钮,出现代码窗口,即可开始编程。
(2)打开项目点击[项目管理]—[打开项目]命令,点击项目文件名(项目文件后缀为.mpf),点击[打开]按钮,即可打开上次保存的项目。
(3)编译点击[项目管理]—[编译/汇编]命令,启动编译器对源文件进行语法检查并编译,在消息窗口中显示编译结果。
(3)模拟仿真当源程序编译无误后,可进行模拟仿真调试。
点击[项目管理]—[产生代码并装入]命令,编译器对源程序进行重新编译并装入。
这时,可使用[调试]菜单中的相关命令进行调试,如设置断点、单步及全速执行等。
(4)生成目标代码点击[项目管理]—[输出Binary文件]命令,生成BIN文件,用下载工具将其下载到实验板的单片机中执行。
STC单片机下载软件STC-ISP的使用
该软件界面如下图所示:
按照界面上的提示:
第一步,设置单片机型号为STC89C52RC。
第二步,点击[OpenFile]按钮,打开编译生成的BIN文件或HEX文件。
第三步,选择串口,设置波特率。
如:
COM1,115200。
第四步,可按默认值不用设置。
第五步,下载程序。
在进行第五步之前,一定要保持实验板的串行通信线及电源线与PC机连接良好,并且实验板的电源开关处于关闭状态,然后,点击[下载]按钮,再打开实验板电源开关,此时,软件将自动完成程序下载,下载完毕,实验板上的单片机立即开始运行。
目前,MCS51内核单片机中STC89C5X(宏晶)和AT89S5X(ATMEL)两种芯片支持在线下载功能。
实验一LED流水灯
一、实验目的
1.学习单片机并口的使用方法。
2.学习延时子程序的编写和使用。
3.学习集成开发环境MedWin的安装与使用。
4.学习STC单片机在线下载软件STC-ISP的使用。
二、实验内容
所谓流水灯就是8个发光二极管(LED)轮流点亮,周而复始。
实验板上以P0口作输出口,经74LS244驱动,接8只发光二极管LED0-LED7。
当单片机的引脚输出为低电平时发光二极管点亮,为高电平时息灭。
编写程序,使8个发光二极管循环点亮,时间间隔约0.5秒。
三、实验电路连线
实验板上与本实验有关的硬件如下图所示。
74LS244驱动输出串联8个限流电阻接8个LED发光管,以防止其电流过大而烧坏。
单片机的主时钟为11.0592MHz。
JMP0和JMP1都短接1-2脚。
四、实验说明
1、P0口作为通用接口时是一准双向口,它作为输出口时与一般的双向口使用方法相同。
由准双向口结构可知当P0口用作输入口时必须先对它置“1”。
若不先对它置“1”,读入的数据是不正确的。
输出时需要接上拉电阻,P0口内部没有上拉电阻,若将外围电路设计为低有效,高无效,则无需再外接上拉电阻。
2、编写一个软件延时子程序,延时时间约0.5秒,采用三重循环实现,汇编语言程序如下:
DELAY:
MOVR7,#198
DEL1:
MOVR6,#50
DEL2:
MOVR5,#23
DJNZR5,$
DJNZR6,DEL2
DJNZR7,DEL1
RET
查指令表可知执行MOV指令需用1个机器周期,DJNZ指令需用2个机器周期,在11.0592MHz晶振时,一个机器周期时间长度为1.085μs,所以该段程序执行时间为:
[1+(1+2×23)×50]×198×1.085μs≈500mS
3、若使用C语言,可用for循环实现延时,下面的程序延时约500mS。
voiddelay(void)
{inti,j;
for(i=0;i<1000;i++)
for(j=0;j<50;j++)
{_nop_();_nop_();}
}
4、流水灯的主程序(汇编语言)为:
ORG0000H
LJMPMAIN
ORG0100H
MAIN:
CLRP1.5;P1.5=0,关闭蜂鸣器。
MOVA,#0FEH
LOP:
MOVP0,A
LCALLDELAY
RLA
SJMPLOP
END
5、流水灯的C语言主程序为:
#include
#include
#include
voidmain(void)
{unsignedchara,c;
P1=0xdf;//P1.5=0,关闭蜂鸣器。
a=0xfe;
while
(1)
{P0=a;
c=a&0x80;
a=a<<1;
a=a|(c==0x80);
delay();
}
}
五、思考题
1.如何使点亮的LED从右往左移动?
2.如何使点亮的LED从两边往中间移动?
实验二用一位数码管循环显示数字0~9
一、实验目的
1.学习单片机并口的使用方法。
2.学习延时子程序的编写和使用。
3.学习LED数码管的驱动、编码。
二、实验内容
实验板上有8个LED数码管,编写程序,使最右边的一个LED数码管循环显示0~9十个数字。
时间间隔约0.5秒,其余LED数码管关闭。
三、实验电路连线
实验板上与本实验有关的硬件如下图所示。
8个共阳的LED数码管(S0-S7)上同名的引脚连接在一起,由单片机P0口通过74HC244驱动(段控制),R12-R19为限流电阻。
单片机P2口的8个引脚分别通过三极管Q0-Q7控制8个LED数码管的公共端(位控制)。
单片机的主时钟为11.0592MHz。
JMP0短接2-3脚,JMP1短接1-2脚。
四、实验说明
1、P0口和P2都是准双向口,输出时需要接上拉电阻。
P0内部没有上拉电阻,P2口内部有弱上拉。
2、下表为驱动LED数码管的段代码表,1--代表对应的笔段亮,0--代表对应的笔段不亮。
若需要在最右边(S0)显示数字“5”,只要将从表中查得的段代码2CH写入P0口,再将P2.0置高,P2.1-P2.7置低即可。
数字
d
p
e
c
g
b
f
a
十六进制
P0.7
P0.6
P0.5
P0.4
P0.3
P0.2
P0.1
P0.0
共阴
共阳
0
1
0
1
1
0
1
1
1
B7
48
1
0
0
0
1
0
1
0
0
14
EB
2
1
0
1
0
1
1
0
1
AD
52
3
1
0
0
1
1
1
0
1
9D
62
4
0
0
0
1
1
1
1
0
1E
E1
5
1
0
0
1
1
0
1
1
9B
64
6
1
0
1
1
1
0
1
1
BB
44
7
0
0
0
1
0
1
0
1
15
EA
8
1
0
1
1
1
1
1
1
BF
40
9
1
0
0
1
1
1
1
1
9F
60
3、实现最右边的一个LED数码管循环显示0~9十个数字的C语言程序如下:
#include
#include
#include
#defineucharunsignedchar
constucharcodetab[]={0x48,0xeb,0x52,0x62,0xe1,0x64,0x44,0xea,0x40,0x60};
voiddelay(void)
{inti,j;
for(i=0;i<1000;i++)
for(j=0;j<50;j++)
{_nop_();_nop_();}
}
voidmain(void)
{uchari;
P2=0x01;
P1=0xdf;
while
(1)
{P0=tab[i];
delay();
i++;
if(i==10)i=0;
}
}
4、实现最右边的一个LED数码管循环显示0~9十个数字的汇编语言程序如下:
ORG0000H
LJMPMAIN
ORG0100H
MAIN:
MOVP1,#0DFH
MOVP2,#01H
MOVR1,#00H
LOOP:
MOVA,R1
MOVDPTR,#TAB
MOVCA,@A+DPTR
MOVP0,A
LCALLDELAY
INCR1
MOVA,R1
CJNEA,#10,LOOP
CLRA
MOVR1,A
SJMPLOOP
DELAY:
MOVR7,#198
DEL1:
MOVR6,#50
DEL2:
MOVR5,#23
DJNZR5,$
DJNZR6,DEL2
DJNZR7,DEL1
RET
TAB:
DB48H,0EBH,52H,62H,0E1H,64H,44H,0EAH,40H,60H
END
五、思考题
1.分别写出
六个字母(用于显示十六进制数)的段代码,编写程序,在最右边数码管上实现0-F的循环显示。
2.能否交替点亮点8个LED数码管?
实验三LED数码管的动态驱动
一、实验目的
1.学习LED数码管的动态驱动编程。
2.学习使用定时/计数器、中断。
3.学习汇编语言的有关运算。
二、实验内容
编写程序,使实验板上的8个LED数码管稳定显示8个不同的数字,并使这四位数从00000000开始,每0.5秒钟加1。
三、实验电路连线
本实验有关的硬件见实验二。
四、实验说明
1.在实验二中,我们已经能够让某一个LED数码管显示需要的数字,比如选让第一个LED显示“1”,隔一较短的时间(如2.5毫秒)后关闭第一个LED,让第二个LED显示“2”,如此周而复始,让8个LED依次显1、2、3、4、5、6、7、8,我们就能看到8个LED上稳定地显示8个不同的数字。
当然,每个瞬间只有一个LED被点亮,大家亮的时间相同,均为2.5毫秒,8个LED数码管点亮一遍需要20毫秒,一秒钟各亮50次,所以看上去不会有闪烁感,但亮度只是实验二中LED亮度的八分之一。
要实现每隔再隔2.5毫秒变换一个LED,最好的方法是使用定时器中断。
2.汇编语言参考程序为:
LED_PORTEQUP0;笔划输出,低有效
SCN_PORTEQUP2;段扫描输出,低有效(P2.4-P2.7)
DSEG
ORG10H
DISP_BUF:
DS8;显示缓冲区
SCN_INX:
DS1;扫描指针
SCN_COD:
DS1;扫描码
CNT:
DS1;中断计数,每2.5ms加1
CSEG
ORG00H
LJMPMAIN;主程序入口,转初始化程序
ORG0BH;定时中断0入口
LJMPINTP0;每2.5ms中断一次,用于刷新显示
;-----------初------始-----化---------------------------------
ORG30H
MAIN:
MOVSP,#50H;初始化堆栈指针
CLRRS0;选用第0组通用寄存器
CLRRS1
CLRP1.5
CLRA
MOVCNT,A
MOVR1,#8
MOVR0,#DISP_BUF
LOOP1:
MOV@R0,A;显示缓冲区清零
INCR0
DJNZR1,LOOP1
MOVSCN_INX,A;扫描指针置0
MOVSCN_COD,#80H;右边LED先点亮
MOVTMOD,#01H;定时器0,方式1
MOVTH0,#0F7H;计数初值,每次2.5ms(11.0592MHz晶振)
MOVTL0,#000H;65536-(2.5ms/1.085us)=65536-2304=63232=0F700H
SETBTR0;启动定时器0
SETBEA;中断总允许
SETBET0;允许定时器0中断
SJMP$;主程序在此循环
;-----------定时器0中断服务程序,间隔2.5ms--------------
INTP0:
PUSHACC
PUSHPSW
MOVTH0,#0F7H;置计数初值
MOVTL0,#00H
SETBRS0;选用第1组通用寄存器
CLRRS1
MOVA,SCN_INX;取扫描指针
ANLA,#07H;清除高5位
ADDA,#DISP_BUF;加显示缓冲区首地址
MOVR1,A
MOVA,@R1
MOVDPTR,#CODE_TAB;DPTR指向笔划代码表
ANLA,#0FH
MOVCA,@A+DPTR;取笔划代码
MOVLED_PORT,A;笔划代码送LED口
MOVA,SCN_COD;取扫描段代码
MOVP2,A
MOVA,SCN_COD
RRA;扫描段代码循环右移一位
MOVSCN_COD,A
INCSCN_INX;扫描指针+1
INCCNT
MOVA,CNT
CJNEA,#200,EN
MOVCNT,#0
INCDISP_BUF+7;个位加一
MOVA,DISP_BUF+7
CJNEA,#10,EN;不进位转移
MOVDISP_BUF+7,#0;进位则个位清零
INCDISP_BUF+6;十位加一
MOVA,DISP_BUF+6
CJNEA,#10,EN
MOVDISP_BUF+6,#0;进位则十位清零
INCDISP_BUF+5;百位加一
MOVA,DISP_BUF+5
CJNEA,#10,EN
MOVDISP_BUF+5,#0;进位则百位清零
INCDISP_BUF+4;千位加一
MOVA,DISP_BUF+4
CJNEA,#10,EN
MOVDISP_BUF+4,#0;进位则千位清零
INCDISP_BUF+3;万位加一
MOVA,DISP_BUF+3
CJNEA,#10,EN
MOVDISP_BUF+3,#0;进位则万位清零
INCDISP_BUF+2;十万位加一
MOVA,DISP_BUF+2
CJNEA,#10,EN
MOVDISP_BUF+2,#0;进位则十万位清零
INCDISP_BUF+1;百万位加一
MOVA,DISP_BUF+1
CJNEA,#10,EN
MOVDISP_BUF+1,#0;进位则百万位清零
INCDISP_BUF+0;千万位加一
MOVA,DISP_BUF+0
CJNEA,#10,EN
MOVDISP_BUF+0,#0;进位则千万位清零
EN:
POPPSW
POPACC
RETI
;----------笔划代码表-------------------------
CODE_TAB:
DB48H,0EBH,52H,62H,0E1H,64H,44H,0EAH,40H,60H
END
3.C语言参考程序为:
#include
#defineucharunsignedchar
constucharcodetab1[]={0x48,0xeb,0x52,0x62,0xe1,0x64,0x44,0xea,0x40,0x60};
constucharcodetab2[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
ucharbuf[8]={0,0,0,0,0,0,0,0};//显示缓冲区,开机先显示"00000000"
voidmain(void)
{P1=0xdf;
EA=1;//允许中断
TMOD=0x01;//设定时器0为模式1(16位)
ET0=1;//定时器0中断允许
TH0=0xf7;//晶振11.0592MHz,2.5ms
TL0=0;
TR0=1;//开始计数
while
(1);//死循环,等待中断
}
voidtimeint(void)interrupt1//定时器0中断服务程序
{staticuchark,count;
chari;
TH0=0xf7;//设置定时器时间常数
TL0=0;
k++;
k&=0x07;
P0=tab1[buf[k]];//笔划代码送P0口
P2=tab2[k];//控制扫描码送P2口
if(++count==200)//计数200次为2.5msX200=0.5s
{count=0;//到0.5秒钟,显示的数字加一
for(i=7;i>=0;i--)
{buf[i]++;
if(buf[i]==10)buf[i]=0;//加到10向前进位
elsebreak;
}
}
}
五、思考题
如何让8个LED数码管从00-00-00开始,每秒钟自动加1,前两位代表时,中间两位代表分,后两位代表秒?
实验四用单片机自动演奏乐曲
一、实验目的
(1)进一步熟悉89C51定时器/计数器的功能及应用;
(2)掌握其初始化与中断服务程序的编程方法;
(3)掌握用定时器/计数器发出不同音调的编程方法。
二、实验内容
用单片机的定时器/计数器0作定时器使用,工作于模式1,中断产生方波发声,根据各个的频率,计算对应的定时时间常数,定时器中断后按此常数赋初值,从而发出对应的音调。
将歌曲的音调和节拍编成一个表,用音调作为定时器的初值,用节拍控制发音时间,就可以实现自动演奏。
三、实验电路连线
本实验有关的硬件如右图所示。
四、实验说明
声单定时初值常数计算方法:
根据下表的音阶频率,计算对应的音阶周期T,用T/2计算定时周期数(晶振11.0592MHz),填入下表中。
定时器的计数初值为65536-定时周期数,在程序计算产生。
定时周期数增加1倍,音阶降低八度,定时周期数降低1倍,音阶升高八度。
音阶(C调)
1
2
3
4
5
6
7
频率(Hz)
256
288
320
341
384
427
480
周期(μs)
3906
3472
3125
2932
2604
2342
2083
定时周期数
3600
3200
2880
2702
2400
2158
1920
自动演奏《东方红》乐曲的C语言程序为:
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitP15=P1^5;
codeuintcyc[]={3600,3200,2880,2702,2400,2158,1920};//音阶1-7对应的计数周期数
codeuchartone[]={15,15,16,12,11,11,06,12,15,15,16,21,16,15,11,11,
06,12,15,12,11,7,6,5,15,12,13,12,11,11,6,12,
13,12,11,12,11,7,6,5,0};//乐曲《东方红》的简谱表
codeuchartime[]={8,4,4,16,8,4,4,16,8,8,4,4,4,4,8,4,
4,16,8,8,8,4,4,8,8,8,4,4,8,4,4,4,
4,4,4,4,4,4,4,16,0};//节拍表(8为1拍,约570mS)
ucharH0,L0,cnt;
voidcntint0(void)interrupt1//定时器0中断用于产生音调
{TH0=H0;
TL0=L0;
P15=~P15;//P1.5是音乐信号输出脚
}
voidcntint1(void)interrupt3//定时器1中断用于产生节拍
{cnt++;/