⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prog44f.asm

📁 主要是8051源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;  PROG44f - Control From the Keyboard  
;
;  Simple Application to Run Different Songs/Sounds Using the Keyboard and
;   Turn OFF when the Bottom Right Button On the Keyboard is Pressed.
;
;  Myke Predko
;  98.05.31
;
;  Hardware Notes:
;  AT89C2051 is used as the Microcontroller
;   - Oscillator Speed is 1.8432 MHz
;  P1 is Connected to the 4x3 Keyboard
;
;   P1.1 - 3rd Row
;   P1.2 - 1st Column
;   P1.3 - 2nd Column
;   P1.4 - 1st Row
;   P1.5 - 4th Row
;   P1.6 - 3rd Column
;   P1.7 - 2nd Row
;
; P1.1 - 1        |     |
; P1.2 - 2    2-4 | 3-4 | 4-6 
; P1.3 - 3   -----+-----+-----
; P1.4 - 4        |     |
; P1.5 - 5    2-7 | 3-7 | 6-7
; P1.6 - 6   -----+-----+-----
; P1.7 - 7        |     |
;             1-2 | 1-3 | 1-6 
;            -----+-----+-----
;                 |     |
;             2-5 | 3-5 | 5-6   
;
;  P3.7 is Connected to a 8 Ohm Speaker Through 0.47 uF Cap

;  Constant Declarations
NLA  EQU 81                     ;  A  -  880 Hz
NLAS EQU 91                     ;  A# -  932 Hz
NLB  EQU 101                    ;  B  -  988 Hz
NLC  EQU 109                    ;  C  - 1046 Hz
NLCS EQU 117                    ;  C# - 1108 Hz
NLD  EQU 125                    ;  D  - 1174 Hz
NLDS EQU 133                    ;  D# - 1249 Hz
NLE  EQU 139                    ;  E  - 1318 Hz
NLF  EQU 146                    ;  F  - 1396 Hz
NLFS EQU 152                    ;  F# - 1480 Hz
NLG  EQU 158                    ;  G  - 1568 Hz
NLGS EQU 164                    ;  G# - 1662 Hz
NHA  EQU 169                    ;  A  - 1760 Hz
NHAS EQU 174                    ;  A# - 1873 Hz
NHB  EQU 178                    ;  B  - 1976 Hz
NHC  EQU 183                    ;  C  - 2094 Hz
NHCS EQU 187                    ;  C# - 2218 Hz
NHD  EQU 191                    ;  D  - 2350 Hz

;  Note Offset Table
LA  EQU 1                       ;  A  -  880 Hz
LAS EQU 2                       ;  A# -  932 Hz
LB  EQU 3                       ;  B  -  988 Hz
LC  EQU 4                       ;  C  - 1046 Hz
LCS EQU 5                       ;  C# - 1108 Hz
LD  EQU 6                       ;  D  - 1174 Hz
LDS EQU 7                       ;  D# - 1249 Hz
LE  EQU 8                       ;  E  - 1318 Hz
LF  EQU 9                       ;  F  - 1396 Hz
LFS EQU 10                      ;  F# - 1480 Hz
LG  EQU 11                      ;  G  - 1568 Hz
LGS EQU 12                      ;  G# - 1662 Hz
HA  EQU 13                      ;  A  - 1760 Hz
HAS EQU 14                      ;  A# - 1873 Hz
HB  EQU 15                      ;  B  - 1976 Hz
HC  EQU 16                      ;  C  - 2094 Hz
HCS EQU 17                      ;  C# - 2218 Hz
HD  EQU 18                      ;  D  - 2350 Hz

;  Variable Declarations
;  R0 - Note Delay Timer
;  R1 - Next Tune Value
;  R2 - Note Beat Count
;  R3 - Current Tune
;  R4 - Current Row Number Pulled Down
;  R5 - Keyboard Value Pressed

Flags EQU 020h                  ;  Bit 0 Is Set for a "Pause"
                                ;  Bit 1 Is Set for "Done"
                                ;  Bit 2 Is Complemented by 


;  Macros
MACRO Note (Value,Duration)
  db      (Value+(Duration SHL 5))
ENDMAC


