推荐答案.docx
- 文档编号:8641224
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:12
- 大小:97.11KB
推荐答案.docx
《推荐答案.docx》由会员分享,可在线阅读,更多相关《推荐答案.docx(12页珍藏版)》请在冰豆网上搜索。
推荐答案
推荐答案
这是我以前自己写的一个实例,你看一下,课程设计还有一些必须东西你自己加,你用这个参考下
实验的目的就是写一个可以调时间的电子时钟。
它使用七段数码管显示。
我买的单片机开发板上自带有两个四位的数码管。
一般数码管的显示驱动可以有几种方法,直接驱动显示和循环扫描显示这是两种最常用的方法。
用于单片机的IO口只有区区的32个,用直接驱动显示就是很浪费IO口的资源,但是它的电路很容易理解。
我用的板子上的数码管是使用循环扫描法显示的。
每一个四位数码管都有12根引脚。
其中的8根用于输入信号,4根用来做选通用。
循环扫描是利用人眼的视觉误差来达到显示目的的。
它是一位接一位的选通(直接驱动显示就是同时都选通),它的选通频率非常的高,这样人看起来就好像数码管的每一位都同时在亮。
如果一个数码管一秒中亮10次,我们眼睛就可以看到他在闪,如果它一秒亮几万次的话,我们人眼看到的效果就是它一直都在亮而并没有闪。
我第一次写的那个程序就是能够看到数码管在闪,因为我写显示子程序的时候用的延时时间太长了,这样单位时间内选通次数也就减少了,人眼就能看到它在闪了。
通过修改延时,将延时时间缩短,改过之后就看不到他在闪了。
下面是我使用的数码管的逻辑电路图,实际电路图也很简单。
它使用P0口用作输入信号,P2口用于输入选通信号。
数码管是使用共阳接法。
那么低电平就是有效电平。
选通信号可以看出也是低电平有效。
数码管的连接原理也很简单:
每一位数码管的每一段和每一位数码管的小数点按序连接到P0端口,8位数码管都这样连接到P0端口,即每一位数码管的第一段并联在一起后然后再与P0.0相串联。
每一位数码管都有一个选通引脚。
8位数码管就需要8个选通引脚。
上图中的P2.0--P2.7就是都起选通作用。
在写程序的时候就是一位接一位分别选通并且都是通过P0口传送数据。
当有很多位时,可以用一个译码器进行选通这样也能节约IO口资源。
如下所示:
MOVP0,#DATA
CLRP2.0
LCALLDELAY;延时一段时间
循环赋值并依次选通各位数码管
使用共阳接法的数码管在写程序的时候如果使用查表法的时候那个表格数据可以这样定义:
TABLE:
DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
在单片机汇编中,8位的立即数如果高四位的值大于等于A,前面一定要加零,否则在编译的时候就会有错误,提示是你的程序中有一个未定义的符号。
不加零时编译器KEILuvision2将立即数视为符号。
我想这是初学者很容易忽略的一个问题。
在用C编写时十六进制立即数只要在其前面加0X就可以了。
下面将这次实例中我做的源程序列出来,然后一点点分析其中要注意的知识点:
源程序
;************************************************************************
;这是一个单片机时钟程序,RESET后显示12-00-00
;调时方法:
按下S6键后,进入调时设置
;按S3键,可以调整小时
;按S1键,可以调整十分钟位
;按S4键,可以调整分钟位
;按S2键,可以调整十秒位
;按S5键,可以调整秒位
;再次按S6键,退出调时设置
;************************************************************************
SECONDEQU30H;定义显示缓冲区
TSECONDEQU31H
MINUTEEQU32H
TMINUTEEQU33H
HOUREQU34H
TCOUNTEQU35H
ORG0000H;中断向量表
AJMPMAIN
ORG0003H
LJMPINT_X0
ORG000BH
LJMPINT_T0
MAIN:
MOVDPTR,#TABLE;初始化赋值
MOVTCOUNT,#00
MOVSECOND,#00;赋显示初值,显示初始化
MOVTSECOND,#00
MOVMINUTE,#00
MOVTMINUTE,#00
MOVHOUR,#12
MOVTMOD,#01H;定时计数器采用工作方式1
MOVTH0,#0D8H;赋定时初值为10ms
MOVTL0,#0F0H
SETBIT0;使定时计数器0中断和外部中断0使能
SETBTR0
SETBET0
SETBEX0
SETBEA
LOOP:
LCALLDISPLAY
AJMPLOOP
INT_X0:
LCALLDELAY;外部中断0中断服务子程序
JBP3.2,EXIT
JNBP3.2,$
LOOP1:
LCALLDISPLAY
JBP3.2,N1
LCALLDELAY
JNBP3.2,EXIT
N1:
JBP3.3,N2
LCALLDELAY
JBP3.3,N2
INCHOUR
MOVA,HOUR
CJNEA,#24,G1
MOVHOUR,#00
G1:
JNBP3.3,$
N2:
JBP3.4,N3
LCALLDELAY
JBP3.4,N3
INCTMINUTE
MOVA,TMINUTE
CJNEA,#6,G2
MOVTMINUTE,#00
G2:
JNBP3.4,$
N3:
JBP3.5,N4
LCALLDELAY
JBP3.5,N4
INCMINUTE
MOVA,MINUTE
CJNEA,#10,G3
MOVMINUTE,#00
G3:
JNBP3.5,$
N4:
JBP3.6,N5
LCALLDELAY
JBP3.6,N5
INCTSECOND
MOVA,TSECOND
CJNEA,#6,G4
MOVTSECOND,#00
G4:
JNBP3.6,$
N5:
JBP3.7,NEXT
LCALLDELAY
JBP3.7,NEXT
INCSECOND
MOVA,SECOND
CJNEA,#10,G5
MOVSECOND,#00
G5:
JNBP3.7,$
NEXT:
AJMPLOOP1
EXIT:
JNBP3.2,$
RETI
INT_T0:
MOVTH0,#0D8H;定时器T0中断服务程序入口
MOVTL0,#0F0H
INCTCOUNT
MOVA,TCOUNT
CJNEA,#100,EXIT_T0
INCSECOND
MOVTCOUNT,#00
MOVA,SECOND
CJNEA,#10,EXIT_T0
INCTSECOND
MOVSECOND,#00
MOVA,TSECOND
CJNEA,#06,EXIT_T0
INCMINUTE
MOVTSECOND,#00
MOVA,MINUTE
CJNEA,#10,EXIT_T0
INCTMINUTE
MOVMINUTE,#00
MOVA,TMINUTE
CJNEA,#06,EXIT_T0
INCHOUR
MOVTMINUTE,#00
MOVA,HOUR
CJNEA,#24,EXIT_T0
MOVHOUR,#00
EXIT_T0:
RETI
DISPLAY:
;显示子程序,循环扫描显示
MOVA,SECOND
MOVCA,@A+DPTR
MOVP0,A
CLRP2.0
LCALLDELAY
SETBP2.0
MOVA,TSECOND
MOVCA,@A+DPTR
MOVP0,A
CLRP2.1
LCALLDELAY
SETBP2.1
MOVP0,#0BFH
CLRP2.2
LCALLDELAY
SETBP2.2
MOVA,MINUTE
MOVCA,@A+DPTR
MOVP0,A
CLRP2.3
LCALLDELAY
SETBP2.3
MOVA,TMINUTE
MOVCA,@A+DPTR
MOVP0,A
CLRP2.4
LCALLDELAY
SETBP2.4
MOVP0,#0BFH
CLRP2.5
LCALLDELAY
SETBP2.5
MOVA,HOUR
MOVB,#10
DIVAB
MOVCA,@A+DPTR
MOVP0,A
CLRP2.7
LCALLDELAY
SETBP2.7
MOVA,B
MOVCA,@A+DPTR
MOVP0,A
CLRP2.6
LCALLDELAY
SETBP2.6
RET
DELAY:
MOVR7,#02;1MS延时子程序
LOOP0:
MOVR6,#250
DJNZR6,$
DJNZR7,LOOP0
RET
TABLE:
DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
END
一:
按键的识别
我使用的几个按键的逻辑电路图如下:
在程序中使用上图中的6个独立按键,可以很清晰的看明白电路图。
当在检测P3.2--P3.7各个引脚时,当检测到某一个引脚为低电平时,说明与之相连的开关闭合,否则就是断开。
在源程序的外部中断服务子程序中,就是一直在检测各个引脚,如果发现被按下,就开始执行相应的操作。
如果没有按下,就跳去检测下一个引脚是否被按下。
在写关于按键的程序段时,先要了解按键识别的过程是怎样的。
在这个过程中,先要检测按键是否被按下,可以用
如JNBP3.3,NEXT或者其它的指令来检测。
如果被按下就转到NEXT去执行。
在有些时候需要对按键进行滤波,可以加一段延时后在又检测P3.3是否被真的按下。
接着就是等待按下键被如果真的按下,就接着后面执行,否则就跳去检测其它的按键。
NEXT后面一般可以写将要执行的操作,一般是一些功能性操作,如本源程序中,可以对时钟的某一位执行加1操作。
在执行完这个操作后,最后就是用一条指令等待按键的释放,如本程序中的G4:
JNBP3.6,$。
按键从检测是否按下到滤波直到最后等待按键的释放一般都是一个完整的过程。
这个按键识别就是有很多个微小的过程组成的。
我在做这个实例的时候,由于在按键按下后没有写等待按键释放的指令,只是用简单地一段延时程序来代替等待按键的按下,这样做的效果很不好,因为你不知道在按下的一瞬间到底有多长时间,按键按得重一点和轻一点都有很大的区别。
这样做的程序也不实用。
二:
定时计数器的使用
在写关于定时计数器的程序时,可以先了解一下关于定时计数器方面的知识。
51/52单片机一般内部有2/3个16位的定时计数器。
每个定时计数器也可以通过设置TMOD模式寄存器将它作为两个8位的定时计数器使用,依据实际情况来设置。
定时其实就是对单片机的时钟脉冲进行计数,每个时钟脉冲都有一个固定的周期。
当计数到一个机器周期时,定时计数值就会加一,当计数满或溢出时,此时TF0或TF1就会被置1,这时就要对TF0或TF1清0,如当选用工作方式1时就要用软件进行清0,当选用外部中断时,硬件会自动将TF0或TF1清0,其它方式下到底是硬清0还是软清0可以查一下,我也不记得了。
由于定时器/计数器的功能是由软件编程确定的,所以一般在使用定时/计数器前都要对其进行初始化,使其按设定的功能工作。
初始货的步骤一般如下:
1、确定工作方式(即对TMOD赋值);
2、预置定时或计数的初值(可直接将初值写入TH0、TL0或TH1、TL1);
3、根据需要开放定时器/计数器的中断(直接对IE位赋值);
4、启动定时器/计数器(若已规定用软件启动,则可把TR0或TR1置“1”;若已规定由外中断引脚电平启动,则需给外引脚步加启动电平。
当实现了启动要求后,定时器即按规定的工作方式和初值开始计数或定时)。
TMOD不能用位寻址,而TCON可以位寻址。
如何设置定时计数器的初值:
定时初值=65536-定时值
例如要定时50ms,定时初值就要设置为65536-50000=15536
即定时计数器从15536开始计数,当记到65536时,单片机就会将TF0或TF1置1,这个过程中就计数了50000个机器周期,当晶振为12MHZ时,一个机器周期就是1us,50000个机器周期就是50ms。
通过软件计数TF0或TF1被置了多少次的1,通过循环就可以定时你想要的时间。
三:
单片机的中断
一般的51单片机有5个中断源。
我对中断源的理解就是可以引起单片机停止当前正在执行的工作的一个外部事件。
一般在存储器的最前面的单元放置的是中断向量表,中断向量表里有可以跳到相应子程序的跳转指令。
这些中断向量一般放置在固定的地址,当有中断产生时,单片机就会调用中断向量,并转到相应的子程序里面去执行。
这些中断源一般包括两个定时计数器中断,两个外部中断,还有一个全双工的串口中断。
在我这次做的程序中,就使用了一个定时计数0中断和一个外部中断。
要使用中断肯定就是先要开中断,先可以开总中断,SETBEA,然后再开具体的中断,如SETBTR0等。
五个中断源的自然优先级与中断服务入口地址
外中断0:
0003H
定时器0:
000BH
外中断1:
0013H
定时器1:
001BH
串口:
0023H
中断中有两个优先级,高优先级和低优先级。
如果几个中断源都是同一优先级,此时因由自然优先级决定它们的执行顺序。
MCS51工作时,在每个机器周期中都会去查询一下各个中断标记,看他们是否是“1“,如果是1,就说明有中断请求了,所以所谓中断,其实也是查询,不过是每个周期都查一下而已
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 推荐 答案