AKUT! Hjälp med att beräkna compare value (Atmel)

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Jennie
Inlägg: 173
Blev medlem: 8 februari 2014, 13:23:00

AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Jennie »

Hej, har en övning här som jag har hållit på med jättelänge och inte kommer vidare med därför att jag har fastnat och är inte helt på det klara med hur jag ska beräkna det här "compare value".

Uppgiften lyder så här:
1. Initilisera några register så att du får en interrupt per 1 ms. på en "compare match" (registererna: OCR1A TCNT1).
Använd CTC-läge så nollställs räknaren varenda gång, det blir en matchning. (se tabell s.148 i datablad).


2. Beräkna compare value, så kriteriet på 1 ms. är uppfyllt, CTC–mode-formeln finns på s.150 i databladet och ska användas där FoCA ska sättas till 0.5*1000 svarande till en periodtid på 2 ms.

[Det vill säga den är formeln:]
Bild

Studera timing diagram s.149.

Bild

Prescalling värde för fosc ska du också sätta, se tabell 17-6 s.161 i databladet, det är viktigt att uppnå ett heltal till compare value registret OCR1A!

Bild

Så håll ett av värdena och finn ett annat. Tabell 17-2 s.148 i databladet beskriver bit för CTC-läge.

Bild
Och så här har jag försökt beräkna och sätta koden men jag är ju inte alls säker på att det är rätt när det gäller CS1n-bitsen, alltså jag kommer liksom inte längre här?

Förutsatt att jag använder en 16-bit timer (TIMER1) och har en CPU Clock Frequency på 16 MHz
Då vet jag att MAX är 2^16 = 65535 (MAX)

En klockperiod är då:
För 16MHz: T = 1 / frekvens ---> T = 1 / 16MHz = 1 / 16 000 000
= 0,0000000625ms

... men nu? Hur räknar jag nu liksom?? :(

Kod: Markera allt

void initTimer1(unsigned int compareValue) {
	
	TCCR1B |= (1 << CS12);   //pre-scaling på 256
	
	TCCR1B |= (1 << WGM11);    //CTC-läge TOP value = OCR1A
	
	OCR1A = compareValue;   
	TIMSK1 |=(1<<OCIE1A);  //interrupt när TCNT1 = OCR1A värdet
    
	}
Tusen tack för hjälp!
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4695
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Swech »

Svarar med frågor så du inte får allt serverat.
Vilken frekvens har kristallen?

Vilken frekvens skall du ha på din signal ?

Hur mycket större är din kristallfrekvens jämfört med önskad signalfrekvens

Räcker det med att dela kristallfrekvensen med ett tal som är maximalt 65536?

OM det inte räcker, har du någon ide om hur du får ned frekvensen till modulen som
skall generera din signal?

Swech
Jennie
Inlägg: 173
Blev medlem: 8 februari 2014, 13:23:00

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Jennie »

Supertack för hjälp!

Ska pröva svara efter bästa förmåga.
Vilken frekvens har kristallen?
16 MHz?

Har en ATmega2560 som har en maxfrekvens på det enligt databladet.

(eller 16*10^6 Hz eller 16 000 000 Hz)
Vilken frekvens skall du ha på din signal ?
500 Hz?

Står i uppgiften "där FoCA ska sättas (...) svarande till en periodtid på 2 ms".

Frekvensformeln är f = 1/T

Så tänker att det blir

f = 1 / 0,002s

= 500 Hz
Hur mycket större är din kristallfrekvens jämfört med önskad signalfrekvens?
32000?

16 000 000 Hz / 500 Hz = 32000 Hz
Räcker det med att dela kristallfrekvensen med ett tal som är maximalt 65536?
OM det inte räcker, har du någon ide om hur du får ned frekvensen till modulen som
skall generera din signal?
Förstår inte helt vad som menas med den här frågan, ärligt talat? Räcker med vad?

Jag tror att 32000 Hz ska delas med något av prescaler-värdena men jag är som osäker på vilket värde för prescalern jag kan välja.
Senast redigerad av Jennie 14 april 2015, 00:18:58, redigerad totalt 3 gånger.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av sodjan »

>> Hur mycket större är din kristallfrekvens jämfört med önskad signalfrekvens?

> 16 000 000 Hz - 500 Hz = 15999500 Hz

Frågan kunde kanske (eller uppenbarligen) missförstås... :-)
Men det tänta svaret ska i alla fall vara:

