DAC fungerar, LCD fungerar. Båda samtidigt fungerar inte.
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
DAC fungerar, LCD fungerar. Båda samtidigt fungerar inte.
PIC18LF2320. 40MHz. MikroBasic.
Jag har under en tid jobbat med mitt laserprojekt där jag (i testsyfte) behöver skicka ut värden till en DAC. Med en knapp-panel styr jag START, STOP mm. Värdena ska synas i en LCD.
Först gjorde jag ett separat program med bara knapparna och LCD'n inblandad. Fungera fint. I nästa program testade jag med bara knapparna och DAC'en. Fungerar fint.
Nu har jag gjort *ett* program som fixar både knappar, LCD och DAC.
Det är här problemet ligger:
När jag startar PIC-kretsen så ser jag att LCD'n initieras rätt. (Kontrasten stämmer på båda raderna och LCD'n är tom, precis som det ska vara.) Trycker jag "RUN" så skriver LCD'n ut RRRRR över hela skärmen, sedan UUUUUU osv. I sann debugger-anda så tog jag bort allt i koden som hade med LCD'n att göra, förutom själva initieringen.
När jag nu startar PIC-kretsen så är LCD'n tom. Precis som det ska vara. Trycker jag "RUN" så är det fortfarande tomt (eftersom jag tagit bort de delarna i koden). Trycker jag däremot STOP eller MIN så fylls LCD'n av svarta fyrkanter som ser ut så här:
11111
11101
11111
11111
11111
11101
11111
Hm?
Har kollat så det inte är några PORT-rader mm som använder samma pinnar för DAC'en och LCD'n.
LCD'n använder hela PORTB, PORTC.1 och PORTC.2.
DAC'en använder PORTC.0, PORTC.3 och PORTC.5.
Tips?
edit: Här finns hela koden.
Jag har under en tid jobbat med mitt laserprojekt där jag (i testsyfte) behöver skicka ut värden till en DAC. Med en knapp-panel styr jag START, STOP mm. Värdena ska synas i en LCD.
Först gjorde jag ett separat program med bara knapparna och LCD'n inblandad. Fungera fint. I nästa program testade jag med bara knapparna och DAC'en. Fungerar fint.
Nu har jag gjort *ett* program som fixar både knappar, LCD och DAC.
Det är här problemet ligger:
När jag startar PIC-kretsen så ser jag att LCD'n initieras rätt. (Kontrasten stämmer på båda raderna och LCD'n är tom, precis som det ska vara.) Trycker jag "RUN" så skriver LCD'n ut RRRRR över hela skärmen, sedan UUUUUU osv. I sann debugger-anda så tog jag bort allt i koden som hade med LCD'n att göra, förutom själva initieringen.
När jag nu startar PIC-kretsen så är LCD'n tom. Precis som det ska vara. Trycker jag "RUN" så är det fortfarande tomt (eftersom jag tagit bort de delarna i koden). Trycker jag däremot STOP eller MIN så fylls LCD'n av svarta fyrkanter som ser ut så här:
11111
11101
11111
11111
11111
11101
11111
Hm?
Har kollat så det inte är några PORT-rader mm som använder samma pinnar för DAC'en och LCD'n.
LCD'n använder hela PORTB, PORTC.1 och PORTC.2.
DAC'en använder PORTC.0, PORTC.3 och PORTC.5.
Tips?
edit: Här finns hela koden.
- EagleSpirit
- Inlägg: 1288
- Blev medlem: 27 maj 2003, 23:15:48
- Ort: Västerås
- Kontakt:
Hihi, lite lustigt skrivet
Nej men blir det samma problem om du skriver ut nåt på displayen?
Tänk på att om du använder interrupt så ska det första och sista du gör vara att du sparar undan W-registret och status-registret och sen lägger tillbaka dom när rutinen är klar. Om inte mikrobasig gör det åt dig förstås. Anledningen är att det du gjorde innan interruptet kan vara förstört när du går ur interrupten. Kan vara värt att tänka på så att det inte blir oregelbundna fel som man inte kan förklara.
Jag ska fundera vidare lite på LCD-problemet.
Kod: Markera allt
PORTB = %00001100 ' Stänger på displayen, Markören är av.
Tänk på att om du använder interrupt så ska det första och sista du gör vara att du sparar undan W-registret och status-registret och sen lägger tillbaka dom när rutinen är klar. Om inte mikrobasig gör det åt dig förstås. Anledningen är att det du gjorde innan interruptet kan vara förstört när du går ur interrupten. Kan vara värt att tänka på så att det inte blir oregelbundna fel som man inte kan förklara.
Jag ska fundera vidare lite på LCD-problemet.
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
> Tänk på att om du använder interrupt så ska det första och sista du gör vara att du sparar undan W-registret och status-registret och sen lägger tillbaka dom när rutinen är klar.
Inte på PIC18 om man kör en interrupt prio-nivå (vilket är normalt).
MikroBasic borde sköta om detta automatiskt beroende på vilken processorserie man kör mot.
Från koden :
> "PORTC.2 = 1 ' E"
Du har ju på ett annat ställe skrivit "symbol RS = PORTC.1", varför inte göra likadant med "E" ??
Det blir enklare att läsa och mer bugg-säkert.
Frågan är om du hinner köra klart DAC och LCD rutinerna innan nästa ADC interrupt.
En annan sak, i "if knapp_status = 1 then ' RUN" så nollar du inte "knapp_status" som du gör i de andra valen. Jag vet inte om det har någon bestydelse, jag bara reagerade på det.
Inte på PIC18 om man kör en interrupt prio-nivå (vilket är normalt).
MikroBasic borde sköta om detta automatiskt beroende på vilken processorserie man kör mot.
Från koden :
> "PORTC.2 = 1 ' E"
Du har ju på ett annat ställe skrivit "symbol RS = PORTC.1", varför inte göra likadant med "E" ??
Det blir enklare att läsa och mer bugg-säkert.
Frågan är om du hinner köra klart DAC och LCD rutinerna innan nästa ADC interrupt.
En annan sak, i "if knapp_status = 1 then ' RUN" så nollar du inte "knapp_status" som du gör i de andra valen. Jag vet inte om det har någon bestydelse, jag bara reagerade på det.
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
>Du har ju på ett annat ställe skrivit "symbol RS = PORTC.1", varför inte göra likadant med "E" ??
Hm, bra fråga. Ska fixa det.
>Frågan är om du hinner köra klart DAC och LCD rutinerna innan nästa ADC interrupt.
Det har jag oroat mig lite för. Särskillt eftersom LCD'n behöver lite tid på sig mellan varje kommando. Nu kör jag med 20ms mellan varje E. Jag vet att det bara behöver gå 0.5µs mellan varje E, men jag testade att öka tiden för att se om det förändrade resultatet.
>En annan sak, i "if knapp_status = 1 then ' RUN" så nollar du inte "knapp_status
Gjorde på det sättet för att "RUN" ska köras så länge man inte trycker något annat. Om jag däremot trycker "MAX" som skickar 4095 till DAC'en så nollställer jag knapp_status för att den sändningen inte ska upprepas hela tiden.
Mitt nästa steg blir att "kommentera bort" det som ligger i DAC_Output.
Hm, bra fråga. Ska fixa det.

>Frågan är om du hinner köra klart DAC och LCD rutinerna innan nästa ADC interrupt.
Det har jag oroat mig lite för. Särskillt eftersom LCD'n behöver lite tid på sig mellan varje kommando. Nu kör jag med 20ms mellan varje E. Jag vet att det bara behöver gå 0.5µs mellan varje E, men jag testade att öka tiden för att se om det förändrade resultatet.
>En annan sak, i "if knapp_status = 1 then ' RUN" så nollar du inte "knapp_status
Gjorde på det sättet för att "RUN" ska köras så länge man inte trycker något annat. Om jag däremot trycker "MAX" som skickar 4095 till DAC'en så nollställer jag knapp_status för att den sändningen inte ska upprepas hela tiden.
Mitt nästa steg blir att "kommentera bort" det som ligger i DAC_Output.
- EagleSpirit
- Inlägg: 1288
- Blev medlem: 27 maj 2003, 23:15:48
- Ort: Västerås
- Kontakt:
Hmm, init-rutinen kan väl inte ligga i main? Då kommer ju init rutinen köras hela tiden... när du inte trycker på någon knapp så går det snabbt igenom interruptrutinen och LCD-"konfigureringen" går smärtfritt, men så trycker du på en knapp och då tar det plötsligt mycket längre tid för interruptrutinen att utföras, då hinner kanske LCD-"konfigureringen" inte bli klar och det blir skit på den... Troligtvis blir det interrupt i en väntinstruktion när du skickar ut signal på E-pinnen eller något..
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Julen har passerat och det är dags att fortsätta...
Provade att ändra tiden mellan varje E till 1ms. Tyvärr hjälpte det inte.
>init-rutinen kan väl inte ligga i main? Då kommer ju init rutinen köras hela tiden...
Nja, init körs bara en gång och det är då det står "init" (dvs efter "main:" ) Rätta mig gärna om detta är fel.
När det gäller delay så använder jag bara det i LCD-initieringen. Då har jag inte tryckt någon knapp. När programmet har hamnat i while-loopen längst ner i koden så trycker jag. Då är LCD'n färdig-initierad.
Kan det bli ett interrupt när jag skickar signal till LCD'ns E-pinne?
Provade att ändra tiden mellan varje E till 1ms. Tyvärr hjälpte det inte.
>init-rutinen kan väl inte ligga i main? Då kommer ju init rutinen köras hela tiden...
Nja, init körs bara en gång och det är då det står "init" (dvs efter "main:" ) Rätta mig gärna om detta är fel.
När det gäller delay så använder jag bara det i LCD-initieringen. Då har jag inte tryckt någon knapp. När programmet har hamnat i while-loopen längst ner i koden så trycker jag. Då är LCD'n färdig-initierad.
Kan det bli ett interrupt när jag skickar signal till LCD'ns E-pinne?
> > init-rutinen kan väl inte ligga i main? Då kommer ju init rutinen
> > köras hela tiden...
> Nja, init körs bara en gång...
Korrekt, det är ju bara det som ligger inom "while true.... wend" som körs hela tiden...
> När det gäller delay så använder jag bara det i LCD-initieringen.
Nja, de finns med i while/wend loopen i main också. 10 ms.
Antingen kan delay_ms avbrytas av ett interrupt, eller också inte, men jag
vet inte om det är avgörande. Att ISR'en eventuellt får vänta på att en
delay_ms(10) ska gå klart, skall inte spela någon roll.
Annars vet jag inte riktigt.
Det är lite svårt att hänga med i vad som händer.
Du beskriver hur flera olika versioner av koden fungerade.
Och koden på länken är full med bortkommenterad kod som det är
lite svårt att veta när den kommenterades bort.
Förenkling tror jag på. Banta ner koden tills det fungerar som du vill.
Lägg sedan till funktioner igen lite i taget. När/om det lägger av igen
har man bättre kontroll på var felet ligger.
> > köras hela tiden...
> Nja, init körs bara en gång...
Korrekt, det är ju bara det som ligger inom "while true.... wend" som körs hela tiden...
> När det gäller delay så använder jag bara det i LCD-initieringen.
Nja, de finns med i while/wend loopen i main också. 10 ms.
Antingen kan delay_ms avbrytas av ett interrupt, eller också inte, men jag
vet inte om det är avgörande. Att ISR'en eventuellt får vänta på att en
delay_ms(10) ska gå klart, skall inte spela någon roll.
Annars vet jag inte riktigt.
Det är lite svårt att hänga med i vad som händer.
Du beskriver hur flera olika versioner av koden fungerade.
Och koden på länken är full med bortkommenterad kod som det är
lite svårt att veta när den kommenterades bort.
Förenkling tror jag på. Banta ner koden tills det fungerar som du vill.
Lägg sedan till funktioner igen lite i taget. När/om det lägger av igen
har man bättre kontroll på var felet ligger.
- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Förstår att det är lite svårt att hänga med. När man debuggar och sedan berättar resultatet så vet ni ju inte exakt hur koden ser ut. Det kanske blir bättre om jag visar koden varje gång jag gjort en ändring och även förklarar lite mer om varje ändring? Vore bra att hitta en 'standard' för detta när man har något kod-problem. -Tips mottages tacksamt.
Jag har nu gjort en test (ett helt nytt program) angående om interruptet kan avbryta en delay. Jag lät en lysdiod (STATUS-LED 1) blinka i 1Hz. Med hjälp av en interrupt-koll (samma som jag använt hela tiden för 'problem-koden' i denna tråd) lät jag RUN-knappen tända STATUS-LED 2 och STOP-knappen släckte den.
Tanken med programmet var att se om man kan tända/släcka *STATUS-LED 2* när loopen är i delayet.
Resultat: Det fungerade. *STATUS-LED 2* kan tändas/släckas omedelbart när man trycker RUN eller STOP, utan att vänta på att *STATUS-LED 1* byter läge.
Koden:
edit: Har nu lagt till LCD-initieringen i init (i denna koden ovan), precis på samma ställe som i 'problem-koden'. Inga skräptecken. Fungerar felfritt.
edit igen: Blandade ihop "STATUS-LED 1" och "STATUS-LED 2"... Fixat.

