📄 noname1.asm
字号:
OUTPUT BIT P1.0 ;定义输出端口;
KEY_F_UP BIT P0.2 ;频率上调按键;
KEY_F_DOWN BIT P0.3 ;频率下调按键;
KEY_DC_UP BIT P0.4 ;占空比上调按键;
KEY_DC_DOWN BIT P0.5 ;占空比下调按键;
TIMER0_H EQU 30H ;定时器0高8位;
TIMER0_L EQU 31H ;定时器0低8位;
TIMER1_H EQU 32H ;定时器1高8位;
TIMER1_L EQU 33H ;定时器1低8位;
PERCENT EQU 34H ;占空比设置变量;
F_H EQU 35H ;频率高8位;
F_L EQU 36H ;频率低8位;
TEMP_H EQU 37H ;临时变量,用于全局数字的传递;
TEMP_L EQU 38H
F_TEMP_H EQU 39H
F_TEMP_L EQU 40H
DC_TEMP_H EQU 41H
DC_TEMP_L EQU 42H
ORG 0000H
AJMP MAIN
ORG 00BH
AJMP TIMER0 ;定时器0中断入口;
ORG 01BH
AJMP TIMER1 ;定时器1中断入口;
ORG 0100H
MAIN: MOV PERCENT,#50 ;初始化占空比为50%;
MOV F_H, #00H ;初始频率设为250HZ;
MOV F_L, #0FAH
MOV TIMER0_H,#0F0H ;设初值;
MOV TIMER0_L,#60H ;设初值;
MOV TIMER1_H,#0F8H ;设初值;
MOV TIMER1_L,#30H ;设初值;
MOV TMOD, #11H ;定时器0和定时器1都工作在方式1下(16位);
MOV TH0, TIMER0_H ;定时器0初始定时为2ms;
MOV TL0, TIMER0_L
MOV TH1, TIMER1_H ;定时器1初始定时4ms;
MOV TL1, TIMER1_L
SETB ET0 ;设置定时器0中断;
SETB ET1 ;设置定时器1中断;
SETB EA ;开启总中断;
SETB TR0 ;开启定时器0;
SETB TR1 ;开启定时器1;
LOOP: ACALL KEYSCAN
SJMP LOOP
DELAY: ;延时子程序;
MOV R2, #20
LOOP1: MOV R3, #20
DJNZ R3, $
DJNZ R2, LOOP1
RET
KEYSCAN: ;键盘扫描子函数;
ACALL DELAY ;延时去抖;
F_UP:
JB KEY_F_UP, F_DOWN ;判断KEY_F_UP键是否按下,没有按下则往下检查KEY_F_DOWN键;
JNB KEY_F_UP, $ ;等待按键松开;
MOV R7, F_H ;频率加10;
MOV R6, F_L
MOV R5, #00H
MOV R4, #0AH
ACALL ADD_16
MOV F_H, R5
MOV F_L, R4
AJMP END_KEY_SCAN_F ;结束;
F_DOWN:
JB KEY_F_DOWN, DC_UP ;判断KEY_F_DOWN键是否按下,没有按下则往下检查KEY_DC_UP键;
JNB KEY_F_DOWN, $ ;等待按键松开;
MOV R7, F_H ;频率减10;
MOV R6, F_L
MOV R5, #00H
MOV R4, #0AH
ACALL SUB_16
MOV F_H, R5
MOV F_L, R4
AJMP END_KEY_SCAN_F ;结束;
DC_UP:
JB KEY_DC_UP, DC_DOWN ;判断KEY_DC_UP键是否按下,没有按下则往下检查KEY_DC_DOWN键;
JNB KEY_DC_UP, $ ;等待按键松开;
MOV A, PERCENT
ADD A, #05H ;脉宽加5;
CLR C
SUBB A, #100 ;判断是不是大于100,大于则重置为1;
JC NEXT1
MOV PERCENT, #01
AJMP END_KEY_SCAN_DC
NEXT1: ADD A, #100
MOV PERCENT, A
AJMP END_KEY_SCAN_DC ;结束;
DC_DOWN:
JB KEY_DC_DOWN, END_KEY_SCAN ;判断KEY_DC_DOWN键是否按下,没有按下则结束;
JNB KEY_DC_DOWN, $ ;等待按键松开;
MOV A, PERCENT
CLR C
SUBB A, #05H ;脉宽,频率减5;
JNC NEXT2 ;判断是否小于0,小于则重置为99;
MOV PERCENT, #99
AJMP END_KEY_SCAN_DC
NEXT2: MOV PERCENT, A
AJMP END_KEY_SCAN_DC ;结束;
END_KEY_SCAN_F:
ACALL CALCULATE_F ;改变频率后要重新计算定时器0的初值;
ACALL CALCULATE_DC ;改变频率后也要重新计算定时器1的初值,以确保占空比不改变;
SJMP END_KEY_SCAN
END_KEY_SCAN_DC:
ACALL CALCULATE_DC ;改变占空比后要重新计算定时器1的初值;
SJMP END_KEY_SCAN
END_KEY_SCAN:
RET
;-------------------------------------------------------------------------------
;void calculate_F()
; {
;
; temp=ALL-F_osc/12.0/FREQ;
; TIMER0_H=(uint)temp/256;
; TIMER0_L=(uint)temp%256;
; }
;下面这段程序是这段程序的翻译汇编语言,Fosc=12M;
;函数功能:频率计算函数,当频率变化,计算出定时器0初值;
;--------------------------------------------------------------------------------
CALCULATE_F:
PUSH ACC
PUSH PSW
MOV R5, #00H
MOV R2, #0FH
MOV R3, #42H
MOV R4, #40H
MOV R6, F_H
MOV R7, F_L
ACALL NDIV42
MOV F_TEMP_H, R3
MOV F_TEMP_L, R4
MOV R7, #0FFH
MOV R6, #0FFH
MOV R5, F_TEMP_H
MOV R4, F_TEMP_L
ACALL SUB_16
MOV TEMP_H, R5
MOV TEMP_L, R4
MOV TIMER0_H, TEMP_H
MOV TIMER0_L, TEMP_L
POP PSW
POP ACC
RET
;---------------------------------------------------------------------------------
; void calculate_W()
; {
; float TEMP;
; TEMP=(1-PERCENT/100.0)*ALL+temp*PERCENT/100.0;
; TIMER1_H=(uint)TEMP/256;
; TIMER1_L=(uint)TEMP%256;
; }
;下面这段程序是这段程序的翻译汇编语言,temp=F_TEMP_H*256+F_TEMP_L;
;函数功能:脉宽计算函数,脉宽变化时,计算出定时器1初值;
;----------------------------------------------------------------------------------
CALCULATE_DC:
PUSH ACC
PUSH PSW
CLR C
MOV A, #64H
SUBB A, PERCENT
MOV R3, #02H
MOV R4, #8FH
MOV R7, A
ACALL NMUL21
MOV DC_TEMP_H,R3
MOV DC_TEMP_L,R4
MOV R3, TEMP_H
MOV R4, TEMP_L
MOV R7, PERCENT
ACALL NMUL21 ;乘积在R2,R3,R4中;
MOV R7, #64H ;商在R3,R4中;
ACALL NDIV31
MOV R7, DC_TEMP_H
MOV R6, DC_TEMP_L
MOV A, R3
MOV R5, A
ACALL ADD_16
MOV TIMER1_H,R5
MOV TIMER1_L,R4
POP PSW
POP ACC
RET
ADD_16: ;16位加法子程序(R7R6+R5R4=R5R4);
CLR C
MOV A, R6
ADDC A, R4
MOV R4, A
MOV A, R7
ADDC A, R5
MOV R5, A
END_ADD:RET
SUB_16: ;16位减法子程序(R7R6-R5R4=R5R4);
CLR C
MOV A, R6
SUBB A, R4
MOV R4, A
MOV A, R7
SUBB A, R5
MOV R5, A
END_SUB:RET
;-------------------------------------------------------------------------------------
;双字节无符号除法程序 (R5R2R3R4/R6R7)=(R2)R3R4 余数R6R7
;入口: R5,R2,R3,R4,R6,R7
;占用资源: ACC,B,F0
;堆栈需求: 4字节
;出口: (R2),R3,R4,R6,R7,OV
;-------------------------------------------------------------------------------------
NDIV42 :MOV A,R1
PUSH ACC
MOV B,#00H
NDV421 :MOV A,R2
CLR C
SUBB A,R7
MOV R1,A
MOV A,R5
SUBB A,R6
JC NDV422
MOV R5,A
MOV A,R1
MOV R2,A
INC B
SJMP NDV421
NDV422 :PUSH B
MOV B,#10H
NDV423 :CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
XCH A,R5
RLC A
XCH A,R5
MOV F0,C
CLR C
SUBB A,R7
MOV R1,A
MOV A,R5
SUBB A,R6
JB F0,NCV424
JC NDV425
NCV424 :MOV R5,A
MOV A,R1
MOV R2,A
INC R4
NDV425 :DJNZ B,NDV423
POP ACC
CLR OV
JNZ NDV426
SETB OV
NDV426 :XCH A,R2
MOV R7,A
MOV A,R5
MOV R6,A
POP ACC
MOV R1,A
RET
;------------------------------------------------------------------
;单字节无符号数乘法程序 (R3R4*R7)=(R2R3R4)
;入口: R3,R4,R7
;占用资源: ACC,B
;堆栈需求: 2字节
;出口: R2,R3,R4
;------------------------------------------------------------------
NMUL21 :MOV A,R4
MOV B,R7
MUL AB
MOV R4,A
MOV A,B
XCH A,R3
MOV B,R7
MUL AB
ADD A,R3
MOV R3,A
CLR A
ADDC A,B
MOV R2,A
CLR OV
RET
;------------------------------------------------------------------------
;单字节无符号除法程序 (R2R3R4/R7)=(R2)R3R4 余数R7
;入口: R2,R3,R4,R7
;占用资源: ACC,B,F0
;堆栈需求: 3字节
;出口: (R2),R3,R4,R7,OV
;------------------------------------------------------------------------
NDIV31 :MOV A,R2
MOV B,R7
DIV AB
PUSH ACC
MOV R2,B
MOV B,#10H
NDV311 :CLR C
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
MOV A,R2
RLC A
MOV R2,A
MOV F0,C
CLR C
SUBB A,R7
JB F0,NDV312
JC NDV313
NDV312 :MOV R2,A
INC R4
NDV313 :DJNZ B,NDV311
POP ACC
CLR OV
JZ NDV314
SETB OV
NDV314 :XCH A,R2
MOV R7,A
RET
TIMER0: ;定时器0中断入口程序;
PUSH ACC
PUSH PSW
SETB TR1 ;
MOV TH0, TIMER0_H
MOV TL0, TIMER0_L
SETB OUTPUT
POP PSW
POP ACC
RETI
TIMER1: ;定时器1中断入口程序;
PUSH ACC
PUSH PSW
CLR TR1
MOV TH1, TIMER1_H
MOV TL1, TIMER1_L
CLR OUTPUT
POP PSW
POP ACC
RETI
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -