Beskrivning av koden:
Denna kod ska ta emot en analog likspänning (på AN3) och omvandla 7st spänningsområden. Resultatet ska visas som ett binärt tal på 3st lysdioder (på GP2 - GP0). Det ska även skickas ut som en PWM-liknande puls på GP5. Omvandlingen ska göras när den analoga ingången genererar ett interrupt. (Naturligtvis är det inte själva ingången som genererar interruptet, men ni förstår nog vad jag menar.)
Problemet:
Kort sagt så får jag inget interrupt. Hur vet jag det? Jo jag har lagt in några debug-rader i interrupt-proceduren som ska blinka med de tre lysdioderna när det blivit ett interrupt. De lysdioderna tänds aldrig och värdet som AD-omvandlaren (ADRESH och ADRESL) ger är iallafall inte över 0.
Jag har läst databladet noga. Särskillt delarna med AD-modulen, TRISIO, ANSEL, Interrupt mm. Eftersom GPIO4 även heter AN3 (dvs inte har samma nummer) så borde det vara lätt att välja fel med TRISIO och ANSEL, men det har jag dubbelkollat många gånger.
En titt på koden:
Kod: Markera allt
'Använder interna oscillatorn.
'INTRC_OSC_NOCLKOUT ska vara satt i Project -> Edit -> Device Flags.
'MCLRE_ON ska också vara satt. (Datablad sid 52. 54 enligt Acrobat.)
'GPIO.0 = LED 0 visar bit0
'GPIO.1 = LED 1 visar bit1
'GPIO.2 = LED 2 visar bit2
'GPIO.4 = Från TempKoll (Analog in. Det blir AN3)
symbol LED0 = GPIO.0 ' Visar bit0
symbol LED1 = GPIO.1 ' Visar bit1
symbol LED2 = GPIO.2 ' Visar bit2
dim ntc_lo as byte ' Låga delen av NTC-värdet
dim ntc_hi as byte ' Höga delen av NTC-värdet
dim ntc as word 'Hela NTC-värdet (10bit används) Förväntar spänning mellan 2.3V och 4.4V
sub procedure Init
TRISIO = %00011000 ' Utgångar överallt, förutom GP4 (AN3) som är ingång. GP3 är alltid ingång.
IOC = %00000000 ' Interrupt on change - Disabled
CMCON.CM2 = 1 ' Comparator Off
CMCON.CM1 = 1 ' Comparator Off
CMCON.CM0 = 1 ' Comparator Off
VRCON = 0 ' VoltRef (Comparator) off
T1CON.TMR1ON = 0 ' Stoppar timern
WPU = %00000000 'Weak Pullup - Disabled
'AD-omvandling initiering
ADCON0.ADFM = 1 ' Högerjusterad
ADCON0.VCFG = 0 ' VDD som referens
ADCON0.CHS1 = 1 ' AN3 som ingång
ADCON0.CHS0 = 1 ' AN3 som ingång
ADCON0.ADON = 1 ' AD-modulen är igång
delay_ms(10)
ADCON0.1 = 1 ' GO/DONE - Sätt den här hög för att starta en AD-omvandling
ANSEL.ADCS2 = 1 ' FOSC/16
ANSEL.ADCS1 = 0 ' FOSC/16
ANSEL.ADCS0 = 1 ' FOSC/16
ANSEL.ANS3 = 1 ' AN3 som analog in
ANSEL.ANS2 = 0 ' Digital I/O
ANSEL.ANS1 = 0 ' Digital I/O
ANSEL.ANS0 = 0 ' Digital I/O
'Interrupt initiering
INTCON.GIE = 1 ' Global interrupt enable
INTCON.PEIE = 1 ' Peripheral Interrupt Enable (AD t.ex)
PIE1.ADIE = 1 ' AD-omvandlare ger interrupt
PIR1.ADIF = 0 ' Clearat interruptet
ntc = 0 ' Nollställer NTC-värdet
LED0 = 0
LED1 = 0
LED2 = 0
end sub
sub procedure ntc_reader
'Ett interrupt har hänt:
if TestBit(PIR1, ADIF) = 1 then
ClearBit(PIR1, ADIF)
LED2 = 1 ' <--- BARA FÖR DEBUGGING. HAR ÄVEN PROVAT UTAN.
LED1 = 1 ' <---
LED0 = 1 ' <---
delay_ms(300) ' <---
LED2 = 0 ' <---
LED1 = 0 ' <---
LED0 = 0 ' <---
delay_ms(300) ' <---
'Läsa av AD-omvandlaren:
ntc_lo = ADRESL
ntc_hi = ADRESH
ntc = (word(ntc_hi << 8)) OR ntc_lo
end if
SetBit(ADCON0, ADON) 'Gör klart för en ny omvandling
SetBit(ADCON0, 1) 'GO/DONE
end sub
main:
init
while true
if (ntc >= 1) and (ntc <= 562) then
'Nivå 1
LED2 = 0
LED1 = 0
LED0 = 1
end if
'KLIPP--- Här finns egentligen fler IF-rader som den ovan, fast med andra värden.
wend
end.
Visst ser det rätt ut? Men något är fel. Frågan är vad...