Interrupt-problem (PIC18LF2320) *Löst* *Fungerar*
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Jag fick inte Mikrobasic's inbyggda USART-funktioner att fungera, men det var ganska enkelt att konfigurera USART direkt med PIC'ens register:
' USART
TXSTA = %00100110
RCSTA = %10010000
SPBRG = 129 ' 19200 baud vid 40MHz
Sedan var det bara att skriva till USART'en med TXREG.
(Ska minska hastigheten till 9600 baud och köra "low speed" sedan. Det här var bara en snabb-test av själv USART-funktionen.) Kan tillägga att det fungerade på första försöket.
Tyvärr hann jag inte prova med interrupt-koden innan datorn började visa bluescreen, men den nya datorn är snart klar för användning...
' USART
TXSTA = %00100110
RCSTA = %10010000
SPBRG = 129 ' 19200 baud vid 40MHz
Sedan var det bara att skriva till USART'en med TXREG.
(Ska minska hastigheten till 9600 baud och köra "low speed" sedan. Det här var bara en snabb-test av själv USART-funktionen.) Kan tillägga att det fungerade på första försöket.

Tyvärr hann jag inte prova med interrupt-koden innan datorn började visa bluescreen, men den nya datorn är snart klar för användning...
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Lyckades installera MikroBasic på 266MHz-burken trots att det egentligen vill ha 64MB minne och jag bara har 48MB ledigt. Så nu kör jag MikroBasic's terminalprogram. Trevligt.
Har testat med ett program som matar ut decimala siffror mellan 0 - 255 och terminalprogrammet visar rätt värden.
Nu tillbaka till problemen.
Jag har gjort såhär:
Men det som landar i terminalprogrammet är:
192 om jag trycker RUN-knappen.
128 om jag trycker STOP-knappen.
192 om jag trycker MIN-knappen.
(skrivet med decimala tal)
När jag inte trycker något så matar terminalprogrammet bara ut nollor.
Vet inte hur detta hänger ihop. Jag borde ju få två värden (knapp_nr_hi och knapp_nr_lo).
Något är galet. Jag eller programmet?
Testade även att skicka ut "123" före och efter TXREG-raderna för att få en liten "inramining". Då såg det ut såhär när jag tryckte "RUN"-knappen:
123 123 123 251 123 251 123 123 123 123
Alltså, förrut gav RUN-knappen 192, nu blir det 251.
Jag *VET* att min knapp-panel och ADC'n ger stabila värden. Har testat detta ett 50-tal gånger och den har *alltid* gett värden mellan 510 och 513 när jag tryckt RUN. I de allra flesta fallen har det blivit 512.
När jag gjorde knapp-panelen så gjorde jag tester för att se vilka värden som ADC'n gav vid tryck på varje knapp:
RUN - 512
STOP - 470
MIN - 268
MAX - 171
MINUS - 451
PLUS - 341
ADC'n gav dessa värden på LCD'n varje gång jag provade. Genom att göra ett program som tände en LED när man tryckte t.ex RUN-knappen så kunde jag verifiera att LCD'n visade rätt värden.
edit: Eftersom terminalprogrammen jag hittat är så oanvändarvänliga så överger jag USART-loggningen och gör en LCD-rutin så jag ser vad ADC'n matar ut. Då behöver jag ju inte separera dem i två bytes, utan kan skriva ett helt word direkt.
edit 2: Förstår varför en del inte gillar MikroBasic.... Det går inte att göra "byte to string" i interruptet. Utan den funktionen så kommer LCD'n få tecken som motsvarar värdet i ADC'n. Dvs om ADC'n ger värdet 32 så kommer det att bli mellanslag i LCD'n.
Om jag hade haft fler lediga portar i PIC'en så kunde jag kopplat på lysdioder och fått värdet binärt, men tyvärr.
Ska fundera vidare...
Har testat med ett program som matar ut decimala siffror mellan 0 - 255 och terminalprogrammet visar rätt värden.
Nu tillbaka till problemen.