;  Mainline
 org 0                          ;  Execution Starts Here
  ajmp    Mainline

 org 003h                       ;  _Int0 Pin Interrupt
 
  reti                          ;  Just Return

 org 00Bh                       ;  Timer0 Interrupt
Timer0:

  jb      0,Timer0End           ;  If a Pause, Don't Trigger the Timer

  cpl     P3.7                  ;  Toggle the Timer

Timer0End:

  reti

 org 01Bh
Timer1:                         ;  Interrupt Every 0.02 Seconds

  push    ACC                   ;  Save the Accumulator
  push    PSW

  djnz    R0,Timer1End          ;  If Not Zero, Then Don't Change Note

  mov     R0,#4                 ;  Reset the Delay Timer

  djnz    R2,Timer1End          ;  Decrement the Beat Counter

  inc     R1                    ;  Point to the Next Value

  mov     A,R1                  ;  Get the Next Note             
  acall   GetTune               ;  Get the Tune in R3
  jz      TuneEnd               ;  Are we at the End of the Tune?

  mov     B,A                   ;  Save the Note Value

  anl     A,#0E0h               ;  Save the Delay Bits
  swap a
  rr a
  mov     R2,A                  ;  Save the Delay Value

  mov     A,B                   ;  Now, Get the Note
  anl     A,#01Fh
  clr     0                     ;  Can we Output the Note?
  acall   GetNote
  mov     TL0,A                 ;   Save the Next Note
  mov     TH0,A

  jnz     Timer1End             ;  If Zero Returned, Then a Pause

  setb    0                     ;  Indicate the Pause

Timer1End:                      ;  Timer1 Interrupt Handler Finished

  pop     PSW
  pop     ACC                   ;  Restore the Accumulator

  reti

TuneEnd:                        ;  At the End of the Tune

  setb    0                     ;  Put the Output into "Pause" Mode  

  mov     A,R3                  ;  Can We Set the "Done" Flag? 
  jz      PauseEnd              ;   Not if Just Pausing
  
  mov     R2,#1                 ;  Just One Beat for the Pause
  mov     R3,#0                 ;  Run the "Pause"
  mov     R1,#0                 ;  At the First Note

  setb    1                     ;  Indicate that the Tune Has Ended

  pop     PSW
  pop     ACC                   ;  Restore the Accumulator

  reti

PauseEnd:                       ;  Return Here After a Pause

  mov     R2,#1                 ;  Just One Beat for the Pause
  mov     R3,#0
  mov     R1,#0

  pop     PSW
  pop     ACC

  reti


MainLine:                       ;  Mainline of the Program

  mov     R0,#4                 ;  R0 is the Beat Timer

  mov     R1,#0FFh              ;  R1 is the Note Counter

  mov     R3,#0                 ;  Start with "Pause"

  mov     R4,#0                 ;  Use R4 as the Row Check

  setb    0                     ;  Start with a Pause
  clr     1                     ;  Turn Off the Program Ending

  mov     R2,#1                 ;  Very Short Pause

  mov     TMOD,#%00000010       ;  Run Timer0 in Mode 2 and Timer1 in Mode 1
  mov     TH0,#0                ;  Enable the Timer to Reload at Maximum Speed  
  mov     TL0,#0
  orl     TCON,#051h            ;  Enable Timer0 to Run
                                ;   _Int0 is Edge Triggered 

  mov     IE,#%10001010         ;  Enable Timer0 Interrupt

Loop:
  cjne    R3,#0,PlayTune

  mov     R4,#0                 ;  Now, Wait for a Keypress

KeyLoop:

  mov     A,R4                  ;  Get the Key Stroke
  acall   GetRow                ;  Get the Row to Display
  mov     P1,A                  ;  Output the Value to Check

  nop                           ;  Wait for the Data to Stabilize

  mov     A,P1                  ;  Now, Look at the Buttons
  anl     A,#%01001100          ;  Clear All Bits but the Buttons
  xrl     A,#%01001100          ;  Now, Was Anything Pressed?
  jnz     HaveKey               ;  If Not Zero, Then we Do

  inc     R4                    ;  Increment the Key Row Check Value
  anl     4,#%00000011          ;  Make Sure it doesn't go above 3
  
  ajmp    KeyLoop