Jag har nu gjort en test (ett helt nytt program) angående om interruptet kan avbryta en delay. Jag lät en lysdiod (STATUS-LED 1) blinka i 1Hz. Med hjälp av en interrupt-koll (samma som jag använt hela tiden för 'problem-koden' i denna tråd) lät jag RUN-knappen tända STATUS-LED 2 och STOP-knappen släckte den.
Tanken med programmet var att se om man kan tända/släcka *STATUS-LED 2* när loopen är i delayet.
Resultat: Det fungerade. *STATUS-LED 2* kan tändas/släckas omedelbart när man trycker RUN eller STOP, utan att vänta på att *STATUS-LED 1* byter läge.
Koden:
Kod: Markera allt
symbol STATUS1 = PORTA.1
symbol STATUS2 = PORTA.2
symbol STATUS3 = PORTA.3
dim knapp_nr_lo as byte
dim knapp_nr_hi as byte
dim knapp_nr as word
sub procedure Init
'LED
TRISA.1 = 0 ' *STATUS-LED 1*
TRISA.2 = 0 ' *STATUS-LED 2*
TRISA.3 = 0 ' *STATUS-LED 3*
'LED-TEST
STATUS1 = 1 ' *STATUS-LED 1*
STATUS2 = 1 ' *STATUS-LED 2*
STATUS3 = 1 ' *STATUS-LED 3*
delay_ms(300)
STATUS1 = 0 ' *STATUS-LED 1*
STATUS2 = 0 ' *STATUS-LED 2*
STATUS3 = 0 ' *STATUS-LED 3*
'AD-omvandlare
ADCON1 = %00001110
ADCON2 = %10000111
ClearBit(ADCON0, CHS3)
ClearBit(ADCON0, CHS2)
ClearBit(ADCON0, CHS1)
ClearBit(ADCON0, CHS0)
SetBit(ADCON0, ADON)
SetBit(ADCON0, GO/DONE)
'Interrupt
SetBit(PIE1, ADIE)
SetBit(INTCON, GIE)
SetBit(INTCON, PEIE)
ClearBit(PIR1, ADIF)
end sub
sub procedure interrupt
if TestBit(PIR1, ADIF) = 1 then
ClearBit(PIR1, ADIF)
knapp_nr_lo = ADRESL
knapp_nr_hi = ADRESH
knapp_nr = (word(knapp_nr_hi << 8)) OR knapp_nr_lo
end if
'RUN
if (knapp_nr >= 509) and (knapp_nr <= 515) then
STATUS2 = 1 ' Om RUN så tänds *STATUS-LED 2*
end if
'STOP
if (knapp_nr >= 468) and (knapp_nr <= 473) then
STATUS2 = 0 ' Om STOP så släcks *STATUS-LED 2*
end if
SetBit(ADCON0, ADON)
SetBit(ADCON0, GO/DONE)
end sub
main:
init
while true
STATUS1 = 1 ' *STATUS-LED 1*
delay_ms(1000)
STATUS1 = 0 ' *STATUS-LED 1*
delay_ms(1000)
wend
end.
edit: Har nu lagt till LCD-initieringen i init (i denna koden ovan), precis på samma ställe som i 'problem-koden'. Inga skräptecken. Fungerar felfritt.
edit igen: Blandade ihop "STATUS-LED 1" och "STATUS-LED 2"... Fixat.
Senast redigerad av JimmyAndersson 28 december 2005, 17:02:33, redigerad totalt 1 gång.
Efter att ha funderat lite och konstaterat att du måste ha blandat ihop
"STATUS-LED 1" och "STATUS-LED 2", så ser det väll OK ut...
EDIT : Hoppblandningen var i meningen efter "Resultat:", eller hur ?
Så interrupt avbryter alltså delay funktionerna, eller hur ?
Sannolikt förlängs delay-tiden med den tid som ISR'en tar, det
skulle bli lite för komplext att hålla reda på det annars.
> Vore bra att hitta en 'standard' för detta när man har något kod-problem.
> -Tips mottages tacksamt.
http://www.elektronikforumet.com/forum/ ... php?t=6057 ??
Det var i och för sig lite olika "bud" om det var bra eller inte,
men jag tycker nog fortfarande det...
> Jag har nu gjort en test (ett helt nytt program)...
Ofta en mycket bra debug metod !
Man städar upp och tvingas tänka till en gång till på alla detaljer.
Sen, eftersom koden du visade nu fungerar (eller hur ?), så
är det inte så mycket att kommentera. Fortsätt och lägg till
funktioner tills det lägger av igen, så får vi se då...
"STATUS-LED 1" och "STATUS-LED 2", så ser det väll OK ut...

