Hello,
I am new to assembly programming. I have been doing fairly well for a while - but I have run into a bit of confusion with a software delay using the TCNT (on a Motorola 6811). I tried it out on a really simple program that samples an ADC and spits it out to a CRT via the SCI port (an ascii conversion happens in there as well). I want to sample the ADC every 1ms - which translates into 2000 cycles on the TCNT (set at 500ns). I branch to a delay subroutine that idles for the appropriate amount of time.
I find that no matter what I do I am always a few cycles off of the perfect 2000. It is driving me crazy and I have stared at it too long.
I am posting two code attempts I have made at a TCNT based software delay. I am trying to write nice code that is commented well - let me know if I am failing at that.
The first one has three seperate delay subroutines as there are 1, 2 and 3 digit outputs to the CRT each requiring a little bit different cycles for the right delay total. I am learning using the Valvano books and this s a modified program out of there so I feel totally unworthy that I can't get it to work. It is off by a few cycles no matter what I change the wait cycles to(!):
ADCTL equ $1030 ;A/D control register
ADR1 equ $1031 ;A/D result register 1
ADR2 equ $1032 ;A/D result register 2
ADR3 equ $1033 ;A/D result register 3
ADR4 equ $1034 ;A/D result register 4
OPTION equ $1039 ;system config register
TCNT equ $100E
PORTE equ $100a ;input port e
org $D000
main lds #$00FF
jsr SCI_Init
jsr ADC_Init
loop ldaa #0
jsr ADC_In
clra
jsr SCI_OutDec
ldaa #CR
jsr SCI_OutCh
bra loop
******* SUBROUTINES WAIT1, 2 & 3 ********
Wait_1 ldd TCNT
addd #1625 ;REG D = TCNT + Wait
wloop1 cpd TCNT
bpl wloop1
bra ODout
Wait_2 ldd TCNT
addd #1435 ;REG D = TCNT + Wait
wloop2 cpd TCNT
bpl wloop2
bra ODout
Wait_3 ldd TCNT
addd #1210 ;REG D = TCNT + Wait
wloop3 cpd TCNT
bpl wloop3
bra ODout
*===============================*
******Initialize ADC*******
*Inputs: None
*Outputs: None
ADC_Init ldaa #$80
staa OPTION ;ADPU=1 enables A/D
rts
******Input sample from ADC*******
*Inputs: RegA is channel number 0-7
*Outputs: RegB is ADC sample
ADC_In staa ADCTL ;4 conversions
wait ldaa ADCTL
anda #$80
beq wait ; wait for SCF
ldab ADR1
rts
*******************SCI routines************************
BAUD equ $102B ;serial baud rate control
SCCR1 equ $102C ;serial control register 1
SCCR2 equ $102D ;serial control register 2
SCSR equ $102E ;serial status register
SCDR equ $102F ;serial data register
CR equ 13
EOT equ 4
BS equ 8
SPACE equ 32
*************SCI_Init********************
* Initalize SCI
* This RITUAL is executed once
* Inputs: none Outputs: none
* Registers modified: CCR
SCI_Init psha
ldaa #$0c
staa SCCR2 enable SCI
ldaa #0
staa BAUD baud rate=125000 bps
pula
rts
* * * * * * * End of SCI_Init* * * * * * * *
***************SCI_OutCh***********************
* Output one character to SCI terminal
* Inputs: RegA is ASCII character Outputs: none
* Registers modified: CCR
TDRE equ $80
SCI_OutCh
psha
OutWait ldaa SCSR
anda #TDRE
beq OutWait Gadfly wait for TDRE
pula
* TDRE=1 when ready for more output
staa SCDR Start Output
rts
* * * * * * * * End of SCI_OutCh * * * * * * * *
****************SCI_OutDec***********************
* Output characters to SCI terminal in decimal format
* as a 16 bit unsigned number
* Inputs: RegD is an unsigned 16 bit Outputs: none
* Registers modified: CCR
SCI_OutDec
psha
pshb
pshx
pshy
ldy #0 Number of characters
ODloop ldx #10 Reg D = input
idiv RegB is digit, RegX is rest of input
pshb Save for later, reverse order
iny
xgdx
cpd #0 Continue until
bne ODloop
cpy #1
beq Wait_1
cpy #2
beq Wait_2
cpy #3
beq Wait_3
ODout pula next digit
adda #'0' convert 0-9 to ASCII 0-9
jsr SCI_OutCh
dey
bne ODout
puly
pulx
pulb
pula
rts
* * * * * * * * End of SCI_OutDec * * * * * * * *
org $FFFE
dc.w main
The second program I did myself (Gulp!) and I tried to use one subroutine that figures out itself how many TCNT cycles are left by
1.Storing the TCNT
2. Runnning through the ADC loop (No CRT or SCI stuff here)
3. Reading the TCNT again
4. NEW_TCNT - OLD_TCNT to figure out delta (branching to correct if TCNT flips)
5. Idling for remainder (2000-TCNT difference (+a few cycles))
Well, this one is off by a bit more, but same problem cropping up (off by a few cycles). It is a bit more complicated and I bet if I fugure out the first one this one will fall shortly after:
Sorry the formatting went a bit crazy
*********************************************************
*********************************************************
* *
* CHAPTER 5 - LAB 5.1 *
* *
*********************************************************
*********************************************************
*********************************************************
******************* SYMBOL DEFINITIONS ******************
*********************************************************
TMSK2 equ $1024
ADCTL equ $1030 ;A/D Control Register
ADR1 equ $1031 ;A/D Result Register 1
OPTION equ $1039 ;A/D System Config Register
PORTE equ $100A ;A/D Input PORTE
TCNT equ $100E ;Timer CouNTer Address
PERIOD equ 3800 ;Cycles for Software Delay
OVERHEAD equ 0 ;16 Bit - Timer overhead
OVERHEAD2 equ 0 ;16 Bit - Timer overhead2
******************* GLOBAL VARIABLES ********************
org $0000 ;First RAM address
OLD_TCNT rmb 2 ;16 Bit - Previous TCNT Cnt
TOTAL rmb 2 ;16 Bit - Total Cycle Cnt
*********************************************************
* *
* MAIN *
* *
*********************************************************
org $D000
main lds #$00FF ;Initialize Stack
jsr ADC_Init
ldaa #0
staa TMSK2
clc
ldd TCNT
std OLD_TCNT ;Intitialize
loop jsr ADC_In ;REG B returns ADC data
jsr Delay_1_ms ;Delay samples @ 1 KHz
ldd TCNT
std OLD_TCNT ;Save for next Calc
bra loop
*********************************************************
* FUNCTION DEFINITIONS *
*********************************************************
;FUNCTION 01 - ADC_Init ;ADC Initialization
;FUNCTION 02 - ADC_In ;Single Conversion, PE0.
;FUNCTION 03 - Delay_1_ms ;1ms Delay, TCNT cycle based
;FUNCTION 04 - SCI_Init NOT DONE
;FUNCTION 05 - SCI_OutCh NOT DONE
;FUNCTION 06 - SCI_OutDec NOT DONE
*********************************************************
***************** FUNCTION 01 - ADC_Init ****************
ADC_Init ldab #$80 ;Enable ADC (ADPU=1)
stab OPTION
rts
*=======================================================*
*********************************************************
****************** FUNCTION 02 - ADC_In *****************
ADC_In ldab #$80 ;Start Single Conversion
stab ADCTL ;on PE0
ADC_Loop ldab ADCTL
andb #$80
beq ADC_Loop
ldab ADR1 ;Data passed to main
clra ;program using REG D
rts
*=======================================================*
*********************************************************
**************** FUNCTION 03 - Delay_1_ms ***************
Delay_1_ms ldd TCNT
subd OLD_TCNT ;Get TCNT count
bmi Neg ;Correct if overflow
addd #OVERHEAD ;Correct for shared
std TOTAL ;Store as total cycles
ldd #PERIOD
subd TOTAL ;Find cycles left to cnt
addd TCNT
Del_Loop cpd TCNT
bpl Del_Loop
rts
Neg ldd #$FFFF
subd OLD_TCNT
addd TCNT
addd #OVERHEAD2 ;Return with correction
rts ;in REG D
*=======================================================*
*********************************************************
********************* RESET VECTOR **********************
*********************************************************
org $FFFE
dc.w main
*=================== END OF LISTING ====================*
Like I said I am just learning (self teaching with the Valvano books) so I have no one else to go to easily. I am assuming this is a fairly easy thing for an
experienced programmer. I have only been actually coding and simulating for just two weeks. Maybe if someone had some canned code that would show me how I am going wrong.
Thank You,
Joe