Jag har gjort såhär:
Kod: Markera allt
sub procedure interrupt
PORTA.2 = 1 ' *STATUS-LED 2*
if TestBit(PIR1, ADIF) = 1 then
knapp_nr_lo = ADRESL ' Läser av ADC's låga byte
knapp_nr_hi = ADRESH ' Läser av ADC's höga byte
knapp_nr = (word(knapp_nr_hi << 8)) + knapp_nr_lo ' Slår ihop.
PORTA.3 = 1 ' *STATUS-LED 3*
' Skickar till USART
TXREG = knapp_nr_hi
TXREG = knapp_nr_lo
192 om jag trycker RUN-knappen.
128 om jag trycker STOP-knappen.
192 om jag trycker MIN-knappen.
(skrivet med decimala tal)
När jag inte trycker något så matar terminalprogrammet bara ut nollor.
Vet inte hur detta hänger ihop. Jag borde ju få två värden (knapp_nr_hi och knapp_nr_lo).
Något är galet. Jag eller programmet?

Testade även att skicka ut "123" före och efter TXREG-raderna för att få en liten "inramining". Då såg det ut såhär när jag tryckte "RUN"-knappen:
123 123 123 251 123 251 123 123 123 123
Alltså, förrut gav RUN-knappen 192, nu blir det 251.
Jag *VET* att min knapp-panel och ADC'n ger stabila värden. Har testat detta ett 50-tal gånger och den har *alltid* gett värden mellan 510 och 513 när jag tryckt RUN. I de allra flesta fallen har det blivit 512.
När jag gjorde knapp-panelen så gjorde jag tester för att se vilka värden som ADC'n gav vid tryck på varje knapp:
RUN - 512
STOP - 470
MIN - 268
MAX - 171
MINUS - 451
PLUS - 341
ADC'n gav dessa värden på LCD'n varje gång jag provade. Genom att göra ett program som tände en LED när man tryckte t.ex RUN-knappen så kunde jag verifiera att LCD'n visade rätt värden.
edit: Eftersom terminalprogrammen jag hittat är så oanvändarvänliga så överger jag USART-loggningen och gör en LCD-rutin så jag ser vad ADC'n matar ut. Då behöver jag ju inte separera dem i två bytes, utan kan skriva ett helt word direkt.
edit 2: Förstår varför en del inte gillar MikroBasic.... Det går inte att göra "byte to string" i interruptet. Utan den funktionen så kommer LCD'n få tecken som motsvarar värdet i ADC'n. Dvs om ADC'n ger värdet 32 så kommer det att bli mellanslag i LCD'n.
Om jag hade haft fler lediga portar i PIC'en så kunde jag kopplat på lysdioder och fått värdet binärt, men tyvärr.
Ska fundera vidare...
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Jag gör ett nytt inlägg eftersom det förra blev så långt.
Har nu konstaterat att programmet går in i interrupt-proceduren (den skriver då ut "INT" i displayen. Däremot *är* något galet med ADC'n.
Gjorde en ny test med LCD'n där det skulle stå:
"RUN" i displayen om ADC'n gav ett värde mellan 500 och 2000.
Det skulle stå "STP" i displayen om ADC'n gav ett värde mellan 40 och 490.
Resultat: Det det händer inget oavsett vilken knapp jag trycker på. "INT" står däremot (på en egen rad) så jag vet att displayen är rätt initierad och att jag kan mata ut text till den.
Så här ser interrupt-proceduren ut nu. (Raderna som visar "INT" i displayen är bortplockade eftersom jag vet att den delen fungerar.)
Initieringen av ADC och interrupt ser ut såhär:
Det skulle som sagt vara bra om man kunde läsa av ADC'n på med USART. Tyvärr har jag inte hittat något terminalprogram som klarar att visa värdena i HEX eller DEC-format. En grejj som skulle underlätta massor var om terminalprogrammen inte skickade ut nollor hela tiden. Jag skulle vilja ha en funktion som tar bort dem. Det blir annars en lååång lista med HEX-data att gå igenom. Smått omöjligt att hitta det man söker då.

Har nu konstaterat att programmet går in i interrupt-proceduren (den skriver då ut "INT" i displayen. Däremot *är* något galet med ADC'n.
Gjorde en ny test med LCD'n där det skulle stå:
"RUN" i displayen om ADC'n gav ett värde mellan 500 och 2000.
Det skulle stå "STP" i displayen om ADC'n gav ett värde mellan 40 och 490.
Resultat: Det det händer inget oavsett vilken knapp jag trycker på. "INT" står däremot (på en egen rad) så jag vet att displayen är rätt initierad och att jag kan mata ut text till den.
Så här ser interrupt-proceduren ut nu. (Raderna som visar "INT" i displayen är bortplockade eftersom jag vet att den delen fungerar.)
Kod: Markera allt
sub procedure interrupt
PORTA.2 = 1 ' *STATUS-LED 2* <---- Lyser
if TestBit(PIR1, ADIF) = 1 then
knapp_nr_lo = ADRESL ' Läser av ADC's låga byte
knapp_nr_hi = ADRESH ' Läser av ADC's höga byte
knapp_nr = (word(knapp_nr_hi << 8)) + knapp_nr_lo ' Slår ihop.
PORTA.3 = 1 ' *STATUS-LED 3* <----- Lyser
end if
'RUN
if (knapp_nr >= 500) and (knapp_nr <= 2000) then ' 512
run = 1
'Skriv ut på LCD -----BÖRJAR-----------
PORTC.1 = 0 ' RS = Instruktion-läge
PORTB = %10000000 ' DDRAM och Kolumn 1 på rad 1
PORTC.1 = 1 ' RS = Data-läge
PORTB = "R"
PORTC.2 = 1 ' E
delay_ms(20)
PORTC.2 = 0
delay_ms(20)
PORTB = "U"
PORTC.2 = 1 ' E
delay_ms(20)
PORTC.2 = 0
delay_ms(20)
PORTB = "N"
PORTC.2 = 1 ' E
delay_ms(20)
PORTC.2 = 0
delay_ms(20)
'Skriv ut på LCD -----SLUTAR-----------
end if
'STOP
if (knapp_nr >= 40) and (knapp_nr <= 490) then ' 470
run = 0
'Skriv ut på LCD -----BÖRJAR-----------
PORTC.1 = 0 ' RS = Instruktion-läge
PORTB = %10000000 ' DDRAM och Kolumn 1 på rad 1
PORTC.1 = 1 ' RS = Data-läge
PORTB = "S"
PORTC.2 = 1 ' E
delay_ms(20)
PORTC.2 = 0
delay_ms(20)
PORTB = "T"
PORTC.2 = 1 ' E
delay_ms(20)
PORTC.2 = 0
delay_ms(20)
PORTB = "P"
PORTC.2 = 1 ' E
delay_ms(20)
PORTC.2 = 0
delay_ms(20)
'Skriv ut på LCD -----SLUTAR-----------
end if
ClearBit(PIR1, ADIF)
SetBit(ADCON0, ADON) ' A/D-omvandlare enable (On)
SetBit(ADCON0, GO/DONE) ' A/D-omvandling
end sub
Initieringen av ADC och interrupt ser ut såhär:
Kod: Markera allt
' AD-omvandlare
ADCON1 = %00001110 ' Analoga IN på AN0
ClearBit(ADCON0, CHS3)
ClearBit(ADCON0, CHS2)
ClearBit(ADCON0, CHS1)
ClearBit(ADCON0, CHS0)
SetBit(ADCON0, ADON) ' A/D-omvandlare enable (On)
SetBit(ADCON0, GO/DONE) ' A/D-omvandling
' Interrupt...
Setbit(PIE1, ADIE) ' A/D-converter Interrupt enable bit
Setbit(INTCON, GIE) ' Global Interrupt enable bit
Setbit(INTCON, PEIE) ' Peripherial Interrupt enable bit. IPEN är defalut låg.
Clearbit(PIR1, ADIF) ' A/D-converter Interrupt -Clearas.
Det skulle som sagt vara bra om man kunde läsa av ADC'n på med USART. Tyvärr har jag inte hittat något terminalprogram som klarar att visa värdena i HEX eller DEC-format. En grejj som skulle underlätta massor var om terminalprogrammen inte skickade ut nollor hela tiden. Jag skulle vilja ha en funktion som tar bort dem. Det blir annars en lååång lista med HEX-data att gå igenom. Smått omöjligt att hitta det man söker då.
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Fortsätter min enmans-show.
Tänkte visa lite närmare varför jag inte får ut något vettigt av USART-loggningen:
Sådär blir utdatat på terminaprogrammet. Det står "0" eftersom jag inte trycker något. Men varför blir det långa rader av "123" när koden ser ut såhär:
Utdata från terminalprogrammet borde (enligt mig) bli:
123 *knapp_nr_hi* 123 *knapp_nr_lo* 123 osv...
Istället blir det: 123 *någon data* 123 123 123 123.....
Sorry för all text, men nu kan ingen säga att jag inte ger någon information.

Tänkte visa lite närmare varför jag inte får ut något vettigt av USART-loggningen:
Kod: Markera allt
123 123 123 0 123 0 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 0 123 0 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123
Kod: Markera allt
sub procedure interrupt
PORTA.2 = 1 ' *STATUS-LED 2*
if TestBit(PIR1, ADIF) = 1 then
knapp_nr_lo = ADRESL ' Läser av ADC's låga byte
knapp_nr_hi = ADRESH ' Läser av ADC's höga byte
knapp_nr = (word(knapp_nr_hi << 8)) + knapp_nr_lo ' Slår ihop.
PORTA.3 = 1 ' *STATUS-LED 3*
end if
' Skickar till USART
TXREG = 123
TXREG = knapp_nr_hi
TXREG = 123
TXREG = knapp_nr_lo
TXREG = 123
'RUN
if (knapp_nr >= 507) and (knapp_nr <= 517) then ' 512
run = 1
end if
'STOP
if (knapp_nr >= 465) and (knapp_nr <= 475) then ' 470
run = 0
end if
ClearBit(PIR1, ADIF)
SetBit(ADCON0, ADON) ' A/D-omvandlare enable (On)
SetBit(ADCON0, GO/DONE) ' A/D-omvandling
end sub
123 *knapp_nr_hi* 123 *knapp_nr_lo* 123 osv...
Istället blir det: 123 *någon data* 123 123 123 123.....
Sorry för all text, men nu kan ingen säga att jag inte ger någon information.

- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Nu blev det bättre. Att jag inte stött på detta tidigare beror på att jag då väntat några hundra millisekunder mellan varje skrivning till TXREG.
Så här blir det nu:
KNAPP / ADC HI / ADC LO
RUN / 192 / 0
STOP 128 / 0
MIN / 63 / 192
MAX / 63 / 0
MINUS / 120 / 0
PLUS / 63 / 192
Jag kan binär-matte, men i detta fallet är det ett litet frågetecken:
Om vi tar RUN-värdena som exempel.
Den "höga" byten är 192 dvs 1100 0000. Men ADC'n ger ju 10bitars värde. Därför ska jag bara använda två bitar från den höga byten, alltså de längst till höger. Men då borde ju inte de två bitarna längst till vänster vara "1"?
Hänger inte med här. Hur ska jag slå ihop ADC HI (ADRESH) med ADC LO (ADRESL) ?
Så här blir det nu:
KNAPP / ADC HI / ADC LO
RUN / 192 / 0
STOP 128 / 0
MIN / 63 / 192
MAX / 63 / 0
MINUS / 120 / 0
PLUS / 63 / 192
Jag kan binär-matte, men i detta fallet är det ett litet frågetecken:
Om vi tar RUN-värdena som exempel.
Den "höga" byten är 192 dvs 1100 0000. Men ADC'n ger ju 10bitars värde. Därför ska jag bara använda två bitar från den höga byten, alltså de längst till höger. Men då borde ju inte de två bitarna längst till vänster vara "1"?
Hänger inte med här. Hur ska jag slå ihop ADC HI (ADRESH) med ADC LO (ADRESL) ?
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Den hade jag missat.
Nu är den satt som "1".
Nu ser det bättre ut. Nu gick det bättre när jag slog ihop ADC_HI och ADC_LO:
RUN = 768
STOP = 512
MIN = 255
MAX = 192
MINUS = 480
PLUS = 255
En lösning föder nytt frågetecken: "MIN" och "PLUS" har samma värde. Det hade de inte förrut. MIN-knappen är ansluten till ett 470ohms-motstånd och PLUS-knappen är ansluten till ett 3.9k motstånd. Det kan inte ge samma värde. Jag har gjort tre loggningar på USART'en, men det blir likadant varje gång. Nåväl, det behöver ni inte fundera på. Jag upptäcker säkert vad det beror på i morgon. -Det är dessutom bara RUN och STOP som jag använder i detta program ändå. (De andra knapparna ska användas när detta program fungerar.)
Så, hur långt har jag kommit nu då:
Jag vet att programmet går in i interruptet.
Jag vet att ADC-avläsningen fungerar.
Det som inte fungerar:
När man trycker på en knapp så hoppar inte programmet vidare.
Ska undersöka detta närmare i morgon.

Nu är den satt som "1".
Nu ser det bättre ut. Nu gick det bättre när jag slog ihop ADC_HI och ADC_LO:
RUN = 768
STOP = 512
MIN = 255
MAX = 192
MINUS = 480
PLUS = 255
En lösning föder nytt frågetecken: "MIN" och "PLUS" har samma värde. Det hade de inte förrut. MIN-knappen är ansluten till ett 470ohms-motstånd och PLUS-knappen är ansluten till ett 3.9k motstånd. Det kan inte ge samma värde. Jag har gjort tre loggningar på USART'en, men det blir likadant varje gång. Nåväl, det behöver ni inte fundera på. Jag upptäcker säkert vad det beror på i morgon. -Det är dessutom bara RUN och STOP som jag använder i detta program ändå. (De andra knapparna ska användas när detta program fungerar.)
Så, hur långt har jag kommit nu då:
Jag vet att programmet går in i interruptet.
Jag vet att ADC-avläsningen fungerar.
Det som inte fungerar:
När man trycker på en knapp så hoppar inte programmet vidare.
Ska undersöka detta närmare i morgon.
255 är ett sådant där värde som reser "röd-flagg".
Du har alltså alla bitar (FF eller '11111111') i låga delen.
Det är inte så sannolikt att man skulle hamna *precis* där, så
det finns anledning att misstänka något fel.
Hur stabila är värderna ?
Om de inte varierar *någonting*, så är sannlikt något fel...
Du kan ju alltid mäta spänningen på pinnen direkt, räkna lite
och se om du får rimliga ADC värden.
Du har alltså alla bitar (FF eller '11111111') i låga delen.
Det är inte så sannolikt att man skulle hamna *precis* där, så
det finns anledning att misstänka något fel.
Hur stabila är värderna ?
Om de inte varierar *någonting*, så är sannlikt något fel...

Du kan ju alltid mäta spänningen på pinnen direkt, räkna lite
och se om du får rimliga ADC värden.
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Mätte spänningen från min knapp-panel. Provade mitt gamla test igen där LCD'n visar värdet från ADC'n (med MikroBasic's egna rutiner.)
Så långt är allt ok, men detta är ju gjort med MikroBasic's ADC-funktion. Jag vet ju inte hur t.ex "A/D Acquisition Time Select bits" är där.
Kod: Markera allt
KNAPP SPÄNNING ADC-värde
RUN 2.58 - 2.59v 512-513
STOP 2.36 - 2.38v 470
MIN 1.34 - 1.36v 267-269
MAX 0.86 - 0.87v 171-172
MINUS 2.27 - 2.28v 451
PLUS 1.71 - 1.74v 341-342
Så långt är allt ok, men detta är ju gjort med MikroBasic's ADC-funktion. Jag vet ju inte hur t.ex "A/D Acquisition Time Select bits" är där.
Det borde i princip inte spela någon roll hur man "kör" ADC'n, d.v.s.
om man kör från MikroBasic eller från ASM, så länge som man gör
samma sak.
Hur som helst, personligen tycker jag att hela tangentbordslösningen
verkar lite "svajig"...
> Jag vet ju inte hur t.ex "A/D Acquisition Time Select bits" är där.
Tja, du kan ju alltid ta registret där de finns och skriva ut det på LCDn...
om man kör från MikroBasic eller från ASM, så länge som man gör
samma sak.
Hur som helst, personligen tycker jag att hela tangentbordslösningen
verkar lite "svajig"...
> Jag vet ju inte hur t.ex "A/D Acquisition Time Select bits" är där.
Tja, du kan ju alltid ta registret där de finns och skriva ut det på LCDn...
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Jag tror tyvärr att det är mitt mätinstrument som står för en del svajjighet. Jag mätte på ett 9v-batteri så ger den 9.29 - 9.30v (växlar däremellan). Mäter jag på nätagget så ger mätinstrumentet 5.15 - 5.16v. Samma nätdel använder jag till denna PIC-processor som kör i 40MHz och det går bra. Exakt 0.01v svajjighet på både ett batteri och nätdel låter smått osannorlikt, därför drar jag slutsatsen att det är mätinstrumentet som är svajjigt vid volt-mätning.
Tangentbordslösningen är bra lödd, har fräscha knappar och nya sladdar. Tyvärr har jag inget annat digitalt mätinstrument att jämföra med.
Men när jag gjorde ett test där LCD'n skrev ut namnen på varje knapp så körde jag med:
if (knapp_nr >= 511) and (knapp_nr <= 513) för RUN-knappen
och det fungerade, så då borde det väl fungera även i programmet med interrupt? Eller blir det känsligare då?
Men trots att jag i detta program (med interruptet) har kört med:
if (knapp_nr >= 500) and (knapp_nr <= 1000) så har den inte gått vidare i programmet oavsett vilken knapp jag tryckt på.
Förresten: AcquistionTime var satt till FRC (clock derived from A/D RC oscillator) när jag använde MikroBasic's rutiner. Hela ADCON2 var 1000 0111.
Tangentbordslösningen är bra lödd, har fräscha knappar och nya sladdar. Tyvärr har jag inget annat digitalt mätinstrument att jämföra med.
Men när jag gjorde ett test där LCD'n skrev ut namnen på varje knapp så körde jag med:
if (knapp_nr >= 511) and (knapp_nr <= 513) för RUN-knappen
och det fungerade, så då borde det väl fungera även i programmet med interrupt? Eller blir det känsligare då?
Men trots att jag i detta program (med interruptet) har kört med:
if (knapp_nr >= 500) and (knapp_nr <= 1000) så har den inte gått vidare i programmet oavsett vilken knapp jag tryckt på.
Förresten: AcquistionTime var satt till FRC (clock derived from A/D RC oscillator) när jag använde MikroBasic's rutiner. Hela ADCON2 var 1000 0111.