EDIT : Hoppblandningen var i meningen efter "Resultat:", eller hur ?
Så interrupt avbryter alltså delay funktionerna, eller hur ?
Sannolikt förlängs delay-tiden med den tid som ISR'en tar, det
skulle bli lite för komplext att hålla reda på det annars.
> Vore bra att hitta en 'standard' för detta när man har något kod-problem.
> -Tips mottages tacksamt.
http://www.elektronikforumet.com/forum/ ... php?t=6057 ??
Det var i och för sig lite olika "bud" om det var bra eller inte,
men jag tycker nog fortfarande det...

> Jag har nu gjort en test (ett helt nytt program)...
Ofta en mycket bra debug metod !
Man städar upp och tvingas tänka till en gång till på alla detaljer.
Sen, eftersom koden du visade nu fungerar (eller hur ?), så
är det inte så mycket att kommentera. Fortsätt och lägg till
funktioner tills det lägger av igen, så får vi se då...

- JimmyAndersson
- Inlägg: 26578
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
>Hoppblandningen var i meningen efter "Resultat:", eller hur ?
Helt riktigt. Jag var tvungen att läsa igenom det några gånger för att hitta felet.
>Så interrupt avbryter alltså delay funktionerna, eller hur ?
Det stämmer.
Jag gick tillbaka till 'problem-koden' (egentligen för att skriva ut den). Provade att kommentera bort DAC-proceduren och DAC-delen från init-proceduren. Då fick jag inte längre några skräptecken i LCD'n!
Det skulle inte förvåna mig om det är MikroBasic's egna DAC-funktioner som ställer till det. Ska prova att flytta LCD'ns E och RS till andra ben på PIC-kretsen. (Jag har hela tiden haft E på PORTC.2 och RS på PORTC.1.).
Det är en liten snabb-test som kan visa om MikroBasic's DAC-funktioner använder dessa. (Har inte hittat någon info om det i MikroBasic's hjälpfiler).
edit: Nu har jag provat flytta E från PORTC.2 till PORTC.7 (RC7/RX/DT) och RS från PORTC.1 till PORTC.6 (RC6/TX/CK). Exakt samma resultat.
Så nu ska jag återgå till koden som fungerade (dvs den i mitt förra inlägg) och lägga till grejj efter grejj.
Förresten: Tycker att tipsen (i din länk) var mycket bra.
Helt riktigt. Jag var tvungen att läsa igenom det några gånger för att hitta felet.

>Så interrupt avbryter alltså delay funktionerna, eller hur ?
Det stämmer.
Jag gick tillbaka till 'problem-koden' (egentligen för att skriva ut den). Provade att kommentera bort DAC-proceduren och DAC-delen från init-proceduren. Då fick jag inte längre några skräptecken i LCD'n!
Det skulle inte förvåna mig om det är MikroBasic's egna DAC-funktioner som ställer till det. Ska prova att flytta LCD'ns E och RS till andra ben på PIC-kretsen. (Jag har hela tiden haft E på PORTC.2 och RS på PORTC.1.).
Det är en liten snabb-test som kan visa om MikroBasic's DAC-funktioner använder dessa. (Har inte hittat någon info om det i MikroBasic's hjälpfiler).
edit: Nu har jag provat flytta E från PORTC.2 till PORTC.7 (RC7/RX/DT) och RS från PORTC.1 till PORTC.6 (RC6/TX/CK). Exakt samma resultat.
Så nu ska jag återgå till koden som fungerade (dvs den i mitt förra inlägg) och lägga till grejj efter grejj.
Förresten: Tycker att tipsen (i din länk) var mycket bra.