1 2 list p=16f874a 3 include <p16f874a.inc> 4 include <coff.inc> 5 6 __CONFIG _WDT_OFF 7 8 ;; The purpose of this program is to test gpsim's ability to simulate a pic 16c71. 9 ;; Specifically, the a/d converter is tested. 10 11 errorlevel -302 12 13; Printf Command 14.command macro x 15 .direct "C", x 16 endm 17 18;---------------------------------------------------------------------- 19;---------------------------------------------------------------------- 20GPR_DATA UDATA_SHR 21 22x RES 1 23t1 RES 1 24t2 RES 1 25avg_lo RES 1 26avg_hi RES 1 27w_temp RES 1 28status_temp RES 1 29 30 31;---------------------------------------------------------------------- 32; ********************* RESET VECTOR LOCATION ******************** 33;---------------------------------------------------------------------- 34RESET_VECTOR CODE 0x000 ; processor reset vector 35 movlw high start ; load upper byte of 'start' label 36 movwf PCLATH ; initialize PCLATH 37 goto start ; go to beginning of program 38 39INT_VECTOR CODE 0x004 ; interrupt vector location 40 ;; 41 ;; Interrupt 42 ;; 43 movwf w_temp 44 swapf STATUS,W 45 movwf status_temp 46 47 bcf STATUS,RP0 ;adcon0 is in bank 0 48 49 btfsc INTCON,ADIE 50 btfsc PIR1,ADIF 51 goto check 52 .assert "'FAILED 16F874a unexpected interrupt'" 53 nop 54 55;; An A/D interrupt has occurred 56check: 57 bsf t1,0 ;Set a flag to indicate we got the int. 58 bcf PIR1,ADIF ;Clear the a/d interrupt 59 60 swapf status_temp,w 61 movwf STATUS 62 swapf w_temp,F 63 swapf w_temp,W 64 retfie 65 66 67 68;---------------------------------------------------------------------- 69; ******************* MAIN CODE START LOCATION ****************** 70;---------------------------------------------------------------------- 71MAIN CODE 72start: 73 74 .sim "module library libgpsim_modules" 75 ; Use a pullup resistor as a voltage source 76 .sim "module load pullup V1" 77 .sim "V1.resistance = 100.0" 78 79 .sim "node na0" 80 .sim "attach na0 V1.pin porta0" 81 82 .sim "module load pullup V2" 83 .sim "V2.resistance = 100.0" 84 85 .sim "node na1" 86 .sim "attach na1 V2.pin porta3" 87 88 ;; Let's use the ADC's interrupt 89 ; RA0 is an Analog Input. 90 ; RA1 - RA5 are all configured as outputs. 91 ; 92 ; Use VDD and VSS for Voltage references. 93 ; 94 ; PCFG = 1110 == AN0 is the only analog input 95 ; ADCS = 110 == FOSC/64 96 ; ADFM = 0 == 6 LSB of ADRESL are 0. 97 ; 98 99 bsf STATUS,RP0 ;adcon1 is in bank 1 100 movlw 1 101 movwf TRISA 102 103 104 movlw (1<<PCFG1) | (1<<PCFG2) | (1<<PCFG3) 105 movwf ADCON1 106 movlw (1<<ADCS1) | (1<<ADON) 107 bsf PIE1,ADIE ;A2D interrupts 108 bcf STATUS,RP0 ;adcon0 is in bank 0 109 movwf ADCON0 110 111 bsf INTCON,GIE ;Global interrupts 112 bsf INTCON,PEIE ;Peripheral interrupts 113 114 115 call Convert 116 117 .assert "adres == 0xff, 'FAILED 16F874a initial test'" 118 nop 119 120 ;; The next test consists of misusing the A/D converter. 121 ;; TRISA is configured such that the I/O pins are digital outputs. 122 ;; Normally you want them to be configued as inputs. According to 123 ;; the data sheet, the A/D converter will measure the voltage produced 124 ;; by the digital I/O output: either 0 volts or 5 volts (or Vdd). 125 ;; [I wonder if this would be a useful way of measuring the power supply 126 ;; level in the event that there's an external reference connected to 127 ;; an3?] 128 129 130 .command "V1.resistance=1e6" 131 132 movlw 0 133 bsf STATUS,RP0 134 movwf PORTA ;Make the I/O's digital outputs 135 movwf ADCON1 ;Configure porta to be completely analog 136 ;(note that this is unnecessary since that's 137 ;the condition they're in at power up.) 138 bcf STATUS,RP0 139 140 movwf PORTA ;Drive the digital I/O's low 141 142 ;; 143 ;; First do a few conversion with porta configured as a digital output 144 ;; that is driving low 145 ;; 146 147 call Convert 148 149 .assert "adres == 0x00, 'FAILED 16F874a digital low'" 150 nop 151 ;; 152 ;; Now do some with the digital output high 153 ;; 154 155 movlw 0xff 156 movwf PORTA 157 158 call Convert 159 160 .assert "adres == 0xff, 'FAILED 16F874a digital high'" 161 nop 162 ;; 163 ;; Now make the inputs analog (like they normally would be) 164 ;; 165 166 .command "V1.resistance=100.0" 167 168 bsf STATUS,RP0 169 movlw 0xff 170 movwf PORTA 171 bcf STATUS,RP0 172 173 call Convert 174 175 .assert "adres == 0xff, 'FAILED 16F874a AN0=5V'" 176 nop 177 178 .command "V1.voltage=1.0" 179 180 call Convert 181 .assert "adres == 0x33, 'FAILED 16F874a AN0=1V'" 182 nop 183 184 ;; 185 ;; Now let's use the external analog signal connected to AN3 186 ;; as the voltage reference 187 188 bsf STATUS,RP0 189 movlw 1<<PCFG0 190 movwf ADCON1 ^ 0x80 191 bcf STATUS,RP0 192 193 .command "V2.voltage=2.0" 194 195 call Convert 196 197 .assert "adres == 0x80, 'FAILED 16F874a AN0=1V Vref+=2V'" 198 nop 199 .assert "'*** PASSED 16F874a a2d test'" 200 201 goto $-1 202 203 204 205Convert: 206 207 clrf t1 ;flag set by the interrupt routine 208 209 bsf ADCON0,GO ;Start the A/D conversion 210 211 btfss t1,0 ;Wait for the interrupt to set the flag 212 goto $-1 213 214 movf ADRESH,W ;Read the high 8-bits of the result 215 216 217 return 218 219 end 220