16 000 000 Hz / 500 Hz = 32000
Jennie
Inlägg: 173
Blev medlem: 8 februari 2014, 13:23:00

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Jennie »

Har läst på lite mer på internet nu, har jag gjort riktigt ifall jag räknat och gjort så här?

Det är alltså förutsatt att vi har en F_CPU på 16 MHz, önskad fördröjning är 1 ms (eller 0.001s)

1. Prescaler: 8
Klockfrekvens = 16 000 000 Hz/prescalern = 16 000 000 Hz/8 = 2000000 Hz
T = 1 / 2000000 Hz = 0,0000005s
Timer Count = (önskad fördröjning / Perioden) -1 = (0,001s / 0,0000005s) -1 = 1999

2. Prescaler: 64
Klockfrekvens = 16 000 000 Hz/prescalern = 16 000 000 Hz/64 = 250000 Hz
T= 1 / 250000 Hz = 0,000004s
Timer Count = (önskad fördröjning / Perioden) -1 = (0,001s / 0,000004s) -1 = 249

3. Prescaler: 256
Klockfrekvens = 16 000 000 Hz/prescalern = 16 000 000 Hz/256 = 62500 Hz
T= 1 / 62500 Hz = 0,000016s
Timer Count = (önskad fördröjning / Perioden) -1 = (0,001s / 0,000016s) -1 = 61.5

4. Prescaler: 1024
Klockfrekvens = 16 000 000 Hz/prescalern = 16 000 000 Hz/1024 = 15625 Hz
T= 1 / 15625 Hz = 0,000064s
Timer Count = (önskad fördröjning / Perioden) -1 = (0,001s / 0,000064s) -1 = 14.625


VAL AV PRESCALER

Så samtiga prescalers faller inom maxgränsen 65535 men då jag ska ha ett heltalsvärde för prescalern så kan jag inte använda 256 eller 1024, då de har decimaler.
Alltså kan jag bara välja mellan prescalern 8 eller 64, och i det fallet är det nog lämpligast att välja 8:an då det ger bättre "resolution".

Är det riktigt det här eller är jag skvatt galen?
bearing
Inlägg: 11265
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av bearing »

Det är riktigt.

Med 16-bit timer skulle jag inte använt prescaler alls för att få hög upplösning. Med 8-bit timer är det å andra sidan nödvändigt. Och då blir också valen av lämplig prescaler mer begränsade.

Nu krävde ju uppgiften att du skulle använda prescaler, så du har gjort rätt.
Jennie
Inlägg: 173
Blev medlem: 8 februari 2014, 13:23:00

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Jennie »

Nästan tror jag. :)
Någon som vet varför min kod ändå inte funkar nu? Jag får min lysdiod att blinka till snabbt men sen fortsätter den bara att lysa och jag får inte de beräknade blinkningarna på 2 sekunder.


Har först listat kraven och sedan min kod (databladsbilderna finns ju i första inlägget ovan).

1. Initilisera några register så att du får en interrupt per 1 ms. på en "compare match" (registererna: OCR1A TCNT1).
Använd CTC-läge så nollställs räknaren varenda gång, det blir en matchning. (se tabell s.148 i datablad).


2. Beräkna compare value, så kriteriet på 1 ms. är uppfyllt, CTC–mode-formeln finns på s.150 i databladet och ska användas där FoCA ska sättas till 0.5*1000 svarande till en periodtid på 2 ms.
Studera timing diagram s.149.
Prescalling värde för fosc ska du också sätta, se tabell 17-6 s.161 i databladet, det är viktigt att uppnå ett heltal till compare value registret OCR1A!
Så håll ett av värdena och finn ett annat. Tabell 17-2 s.148 i databladet beskriver bit för CTC-läge.


3. Sätt värden in i compare value-registeret: OCR1A = ”compare value hittat i tidigare fråga”

4. Initilalisera bit i TIMSK1A-registeret och enable global interrupt.

5. Skriv interrupt service routinen ISR(vektornamn – c-compilermanual för namn på vektoren) I service routinen räknas en global variabel upp för varje gång det är interrupt.

6. I main funktionen testas – med ett if statement – ifall räknaren har nått 999, om den är 999 nollställs räkne-variablen och så tänds LED på PB7 varannan gång och släcks varannan gång (toogle). Kontrollera med en klocka att det passar med ett blink på 2 sek. – när det är klart så är koden i main klar till att integreras ihop med uppgiften från förra veckan.


Och här är min kod, varför fungerar det inte?

16 MHz
Prescale: 8 (vilket jag i databladet kom fram till att vara "(1 << CS11)").
Operationsläge: CTC (vilket jag i databladet kom fram till att vara "(1 << WGM12)").
Compare value: 1999 (beräkning finns i mitt tidigare inlägg, är fortfarande lite osäker på ifall det är rätt dock)

Kod: Markera allt

#include <avr/interrupt.h>
#include <avr/io.h>

void initTimer1(unsigned int compareValue) {
	
	TCCR1B |= (1 << CS11) | (1 << WGM12);   // Mode = CTC, Prescaler = 8  
	
	TCNT1 = 0;
	
	OCR1A = compareValue;   
	TIMSK1 |= (1 << OCIE1A);  //interrupt when TCNT1 = OCR1A value
    
	}

int main(void)
{   
	
	DDRB |= (1<<DDB7);   //enable led output
	initTimer1(1999);   
		
	sei(); // enable global interrupt
		
    for(;;)
    {
			if (TCNT1 >= 999) // Talet som efterfrågades i uppgift 6 och ska ge blinkningar på 2 sek.
			{
					PORTB ^= ( 1 << PB7);
			
					TCNT1 = 0; // Reset timer value
			}
		
      asm("NOP"); //TODO::  
   // PORTB |=(1<<PB7);
		}
}

ISR(TIMER1_COMPA_vect)
{
	static char togle=0;
	if (togle==0) {
		PORTB |= (1 << PB7);
		togle=1;
	}
      else{
		PORTB &=~ (1 << PB7);
		togle=0;
	} 
}
bearing
Inlägg: 11265
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av bearing »

Du har missförstått uppgift 5 och 6. TCNT1 är själva hårdvarutimern. Den räknar mellan 0 och 1999 väldigt fort. Varje gång den når 1999 (och nollställs) körs interruptrutinen (varje millisekund i ditt program). Enligt uppgift 5 ska du, i interruptet, räkna upp en global variabel (som du definierat själv). Den variabeln ska sedan jämföras med 999 i mainloopen, för att växla lysdiodens läge en gång per sekund.

Det är inte lämpligt att läsa och skriva TCNT1 i mainloopen. Låt hårdvarutimern räkna på automatiskt. Eftersom att TCNT1 nollställs i mainloopen när den är större än 999, kommer TCNT1 aldrig att nå 1999, d.v.s det blir inte något interrupt.
Jennie
Inlägg: 173
Blev medlem: 8 februari 2014, 13:23:00

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Jennie »

^ Tack igen!

Försökte göra som du som nu och får den till att blinka nästan med 2 sekunders mellanrum, men jag vet inte om det är särskilt exakt.

Ser det rimligt ut? :D

Kod: Markera allt

#include <avr/interrupt.h>
#include <avr/io.h>

volatile uint16_t counter;

void initTimer1(unsigned int compareValue) {
	
	TCCR1B |= (1 << CS11) | (1 << WGM12);   // Mode = CTC, Prescaler = 8 
	
	TCNT1 = 0;
	
	OCR1A = compareValue;   
	TIMSK1 |= (1 << OCIE1A);  //interrupt when TCNT1 = OCR1A value
    
	}

int main(void)
{   
	
	DDRB |= (1<<DDB7);   //enable led output
	initTimer1(1999);   //for getting a compare match for every 1 ms
	
	sei(); // enable global interrupt

	
    while(1)
    {
      asm("NOP"); //TODO:: 
	  
	  if (counter >= 999)
	  {
		  PORTB ^= ( 1 << PB7);
		  
		  counter = 0; // Reset timer value
	  }
     }
}

ISR(TIMER1_COMPA_vect)
{
	 counter++;
}
bearing
Inlägg: 11265
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av bearing »

Det ser rimligt ut. counter bör initieras i början av programmet, annars tänds dioden slumpmässigt med ca 64/65-dels sannolikhet vid programstart. (Från spänningslöst tillstånd. Vid enbart reset behåller variabeln sannolikt värdet den hade innan reset.) Alternativt deklarera static volatile eftersom att static initieras till 0. Om enbart volatile gör det minns jag inte, men tror inte det.

Eftersom att du inte har några avrundningar i beräkningarna borde lysdioden blinka i 0,5Hz med lika stor noggrannhet som kristallen. Kristaller brukar ha 50ppm.
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Wedge »

"Static" har ingenting alls med initiering till noll att göra, och inte "volatile" heller.
Nerre
Inlägg: 26717
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Nerre »

Den här sidan http://www.java-samples.com/showtutoria ... rialid=528 påstår att
In the absence of explicit initialization, external and static variables are guaranteed to be initialized to zero; automatic and register variables have undefined (i.e., garbage) initial values.
(Trots sidans namn handlar artikeln om C och inte java.)
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Wedge »

Visst är det så, men ...
http://en.wikipedia.org/wiki/Static_(keyword)
In these languages, the term "static variable" has two meanings which are easy to confuse:
1.A variable with the same lifetime as the program, as described above (language-independent); or
2.(C-family-specific) A variable declared with storage class static.
Den länkade artikeln talar om "static variables", dvs definition 1.
"volatile uint16_t counter;" ger en "static variable" som lever under hela programmets livslängd. Den ÄR initierad när programmet går igång. Att kasta på nyckelordet "static" och tala om initiering är nonsens. Att dra in "volatile" i initieringsdiskussionen likaså.

Lagringsklassen static i C (definition 2) styr synlighet och åtkomst, plus att inuti en funktion ger det funktionsmässigt en variabel enligt typdefinition 1, men med åtkomst enbart inuti funktionen.
Nerre
Inlägg: 26717
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Nerre »

En variabel som deklareras med static (enligt din definition 2) blir också en variabel som har en statisk lagring (enligt din definition 1).

Mina fet- och kursivmarkeringar nedan:
6.2.4
An object whose identifier is declared with external or internal linkage, or with the storage-class specifier static has static storage duration.
5.1.2
All objects with static storage duration shall be initialized (set to their initial values) before program startup.
http://www.open-std.org/JTC1/sc22/wg14/ ... /n1256.pdf
Användarvisningsbild
Wedge
Inlägg: 1026
Blev medlem: 8 juli 2012, 17:33:33

Re: AKUT! Hjälp med att beräkna compare value (Atmel)

Inlägg av Wedge »

Javisst. Men enda gången static gör nån skillnad är inuti funktioner. Där kommer static-deklarationen att påverka livslängd, lagring och initiering. Det är inte detta beteende vi diskuterar, inte jag åtminstone. Dessutom torde det vara onödigt meckigt att få en static-deklarerad lokal variabel att lira ihop med en interruptrutin, men visst går det om man är envis.

I globalt scope så är "static int foo;" exakt samma sak som "int foo;" och initieras till noll. Med eller utan static. Alla variabler i globalt scope har statisk lagring/livslängd. Static tillför där ingenting funktionellt, bara en inkapslingsförstärkning av symbolen, så att den bara blir synlig i den fil den står definerad i. Att hävda att static där påverkar initieringen är trams.
Skriv svar