EMICROS How-To-Guide; Using the 68hc11 Analog to Digital Converter


The following is contained in this document;


The 68HC11 contains an 8 channel A/D that converts an analog input signal to an 8-bit digit value. One of the 8 input lines (PORTE) are connected to the A/D using an internal multiplexer. The A/D is a successive approximation with a sample and hold circuit to minimize error caused by fast changing signals. Linearity error is +-1/2 least significant bit. Vrh and Vrl provides the input for the voltage reference and is usually connected to +5v for Vrh and ground for Vrl.

The A/D is enabled by setting the ADPU bit (7) of the OPTION register ($1039). The ADCTL register ($1030) controls the operation of the A/D. The channel is selected by writting the number to bits 0-3. The SCAN bit (5) selects 4 conversions and stop (0), or convert continuous (1). Also, a single conversion or 4 channels can be converted if the MULT bit (4) is cleared or set. The conversion is completed when the CCF bit (7) is set to 1. The results are written to registers AD1-ADR4 ($1031-$1034).

The A/D charge pump is clocked by either of 2 sources, E-clock or a 2.5Mhz RC internal oscillator. Selection is by clearing (E-clock) or setting (2.5Mhz RC) the CSEL bit (6) in the OPTION register ($1039). Under normal operating conditions with a 2Mhz E-clock (8Mhz oscillator), use the E-clock option. The internal RC is recommended for E-clocks less than 1Mhz.

The A/D will resume normal operations after a WAIT or STOP mode (STOP mode must exit with delay). It is recommended to turn off the A/D before STOP or WAIT mode is entered. The following shows 2 A/D routines, a normal 4 sample/64usec routine, and a fast 16usec routine.

*----------------------------------------------------------------------
* subroutine:   AD_READ
* description:  This subroutine reads the A/D channel in A and returns
*               value in A.
*----------------------------------------------------------------------
AD_READ
	STAA    ADCTL           ; Start the conversion
ADL00   LDAA    ADCTL           ; Get the status
	BPL     ADL00           ; Wait until complete, bit 7 is set
	LDAA    ADR4            ; Return the result in A
	RTS                     ; Return from subroutine
*----------------------------------------------------------------------
* subroutine:   FAST_AD_READ
* description:  This subroutine reads the A/D channel in 16useconds.
*----------------------------------------------------------------------
FAST_AD_READ
	STAA    ADCTL           ; Start the conversion
	LDAB    #6              ; 1us - Load Loop counter
ADF00   DECB                    ; 6 x 1us - Decrement the loop counter
	BNE     ADF00           ; 6 x 1.5us - Loop back if not done
	LDAA    ADR1            ; Get results to A
	RTS                     ; Return from subroutine

68hc11 Analog to Digital Tutorial

Let's design an application to show how to use the A/D converter. In this example, the micro does the following;

  1. Wait for a serial command to read an A/D channel
  2. Converts the received A/D channel
  3. Sends the converted A/D results out the serial interface

The general format of the 68hc11 program is to initialize the system, initialize the serial channel, and then wait for a byte to be received on the serial channel. Notice that the interrupts are disable and the micro 'polls' the serial data receive flag for a received character. The following shows the Read A/D Software. This program can be assembled and executed on the DEV11 board.


*-----------------------------------------------------------------------
* file:         A2D.SRC
* description:  The file is the 68hc11 A/D example.
* last update:  1/6/96 rpr
*
* Assembling Instruction: Using the MOTOROLA Freeware Assembly program
*                         with the following command line input.
*
*                         as11 a2d.src register.src -l cre >a2d.lst
*-----------------------------------------------------------------------
	ORG     $8000           ; Set the program starting address.
				; $8000 is for 32k DEV11 board.
				; $E000 is for 8k parts (A8). 
				; $D000 for 12k parts (E9).
*----------------------------------------------------------------------
* ISR:  RESET
*----------------------------------------------------------------------
RESET   LDS     #$1FF           ; Set the Top of Stack
	BSR     FIRST64         ; Setup the time-protected registers
*----------------------------------------------------------------------
* MAINLOOP BACKGROUP PROCESSING
*
* The main loop is continuously executed.
*----------------------------------------------------------------------
MAIN    LDS     #$1FF           ; Maintain the top of stack
	SEI                     ; Keep interrupts disabled
	BSR     MAINTAIN        ; Make sure registers are set
	BSR     RESET_WATCHDOG  ; Reset the watchdog timer
*-------------------------------------------
* Check for a received A/D channel number 
*-------------------------------------------
	LDAA    SCSR            ; Get the SCI status register
	ANDA    #RDRF           ; Mask out the receiver full flag
	BEQ     MAIN            ; Loop back if no new received character
	LDAA    SCDR            ; Get A/D channel number
	ANDA    #$07            ; Allow only channels 0 - 7
	BSR     AD_READ         ; Read the requested A/D channel
	STAA    SCDR            : Send the results out the serial interface
	BRA     MAIN            ; Branch back and execute again
*----------------------------------------------------------------------
* subroutine:   FIRST64
* description:  This subroutine initializes the time-protected registers
*               that can only be set within the first 64 E-cycles.
*               This is done for a hard reset, COP reset, or Clock
*               Monitor fail.
*----------------------------------------------------------------------
FIRST64
	LDAA    #$01            ; Locate registers at $1000, RAM at $0000
	STAA    INIT            ; INIT = #$01

	LDAA    #ADPU+IRQE+DLY+CR1 ; Turn on the A/D, set /IRQE for edge,
	STAA    OPTION          ; enable STOP startup delay, set COP timeout
*                               ; period to 262.14 ms

	LDAA    #PR0            ; Set TMSK2. Select 2us/cnt for timers
	STAA    TMSK2           ; $00 --> prescaler = 1 (1us/cnt),  65ms overflow
*                               ; $01 --> prescaler = 4 (2us/cnt), 131ms overflow
*                               ; $02 --> prescaler = 8 (4us/cnt), 262ms overflow
*                               ; $03 --> prescaler =16 (8us/cnt), 524ms overflow
*
	RTS                     ; Return from subroutine
*----------------------------------------------------------------------
* subroutine:   RESET_WATCHDOG
* description:  This subroutine writes the reset pattern to the COP
*               reset register ($103A).
*----------------------------------------------------------------------
RESET_WATCHDOG
	LDD     #$55AA          ; Set values to reset watchdog timer
	STAA    COPRST          ; Write the $55
	STAB    COPRST          ; Write the $AA. This completes the reset
	RTS                     ; Return from subroutine
*----------------------------------------------------------------------
* subroutine:   AD_READ
* description:  This subroutine reads the A/D channel in A and returns
*               value in A.
*----------------------------------------------------------------------
AD_READ
	STAA    ADCTL           ; Start the conversion
ADL00   LDAA    ADCTL           ; Get the status
	BPL     ADL00           ; Wait until complete, bit 7 is set
	LDAA    ADR4            ; Return the result in A
	RTS                     ; Return from subroutine
*----------------------------------------------------------------------
* subroutine:   MAINTAIN
* description:  This subroutine maintains the base configuration by
*               continually rewritting the registers that are constant.
*
* returns:      A = 0
*----------------------------------------------------------------------
MAINTAIN
	CLRA                    ; Clear the A register for use here.
	STAA    TMSK2           ; Disable Timer Overflow Interrupt
*                               ; Disable Real-Time Interrupt
*                               ; Disable Pulse Accumulator interrupts. 
*                               ; Timer prescaler PR1,PR0 = 1 factor
*                               ; Note: PR1 & PR0 time-protected but must be
*                               ;       maintained incase MAINTAIN is executed
*                               ;       within 64 E-cycles
	STAA    TMSK1           ; Disable Output Compares and Input Captures
*
* Enable SCI receiver and transmitter, no interupts
*
	LDAB    #TE+RE          ; Set SCCR2
	STAB    SCCR2           ;
*
* Keep baud rate at 9600 buad
*
	LDAB    #$30            ; Don't want to rewrite baud rate all the time
	CMPB    BAUD            ;
	BEQ     M01
	STAB    BAUD
M01     RTS                     ; Return from subroutine
*----------------------------------------------------------------------
*       INTERRUPT VECTORS
*----------------------------------------------------------------------
* The following table defines the interrupt vectors. Whenever an interrupt
* is acknowledged, the address contained in the vector table associated
* with the interrupt needing attention is vectored (jumped) to.
*----------------------------------------------------------------------
	ORG     $FFC0

	FDB     RESET           ; Serial Communications
	FDB     RESET           ; Serial Peripherial Interface
	FDB     RESET           ; Pulse Accumulator Input Edge
	FDB     RESET           ; Pulse Accumulator Overflow
	FDB     RESET           ; Timer Overflow
	FDB     RESET           ; Timer Output Compare #5
	FDB     RESET           ; Timer Output Compare #4
	FDB     RESET           ; Timer Output Compare #3
	FDB     RESET           ; Timer Output Compare #2
	FDB     RESET           ; Timer Output Compare #1
	FDB     RESET           ; Timer Input Capture #3
	FDB     RESET           ; Timer Input Capture #2
	FDB     RESET           ; Timer Input Capture #1
	FDB     RESET           ; Real Time Interrupt
	FDB     RESET           ; /IRQ
	FDB     RESET           ; /XIRQ
	FDB     RESET           ; Software Interrupt
	FDB     RESET           ; Illegal Opcode
	FDB     RESET           ; Watchdog (COP) timer reset
	FDB     RESET           ; Clock monitor fail
	FDB     RESET           ; Power on, /RESET vector
*----------------------------------------------------------------------
*       End of file A2D.SRC
*----------------------------------------------------------------------

The following is a QuickBasic program to send the channel to the micro and read the results.

'----------------------------------------------------------
' file:         A2D.BAS
'
' description:  This file is the basic interface file for
'               the 68hc11 A/D tutorial.
'
' last update:  January 6, 1996 rpr
'----------------------------------------------------------
CLS
PRINT "opening com1"
OPEN "COM1:9600,N,8,1,cd0,cs0,ds0,rb1000" FOR RANDOM AS #1
PRINT "com1 opened"

ak$ = ""
DO WHILE ak$ <> "E"
     ak$ = UCASE$(INKEY$)
     IF ak$ <> "" THEN
	IF ak$ >= "0" AND ak$ <= "7" THEN
	   x = VAL(ak$) - VAL("0")
	   PRINT "Sending Channel "; x
	   PRINT #1, CHR$(x);
	   y = 0
	   WHILE LOC(1) < 1 AND y < 5000
	      y = y + 1
	   WEND
	   IF y >= 5000 THEN
	      PRINT "Value not received"
	      BEEP
	   ELSE
	      z = ASC(INPUT$(1, #1))
	      PRINT "A/D Channel #"; x; "="; z
	   END IF
	ELSEIF ak$ = "E" THEN
	   PRINT "A2D example completed."
	ELSE
	   PRINT "Invalid entry."
	END IF
     END IF
LOOP
END

Last update; January 6, 1996