Sida 1 av 2

Timer0 och PIC16F877A

Postat: 5 augusti 2006, 17:10:14
av Seven11
Jag försöker göra en 1 sekunds timer med hjälp av den inbyggda Timer0 och avbrott. Men dom enda resultaten jag får är en för snabb timer eller ingen som fungerar.
Är det någon som råkar ha kod för detta, helst i C men det ska nog gå att konvertera i värsta fall.

Postat: 5 augusti 2006, 18:38:50
av sodjan
> Jag försöker.....

Hur då ?

Postat: 5 augusti 2006, 19:43:03
av Seven11
#define TIMER0_PRESCALAR 0b111 //1:256
#define TIMER0_HOW_MANY_INTS 46 //ceiling(TIMER0_INTERVAL/((1/PIC_CLK) * TIMER0_PRESCALAR)/255)

int TMR0_BIG_VALUE = TIMER0_HOW_MANY_INTS;
bit ReadTemp_Part2_Done;
bit ReadTemp_INT_recived;



//Testa timer0
while(1)
{
ReadTemp_INT_recived=0;
OPTION|=TIMER0_PRESCALAR;
TMR0_BIG_VALUE = 1;TIMER0_HOW_MANY_INTS;
TMR0=0x00;
T0IE=1;

while(!ReadTemp_INT_recived);
lcd_clear();
lcd_hexa(testtmr++);
};

void interrupt ISR()
{
//Timer0
if (T0IF)
{
if (!(TMR0_BIG_VALUE--))
{
//Stänger av den gamla timningen för tillfället...
T0IF=0;
//Säger till huvudkoden att temperaturen kan hämtas...
ReadTemp_INT_recived = 1;
}
else
{
//Sätter igång en ny TMR0...
OPTION|=TIMER0_PRESCALAR;
TMR0=0x00;
T0IF=0;
}
}
}

Postat: 5 augusti 2006, 20:02:30
av sodjan
Väldigt dåligt med kommenterar !! Det är inte lätt
att gissa vad *du* trodde att du gjorde när du skrev koden...

Men ett par saker i alla fall...

Varför sätter du om OPTION i ISR'en ?
Varför sätter du TMR0 = h'00' i ISR'en ?

> //Stänger av den gamla timningen för tillfället...
> T0IF=0;

Vad är det du stänger av här ?

> Men dom enda resultaten jag får är en för snabb timer eller ingen som fungerar.

Helt slumpmässigt ?
Eller när inträffar det ena resp det andra ?

Postat: 5 augusti 2006, 20:09:17
av Seven11
jag använder bara dom kommentarer jag tycker är nödvändiga i C, eftersom det är bara jag som ska se koden (i 99% av fallen) så blir det bara dumt att kommentera för mycket.

>Varför sätter du om OPTION i ISR'en ?
>Varför sätter du TMR0 = h'00' i ISR'en ?
>
>> //Stänger av den gamla timningen för tillfället...
>> T0IF=0;
>
>Vad är det du stänger av här ?

jag trodde att det inte gick att få 1 sekunds delay på PIC16F877A @20 MHz med Timer0 så jag körde flera avbrott för att 1 sekund så timer:n startas om 46 ggr och det trodde jag skulle bli 1 sekund.

>Helt slumpmässigt ?
>Eller när inträffar det ena resp det andra ?

nej jag testade att skriva om koden (detta är revision 2 så att säga) och den första koden gav för kort delay...

Postat: 5 augusti 2006, 20:41:40
av sodjan
> jag trodde...

Sluta tro och börja läsa databladet istället...
TMR0 (med max prescaler) ger maximalt 256*256 Tcy delay.
256 från prescalern och 256 från TMR0.

Prescaler = 256
TMR0 = 256
256 * 256 = 65.536
20 Mhz -> Tcy = 0.2 us
1 / (0.2 us * 65.536) = (ca) 76

Så det går åt 76 interrupt för att få (ca) 1 sek vid 20 Mhz.

Jag kanske har missat något. Hur fick du 46 ?

> eftersom det är bara jag som ska se koden...

Att posta kod som bara *du* ska läsa verkar lite konstigt...

> Men dom enda resultaten jag får är en för snabb timer

Och hur mycket är "för snabb" !?

Postat: 5 augusti 2006, 20:57:32
av Seven11
> Sluta tro och börja läsa databladet istället...

har läst databladet! skrev "trodde" för att visa att jag antog att det var så men det verkade vara fel.

använde samma uträkning som du men visste inte att jag skulle ha två 256 termer utan använde bara den för prescalar samt att jag körde på 0,75 sekunder då. Sen hur fick du 0.2 us (1/(20*1000*1000) = 0,00000005 = 0,05 us), går timer klockan 4 ggr segare än klockfrekvensen?



Hur hade du löst detta?

Postat: 5 augusti 2006, 21:27:56
av sodjan
Fosc = 20 Mhz
Fcy = Fosc/4 = 5 Mhz (d.v.s 5 "MIPS", som Microchip kallar det...)
Tcy = 1/Fcy = 1/5Mhz = 0.2 us (d.v.s en "instruction cycle")

> går timer klockan 4 ggr segare än klockfrekvensen?

Se "FIGURE 5.1 : BLOCK DIAGRAM OF THE TIMER0/WDT PRESCALER"
i databladet. Högst upp i figuren, där står "CLKO (= FOSC/4)".

Och i texten straxt ovanför figuren : "In Timer mode, the Timer0
module will increment every instruction cycle (without prescaler)."

> Hur hade du löst detta?

Med assembler... :-)
Med det är klart att det går med C också, jag har bara lite svårt
att hänga med i vad du gör.

Och kanske med TMR1 vilken ger längre tid mellan interrupt (256*256*8 ),
eller med TMR2, vilken kan ge en mer exakt tid eftersom man kan sätta
värdet där den "börjar om" (inte bara FF som för TMR0). Det beror på
hur "nära" 1 sek du behöver ligga.

Jag förstår fortfarande inte riktigt hur du fick "46"

Postat: 5 augusti 2006, 22:29:54
av Greve Hamilton
Lite svårt att förstå vad du försöker göra, men...
Du får ju inte glömma GIE osv.

Ta en titt på INTCON-registret i databladet.

Nä, posta hela koden och lämna kommentarer hela vägen så att vi kan se vad du försöker med.

Postat: 5 augusti 2006, 22:41:18
av sodjan
Nej, jag såg inte heller GIE, men jag *tolkade* det som om
interruptet i alla fall fungerade, så jag utelämnade den detaljen...
Men som sagt, fel att gissa så klart... :-)

Postat: 5 augusti 2006, 22:53:40
av Greve Hamilton
sodjan; Hehe, reagerade lite på att det verkade fungera "lite", även utan GIE, men jag såg det hur som helst inte i koden, så... :)

Seven11; Här har du både hur man ska räkna och hur det kan se ut:

http://www.mikroe.com/forum/viewtopic.p ... =interrupt

Postat: 6 augusti 2006, 00:47:17
av Seven11
använde TMR1 istället (slipper slösa kraft på en massa avbrott)...
här är koden om någon nångång skulle behöva:

TimerX.c :

Kod: Markera allt

#include <pic.h>
#include "TimerX.h"

void init_Timer1()
{
	//Ställer in avbrotsbitar
                        GIE=1;
			PEIE = 1; 
			TMR1IE = 1;
    //Ställer in Timer1 kontrollregister
			  T1CKPS1 = 1;
			  T1CKPS0 = 1; //1:8 prescalar
			  T1OSCEN = 0; //ingen oscillator
			  TMR1CS = 0; //Använder Fosc/4 som insignal
			  TMR1ON = 1; 

			  TMR1L = 0x00;
			  TMR1H = 0x00;
}
TimerX.h :

Kod: Markera allt

void init_Timer1();

main.c (avbrottsdelen) :

Kod: Markera allt

void interrupt ISR()
{
 //Timer1
	if (TMR1IF)
   	{
       //Stänger av den gamla timningen för tillfället...
       		TMR1IF=0;
       //Meddelar alla "applikationer"

   	}
}
kompilerat med Hi-Tech PICC Lite

Postat: 6 augusti 2006, 01:46:29
av sodjan
OK, med TMR1 får du alltså 256*256*8 (TMR1L * TMR1H * prescale-8),
eller lite drygt 500.000 Tcy mellan varje interrupt. Eller med andra ord
ca 10 interrupt/sek vid 20 Mhz Fosc. Det kanske är OK, men det stämmer
inte med de krav du hade från början. Har kraven ändrats under tiden ?

Postat: 6 augusti 2006, 17:32:21
av nanopile
....ermer utan använde bara den för prescalar samt att jag körde på 0,75 sekunder då. Sen hur fick du 0.2 us (1/(20*1000*1000) = 0,00000005 = 0,05 us), går timer klockan 4 ggr segare än klockfrekvensen?

......

Tycker något behöver förtydligas...
Ja, de anger en klockfrekvens men den är tillmyglad för de har konstruerat "machincecykles" eller något som består av fyra "Quarters" som är 1 Hertz långa.
Så när man kör 40MHz så blir det bara 10Mhz egentligen trots att Microchip påstår att alla instruktioner går att göra på en klockcykel, enligt mig är en klockcykel 1 Hertz men tydligen inte enligt Microchip.
Dessutom är instruktionerna så begränsade att det tar lika lång tid att köra ett program eftersom varje sak som ska göras måste byggas upp av en rad instruktioner.

Bort med all c och c++ assembler är enklare :)

Postat: 6 augusti 2006, 17:45:23
av sodjan
nanopile> Tycker något behöver förtydligas...

Japp, du kan ju börja med *ditt* inlägg... :-)

Var får du "1 Hertz" från t.ex ??

När det gäller olika begrepp och uttryck som används
för PIC processorerna, så tycker jag att det är mycket enklare
att köra med den modell som Microchip har valt. Att påstå att
de "myglar" eller "påstår" saker o.s.v är ju bara löjligt...

Jag tänkte be om förtydligande på en del andra saker du skrev,
men det är så förvirrat det hela så jag får inte till någon bra fråga...

Det enda som var vettigt var sista raden. :-) :-)