HaveKey:                        ;  Key Pressed, Figure Out What it is

  cjne    A,#%01000000,NotHaveKey6
  
  mov     R5,#2                 ;  Have Key Six

  ajmp    HaveKeyColumn

NotHaveKey6:

  cjne    A,#%00001000,HaveKey2 ;  Check for Column 3

  mov     R5,#1

  ajmp    HaveKeyColumn

HaveKey2:

  mov     R5,#0

HaveKeyColumn:

  mov     A,R4                  ;  Now, Get the Column Offset
  rl a                          ;  Multiply by 2
  add     A,R4                  ;  Add 1 to Multiply by 3

  add     A,R5                  ;  Add the Row Number
  mov     R5,A                  ;  Have the Row/Column Information

OpenLoop:                       ;  Wait for the Key to be Released
  mov     A,P1
  anl     A,#%01001100          ;  Should Have Zero for Release
  xrl     A,#%01001100
  jnz     OpenLoop

  mov     A,R5                  ;  Now, We Have the Tune To Play
  inc     A                     ;  Don't Want to Have a "Pause"

  clr     IE.7                  ;  Disable Interrupts During Tune Change

  mov     R3,A
  mov     R1,#0FFh              ;  Start at the First Note When Possible
  
  clr     1                     ;  Clear the "Done" bit

  setb    IE.7                  ;  Enable Interrupts for Tune Change  
  
  ajmp    Loop

PlayTune:                       ;  Wait for the Tune to End
  jnb     1,PlayTune            ;  Loop On the Tune Being Played
  
  clr     1                     ;  Clear the "Done" Bit

  cjne    R5,#11,Loop           ;  If Not Button 11, then Loop Around Again

  mov     P1,#%10111100         ;  Enable the Idle Mode Reset

  nop

  clr     TCON.1                ;  Clear TCON Interrupt

  mov     IE,#081h              ;  Just Enable Pin _Int0

  orl     PCON,#1               ;  Put the AT89C2051 Into "Idle" Mode

  mov     P1,#0FCh              ;  Put All of the Lines High Again

  nop

  mov     IE,#08Ah              ;  Turn Off the _Int0 Pin and Turn On Timer Interrupts

  mov     A,R5                  ;  Play the Note Again
  inc     A                     ;  Don't Want to Have a "Pause"

  clr     IE.7                  ;  Disable Interrupts During Tune Change

  mov     R3,A
  mov     R1,#0FFh              ;  Start at the First Note When Possible
  
  clr     1                     ;  Clear the "Done" bit

  mov     R5,#0                 ;  Make Sure We Don't Fall Into a Loop

  setb    IE.7                  ;  Enable Interrupts for Tune Change  

  ajmp    Loop                  ;  Now, Wait for the Next Keystroke


GetNote:                        ;  Return the Note Value for the Index in "A"

  add     A,#(NoteTable-InitNoteTable)  ;  Restore the Table Position with Note
  movc A,@A+PC			;  Get the Table Value
InitNoteTable:			;  Table Offset to Display

  ret

NoteTable:                      ;  Table of Notes
  db      0                     ;  First Value is a "Pause"
  db      NLA
  db      NLAS
  db      NLB
  db      NLC
  db      NLCS
  db      NLD
  db      NLDS
  db      NLE
  db      NLF
  db      NLFS
  db      NLG
  db      NLGS
  db      NHA
  db      NHAS
  db      NHB
  db      NHC
  db      NHCS
  db      NHD


GetRow:                         ;  Return the Next Table Value to Drop

  add     A,#(RowTable-InitRowTable)  ;  Restore the Table Position with Note
  movc A,@A+PC			;  Get the Table Value
InitRowTable:			;  Table Offset to Display

  ret

RowTable:                       ;  Table of Rows to Disable
  db      0EEh                  ;  Row 4 (First Row)
  db      07Eh                  ;  Row 7 (Second Row)
  db      0FCh                  ;  Row 1 (Third Row)
  db      0DEh                  ;  Row 5 (Fourth Row)


GetTune:                        ;  According to R3, Get the Correct Tune

  push    ACC                   ;  Save the Tune Value

  mov     DPTR,#TuneTable

  mov     A,R3                  ;  Get the Song to Play
  rl a

  jmp @A+DPTR                   ;  Jump to the Correct Song Subroutine

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -