📄 muscle.asm
字号:
; Sample program: Microcontroller-Manipulated Metal Muscles
;
; Copyright (C) Brett Glass 1990
;
; Commercial use by permission only
;
; Serial port and timer parameters
SCONINI EQU 01010010b ; Set UART for 8 bits, no interprocessor
; communication features, ready to transmit.
PCONINI EQU 01000000b ; No double baud rate; give access to FE
T1CONBITS EQU 11001100b ; Timer 1 bits in TCON
T1MODBITS EQU 11110000b ; Timer 1 bits in TMOD
T1AUTORELMOD EQU 00100000b ; Set this bit in TMOD for Timer 1
; auto-reload mode
TH1INI EQU -104 ; 300 baud -- Constant for Timer 1 (.1-.2% error)
T0CONBITS EQU 00110011b ; Timer 0 bits in TCON
T0MODBITS EQU 00001111b ; Timer 0 bits in TMOD
T0AUTORELMOD EQU 00000010b ; Set this bit in TMOD for Timer 0
; auto-reload mode
TH0INI EQU 11111100b ; Make Timer 0 overflow and
; reload every 4 counts, making
; a divide-by-4 prescaler.
CMODINI EQU 00000100b ; Initialize PCA to use Timer 0 as
; a prescaler
PCM EQU 01000010b ; Set a PCA module for PCM mode
; Initial stack pointer
INITSP EQU 7Fh ; Use the top 128 bytes of RAM for the
; stack. This is not possible on all 8051
; derivatives, so you may need to change
; this equate in your system.
DEACTIVATE EQU P0.0,BIT ; Deactivates Biometal driver
LED EQU P0.1,BIT ; In my test setup, this bit lights an
; LED when cleared. Used to monitor
; serial transmit.
; PCA Register definitions (AVCASE does not include these)
CCON EQU 0D8h ; PCA Counter Control Register
CMOD EQU 0D9h ; PCA Counter Mode Register
CL EQU 0E9h ; PCA Counter Low
CH EQU 0F9h ; PCA Counter High
CCAPM0 EQU 0DAh ; Compare/Capture Module 0 Mode
CCAP0L EQU 0EAh ; Compare/Capture Register 0 Low
CCAP0H EQU 0FAh ; Compare/Capture Register 0 High
CCAPM1 EQU 0DBh ; Compare/Capture Module 1 Mode
CCAP1L EQU 0EBh ; Compare/Capture Register 1 Low
CCAP1H EQU 0FBh ; Compare/Capture Register 1 High
CCAPM2 EQU 0DCh ; Compare/Capture Module 2 Mode
CCAP2L EQU 0ECh ; Compare/Capture Register 2 Low
CCAP2H EQU 0FCh ; Compare/Capture Register 2 High
CCAPM3 EQU 0DDh ; Compare/Capture Module 3 Mode
CCAP3L EQU 0EDh ; Compare/Capture Register 3 Low
CCAP3H EQU 0FDh ; Compare/Capture Register 3 High
CCAPM4 EQU 0DEh ; Compare/Capture Module 4 Mode
CCAP4L EQU 0EEh ; Compare/Capture Register 4 Low
CCAP4H EQU 0FEh ; Compare/Capture Register 4 High
CR EQU CCON.6,BIT ; Define CR (Counter Run) for PCA
START:
SETB DEACTIVATE ; Deactivate the PCM output to the wire
CLR LED ; Turn LED on
MOV SCON,#SCONINI ; Configure SCON
MOV PCON,#PCONINI ; Configure PCON
ANL TCON,#LOW(NOT T1CONBITS) ; Clear Timer 1 bits in TCON
ANL TMOD,#LOW(NOT T1MODBITS) ; Clear Timer 1 bits in TMOD
ORL TMOD,#T1AUTORELMOD ; Put Timer 1 in auto-reload mode
MOV TH1,#TH1INI ; Set baud rate
MOV TL1,#TH1INI ; in both registers
SETB TR1 ; Start Timer 1 baud rate generator
ANL TCON,#LOW(NOT T0CONBITS) ; Clear Timer 0 bits in TCON
ANL TMOD,#LOW(NOT T0MODBITS) ; Clear Timer 0 bits in TMOD
ORL TMOD,#T0AUTORELMOD ; Put Timer 1 in auto-reload mode
MOV TH0,#TH0INI ; Set prescale count
MOV TL0,#TH0INI ; in both registers
SETB TR0 ; Start prescaler
MOV CMOD,#CMODINI ; Configure PCA timer
MOV CCAPM0,#PCM ; Set PCA module 0 to PCM mode
MOV CCAP0L,#0 ; Reset module's counter to 0
MOV CCAP0H,#0 ; Start the PWM counter at 0 (0% duty cycle)
MOV CL,#0 ; Zero PCA counter
MOV CH,#0
SETB CR ; Start PCA via Counter Run bit
MOV SP,#INITSP ; Move the stack
MOV DPTR,#INTROMSG ; Send a message
ACALL SNDSTR
BEEP:
MOV A,#07h ; Send an ASCII BEL character
ACALL SNDCHR
REPEAT: ; Interactive loop
ACALL GETCHR ; Get a character
ACALL SNDCHR ; Echo it
CLR C ; Clear carry
SUBB A,#'0' ; Subtract ASCII '0'
JZ ZERO ; If '0', special processing
JC REPEAT ; If less than '0', it wasn't a digit
; from '0' through '7', of course.
CJNE A,#8,NOTEIGHT ; Compare nondestructively to the number '8'
JMP BEEP ; A '8' is ignored
NOTEIGHT
JNC BEEP ; Anything over '8' is ignored.
; If execution reaches this point, we
; have a number corresponding to a
; digit between 1 and 7, inclusive.
RL A ; Shift the number, multiplying it by 32
RL A ; The maximum duty cycle is produced when
RL A ; a 7 is entered, in which case
RL A ; it's 7/8.
RL A
MOV CCAP0H,A ; Move the count into the PWM register
CLR DEACTIVATE ; Activate the output
JMP REPEAT
ZERO:
SETB DEACTIVATE ; Deactivate Biometal driver
MOV CCAP0H,#0h ; Set 0% duty cycle
JMP REPEAT
INTROMSG:
DB 0DH,0AH
DB "Hit 1-7 to activate Biometal with different duty cycles."
DB 0DH,0AH
DB "Hit 0 to deactivate Biometal."
DB 0DH,0AH,0
SNDCHR PROC ; Routine to send a character
CLR LED ; Turn on the LED to indicate we are sending
JNB TI,$ ; Wait until the UART is ready
CLR TI ; Mark it as not ready
MOV SBUF,A ; Send character
SETB LED ; Turn off the LED
RET ; And return
SNDCHR ENDPROC
SNDSTR PROC ; Routine to send a string pointed to
; by R0. R0 destroyed on return.
MOV A,#0 ; Clear the accumulator
MOVC A,@A+DPTR ; Get a character
JNZ L?SEND ; If null, we're done
RET
L?SEND:
ACALL SNDCHR ; Otherwise send the character
INC DPTR ; And increment the pointer
JMP SNDSTR
SNDSTR ENDPROC
GETCHR PROC ; Routine to get a character
JNB RI,$ ; Loop until character received
CLR RI ; Clear received char flag right away
JNB RB8,GETCHR ; If framing error (stop bit not a 1),
; reject character
MOV A,SBUF ; Get char into A
RET
GETCHR ENDPROC
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -