欢迎来到学术参考网

免电源的电话使用计时器

发布时间:2015-07-07 09:36
前言:
在通讯沟通频繁的今日,相信家家户户都有一台以上的电话机,您家必定发生过打完电话后未挂好而造成电话无法打进的困扰吧。或者您的家人或同事或朋友打电话一打就打了许久又不自知吧。


下面为您介绍一款diy制作「免电源电话使用计时器」供您避免上述现象之产生,总共才用了12个元件(单片机1个,led七字显示数码管2个,电容3个,电阻1个,桥式整流子1个,电感1个,石英晶体1个,稳压二极管1个,按键1个),相信只需要20多元及1个休息日即可组装完成做出一个前所未有的趣味电子产品了。


 特点说明:
diy制作基本上要有着三个特点:
一看就懂:指电路简单明了。
一买就有:指电路容易取得。
一做就成:指制作成功率高。
当您看完本篇文章之后一定会有种跃跃欲试的感觉,那么请跟着感觉走是不会错的。整个diy制作虽然小小的,不过特点倒是挺多项。
免用外部电源,整个diy电子产品是利用电话线电压来工作的,故可免除许多烦人的事(指怕停电,浪费电,体积大,成本高,配线难),在使用上没有任何不适的感觉,也不须担心电信局测试。
对通话品质无影响,所谓的无影响其实有着二个含意,一为无杂讯干扰,一为通话音量不增减。大家都知道多位数的led七段显示得用扫描方式,如此一来会有脉冲电流杂讯产生,这点对听觉灵敏的耳朵而言是不可忽视的。另外整个电路的ac阻抗得非常的低,以免除声音的衰减。针对这二个要求,这里介绍一个简单又实用的电源取得电路供您参考。
led七段显示,非常适合夜晚来使用,同时由于亮度很够,即使在白天也是清清楚楚,这点就是lcd显示望尘莫及的。
led显示不但能做使用时间的显示之外,也能表示电话线正被使用中,故可当未挂好话筒之提醒指示之用。
led显示采用最省元件的互补式,即一个led七段显示器为共阴,另一为共阳,如此即可直接用单片机四个i/o直接推动而得到最高亮度了。
利用otp型单片机em78p156来做核心控制,整个程序小小的,若您想更改或增加功能都是非常容易的。


 功能说明:
当您的电话使用后没有放置好,或者是打电话聊长天的时候给您显示通话使用时间给予心理压力。基本上可算是有提醒指示及显示二大功能。


 提醒指示:
只要led七段显示器点亮则表示电话线正被使用,此时不是您正在打电话就是话筒未被放置好。


 显示:
只要话筒一被拿起,电话回路被建立后单片机开始做计时及显示动作,以分为单位,最大可显示99分,之后又从0开始。若您要有精准的计时时可在电话通之后按clr键,此时单片机清除计数从新开始计数显示。


 线路图:


图1线路说明:

g of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
dl == 0x10 ;delay loop
min == 0x11 ;minute
sec == 0x12 ;second
dd == 0x13 ;display digit
ddh == 0x14 ;display digit high
ab == 0x15 ;a back_up
rfb == 0x16 ;rf back_up
org 0
0000 jmp init ;program start
org 8
;tcc interrupt---------------------------------------------
tcci:
0008 mov ab,a ;ab <- a
0009 swap ab ;ab <- ba
000a swapa rf
000b mov rfb,a ;rfb<- fr
000c inc sec
check:
000d mov a,sec
000e sub a,@59 ;59-sec=a
000f jbc rf,fc
0010 jmp c_min
0011 clr sec
0012 inc min
c_min:
0013 mov a,min
0014 sub a,@99 ;99-min=a
0015 jbs rf,fc
0016 clr min
tcce:
0017 swapa rfb
0018 mov rf,a ;rf<- rfb
0019 swapa ab ;a <- ba
001a bc 0x0f,0 ;clear tcc_int
001b reti
;table 7 segement------------------------------------------------------
t7:
001c add pc,a ; gfe dcba
001d retl @0b01000000 ;0 0100 0000
001e retl @0b01111001 ;1 0111 1001
001f retl @0b00100100 ;2 0010 0100
0020 retl @0b00110000 ;3 0011 0000
0021 retl @0b00011001 ;4 0001 1001
0022 retl @0b00010010 ;5 0001 0010
0023 retl @0b00000010 ;6 0000 0010
0024 retl @0b01011000 ;7 0101 1000
0025 retl @0b00000000 ;8 0000 0000
0026 retl @0b00010000 ;9 0001 0000
;delay ------------------------------------------------------------------------
delay:
0027 mov p5,a
0028 mov a,@20
0029 mov dl,a
d_1:
002a djz dl
002b jmp d_1
002c mov a,@0xff
002d iow p6
002e ret
;init ------------------------------------------------------------------------------
init:
002f mov a,@0x00
0030 mov min,a
0031 mov sec,a
0032 iow 0x0e ;disable wdt
0033 iow p5 ;port 5 output
0034 iow p6 ;port 6 output
0035 mov a,@0x01
0036 iow 0x0f ;enable tcc_int
0037 mov a,@0x05 ;1/64
0038 contw
0039 eni
;scan ---------------------------------------------------------------------------
scan:
003a mov a,min
htd:
003b clr ddh
h_h:
003c add a,@246 ;a=a-10
003d jbs rf,fc
003e jmp h_l
003f inc ddh
0040 jmp h_h
h_l:
0041 add a,@10
0042 call t7
0043 iow p6
0044 mov p6,a
0045 mov a,@255 ;display digit 0
0046 call delay
0047 mov a,ddh
0048 call t7
0049 iow p6
004a xor a,@0xff
004b mov p6,a
004c mov a,@00 ;display digit 1
004d call delay
004e jmp scan
程序说明:
程序就像日常说话一样,只要能够表达清楚意思,那么,愈短愈受人欢迎(当然得在保证有正常功能的情况下而言)。此次diy制作的软件程序长度仅有78个指令,够短了吧,相信看懂也不难。整个程序可以分成5个段落来做说明,寄存器使用说明:
dl ----- 子程序用寄存器
min ----- 存放分钟资料寄存器
sec ----- 存放秒钟资料寄存器
dd ----- 存放显示位数资料寄存器
ddh ----- 存放显示资料寄存器
ab ----- 存放acc的副本
rfb ----- 存放status的副本
tcc中断子程序:
从0000--001b行为每秒发生一次的tcc中断子程序,其中0008--000b及0017--0019行为进入及离开中断子程序的acc及status保留动作。其中000c为每进入一次中断子程序就将sec这寄存器予以进位。其中000d--0012为判断sec寄存

器是否大于59,是则将min寄存器予以进位并清除sec寄存器。其中0013--0016为判断min寄存器是否大于99,是则将min寄存器予以清除,其中001a为清除tcc中断旗标。
led字型转换程序:
从001c--0026行存放了字型转换表,可将0--9的数字转成相对的led七字显示器的资料。
显示时间长度延迟程序:
从0028--002b延迟程序,而0027及002c--002d为启动显示及关掉显示之指令。
微控制器启始设定程序:
从002f--0039行对微控制器内部相关硬件做了必要性的设定动作。值得特别一提的是0035--0039行对tcc中断记数器予以设定成每秒中断一次。计算式如下:
系统时基/(2周期模式×1秒×256进位)而得预除数为64。
七字显示器扫描主程序:
从003a--004e行为本软件程序之主程序部份,又可分三部份。003c--0040行为取得min的拾位数之值。0042--0046行显示min的个位数资料到共阳极的led七字显示器上。0047--004d行为显示min的拾位数资料到共阴极的led七字显示器上。希望这短短的程序难不倒您才是。

程序撰写步骤:
许多人习惯上撰写程序的过程是依照「先小而大」,「先难后繁」,「边测边写」等三项原则来从事的,底下便将电话使用计时器程序分成八个段落来完成。
1.先给予心跳:

一般撰写程序碰到计时的工作时不外乎三个方式来解决:

「用timer计数器来产生中断来计时」「用polling timer计数器来计时」
「用计算程序指令个数来计时」
这三个方式中以方式一最为简单也最为准确,故这里打算最重要之秒的进位问题就交给timer计数器中断方式来解决了。

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
org 0
0000 jmp init ;program start
org 8
;tcc interrupt-------------------------------------------------------
tcci:
0008 com p6
tcce:
0009 bc 0x0f,0 ;clear tcc_int
000a reti
;init -------------------------------------------------------------------------
init:
000b mov a,@0x00
000c mov p6,a ;port 6 = 0
000d iow 0x0e ;disable wdt
000e iow p5 ;port 5 output
000f iow p6 ;port 6 output
0010 mov a,@0x01
0011 iow 0x0f ;enable tcc_int
0012 mov a,@0x05 ;1/64
0013 contw
0014 eni
;scan -----------------------------------------------------------------------
scan:
0015 jmp scan
这程序的目的是欲了解tcc中断能否满足秒的进位问题。
程序说明:
中断子程序:
从0008--000a行为简单的中断子程序,每做一次就将port6反向一次,离开前顺便清除中断flag。
微控制器起始设定程序:
起始设定是每个程序一开始必须做的,主要功能是将一些会用到的硬件部份做一起始状态的设定以发挥充分的掌控能力。
从000b~0013行为起始设定程序
000b mov a, @0x00 ;将a内放置零
000c mov p6, a ;将p6内放置零
000d iow 0x0e ;将wdt功能除能
000e iow p5 ;将p5设为output
000f iow p6 ;将p6设为output
在em78系列中有所谓的memory及i/o两大空间,一些memory空间的寄存器处理时可用mov、bs、bc、xor、or……等指令,而另一些i/o空间的控制寄存器处理时可用iow、ior等指令,这点不要弄混了才是。
0010 mov a, @0x01 ;将a内放置1
0011 iow 0x0f ;仅致能tcc中断能力
在em78156中原本能有wdt中断、外部中断及tcc中断等三种能力,如今我们只保留tcc中断来使用。
0012 mov a, @0x05 ;将a内放置5
0013 contw ;设定tcc控制寄存器
0014 eni ;启动中断能力
tcc是一个很好用也很复杂的硬件线路,下面仅列出局部有关的地方于附录供大家参考。由于系统时基是采用32768hz的石英晶体,故本制作之准确度应该不被怀疑才是。当选用2 cycle及2 clock的状态时,若再将tcc设成除以64,那刚好每一秒钟tcc发生溢位中断一次。
扫描程序:
从0015--0015行,总共1行,仅做跳跃自身之用。
效果观察:
程序写到此时,倘若您手上的线路没焊错的话,那么您将会看到七字显示屏幕显示8并且以1秒亮1秒灭的速度亮灭着。
到此总共用315个指令,恭喜您的宝宝已经有心跳产生了。
2.具有七段显示能力:

有了秒的心跳之后,接下来就是加强扫描能力,使它有着正确的显示数字的能力。

;

; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
pc == 02
rf == 03 ;status
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
sec == 0x10 ;second
org 0
0000 jmp init ;program start
org 8
;tcc interrupt----------------------------------------------
tcci:
0008 inc sec
tcce:
0009 bc 0x0f,0 ;clear tcc_int
000a reti
;table 7 segement-------------------------------------------
t7:
000b add pc,a ; gfe dcba
000c retl @0b01000000 ;0 0100 0000
000d retl @0b01111001 ;1 0111 1001
000e retl @0b00100100 ;2 0010 0100
000f retl @0b00110000 ;3 0011 0000
0010 retl @0b00011001 ;4 0001 1001
0011 retl @0b00010010 ;5 0001 0010
0012 retl @0b00000010 ;6 0000 0010
0013 retl @0b01011000 ;7 0101 1000
0014 retl @0b00000000 ;8 0000 0000
0015 retl @0b00010000 ;9 0001 0000
;init -----------------------------------------------------------------
init:
0016 mov a,@0x00
0017 mov sec,a
0018 iow 0x0e ;disable wdt
0019 iow p5 ;port 5 output
001a iow p6 port 6 output
001b mov a,@0x01
001c iow 0x0f ;enable tcc_int
001d mov a,@0x05 ;1/64
001e contw
001f eni
;scan ---------------------------------------------------------------
scan:
0020 mov a,sec
0021 call t7
0022 iow p6
0023 mov p6,a
0024 mov a,@255 ;display digit 0
0025 mov p5,a
0026 jmp scan
整个程序与最大的差异就是增加了sec计数的显示能力,故有三处改动:
中断子程序中有了inc sec指令来做每秒进位的动作。
增加了led显示屏幕七段转换表,从000b--0015行即为0到9的转换表。
扫描程序功能加强:
从0020--0026行所做之事为重覆的将sec数字经过查表后丢到p6上。为了方便了解,此时仅对数字0有做显示动作。
效果观察:
程序到此时您会看到个位数的七字显示屏幕从0→9每秒进位一次。到9以后程序将会错乱(?why?)。
3.具有二位数的显示能力:

能够做七段显示之后,各位最想看到的当然是二位数字的显示了,由于这里采用一共阴、一共阳的七段显示器,故处理起来还得稍费脑筋。

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
pc == 02
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
sec == 0x10 ;second
org 0
0000 jmp init ;program start
org 8
;tcc interrupt-------------------------------------------------
tcci:
0008 inc sec
tcce:
0009 bc 0x0f,0 ;clear tcc_int
000a reti
;table 7 segement-----------------------------------------
t7:
000b add pc,a ; gfe dcba
000c retl @0b01000000 ;0 0100 0000
000d retl @0b01111001 ;1 0111 1001
000e retl @0b00100100 ;2 0010 0100
000f retl @0b00110000 ;3 0011 0000
0010 retl @0b00011001 ;4 0001 1001
0011 retl @0b00010010 ;5 0001 0010
0012 retl @0b00000010 ;6 0000 0010
0013 retl @0b01011000 ;7 0101 1000
0014 retl @0b00000000 ;8 00

00 0000
0015 retl @0b00010000 ;9 0001 0000
;init -----------------------------------------------------------------
init:
0016 mov a,@0x00
0017 mov sec,a
0018 iow 0x0e ;disable wdt
0019 iow p5 ;port 5 output
001a iow p6 ;port 6 output
001b mov a,@0x01
001c iow 0x0f ;enable tcc_int
001d mov a,@0x05 ;1/64
001e contw
001f eni
;scan --------------------------------------------------------------
scan:
0020 mov a,sec
0021 call t7
0022 iow p6
0023 mov p6,a
0024 mov a,@255 ;display digit 0
0025 mov p5,a
0026 mov a,sec
0027 call t7
0028 iow p6
0029 xor a,@0xff
002a mov p6,a
002b mov a,@00 ;display digit 1
002c mov p5,a
002d jmp scan
程序与差异之处仅在扫描动作上不同罢了。
若要扫共阳的位数时,必须将port5外设为高电位输出,而要亮的字划,在port6外设为低电位输入即可。若要扫共阴的位数1时,必须将port5外设为低电位输出即可,而要亮的字划,在port6外设为高电位输出即可。故有了0020--0025行,位数0的显示处理及0026--002c行,位数1的显示处理。
效果观察:
程序到此时您会看到二位数的七字显示屏幕,同时从0→9每秒进位一次,到9以后程序将会错乱(?why?)。
具有限数能力:
以上的程序对sec(秒)都不予限数,当然会造成call table retew错误发生,故底下增加min(分)并对sec、min做59及99的限数动作。

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
pc == 02
rf == 03 ;status
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
min == 0x10 ;minute
sec == 0x11 ;second
dd == 0x12 ;display digit
ddh == 0x13 ;display digit high
ab == 0x14 ;a back_up
rfb == 0x15 ;rf back_up
org 0
0000 jmp init ;program start
org 8
;tcc interrupt---------------------------------------
tcci:
0008 mov ab,a ;ab <- a
0009 mov a,rf ;a <- rf
000a mov rfb,a ;rfb<- rf
000b inc sec
check:
000c mov a,sec ;比较59秒
000d sub a,@59 ;59-sec=a
000e jbc rf,fc
000f jmp c_min
0010 clr sec
0011 inc min
c_min:
0012 mov a,min ;比较99分
0013 sub a,@99 ;99-min=a
0014 jbs rf,fc
0015 clr min
tcce:
0016 mov a,rfb ;a <- rfb
0017 mov rf,a ;rf<- rfb
0018 mov a,ab ;a <- ab
0019 bc 0x0f,0 ;clear tcc_int
001a reti
;table 7 segement-----------------------------------
t7:
001b add pc,a ; gfe dcba
001c retl @0b01000000 ;0 0100 0000
001d retl @0b01111001 ;1 0111 1001
001e retl @0b00100100 ;2 0010 0100
001f retl @0b00110000 ;3 0011 0000
0020 retl @0b00011001 ;4 0001 1001
0021 retl @0b00010010 ;5 0001 0010
0022 retl @0b00000010 ;6 0000 0010
0023 retl @0b01011000 ;7 0101 1000
0024 retl @0b00000000 ;8 0000 0000
0025 retl @0b00010000 ;9 0001 0000
;init -----------------------------------------------
init:
0026 mov a,@0x00
0027 mov min,a
0028 mov sec,a
0029 iow 0x0e ;disable wdt
002a iow p5 ;port 5 output
002b iow p6 ;port 6 output
002c mov a

,@0x01
002d iow 0x0f ;enable tcc_int
002e mov a,@0x05 ;1/64
002f contw
0030 eni
;scan -----------------------------------------------
scan:
0031 mov a,min
htd:
0032 clr ddh
h_h:
0033 add a,@246 ;a=a-10 16进制转10进制
0034 jbs rf,fc
0035 jmp h_l
0036 inc ddh
0037 jmp h_h
h_l:
0038 add a,@10
0039 call t7 ;显示个位
003a iow p6
003b mov p6,a
003c mov a,@255 ;display digit 0
003d mov p5,a
003e mov a,ddh ;显示十位
003f call t7
0040 iow p6
0041 xor a,@0xff
0042 mov p6,a
0043 mov a,@00 ;display digit 1
0044 mov p5,a
0045 jmp scan
程序与差异之处有下:
tcc中断子程序部份增加了a,r3的暂存动作及sec、min的限数动作。0008--000a及0016--0018行系对a及r3做暂存及复原的动作。
000c--0011行系对秒做59的比较动作,sec比59大则sec=0,min=min+1。
0012--0015行系对分做99的比较动作,若min比99大则min=0。
此处为何要对中断子程序做a及r3的暂存及复原的动作呢?这是因为在主程序(scan)内时时会用到a及r3,及中断子程序中也会用到a及r3之故,若不在中断前后将a及r3的数值维持不变,那么主程序将会有错乱的情形产生。
在扫描程序部份增加了16进制变成10进制的动作。纵然二位数字来显示min(分)的讯息是可行的,然将16进制变成10进制才能符合人类的习性。0033--0038行即在做16进制转10进制的动作,将min的数值拆成个位数及拾位数,并在0039--003d时显示个位数,而在003e--0044时显示拾位数。
效果观察:
程序到此为止,理论上已做完该完成的所有行为了。但执行起来….为何….为何….忽好忽坏呢???
完成正确功能:
将程序左看右看,上看下看,怎么看也看不出破绽出来,但为何程序跑起来很不稳定,忽好忽坏的呢?是ice不稳呢?还是程序错误呢?答案当然是程序错误。

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
pc == 02
rf == 03 ;status
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
min == 0x10 ;minute
sec == 0x11 ;second
dd == 0x12 ;display digit
ddh == 0x13 ;display digit high
ab == 0x14 ;a back_up
rfb == 0x15 ;rf back_up
org 0
0000 jmp init ;program start
org 8
;tcc interrupt-------------------------------------------------------------
tcci:
0008 mov ab,a ;ab <- a
0009 swap ab ;ab <- ba
000a swapa rf
000b mov rfb,a ;rfb<- fr
000c inc sec
check:
000d mov a,sec
000e sub a,@59 ;59-sec=a
000f jbc rf,fc
0010 jmp c_min
0011 clr sec
0012 inc min
c_min:
0013 mov a,min
0014 sub a,@99 ;99-min=a
0015 jbs rf,fc
0016 clr min
tcce:
0017 swapa rfb
0018 mov rf,a ;rf<- rfb
0019 swapa ab ;a <- ba
001a bc 0x0f,0 ;clear tcc_int
001b reti
;table 7 segement-----------------------------------------------------
t7:
001c add pc,a ; gfe dcba
001d retl @0b01000000 ;0 0100 0000
001e retl @0b01111001 ;1 0111 1001
001f retl @0b00100100 ;2 0010 0100
0020 retl @0b00110000 ;3 0011 0000
0021 retl @0b00011001 ;4 0001 1001
0022 retl @0b00010010 ;5 0001 0010
0023 retl @0b00000010 ;6 0000 0010
0024 retl @0b01011000 ;7 0101 1000
0025 retl @0b00000000 ;8 0000 0000
0026 retl @0b00010000 ;9 0001 0000
;init ------------------------------

---------------------------------------------
init:
0027 mov a,@0x00
0028 mov min,a
0029 mov sec,a
002a iow 0x0e ;disable wdt
002b iow p5 ;port 5 output
002c iow p6 ;port 6 output
002d mov a,@0x01
002e iow 0x0f ;enable tcc_int
002f mov a,@0x05 ;1/64
0030 contw
0031 eni
;scan -------------------------------------------------------------------------
scan:
0032 mov a,min
htd:
0033 clr ddh
h_h:
0034 add a,@246 ;a=a-10
0035 jbs rf,fc
0036 jmp h_l
0037 inc ddh
0038 jmp h_h
h_l:
0039 add a,@10
003a call t7
003b iow p6
003c mov p6,a
003d mov a,@255 ;display digit 0
003e mov p5,a
003f mov a,ddh
0040 call t7
0041 iow p6
0042 xor a,@0xff
0043 mov p6,a
0044 mov a,@00 ;display digit 1
0045 mov p5,a
0046 jmp scan
原来问题就在中断子程序的a及r3暂存及复原这部份。
原来程序在a及r3的暂存部份:
0008 mov ab, a ;ab←a
0009 mov a, rf ;a←rf
000a mov rfb, a ;rfb←rf
错就错在0009时mov a, rf指令会破坏zero flag的资料。故改变指令的用法即可恢复正常,新的程序在a及r3的暂存部份:
0008 mov ab, a ;ab←a
0009 swap ab
000a swapa rf
000b mov rfb, a ;rfb←fr
新的程序在a及r3的复原部份:
0017 swapa rfb
0018 mov rf, a ;rf←rfb
0019 swapa ab ;a←ba
动作有点别扭,但是好用得很,请尽量用。
效果观察:
此时此刻的您一定是欢喜异常,眼睛看着分钟一分一分的增加又不死机,刚才紧绷的心情顿时得到解脱,一切的心血总算有了回报了。
增加花招:
拿着半成品把玩半天总觉得有些不够完美的,原来是一分钟才变化一次会让人觉得成品好像没在正常工作,总是怀疑成品是死的,好吧,再动些手脚将秒的闪烁呈现在七段的小数点上以满足动感要求。

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
pc == 02
rf == 03 ;status
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
dl == 0x10 ;delay loop
min == 0x11 ;minute
sec == 0x12 ;second
dd == 0x13 ;display digit
ddh == 0x14 ;display digit high
ab == 0x15 ;a back_up
rfb == 0x16 ;rf back_up
fg == 0x17 ;flag
org 0
0000 jmp init ;program start
org 8
;tcc interrupt---------------------------------------------------------------
tcci:
0008 mov ab,a ;ab <- a
0009 swap ab ;ab <- ba
000a swapa rf
000b mov rfb,a ;rfb<- fr
000c com fg
000d inc sec
check:
000e mov a,sec
000f sub a,@59 ;59-sec=a
0010 jbc rf,fc
0011 jmp c_min
0012 clr sec
0013 inc min
c_min:
0014 mov a,min
0015 sub a,@99 ;99-min=a
0016 jbs rf,fc
0017 clr min
tcce:
0018 swapa rfb
0019 mov rf,a ;rf<- rfb
001a swapa ab ;a <- ba
001b bc 0x0f,0 ;clear tcc_int
001c reti
;table 7 segement------------------------------------------------------
t7:
001d call table ;用来增加小数点闪烁
001e jbc fg,00
001f xor a,@0x80
0020 ret
;table -------------------------------------------------------------------------
table:
0021 add pc,a ; gfe dc

ba
0022 retl @0b01000000 ;0 0100 0000
0023 retl @0b01111001 ;1 0111 1001
0024 retl @0b00100100 ;2 0010 0100
0025 retl @0b00110000 ;3 0011 0000
0026 retl @0b00011001 ;4 0001 1001
0027 retl @0b00010010 ;5 0001 0010
0028 retl @0b00000010 ;6 0000 0010
0029 retl @0b01011000 ;7 0101 1000
002a retl @0b00000000 ;8 0000 0000
002b retl @0b00010000 ;9 0001 0000
;init -----------------------------------------------------------------------------
init:
002c mov a,@0x00
002d mov min,a
002e mov sec,a
002f iow 0x0e ;disable wdt
0030 iow p5 ;port 5 output
0031 iow p6 ;port 6 output
0032 mov a,@0x01
0033 iow 0x0f ;enable tcc_int
0034 mov a,@0x05 ;1/64
0035 contw
0036 eni
;scan ------------------------------------------------------------------------------
scan:
0037 mov a,min
htd:
0038 clr ddh
h_h:
0039 add a,@246 ;a=a-10
003a jbs rf,fc
003b jmp h_l
003c inc ddh
003d jmp h_h
h_l:
003e add a,@10
003f call t7
0040 iow p6
0041 mov p6,a
0042 mov a,@255 ;display digit 0
0043 mov p5,a
0044 mov a,ddh
0045 call t7
0046 iow p6
0047 xor a,@0xff
0048 mov p6,a
0049 mov a,@00 ;display digit 1
004a mov p5,a
004b jmp scan
要如何增加小数点秒的闪烁呢?其实看结果一点也不困难(话虽如此却也着实的伤了好几条的脑筋)。
增加001d~0020这四行程序就可迎刃而解了。
效果观察:
看着一秒亮一秒灭的成品,此时此刻仅可用一个”爽”字来形容心情,愈来愈觉得其实单片机制作并不是高不可及啊!
7.好上加好:
如果用示波器来看看制作成果的良好程度时,可以看到显示周期比才近50%左右,让人总觉得可惜,倘若能够让显示周期比接近100%不亦快哉!
再动手改吧.

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
pc == 02
rf == 03 ;status
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
dl == 0x10 ;delay loop
min == 0x11 ;minute
sec == 0x12 ;second
dd == 0x13 ;display digit
ddh == 0x14 ;display digit high
ab == 0x15 ;a back_up
rfb == 0x16 ;rf back_up
fg == 0x17 ;flag
org 0
0000 jmp init ;program start
org 8
;tcc interrupt-----------------------------------------------------------------
tcci:
0008 mov ab,a ;ab <- a
0009 swap ab ;ab <- ba
000a swapa rf
000b mov rfb,a ;rfb<- fr
000c com fg
000d inc sec
check:
000e mov a,sec
000f sub a,@59 ;59-sec=a
0010 jbc rf,fc
0011 jmp c_min
0012 clr sec
0013 inc min
c_min:
0014 mov a,min
0015 sub a,@99 ;99-min=a
0016 jbs rf,fc
0017 clr min
tcce:
0018 swapa rfb
0019 mov rf,a ;rf<- rfb
001a swapa ab ;a <- ba
001b bc 0x0f,0 ;clear tcc_int
001c reti
;table 7 segement--------------------------------------------------------
t7:
001d call table
001e jbc fg,00
001f xor a,@0x80
0020 ret
;table ------------------

----------------------------------------------------------
table:
0021 add pc,a ; gfe dcba
0022 retl @0b01000000 ;0 0100 0000
0023 retl @0b01111001 ;1 0111 1001
0024 retl @0b00100100 ;2 0010 0100
0025 retl @0b00110000 ;3 0011 0000
0026 retl @0b00011001 ;4 0001 1001
0027 retl @0b00010010 ;5 0001 0010
0028 retl @0b00000010 ;6 0000 0010
0029 retl @0b01011000 ;7 0101 1000
002a retl @0b00000000 ;8 0000 0000
002b retl @0b00010000 ;9 0001 0000
;delay ----------------------------------------------------------------------------
delay:
002c mov p5,a ;增加显示时间之比
002d mov a,@20
002e mov dl,a
d_1:
002f djz dl
0030 jmp d_1
0031 mov a,@0xff
0032 iow p6
0033 ret
;init --------------------------------------------------------------------------------
init:
0034 mov a,@0x00
0035 mov min,a
0036 mov sec,a
0037 iow 0x0e ;disable wdt
0038 iow p5 ;port 5 output
0039 iow p6 ;port 6 output
003a mov a,@0x01
003b iow 0x0f ;enable tcc_int
003c mov a,@0x05 ;1/64
003d contw
003e eni
;scan -----------------------------------------------------------------------------
scan:
003f mov a,min
htd:
0040 clr ddh
h_h:
0041 add a,@246 ;a=a-10
0042 jbs rf,fc
0043 jmp h_l
0044 inc ddh
0045 jmp h_h
h_l:
0046 add a,@10
0047 call t7
0048 iow p6
0049 mov p6,a
004a mov a,@255 ;display digit 0
004b call delay
004c mov a,ddh
004d call t7
004e iow p6
004f xor a,@0xff
0050 mov p6,a
0051 mov a,@00 ;display digit 1
0052 call delay
0053 jmp scan
人的眼眼睛实在很容易被欺骗,只要扫描频率大于30hz其实已经看不到闪烁的现象,故在不产生闪烁的现象中如何增加显示周期比呢?
增加显示时之时间,故这里增加了一个delay子程序(002c--0033行所示)供扫描显示时呼叫之用。固定的在个位数及拾位数显示时各呼叫一次来增加显示周期比。
效果观察:
增加了delay子程序之后约可提升亮度一倍左右。
8.要善始善终-----永不死机:
正当要关掉ice准备烧写otp的时候,仔细想想程序才那么小小的,留那么多的空白做什么?不妨拿来「增加稳定度」之用。
还要动手.?

;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
iar == 00 ;indirect ar
pc == 02
rf == 03 ;status
rsr == 04 ;ram selector
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
dl == 0x10 ;delay loop
min == 0x11 ;minute
sec == 0x12 ;second
dd == 0x13 ;display digit
dg == 0x14 ;display digit high dg=dd=ddh
ab == 0x15 ;a back_up
rfb == 0x16 ;rf back_up
fg == 0x17 ;flag
org 0
0000 jmp init ;program start
// // // //
0007 jmp init ;program start
;tcc interrupt-------------------------------------------------------------
tcci:
0008 mov ab,a ;ab <- a
0009 swap ab ;ab <- ba
000a swapa rf
000b mov rfb,a ;rfb<- fr
000c com fg
000d inc sec
check:
000e mov a,sec
000f sub a,@59 ;5

9-sec=a
0010 jbc rf,fc
0011 jmp c_min
0012 clr sec
0013 inc min
c_min:
0014 mov a,min
0015 sub a,@99 ;99-min=a
0016 jbs rf,fc
0017 clr min
tcce:
0018 swapa rfb
0019 mov rf,a ;rf<- rfb
001a swapa ab ;a <- ba
001b bc 0x0f,0 ;clear tcc_int
001c reti
001d jmp init ;program start
// // // //
0028 jmp init ;program start
;table 7 segement-------------------------------------------------------
t7:
0029 call table
002a jbc fg,00
002b xor a,@0x80
002c ret
002d jmp init ;program start
// // // //
003b jmp init ;program start
;table ---------------------------------------------------------------------------
table:
003c add pc,a ; gfe dcba
003d retl @0b01000000 ;0 0100 0000
003e retl @0b01111001 ;1 0111 1001
003f retl @0b00100100 ;2 0010 0100
0040 retl @0b00110000 ;3 0011 0000
0041 retl @0b00011001 ;4 0001 1001
0042 retl @0b00010010 ;5 0001 0010
0043 retl @0b00000010 ;6 0000 0010
0044 retl @0b01011000 ;7 0101 1000
0045 retl @0b00000000 ;8 0000 0000
0046 retl @0b00010000 ;9 0001 0000
0047 jmp init ;program start
// // // //
0055 jmp init ;program start
;delay ---------------------------------------------------------------------------
delay:
0056 wdtc
0057 mov p5,a
0058 mov a,@00
0059 iow p5
005a mov a,@0x3f
005b mov rsr,a
005c mov a,@0x1f
005d mov dl,a
005e clra
delay1:
005f add a,iar
0060 dec rsr
0061 djz dl
0062 jmp delay1
0063 or a,@00
0064 jbs rf,fz
0065 jmp init ;program start
0066 mov a,@0xff
0067 iow p6
0068 ret
0069 jmp init ;program start
// // // //
007f jmp init ;program start
;init -------------------------------------------------------------------------------
init:
0080 mov a,@0x3f
0081 mov rsr,a
0082 mov a,@0x2f
0083 mov dl,a
init1:
0084 clr iar
0085 dec rsr
0086 djz dl
0087 jmp init1
0088 mov a,@0x00
0089 iow p5 ;port 5 output
008a iow p6 ;port 6 output
008b mov a,@0x80
008c iow 0x0e ;enable wdt
008d mov a,@0x01
008e iow 0x0f ;enable tcc_int
008f mov a,@0x05 ;1/64
0090 contw
0091 eni
0092 jmp scan
0093 jmp init ;program start
// // // //
00b8 jmp init ;program start
;scan -----------------------------------------------------------------------------
scan:
00b9 mov a,min
htd:
00ba clr dg
h_h:
00bb add a,@246 ;a=a-10
00bc jbs rf,fc
00bd jmp h_l
00be inc ddh
00bf jmp h_h
h_l:
00c0 add a,@10
00c1 call t7
00c2 iow p6
00c3 mov p6,a
00c4 mov a,@255 ;display digit 0
00c5 call delay
00c6 mov a,dg
00c7 call t7
00c8 iow p6
00c9 xor a,@0xff
00ca mov p6,a
00cb mov a,@00 ;display digit 1
00cc call delay
00cd jmp scan
00ce jmp init ;program start
// // // //
03ff jmp init ;pr

ogram start
与程序的差异之处:
在每个程序的段落「加入jmp init」指令。
在程序节结尾以后「加入jmp init」指令。
如此一来,不论ic何时死机错乱都会跳到开始来执行了。
加入watch dog timer:
来避免程序的错误而造成死loop现象。
加入错误侦测能力:
利用剩余的寄存器来做引子,随时去读取这些寄存器,若和不为零则代表错误发生了,应该重新开始。
效果观察:
不论如何故意的去弄死机都会从头开始正常执行程序了,大功告成。可以加上您认为漂亮合适的外壳,投入使用了。

附源程序:
;
; file name:
; date :1999,5,5
; by :hwang jyn_guo
;
; function description:
; using tcc to get 1 sec interrupt
; 32768/(2*64*256)= 1 sec
; crystal mode 32768 hz
; 2 cycle and 2 clock mode
;
iar == 00 ;indirect ar
pc == 02
rf == 03 ;status
rsr == 04 ;ram selector
fz == 02 ;flag of zero
fc == 00 ;flag of carry
p5 == 0x05 ;port 5
p6 == 0x06 ;port 6
dl == 0x10 ;delay loop
min == 0x11 ;minute
sec == 0x12 ;second
dd == 0x13 ;display digit
dg == 0x14 ;display digit high dg=dd=ddh
ab == 0x15 ;a back_up
rfb == 0x16 ;rf back_up
fg == 0x17 ;flag
org 0000
jmp init ;program start

jmp init ;program start
;tcc interrupt-------------------------------------------------------------
tcci:
mov ab,a ;ab <- a
swap ab ;ab <- ba
swapa rf
mov rfb,a ;rfb<- fr
com fg
inc sec
check:
mov a,sec
sub a,@59 ;59-sec=a
jbc rf,fc
jmp c_min
clr sec
inc min
c_min:
mov a,min
sub a,@99 ;99-min=a
jbs rf,fc
clr min
tcce:
swapa rfb
mov rf,a ;rf<- rfb
swapa ab ;a <- ba
bc 0x0f,0 ;clear tcc_int
reti
jmp init ;program start

jmp init ;program start
;table 7 segement-------------------------------------------------------
t7:
call table
jbc fg,00
xor a,@0x80
ret
jmp init ;program start

jmp init ;program start
;table ---------------------------------------------------------------------------
table:
add pc,a ; gfe dcba
retl @0b01000000 ;0 0100 0000
retl @0b01111001 ;1 0111 1001
retl @0b00100100 ;2 0010 0100
retl @0b00110000 ;3 0011 0000
retl @0b00011001 ;4 0001 1001
retl @0b00010010 ;5 0001 0010
retl @0b00000010 ;6 0000 0010
retl @0b01011000 ;7 0101 1000
retl @0b00000000 ;8 0000 0000
retl @0b00010000 ;9 0001 0000
jmp init ;program start

jmp init ;program start
;delay ---------------------------------------------------------------------------
delay:
wdtc
mov p5,a
mov a,@00
iow p5
mov a,@0x3f
mov rsr,a
mov a,@0x1f
mov dl,a
clra
delay1:
add a,iar
dec rsr
djz dl
jmp delay1
or a,@00
jbs rf,fz
jmp init ;program start
mov a,@0xff
iow p6
ret
jmp init ;program start

jmp init ;program start
;init -------------------------------------------------------------------------------
init:
mov a,@0x3f
mov rsr,a
mov a,@0x2f
mov dl,a
init1:
clr iar
dec rsr
djz dl
jmp init1
mov a,@0x0

0
iow p5 ;port 5 output
iow p6 ;port 6 output
mov a,@0x80
iow 0x0e ;enable wdt
mov a,@0x01
iow 0x0f ;enable tcc_int
mov a,@0x05 ;1/64
contw
eni
jmp scan
jmp init ;program start

jmp init ;program start
;scan -----------------------------------------------------------------------------
scan:
mov a,min
htd:
clr dg
h_h:
add a,@246 ;a=a-10
jbs rf,fc
jmp h_l
inc ddh
jmp h_h
h_l:
add a,@10
call t7
iow p6
mov p6,a
mov a,@255 ;display digit 0
call delay
mov a,dg
call t7
iow p6
xor a,@0xff
mov p6,a
mov a,@00 ;display digit 1
call delay
jmp scan
jmp init ;program start

jmp init ;program start


上一篇:确保信号完整性的电路板设计准则

下一篇:集系统级FPGA芯片XCV50E的结构与开发