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