I need some help with an assembly language program. I am in the process of writi
ID: 1813436 • Letter: I
Question
I need some help with an assembly language program. I am in the process of writing a program which is supposed to diplay a
digital clock on the 68HC11 microcontroller trainer board. When I try to download the program to the board, I get a "RCVR Error"
message and I can't figure out why. I also need to add the ability to use the dip switches to increase the time by one hour when
a swtich is turned on. Here is what I have so far.
MODE_EH EQU $00
MODE_EL EQU $01
INT_COUNT EQU $02
TEMP0 EQU $03
DIS_1_2 EQU $62
DIS_END EQU $73
TIMER_COUNT EQU 5000
ORG $B600 ; Start of EEPROM
INTIT:
LDX #$400f ; set up Control Mode
STX MODE_EH
LDAB #$FF
STAB $1007 ; set port C, all bits for output
LDAB #$04
LOOPB:
LDAA #$03
JSR Write_Nibble
LDX #$0480 ; 1152 loops * 3.5 uS = 4.032 mS
LOOPY1:
DEX ; 4 cycles = 2 uS
BNE LOOPY1 ; 3 cycles + ? = 1.5 uS
DECB
BNE LOOPB
LDX #LCD_Init_Table
MOREINTIT:
LDAA $00,x
BEQ LCD_Init_Done
BSR Write_C_Byte
INX
BRA MoreInit
LCD_Init_Done:
CopyLCDTable:
ldx #DIS_1_2 ; To
ldy #Display_1_2 ; From
Copy_More:
ldaa $00,y
staa $00,x
inx
iny
cpx #DIS_END
bne Copy_More
CopyJMP:
ldx IntJmp
stx $100-33
ldaa IntJmp+2
staa $100-33+2
InitTimer:
jsr Inc_Timer ; A will be set to #$80
staa $1022 ; Enable timer 1
ldaa #$14
staa $00
tpa ; clear interrupt disable mask
anda #$EF
tap
ldaa #$80 ; clear any pending events
staa $1023
InitVars:
ldx #$0000
ldaa #40 ; 50000 * 500 nS * 40 = 1 second.
staa INT_COUNT
ldx #Display_1_1
bsr Write_Line_1
ldx #DIS_1_2
bsr Write_Line_2
LoopHere:
bra LoopHere
LCD_Init_Table:
fcb $28
fcb $08
fcb $01
fcb $06
fcb $0C
fcb $00
Wait4BF:
Delay:
pshb
ldab #$10 ; 16 loops * 2.5 uS = 40 uS
d_loop: decb ; 3 cycles = 1.0 uS
bne d_loop ; 3 cycles = 1.5 uS
pulb
rts
Write_Line_1:
psha
pshx
ldaa #$80 ; Line 1 in Display Data RAM
bra Write_Line
Write_Line_2:
psha
pshx
ldaa #$A8 ; Line 2 in Display Data RAM ($80 + 40 ($28))
Write_Line:
bsr Write_C_Byte
Next_Character:
ldaa $00,x
beq Write_Line_Done
bsr Write_D_Byte
inx
bra Next_Character
Write_Line_Done:
pulx
pula
rts
Write_D_Byte:
pshx
ldx #$501F
bra Write_LCD_Byte
Write_C_Byte:
pshx
ldx #$400F
Write_LCD_Byte:
stx MODE_EH
pulx
psha
lsra
lsra
lsra
lsra
bsr Wait4BF
bsr Write_Nibble
pula
psha
bsr Write_Nibble
cmpa #$01
bne Not_Clear
ldaa #$20 ; 32 * 50uS = 1.6 mS
Do_Not_Clear:
bsr Wait4BF
deca
bne Do_Not_Clear
Not_Clear:
pula
rts
Write_Nibble:
psha
anda #$0F ; set upper 4 bits to zero
oraa MODE_EH ; E=H, R/W=L, RS=H or L
staa $1003
anda MODE_EL ; E=L, R/W=L, RS=H or L
staa $1003
pula
rts
IntJmp JMP Interrupt
Inc_Timer:
ldd #TIMER_COUNT
addd $1016
std $1016
ldaa #$80
staa $1023
rts
Interrupt:
dec INT_COUNT
bne Over
ldaa #40 ; 50000 * 500 nS * 40 = 1 second.
staa INT_COUNT
bsr Inc_Display
ldx #DIS_1_2
bsr Write_Line_2
Over:
bsr Inc_Timer
rti
* End of Interrupt
Inc_Display:
ldx #DIS_1_2
bsr Inc_Time
Not_Off_Hook:
rts
Inc_Time:
inc $0F,x ; Tenths
ldaa $0F,x
cmpa #'5
bne Over_Colon
ldaa #' ; space
staa $0E,x
staa $0B,x
staa $08,x
bra Time_Done
Over_Colon:
cmpa #'9+1
bne Time_Done
ldaa #'0
staa $0F,x
ldaa #':
staa $0E,x
staa $0B,x
staa $08,x
dex
dex
bsr Inc_Digits ; Seconds
cmpa #'6
bne Time_Done
bsr Zero_Digit
cmpa #'6 ; minutes
bne Time_Done
bsr Zero_Digit
cpd #'2'4 ; Hours
bne Time_Done
ldd #'0'0
std $0E,x
Time_Done:
rts
Inc_Digits:
inc $0F,x
ldaa $0F,x
cmpa #'9+1
bne Dig_Done
ldaa #'0
staa $0F,x
inc $0E,x
Dig_Done:
ldd $0E,x ; get ready for cmp
rts
Zero_Digit:
ldaa #'0
staa $0E,x
dex
dex
dex
bsr Inc_Digits
rts
* LCD Display tables
Display_1_1:
fcc "The Time Is "
fcb $00
Display_1_2:
fcc "HMST 00:00:00:0"
fcb $00
Here is a link to the programmers guide
http://www.freescale.com/files/microcontrollers/doc/ref_manual/M68HC11ERG.pdfhref="http:>
Explanation / Answer
PT l,c,cre,s *======================================================================== * Program organization: * * Init * +-WriteNibble * | +-Wait4BF * MoreInit * +-WriteCByte * | +-Wait4BF * CopyLCDTable * CopyJMP * InitTimer * +-Inc_Timer * InitVars * LoopHere * * Interrupt * +-Check_Input * +-Inc_Displays * +-Display_LCD * * The LCD is connected to port C with the following bit assignments: * V+ :LCD2 * Gnd :LCD1 * Vref:LCD3 * C0 :LCD11 data I/O to LCD data bit 4 * C1 :LCD12 data I/O to LCD data bit 5 * C2 :LCD13 data I/O to LCD data bit 6 * C3 :LCD14 data I/O to LCD data bit 7 * C4 :LCD4 RS (register select) L=control, H=data * C5 :LCD5 R/W H=read, L=write * C6 :LCD6 E (enable) H is enabled, transaction on H->L edge. * C7 -unused- * *======================================================================== * RAM usage: * $00-$01 Mode variables * * MODE_EH $00 Mode (data/control) with Enable High * MODE_EL $01 Mode (data/control) with Enable Low * INT_COUNT $02 Interput count, 40 for a second. * TEMP0 $03 Tempory variable space * * Display data: * Mode) * 1) $62-72 'Tom's LCD Clock ' $0 * $95-A5 ' hh:mm:ss' $00 * * $DF-E1 JMP Instruction for timer 1 interrupt (In boot ROM) * $E2-FF Stack (30 bytes: RTI uses 9 bytes) * *======================================================================== * Addresses of RAM variables: MODE_EH EQU $00 MODE_EL EQU $01 INT_COUNT EQU $02 TEMP0 EQU $03 * Addresses of RAM Display Tables: DIS_1_2 EQU $62 DIS_END EQU $73 *======================================================================== * Numeric Constants: TIMER_COUNT EQU 5000 *======================================================================== *======================================================================== * Initialization: ORG $B600 ; Start of EEPROM Init: ldx #$400f ; set up Control Mode stx MODE_EH ldab #$FF stab $1007 ; set port C, all bits for output ldab #$04 LOOPB: ldaa #$03 jsr Write_Nibble ldx #$0480 ; 1152 loops * 3.5 uS = 4.032 mS LOOPY1: dex ; 4 cycles = 2 uS bne LOOPY1 ; 3 cycles + ? = 1.5 uS decb bne LOOPB ldx #LCD_Init_Table *======================================================================== MoreInit: ldaa $00,x beq LCD_Init_Done bsr Write_C_Byte inx bra MoreInit LCD_Init_Done: *======================================================================== CopyLCDTable: * Copy the LCD Display Tables to RAM ldx #DIS_1_2 ; To ldy #Display_1_2 ; From Copy_More: ldaa $00,y staa $00,x inx iny cpx #DIS_END bne Copy_More *======================================================================== CopyJMP: * copy the jump to the interrupt vector location for timer 1 ldx IntJmp stx $100-33 ldaa IntJmp+2 staa $100-33+2 *======================================================================== InitTimer: * Initialize the interrupt timer jsr Inc_Timer ; A will be set to #$80 staa $1022 ; Enable timer 1 ldaa #$14 staa $00 tpa ; clear interrupt disable mask anda #$EF tap lda #$80 ; clear any pending events sta $1023 *======================================================================== InitVars: * Initialize variables ldx #$0000 ldaa #40 ; 50000 * 500 nS * 40 = 1 second. staa INT_COUNT *======================================================================== ldx #Display_1_1 bsr Write_Line_1 ldx #DIS_1_2 bsr Write_Line_2 *======================================================================== LoopHere: bra LoopHere *======================================================================== *======================================================================== LCD_Init_Table: fcb $28 ; Data length (bit 4) = 4-bit, number of lines (bit 2) = 2 fcb $08 ; Display on (bit 2), cursor on (bit 1), blink cursor (bit 0) fcb $01 ; Clear display fcb $06 ; Entry mode, I/D (bit 1) inc/dec, S (bit) display shift fcb $0C ; Display on (bit 2), cursor on (bit 1), blink cursor (bit 0) fcb $00 *======================================================================== Wait4BF: Delay: pshb ldb #$10 ; 16 loops * 2.5 uS = 40 uS d_loop: decb ; 3 cycles = 1.0 uS bne d_loop ; 3 cycles = 1.5 uS pulb rts *======================================================================== Write_Line_1: * ; x points to start of NULL terminated line psha pshx ldaa #$80 ; Line 1 in Display Data RAM bra Write_Line *------------------------------------------------------------------------ Write_Line_2: psha pshx ldaa #$A8 ; Line 2 in Display Data RAM ($80 + 40 ($28)) *------------------------------------------------------------------------ Write_Line: bsr Write_C_Byte Next_Character: lda $00,x beq Write_Line_Done bsr Write_D_Byte inx bra Next_Character Write_Line_Done: pulx pula rts *======================================================================== Write_D_Byte: pshx ldx #$501F ; Masks for Data mode bra Write_LCD_Byte *------------------------------------------------------------------------ Write_C_Byte: pshx ldx #$400F ; Masks for Control mode *------------------------------------------------------------------------ Write_LCD_Byte: stx MODE_EH pulx psha lsra lsra lsra lsra bsr Wait4BF bsr Write_Nibble pula psha bsr Write_Nibble cmpa #$01 ; if clear, then we need to wait 1.64 mS bne Not_Clear ldaa #$20 ; 32 * 50uS = 1.6 mS Do_Not_Clear: bsr Wait4BF deca bne Do_Not_Clear Not_Clear: pula rts *======================================================================== * Write nibble is low 4 bits of A Write_Nibble: psha anda #$0F ; set upper 4 bits to zero oraa MODE_EH ; E=H, R/W=L, RS=H or L staa $1003 anda MODE_EL ; E=L, R/W=L, RS=H or L staa $1003 pula rts *======================================================================== IntJmp JMP Interrupt ; Code to copy to RAM jump vector for Timer 1 *======================================================================== Inc_Timer: ldd #TIMER_COUNT ; Add 50,000 to timer 1 to get next time addd $1016 ; timer std $1016 lda #$80 ; clear any pending events sta $1023 ; init routines assumes A = #$80 rts *======================================================================== *======================================================================== * The timer is incremented every 500 nS, * 50000 = 25 mS * 40 = 1 Sec Interrupt: dec INT_COUNT bne Over ldaa #40 ; 50000 * 500 nS * 40 = 1 second. staa INT_COUNT bsr Inc_Display ldx #DIS_1_2 bsr Write_Line_2 Over: bsr Inc_Timer rti * End of Interrupt *======================================================================== *======================================================================== Inc_Display: ldx #DIS_1_2 bsr Inc_Time Not_Off_Hook: rts *======================================================================== Inc_Time: inc $0F,x ; Tenths ldaa $0F,x cmpa #'5 bne Over_Colon ldaa #' ; space staa $0E,x staa $0B,x staa $08,x bra Time_Done Over_Colon: cmpa #'9+1 bne Time_Done ldaa #'0 staa $0F,x ldaa #': staa $0E,x staa $0B,x staa $08,x dex dex bsr Inc_Digits ; Seconds cmpa #'6 bne Time_Done bsr Zero_Digit cmpa #'6 ; minutes bne Time_Done bsr Zero_Digit cpd #'2'4 ; Hours bne Time_Done ldd #'0'0 std $0E,x Time_Done: rts *======================================================================== Inc_Digits: inc $0F,x ldaa $0F,x cmpa #'9+1 bne Dig_Done ldaa #'0 staa $0F,x inc $0E,x Dig_Done: ldd $0E,x ; get ready for cmp rts *======================================================================== Zero_Digit: ldaa #'0 staa $0E,x dex dex dex bsr Inc_Digits rts *======================================================================== *======================================================================== * LCD Display tables Display_1_1: fcc "Tom's LCD Clock " fcb $00 Display_1_2: fcc "HMSt 00:00:00:0" fcb $00