📄 mcu.asm
字号:
mov SCON,#50h ;设置串口工作方式1,REN=1,允许接收。
setb TR1 ;定时器开始工作。
ret ;返回。
;;;;;;;;;;;;;;;;初始化串口子程序结束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;毫秒表子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>资源占用报告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>临时占用a,c,dptr,bank0区r2~r6
;>>>>>>>>>>>>>>>报告完毕>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;'''''''''''''''操作指南''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
;1:当程序处于毫秒表功能时,按下BUTTON_MIL键开始毫秒计时,再次按下结束计时。
;2:如果您打算返回主菜单,首先按下键盘任意键,然后再连续按下两次BUTTON_MIL键。
;'''''''''''''''指南完毕''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FUNCTION7: mov a,STATUS ;
anl a,#0FEh ;进入毫秒表功能。
mov STATUS,a ;
mov dptr,#8100h ;
movx @dptr,a ;
nop ;
nop ;
call ENABLEINT1 ;开启外部中断1。
FUNCTION7_1: mov a,RETURNFLAG ;检查返回标志,决定是否返回。
jz FUNCTION7_CON ;
jmp main ;
FUNCTION7_CON: mov r2,#00h ;r2,r3,r4,r5保存计时值。
;足够计时1个多小时。您不会
;为了测试一下而让Proteus仿真
;1个小时吧:(
mov r3,#00h ;
mov r4,#00h ;
mov r5,#00h ;
FUNCTION7_2: mov a,MILSTART ;MILSTART保存计时标志,第一次
;按下BUTTON_MIL键后触发外部中
;断1,将MILSTART设定为0FFh,开
;始计时。再次按下BUTTON_MIL键
;后触发外部中断1,将MILSTART设
;定为00h。
jz FUNCTION7_2 ;
FUNCTION7_3: clr c ;=====这部分程序是进行4个字节
mov a,r5 ;=====的加1操作。r2是最高字节,
addc a,#01h ;=====r5是最低字节。
mov r5,a ;=====这部分程序占用16个机器周
mov a,r4 ;=====期,所以计时后的r2r3r4r5
addc a,#00h ;=====乘以16便是以微秒为单位的
mov r4,a ;=====时间。注意时钟晶体=12MHz。
mov a,r3 ;=====
addc a,#00h ;=====
mov r3,a ;=====
mov a,r2 ;=====
addc a,#00h ;=====
mov r2,a ;=====
mov a,MILSTART ;=====
jnz FUNCTION7_3 ;=====
mov r6,#04h ;
FUNCTION7_4: clr c ;>>>>>这部分程序完成乘以16的操作,
mov a,r5 ;>>>>>乘以16不就是向左移4bit吗。
rlc a ;>>>>>
mov r5,a ;>>>>>
mov a,r4 ;>>>>>
rlc a ;>>>>>
mov r4,a ;>>>>>
mov a,r3 ;>>>>>
rlc a ;>>>>>
mov r3,a ;>>>>>
mov a,r2 ;>>>>>
rlc a ;>>>>>
mov r2,a ;>>>>>
djnz r6,FUNCTION7_4 ;>>>>>
mov r0,#DIVD4ADDRESS0 ;以下显示结果,唯一需要解释的就是删
mov r1,#DIVD4ADDRESS4 ;去最低2位数字不显示,精确到0.1mS。
mov a,r2 ;
mov @r1,a ;
inc r1 ;
mov a,r3 ;
mov @r1,a ;
inc r1 ;
mov a,r4 ;
mov @r1,a ;
inc r1 ;
mov a,r5 ;
mov @r1,a ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#0Ah ;
mov dptr,#LCD0 ;
call DIVD4 ;
call DIVD4 ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULTA,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT8,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT7,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT6,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT5,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT4,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT3,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT2,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT1,a ;
mov a,#0Dh ;
movc a,@a+dptr ;
mov RESULT9,a ;
mov a,#10h ;
movc a,@a+dptr ;
mov RESULTB,a ;
mov a,#11h ;
movc a,@a+dptr ;
mov RESULTC,a ;
mov a,#00h ;
mov RESULTD,a ;
mov a,#LCD_CLS ;
call WRCMD ;
call WRRESULT ;
jmp FUNCTION7_1 ;
;;;;;;;;;;;;;;;;毫秒表子程序结束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;马达驱动子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>资源占用报告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>临时占用a,dptr,bank0区r5~r7
;>>>>>>>>>>>>>>>报告完毕>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;???????????????以下程序只是小小的演示。作者正在构思一个充满想象力的设计,敬请留意。????????????
FUNCTION8: mov dptr,#8100h ;
mov a,STATUS ;
orl a,#10h ;
anl a,#0DFh ;
mov STATUS,a ;
movx @dptr,a ;右转左不转。
call F8DELAY ;
mov a,RETURNFLAG ;检查返回标志,决定是否返回。
jz FUNCTION8_1 ;
jmp main ;
FUNCTION8_1: mov a,STATUS ;
orl a,#20h ;
anl a,#0EFh ;
mov STATUS,a ;
movx @dptr,a ;左转右不转。
call F8DELAY ;
mov a,RETURNFLAG ;检查返回标志,决定是否返回。
jz FUNCTION8_2 ;
jmp main ;
FUNCTION8_2: mov a,STATUS ;
anl a,#0CFh ;
mov STATUS,a ;
movx @dptr,a ;两个都不转。
call F8DELAY ;
mov a,RETURNFLAG ;检查返回标志,决定是否返回。
jz FUNCTION8_3 ;
jmp main ;
FUNCTION8_3: mov a,STATUS ;
orl a,#30h ;
mov STATUS,a ;
movx @dptr,a ;两个都在转。
call F8DELAY ;
mov a,RETURNFLAG ;检查返回标志,决定是否返回。
jz FUNCTION8_4 ;
jmp main ;
FUNCTION8_4: jmp FUNCTION8 ;
F8DELAY: mov r5,#10h ;
D18: mov r6,#0FFh ;
D19: mov r7,#0FFh ;
D20: djnz r7,D20 ;
djnz r6,D19 ;
djnz r5,D18 ;
ret ;
;;;;;;;;;;;;;;;;马达驱动子程序结束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;频率测量子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>资源占用报告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>临时占用a,b,c,dptr,bank0区r5~r7
;>>>>>>>>>>>>>>>报告完毕>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
FUNCTION9: mov a,RETURNFLAG ;检查返回标志,决定是否返回。
jz FUNCTION9_CON ;
jmp main ;
FUNCTION9_CON: mov dptr,#0000h ;初始化计数值。
setb c ;
mov p3.5,c ;使得p3.5端口处于高阻态,准备读取数据。
FUNCTION9_1: mov c,p3.5 ;
jc FUNCTION9_1 ;=====这部分程序的功能是等待待测信号,
FUNCTION9_2: mov c,p3.5 ;=====直到上升沿的到来。
jnc FUNCTION9_2 ;=====
FUNCTION9_3: inc dptr ;>>>>>这部分程序的功能是在待侧信号的一
mov c,p3.5 ;>>>>>个周期内计数。inc dptr指令需要2
jc FUNCTION9_3 ;>>>>>个机器周期,mov c,p3.5指令需要1
FUNCTION9_4: inc dptr ;>>>>>个机器周期,jc FUNCTION9_3和
mov c,p3.5 ;>>>>>jnc FUNCTION9_4需要2个机器周期。
jnc FUNCTION9_4 ;>>>>>所以待侧信号周期=5xdptr微秒。注意
;使用12MHz晶体。那么待侧信号频率=
;1000000/5/dptr=200000/dptr赫兹。
mov a,FREQLOW ;FREQHIGH和FREQLOW存储上一次扫描的dptr
;数值,如果频率没有变化,那么前后两次扫
;描数值相同,不更新LCD显示。
;实际上,即使您不改变待测信号频率,前后
;两次扫描的dptr也不相同。因为这里采用的
;是等待上升沿到来再计数,哪有这么幸运,
;恰好让您赶上精确的上升沿时刻,总有些误
;差。
anl a,#0FCh ;所以,屏蔽最低2bit数值,降低精度,模糊
;比较。这样做会不会降低测量的精度呢?用
;这里的方法测量频率本身就有误差,频率越
;高误差越大。所以屏蔽不屏蔽2bit不是主要
;矛盾所在。注意,本电路图测量的频率范围
;不要超过10000Hz,最大误差大约30-50Hz。
;再强调一次,频率越高误差越大,您自己思
;考为什么。
;那又没有其它的算法或者电路设计能够做到
;比较精确而且测量频率范围更大呢?有啊,
;但是作者现在不想告诉您:(
mov FREQLOW,a ;
mov a,dpl ;
anl a,#0FCh ;
xrl a,FREQLOW ;把dpl和FREQLOW做异或运算,得到结果暂存b中。
mov b,a ;
mov a,dph ;
xrl a,FREQHIGH ;把dph和FREQHIGH做异或运算,得到结果暂存a中。
orl a,b ;把a和b做或运算,如果结果为零,说明前后
;两次扫描数值相同。
jz FUNCTION9 ;
mov FREQHIGH,dph ;将本次dptr扫描数值存储。
mov FREQLOW,dpl ;
mov r0,#DIVD4ADDRESS0 ;以下求频率并显示,类似前面的程序,不多
;解释了。
mov r1,#DIVD4ADDRESS4 ;
mov a,#00h ;
movx @r1,a ;
inc r1 ;
mov a,#03h ;
mov @r1,a ;
inc r1 ;
mov a,#0Dh ;
mov @r1,a ;
inc r1 ;
mov a,#40h ;
mov @r1,a ;
inc r1 ;
mov a,#00h ;
mov @r1,a ;
inc r1 ;
mov @r1,a ;
inc r1 ;
mov @r1,dph ;
inc r1 ;
mov @r1,dpl ;
call DIVD4 ;
mov r1,#DIVD4ADDRESS8 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#0Ah ;
mov dptr,#LCD0 ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT5,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT4,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT3,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT2,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT1,a ;
mov a,#0Eh ;
movc a,@a+dptr ;
mov RESULT6,a ;
mov a,#0Fh ;
movc a,@a+dptr ;
mov RESULT7,a ;
mov a,#00h ;
mov RESULT8,a ;
mov a,#LCD_CLS ;
call WRCMD ;
call WRRESULT ;
F9DELAY: mov r5,#05h ;
D26: mov r6,#0FFh ;
D27: mov r7,#0FFh ;
D28: djnz r7,D28 ;
djnz r6,D27 ;
djnz r5,D26 ;
jmp FUNCTION9 ;
;;;;;;;;;;;;;;;;频率测量子程序结束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;正弦波显示子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>资源占用报告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>临时占用a,bank0区r7
;>>>>>>>>>>>>>>>报告完毕>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;'''''''''''''''友情提示''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
;1:您不能指望51单片机进行正弦函数计算(sin),51单片机只是8位机,算术运算指令弱,
;运算速度慢。不是不能做出正弦子程序,而是不能实时计算出来。如果您非要实时计算,建
;议您换一颗奔腾的芯,或者用TMS320XXXX。
;2:这里采用查表的方法。用C语言编写程序,事先算好,粘贴在这里。您察看一下压缩包里
;面有一个名称为SineTable的可执行程序和源文件,您可以按照自己的需要修改。为了减小
;压缩包体积,完整的C++工程文件没有给出,只有.cpp的源文件。
;3:在Proteus下,也许您运行显示正弦波的功能时,示波器更新很慢,CPU资源100%占用,画
;面极不流畅的情况。原因是这样:在作者这个软件运行时,首先显示菜单,然后您选择功能,
;当切换到正弦波的时候,Proteus反映就很慢,这是Proteus固有的缺点。解决的方法:您可以
;重新写一个程序,删去所有其它功能,一上来就显示正弦波,那样还比较流畅
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -