list p=18f452 ; list directive to define processor
include <p18f452.inc> ; processor specific variable definitions
include <coff.inc> ; Grab some useful macros
.command macro x
.direct "C", x
endm
;----------------------------------------------------------------------
;----------------------------------------------------------------------
GPR_DATA UDATA
temp RES 1
temp1 RES 1
temp2 RES 1
failures RES 1
a2dIntFlag RES 1 ;LSB is set when an A2D interrupt occurs
GLOBAL done
GLOBAL a2dIntFlag
;------------------------------------------------------------------------
STARTUP CODE 0
bra Start
;------------------------------------------------------------------------
;
; Interrupt Vector
;
;------------------------------------------------------------------------
INT_VECTOR CODE 0x008 ; interrupt vector location
check_TMR0_interrupt:
btfsc PIR1,ADIF ;If A2D int flag is not set
btfsc PIE1,ADIE ;Or the interrupt is not enabled
goto a2dint
.assert "\"FAIL 18F452 unexpected interrupt\""
nop
RETFIE 1 ; Then leave
;; An A/D interrupt has occurred
a2dint:
bsf a2dIntFlag,0 ;Set a flag to indicate we got the int.
bcf ADCON0,ADIF ;Clear the a/d interrupt
ExitInterrupt:
RETFIE 1
;----------------------------------------------------------------------
; ******************* MAIN CODE START LOCATION ******************
;----------------------------------------------------------------------
MAIN CODE
.sim "module library libgpsim_modules"
; Use a pullup resistor as a voltage source
.sim "module load pullup V1"
.sim "V1.resistance = 100.0"
.sim "module load pullup V2"
.sim "V2.resistance = 100.0"
; V3 and na1 required for A/D to see voltage bug ?
; RRR 5/06
.sim "module load pullup V3"
.sim "V3.resistance = 10e6"
.sim "node na0"
.sim "attach na0 V1.pin porta0"
.sim "node na1"
.sim "attach na1 V3.pin porta1"
.sim "node na3"
.sim "attach na3 V2.pin porta3"
Start:
; RA0 is an Analog Input.
; RA1 - RA5 are all configured as outputs.
;
; Use VDD and VSS for Voltage references.
;
; PCFG = 1110 == AN0 is the only analog input
; ADCS = 110 == FOSC/64
; ADFM = 0 == 6 LSB of ADRESL are 0.
;
MOVLW 1<<RA0
MOVWF TRISA
MOVLW (1<<ADCS2) | (1<<PCFG1) | (1<<PCFG2) | (1<<PCFG3)
MOVWF ADCON1
MOVLW (1<<ADCS1) | (1<<ADON)
MOVWF ADCON0
BSF INTCON,GIE ;Global interrupts
BSF INTCON,PEIE ;Peripheral interrupts
BSF PIE1,ADIE ;A2D interrupts
RCALL Convert
.assert "adresh == 0xff, \"FALIED 18F452 a2d AN0=5V\""
nop
;; The next test consists of misusing the A/D converter.
;; TRISA is configured such that the I/O pins are digital outputs.
;; Normally you want them to be configued as inputs. According to
;; the data sheet, the A/D converter will measure the voltage produced
;; by the digital I/O output: either 0 volts or 5 volts (or Vdd).
;; [I wonder if this would be a useful way of measuring the power supply ;; level in the event that there's an external reference connected to
;; an3?]
; .command "V1.resistance=1e6"
movlw 0
movwf TRISA ;Make the I/O's digital outputs
movwf ADCON1 ;Configure porta to be completely analog
bsf ADCON0,CHS0 ;Use AN1
movwf PORTA ;Drive the digital I/O's low
RCALL Convert
.assert "adresh == 0x00, \"FAILED 18F452 Digital low\""
nop
movlw 0x02
movwf PORTA ; drive bit 1 high
RCALL Convert
.assert "adresh == 0xff, \"FAILED 18F452 Digital high\""
nop
movlw 0xff
movwf TRISA ;Make the I/O's inputs
bcf ADCON0,CHS0 ;Use AN0
.command "V1.voltage=1.0"
rcall Convert
.assert "adresh == 0x33, \"FAILED 18F452 AN0=1V\""
nop
.command "V2.voltage=2.0"
bsf ADCON1,PCFG0 ; RA3 is Vref
rcall Convert
.assert "adresh == 0x80, \"FAILED 18F452 AN0=1V Vref+=2V\""
nop
done:
.assert "\"*** PASSED 18F452 a2d test\""
bra $
Convert:
BCF a2dIntFlag,0 ;Clear interrupt handshake flag
BSF ADCON0,GO
LWait:
BTFSS a2dIntFlag,0 ;Wait for the interrupt to set the flag
bra LWait
MOVF ADRESH,W ;Read the high 8-bits of the result
RETURN
end
syntax highlighted by Code2HTML, v. 0.9.1