Bilbatteri laddare med PIC12F683 (5 / 8 steg)
Steg 5: Kort intro om PIC och timers
Timers kan användas för en hel del uppgifter: att skapa tid-baser, utlöser periodiskt återkommande händelser, mäta tiden mellan två händelser (mäta frekvens), och mycket mer. I min lilla firmware använde jag en timer för att göra mig själv en tio millisekund-bas. Räknar det hundra gånger gav mig en flagga som fick in varje gång en sekund passerade. Detta behövdes, eftersom jag visste att jag ville att ladda i 10 minuter och att mäta för 5 sekunder – en normaltid-base hade involveras i projektet på något sätt.
Om PIC timers
En processor kan utföra tusentals instruktioner i bråkdelar av en sekund, större tid-baser är vanligtvis konstruerade genom att räkna millisekunder en flera hundratals gånger. För att kunna beräkna en liten timing, som en av 1ms, behöver vi veta hur snabbt PIC verkligen körs på. PIC12F683 har en intern oscillator för maximalt 8MHz, detta är vad jag brukade ta tid på enheten. Att veta att PIC behöver fyra klockor en enda instruktion, undervisning-cykeln är 2 MHz. baserat på det, den tid som behövs av PIC en instruktion är 1/2.000.000 = 500ns. Detta är den tid-base inre timers kommer att gå vidare med. Varje timer har en tillhörande interna 8 eller 16 bitars register, vilket ökar dess värde varje gång denna 500ns passerar. Detta register kan läsas och skrivit när som helst. När de 8 eller 16 bitars registrera svämmar över, anges en flagga denna händelse.
Prescalers och postscalers kan tilldelas timers, att uppnå längre temporizations. En prescaler eller postscaler är en räknare på egen hand, kan konfigureras på en mängd olika sätt. Enkelt uttryckt, delar dessa klockan på deras ingång med ett värde som kan ändras av programvara. En 1:8 prescaler ger en klocksignal på sin produktion efter varje 8: e klockan vid dess ingång. Detta innebär, att lägga till en 1:8 prescaler på en timer ingång kommer att bromsa hastigheten denna timer förskott av 8. Postscalers fungerar på exakt samma sätt, är det oftast den position av dessa kretsar (i beaktande med timer registret), som avgör om vi pratar om en prescaler eller en postscaler. Prescalers bromsa förskott av timer registret, postscaler dröjsmål nu när en overflow händelse utlöses. Med dessa kretsar kan vi skapa tidsstämplar för längre perioder. Den händelse som inträffar vid varje overflow beskrivs ofta som "inställning av flaggan avbrott".
Låt oss se konfigurationen av timern i vår gäller till exempel!
Konfigurera tidtagare 0
I vår processor det finns tre timers, vi kommer att använda endast en: timer nummer 0. De journaler som behöver konfigureras för modulen att arbeta är: OPTION_REG, INTCON.
Konfiguration av OPTION_REG
Den högre nibble registret har inte någon effekt på timer0, jag kommer att sätta dem till nollor. Den lägre nibble består av PSA lite (stycke 3) som bestämmer där prescaler kommer få tilldelat, till timer 0 eller till watchdog timer. Jag vill dela in advance andelen timer 0 timer registret, så vi måste sätta den till 0. Nästa, vill jag ställa in den att dela upp klockan så mycket som det kan 1:256. För att uppnå detta, måste jag ange de PS2:PS0 bitarna till 111. Detta resulterar i OPTION_REG anges till 0b00000111 = 0x07.
Konfiguration av INTCON
Detta register har lite att göra med timer 0 eftersom det är ett avbrott konfigurationen register, men – eftersom vi använder avbrott med timer 0 – jag måste nämna det. De tre bitar som är relaterade med timer 0 är följande: GIE, T0IF, T0IE.
GIE är lite som aktiverar avbrott på global nivå, om detta anges till 0, inga avbrott kommer att utlösas. Vi behöver naturligtvis ställa det till 1.
T0IE är ett avbrott aktiverar bit också, men detta är strikt där för att aktivera/inaktivera timern 0 avbrottet. Vi måste ställa det till 1 också.
T0IF är timer 0 avbrott flagga lite som får in varje gång timer 0 registrera svämmar över, vi måste klara denna bit vid start, sätts av hårdvara när timer registret når sitt maximala värde och svämmar över. T0IF är därför att sättas till 0.
Vi måste ställa in INTCON till 0b11100000 = 0xE0 för att göra denna timer fungerar som vi vill.
Andra saker som behöver göras
För att skapa exakta tidpunkten för en millisekunder, kommer vi att behöva pre-load timer registret. Numrera av timer steg dividerat med 256 (på grund av prescaler jag valde) lagt till med denna förspänning värdet bör ge overflow värdet av timer registret. I vårt fall är detta värde 256, eftersom vi använder en 8-bitars timer.
De saker vi vet:
- oscillator klocka = 8 MHz
- instruktion klocka = 2 MHz
- instruktion period = 500 ns
- prescaler används = 1:256
- timing vill vi ha = 10 ms
De saker vi vill ta reda på:
- timer-registret före belastning värde.
Vi vet att vi vill ha en 10 ms timing, och vi vet att våra timer steg i en takt av 256 * 500 ns. Lösa att multiplikation berättar att timer 0 registret kommer att avancera när 128 μs passerar. 10 ms / 128 μs = 78, detta nummer är viktigt eftersom det uttrycker våra 10 ms i antal timer steg. Vi vet att vi vill ha timer register översvämningen efter 10 ms, och vi vet att detta inträffar efter värdet maximalt 8 bit, 255. Enkelt nog, vi måste bara sätta 256 – 78 = 178 i registret timer, och vänta på flaggan för att ställa in. Detta kommer att ske efter 10 ms.
Detta är inte tillräckligt, vi måste också uppdatera registret timer med detta värde efter varje overflow. Om vi inte gör det, timer registret räknas startar från noll och tiderna blir helt off (128 μs * 256 är inte 10 ms).
Jag nämnde hur dessa overflow flaggor kan utlösa avbrott (kan och kommer att, eftersom vi aktiverat denna funktion i INTCON register). Avbrotten hanteras i en särskild del av programmet kallas en avbrottstjänstens rutin. När ett avbrott utlöses, programmet hoppar till denna särskilda del av programmet, och kör den. När det utför den del av koden (ofta kallad avbrottet som hanteras), fortsätter programmet där den slutade innan avbrottet var signalerade. Detta gör att en programmerare att reagera snabbt på denna typ av händelser, i själva verket, detta är skälet till varför avbryter "uppfanns". Avbryta tjänsten rutiner bör göras kort, så deras utförande är tillräckligt snabbt. Jag skrev timer registret omlastning i avbrottstjänstens rutin, detta garanterar att timern 0 översvämningar inträffar efter 10 ms om och om igen. Flaggan avbrott måste rensas också, annars processorn kommer "tror" att en avbrottet signaleras – det kommer att fastna i rutinen och inte kommer att nå den viktigaste koden igen. Detta är ett klassiskt fel och kan hålla dig tillbaka för ganska lång tid.