如何用单片机汇编语言设计一个秒表
设计一个秒表,需要考虑以下因素:
1、因为视觉暂留的因素,一般而言到0.1秒的精度就可以了。
2、需要有按键控制启动、停止、清零这些功能。
KEYVAL EQU 30H
DAT EQU 33H
SCANLED EQU 39H
CLK EQU 77H
SEC EQU 78H
SEC1 EQU 79H
SEC2 EQU 7AH
DOT BIT 00H
ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EXTINT0
ORG 000BH
LJMP T0ISR 50ms定时
ORG 001BH
LJMP T1ISR 扫描显示
ORG 0030H
MAIN:
MOV SP,#5FH
MOV TMOD,#11H
MOV TH0,#03CH
MOV TL0,#0B0H
MOV TH1,#0ECH
MOV TL1,#078H
MOV KEYVAL,#2
MOV 33H,#10H
MOV 34H,#10H
MOV 35H,#10H
MOV 36H,#10H
MOV CLK,#0
SETB IT0
SETB EX0
CLR TR0
CLR ET0
MOV R2,#0
SETB TR1
SETB ET1
SETB EA
LOOP:
MOV A,KEYVAL
LOOP1:
JNZ LOOP2 启动
SETB TR0
SETB ET0
SJMP LOOP
LOOP2:
DEC A
JNZ LOOP3 暂停
CLR TR0
CLR ET0
SJMP LOOP
LOOP3:
DEC A
JNZ LOOP 清零
MOV 36H,#0
MOV 35H,#0
MOV 34H,#0
MOV 33H,#0
SJMP LOOP
EXTINT0:
PUSH ACC
INC KEYVAL
MOV A,KEYVAL
CJNE A,#3,EXT00
EXT00:
JC EXT01
MOV KEYVAL,#0
EXT01:
POP ACC
RETI
T0ISR:
PUSH ACC
CLR TR0
MOV TH0,#3CH
MOV TL0,#0B0H
SETB TR0
INC CLK
MOV A,CLK
CJNE A,#2,T0ISRE
MOV CLK,#0
INC 36H
MOV A,36H
CJNE A,#10,T0ISRE
MOV 36H,#0
INC 35H
MOV A,35H
CJNE A,#10,T0ISRE
MOV 35H,#0
INC 34H
MOV A,34H
CJNE A,#6,T0ISRE
MOV 34H,#0
INC 33H
MOV A,33H
CJNE A,#10,T0ISRE
MOV 33H,#0
T0ISRE:
POP ACC
RETI
T1ISR:
PUSH ACC
CLR TR1
MOV TH1,#0ECH
MOV TL1,#78H
SETB TR1
MOV DPTR,#LEDTAB
T100:
MOV R0,#DAT
MOV A,SCANLED
ADD A,R0
MOV R0,A
MOV A,SCANLED
JNZ T101
MOV P2,#01H
SETB DOT
SJMP T1DIS
T101:
DEC A
JNZ T102
MOV P2,#02H
CLR DOT
SJMP T1DIS
T102:
DEC A
JNZ T103
MOV P2,#04H
SETB DOT
SJMP T1DIS
T103:
MOV P2,#08H
CLR DOT
T1DIS:
MOV A,@R0
MOVC A,@A+DPTR
JNB DOT,T1DIS1
ORL A,#01H
T1DIS1:
CPL A
MOV P0,A
INC SCANLED
MOV A,SCANLED
CJNE A,#4,T1END
MOV SCANLED,#0
T1END:
POP ACC
RETI
LEDTAB: DB 0FCH "0" 00H
DB 60H "1" 01H
DB 0DAH "2" 02H
DB 0F2H "3" 03H
DB 66H "4" 04H
DB 0B6H "5" 05H
DB 0BEH "6" 06H
DB 0E0H "7" 07H
DB 0FEH "8" 08H
DB 0F6H "9" 09H
DB 0EEH "A" 0AH
DB 3EH "B" 0BH
DB 9CH "C" 0CH
DB 7AH "D" 0DH
DB 9EH "E" 0EH
DB 8EH "F" 0FH
DB 00H " " 10H
END
原理图如下,
程序如下:
=================================================
寄存器分配定义
=================================================
LED_BUF EQU 50H 显示数据首址
COUNTER_INT EQU 3BH 中断计数器
SECOND EQU 3DH 秒单元
=================================================
常数定义
=================================================
CN_COUNT_INT EQU 100 10ms * 100 = 1S
SET_MODEL EQU 0FFH 完全译码模式
SET_BRIGHT EQU 04H 占空比为15/32显示亮度
SET_LIMIT EQU 01H 2位显示方式
SET_NORMAL EQU 01H 测试模式
SET_START EQU 01H 进入启动工作方式?
=================================================
管脚分配定义
=================================================
m7219_DIN BIT P3.0
m7219_LOAD BIT P3.1
m7219_CLK BIT P3.2
KEYSTART BIT P1.0
KEYRESET BIT P1.1
============================================
模拟主程序
===========================================
org 0000h
ajmp main
ORG 000BH
LJMP Timer0Interrupt
org 0030h
main:
mov sp,#70h
lcall Init_M7219
lcall InitTimer0
MOV SECOND,#95H TEST
Loop:
CALL disp
key_reset:
SETB KEYRESET
JB KEYRESET,key_start
DELAY
NOP
NOP
NOP
JB KEYRESET,key_start
JNB KEYRESET,$
CLR TR0
MOV A,#0
MOV SECOND,A
MOV led_buf,A
MOV LED_BUF+1,A
JMP key_SCAN_END
key_start:
SETB KEYSTART
JB KEYSTART,key_SCAN_END
DELAY
NOP
NOP
NOP
JB KEYSTART,key_SCAN_END
JNB KEYSTART,$
SETB TR0
key_SCAN_END:
JMP loop
===========================================
InitTimer0:10ms一次中断
MOV TMOD,#01H
MOV TH0,#0D8H
MOV TL0,#0F0H
SETB EA
SETB ET0
RET
===========================================
Timer0Interrupt:
PUSH DPH
PUSH DPL
PUSH ACC
MOV TH0,#0D8H
MOV TL0,#0F0H
========================
INC COUNTER_INT
MOV A,COUNTER_INT 10ms 计数值加1
CJNE A,#CN_COUNT_INT,Timer0Interrupt_EXIT
MOV COUNTER_INT,#0
MOV A,SECOND
CJNE A,#99H,Timer0Int_sec
CLR TR0关闭计时
JMP Timer0Interrupt_EXIT
Timer0Int_sec:
ADD A,#01 秒加1
DA A
MOV SECOND,A
SWAP A
ANL A,#0fH
MOV led_buf,A
MOV A,SECOND
ANL A,#0FH
MOV LED_BUF+1,A
========================
Timer0Interrupt_EXIT:
POP ACC
POP DPL
POP DPH
RETI
====================================================
function:Init_M7219 初始化max719
input: ------------
output: ----------
usage: a,b
====================================================
Init_M7219: 初始化Max7219
MOV a,#0bh 设置扫描界限
MOV b,#set_limit 设置位数
lcall w_7219
MOV a,#09h 设置译码模式
MOV b,#set_model 00h非译码模式ffh为BCD译码模式
lcall w_7219
MOV a,#0ah 设置亮度
MOV b,#set_bright 15/32亮度
lcall w_7219
MOV a,#0fh 设置工作方式
MOV b,#set_normal 正常工作方式
lcall w_7219
MOV a,#0ch 进入启动工作方式
MOV b,#set_start
lcall w_7219
RET
===================================================
function:disp 显示子程序
input: r0
output: -----------
usage: r0,r3,r4,a,b
===================================================
disp:
MOV r0,#led_buf
MOV r4,#01h
MOV r3,#set_limit
INC r3
disp1:
MOV a,@r0
MOV b,a
MOV a,r4
lcall w_7219
INC r0
INC r4
djnz r3,disp1
RET
===================================================
function:w_7219 显示驱动程序
input: a 传送7219的地址
b 传送7219的数据
output:-------------
usage: a,r2
====================================================
w_7219:
CLR M7219_clk
CLR M7219_din
CLR M7219_load 置load=0
lcall sd_7219 传送7219的地址
MOV a,b
lcall sd_7219 传送数据
setb M7219_load 数据装载
CLR M7219_din
RET
=================================================
function:sd_7219 向7219传送数据或地址子程序
input: a
output: max7219
usage: a, r2
==================================================
sd_7219: 向7219送地址或数据
MOV r2,#08h
c_sd:
CLR C
CLR M7219_clk
RLC a
MOV M7219_din,c 准备数据
NOP
setb M7219_clk 上升沿将数据传入
NOP
NOP
CLR M7219_clk
djnz r2,c_sd
RET
END
#include <reg51.H>
sbit P3_5 =P3^5
unsigned char code dispcode[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x00}
unsigned char second
unsigned char keycnt
unsigned int tcnt
void main(void)
{
unsigned char i,j
TMOD=0x02
ET0=1
EA=1
second=0
P1=dispcode[second/10]
P2=dispcode[second%10]
while(1)
{
if(P3_5==0)
{
for(i=20i>0i--)
for(j=248j>0j--)
if(P3_5==0)
{
keycnt++
switch(keycnt)
{
case 1:
TH0=0x06
TL0=0x06
TR0=1
break
case 2:
TR0=0
break
case 3:
keycnt=0
second=0
P1=dispcode[second/10]
P2=dispcode[second%10]
break
}
while(P3_5==0)
}
}
}
}
void t0(void) interrupt 1 using 0
{
tcnt++
if(tcnt==4000)
{
tcnt=0
second++
if(second==100)
{
second=0
}
P1=dispcode[second/10]
P2=dispcode[second%10]
}
}
数字电子技术基础
课程设计
电子秒表
一.设计目的:
1、了解计时器主体电路的组成及工作原理
2、熟悉集成电路及有关电子元器件的使用
3、学习数字电路中基本RS触发器、时钟发生器及计数、译码显示等单元电路的综合应用。
二.设计任务及说明:
电子秒表电路是一块独立构成的记时集成电路芯片。它集成了计数器、、振荡器、译码器和驱动等电路,能够对秒以下时间单位进行精确记时,具有清零、启动计时、暂停计时及继续计时等控制功能。
设计一个可以满足以下要求的简易秒表
1.秒表由5位七段LED显示器显示,其中一位显示“min”,四位显示“s”,其中显示分辩率为0.01 s,计时范围是0—9分59秒99毫秒;
2.具有清零、启动计时、暂停计时及继续计时等控制功能;
3.控制开关为两个:启动(继续)/暂停记时开关和复位开关
三.总体方案及原理:
电子秒表要求能够对时间进行精确记时并显示出来,因此要有时钟发生器,记数及译码显示,控制等模块,系统框图如下:
时钟发生器 记数器 译码器
显示器
控制器
图1.系统框图
其中:
(1)时钟发生器:利用石英震荡555定时器构成的多谐振荡器做时钟源,产生100HZ的脉冲
(2)记数器:对时钟信号进行记数并进位,毫秒和秒之间10进制,秒和分之间60进制
(3)译码器:对脉冲记数进行译码输出到显示单元中;
(4)显示器:采用5片LED显示器把各位的数值显示出来,是秒表最终的输出,有分、秒、和毫秒位;
(5)控制器:控制电路是对秒表的工作状态(记时开始/暂停/继续/复位等)进行控制的单元,可由触发器和开关组成。
四.单元电路设计,参数计算和器件选择:
1.时钟发生单元
时钟发生器可以采用石英晶体震荡产生100HZ时钟信号,也可以用555定时器构成的多谐振荡器,555定时器是一种性能较好的时钟源,切构造简单,采用555定时器构成的多谐振荡器做为电子秒表的输入脉冲源。
因输出要求为100HZ的,选择占空比为55%,可根据
T=( )Cln2=0.01
可选择的电阻进行连接可在输出端3获得频率为100HZ的矩形波信号,即T=0.01S的时钟源,当基本RS触发器Q=1时,门5开启,此时100HZ脉冲信号通过门5作为计数脉冲加于计数器①的计数输入端CP2。
图2.时钟发生器555定时器构成的多谐振荡器
2.记数单元
记数器74160、74ls192、74ls90等都能实现十进制记数,本设计采用二—五—十进制加法计数器74LS90构成电子秒表的计数单元,如图3所示,555定时器构成的多谐振荡器作为计数器①的时钟输入。计数器①及计数器②接成8421码十进制形式,其输出端与实验装置上译码显示单元的相应输入端连接,可显示0.01~0.09秒;0.1~0.9秒计时,计数器②及计数器③,计数器③和计数器④也接成8421码十进制形式,计数器④和计数器⑤接成60进制的形式,实现秒对分的进位。
集成异步计数器74LS90简介
74LS90是异步二—五—十进制加法计数器,它既可以作二进制加法计数器,又可以作五进制和十进制加法计数器。
图3为74LS90引脚排列,表1为功能表。
通过不同的连接方式,74LS90可以实现四种不同的逻辑功能;而且还可借助R0(1)、R0(2)对计数器清零,借助S9(1)、S9(2)将计数器置9。其具体功能详述如下:
(1)计数脉冲从CP1输入,QA作为输出端,为二进制计数器。
(2)计数脉冲从CP2输入,QDQCQB作为输出端,为异步五进制加法计数器。
(3)若将CP2和QA相连,计数脉冲由CP1输入,QD、QC、QB、QA作为输出端,
则构成异步8421码十进制加法计数器。
(4)若将CP1与QD相连,计数脉冲由CP2输入,QA、QD、QC、QB作为输出端,
则构成异步5421码十进制加法计数器。
(5)清零、置9功能。
a) 异步清零
当R0(1)、R0(2)均为“1”;S9(1)、S9(2)中有“0”时,实现异步清零功能,即QDQCQBQA=0000。
b) 置9功能
当S9(1)、S9(2)均为“1”;R0(1)、R0(2)中有“0”时,实现置9功能,即QDQCQBQA=1001。
图3.74LS90引脚排列(下)
输 入 输 出 功 能
清 0 置 9 时 钟 QD QC QB QA
R0(1)、R0(2) S9(1)、S9(2) CP1 CP2
1 1 0
× ×
0 × × 0 0 0 0 清 0
0
× ×
0 1 1 × × 1 0 0 1 置 9
0 ×
× 0 0 ×
× 0 ↓ 1 QA 输 出 二进制计数
1 ↓ QDQCQB输出 五进制计数
↓ QA QDQCQBQA输出8421BCD码 十进制计数
QD ↓ QAQDQCQB输出5421BCD码 十进制计数
1 1 不 变 保 持
表1 .74LS90功能表
10秒到分位的6进制位可在十进制的基础上将QB、QC连接到一个与门,它的置零信号与系统的置零信号通过一个或门连接接至R0(1),即当记数为6或有置零信号是均置零,如图4所示。
图4 .74ls90组成的6进制记数器
3 .译码显示单元
74LS248(74LS48)是BCD码到七段码的显示译码器,它可以直接驱动共阴极数码管。它的管脚图如图5所示. 显示器用 LC5011-11 共阴极LED显示器.(注:在multisim中仿真可以用译码显示器DCD_HEX代替译码和显示单元)。
图5. 74LS248管脚图
4 .控制单元
(1) 启动(继续)/暂停记时开关
采用集成与非门构成的基本RS触发器。属低电平直接触发的触发器,有直接置位、复位的功能。
它的一路输出作为单稳态触发器的输入,另一路输出Q作为与非门5的输入控制信号。
按动按钮开关B(接地),则门1输出 =1;门2输出Q=0,K2复位后Q、状态保持不变。再按动按钮开关K1 ,则Q由0变为1,门5开启, 为计数器启动作好准备。由1变0,送出负脉冲,启动单稳态触发器工作。
(2) 清零开关
通过开关对每个计数器的R0(2)给以高电平能实现系统的清零。
五:在MULTISIM中进行仿真
将各个芯片在MULTISIM8中连接并进行仿真,仿真如图6所示,结果正确。
六:设计所需元件
555触发器一片,74ls90五片,74ls248五片,LC5011-11 共阴极LED显示器五片,
电容、电阻若干。
七:设计心得
本次课程设计对数字电子技术有了更进一步的熟悉,实际操作和课本上的知识有很大联系,但又高于课本,一个看似很简单的电路,要动手把它设计出来就比较困难了,因为是设计要求我们在以后的学习中注意这一点,要把课本上所学到的知识和实际联系起来,同时通过本次电路的设计,不但巩固了所学知识,也使我们把理论与实践从真正意义上结合起来,增强了学习的兴趣,考验了我们借助互联网络搜集、查阅相关文献资料,和组织材料的综合能力。
参考资料:http://blog.sina.com.cn/gaowentao
S3 BIT P2.6
S2 BIT P2.5
S1 BIT P2.4
CLK BIT P0.0
DAT BIT P0.1
STR BIT P0.2
BUF BIT P1.0
ORG 0000H
AJMP MAIN
ORG 0003H
AJMP LOOP
ORG 000BH
AJMP L2
ORG 0100H
MAIN:
MOV IE,#83H
MOV TCON,#01H
MOV TMOD,#51H
MOV TH0,#0DCH
MOV TL0,#010H
MOV R0,#0
mov R3,#0
MOV R1,#0
MOV 51H,#0
L4:判断中断计数的标志位,作相应的动作
CJNE R1,#1,T4
SETB BUF
ACALL L8
CLR BUF
SETB TR0
T4:
CJNE R1,#2,T2
SETB BUF
ACALL L8
CLR TR0
T2:
CJNE R1,#3,T3
CLR BUF
ACALL L8
MOV R1,#0
MOV R0,#0
MOV R3,#0
T3:数据输出,四位输出
MOV A,R0
MOV B,#10
DIV AB
MOV R6,A
MOV A,B
SETB S2
SETB S1
SETB S3
CLR S4
ACALL L7
ACALL L8
MOV A,R6
SETB S4
CLR S3
ACALL L7
ACALL L8
MOV A,R3
MOV B,#10
DIV AB
MOV R4,A
MOV A,B
SETB S3
CLR S2
ACALL L7
ACALL L8
MOV A,R4
SETB S2
CLR S1
ACALL L7
ACALL L8
AJMP L4
L7:按位取数据输出
MOV DPTR,#TAB
MOVC A,@A+DPTR
CPL A
L5:MOV R7,#8
CLR STR
L6:8位数据的输出
RRC A
MOV DAT,C
NOP
CLR CLK
NOP
NOP
SETB CLK
DJNZ R7,L6
SETB STR
CLR STR
RET
L8:MOV R7,#50 延迟函数50.50
dip:MOV R5,#50
DJNZ R5,$等待中断
DJNZ R7, DIP
RET
L2:定时中断
INC R0
CJNE R0,#99,L3
MOV R0,#0
INC R3
CJNE R3,#60,L3
MOV R3,#0
L3:付值语句
MOV TH0,#0DCH定时初值
MOV TL0,#010H定时初值
RETI返回函数
LOOP:外部中断程序
INC R1
RETI返回主函数
TAB: DB 0F5H,05H,0E3H,67H,17H,76H,0F6H,25H
DB 0F7H,77H
END
//12M晶振。6位共阴数码管,P0 段码,P2.0~P2.5 位控
//显示 00.00.00 最小为0.01s ,
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit P20=P2^0
sbit P21=P2^1
sbit P22=P2^2
sbit P23=P2^3
sbit P24=P2^4
sbit P25=P2^5
sbit P07=P0^7
sbit P05=P0^5
sbit KS=P1^0 //开始/暂停
sbit KC=P1^1 //清零
uchar time,xs2,xs,ge,shi,bai,qian
uchar code tab[ ]= {
0x3F,
0x06,
0x5B,
0x4F,
0x66,
0x6D,
0x7D,
0x07,
0x7F,
0x6F,
}
void delay_ms(uint ms) //1ms延时
{
uchar a
while(ms--)
for(a=123a>0a--)
}
void display()
void t0intinit( ) //定时器T0
{
TMOD=0x01
TH0=(65536-10000)/256 //10ms定时
TL0=(65536-10000)%256
EA=1
ET0=1
}
void main()
{
t0intinit( )
while(1)
{
display( )
while(!KS) //开始键
{
display( )
if(KS)
TR0=!TR0
}
while(!KC) //清零键
{
display( )
if(KC)
TR0=0
qian=0
bai=0
shi=0
ge=0
xs=0
xs2=0
}
if(ge==10)
{
ge=0
shi++
}
if(shi==6)
{
shi=0
bai++
}
if(bai==10)
{
bai=0
qian++
}
if(qian==6)
qian=0
}
}
void display( )
{
P25=0
P0=tab[xs2]
delay_ms(1)
P25=1
P24=0
P0=tab[xs]
delay_ms(1)
P24=1
P23=0
P0=tab[ge]
P07=1
delay_ms(1)
P23=1
P22=0
P0=tab[shi]
delay_ms(1)
P22=1
P21=0
P0=tab[bai]
P07=1
delay_ms(1)
P21=1
P20=0
P0=tab[qian]
delay_ms(1)
P20=1
}
void T0int( ) interrupt 1 //定时器T0中断 方式1
{
TH0=(65536-10000)/256 //10ms定时
TL0=(65536-10000)%256
xs2++
if(xs2==10)
{
xs2=0
xs++
}
if(xs==10)
{
xs=0
ge++
}
}