www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430x169 und TIMERA compare register


Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hy folks,

ich habe hier eine grundelegende Frage. Ich benutze den TIMERA im 
compare mode. Es werden mir dazu ja 3 verschiedene Register zur Auswahl 
gestellt. Da ich das CCR0 schon im capture mode verwende, wollte ich das 
CCR1 register benutzen. Diese habe ich wie folgt initialisiert
...........
init_TIMERA1(0x0212, 0x0000, (timer_MANCODE/2));
.............
void init_TIMERA1(unsigned int mode, unsigned int control, unsigned int cycles )
//------------------------------------------------------------------------------
{    
TACTL = (mode&0xFFCF) | TACLR;  // set timer register, clear TAR
  
    CCTL1 = control;      // set control register
  if (control < 16384) 
    CCR1 = cycles;    // set compare register if compare mode selected    

    TACTL |= (mode&0x30);            // Start/stop TIMER_A 
}
In timer_MANCODE ist das Ergebnis aus dem Capture mode. Wenn ich das 
ganze jetzt starte bekomme ich ein willkürliches Ergebnis vom Timer.
Daraufhin habe ich das Datenblatt etwas genauer studiert und gesehen das 
durch die MCx bits der Upmode für das CCR0 Register gestartet wird?!
Meine Frage jetzt ist es gar nicht möglich im compare mode das Register 
CCR1 oder CCR2 zu benutzen. Im Datenblatt finde ich nichts weiteres. Und 
wenn ja wieso gibt es denn drei verschiedene Compare/Capture Register??

Hoffe hier kann mir jemand helfen. Dann auch schon mal vielen Dank!!

Mfg
Stephan

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aaaalso,
den TimerA mit all seinen Möglichkeiten hier zu beschreiben, ist viel zu 
umfangreich. Du solltest Dir hierzu nicht das Datenblatt sondern den 
User-Guide 'MSP430x1xx Family' anschauen!

Dein Code-Bsp. ist mir auch nicht ganz klar.
>bekomme ich ein willkürliches Ergebnis vom Timer
Wo liest Du denn den Timer aus?

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich benutze nicht den Timer wert den habe ich ja schon durch den capture 
mode ermittelt und der ist auch OK.
Das Problem ist das ich ja einen Interrupt auslöse und da ich das mit 
CCR1 Register machen wollte bekam ich einen Interrupt in einer 
willkürlichen Zeit. Meines achtens liegt es daran das der Interrupt dann 
durch das CCR0 Register initialisiert wurde, welches meinen capture Wert 
entsprach.
Um es noch genauer zu sagen es geht mir nur darum mit dem CCR1 register 
einen Interrupt, in der vorher durch den capture mode des TIMERA0 (CCR0 
register) ermittelten Wert, auszulösen.
Hoffe das ist jetzt genauer. Werde mir jetzt erst mal den User Guide 
anschauen, hoffentlich werde ich da fündig.

mfg

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einen CCR1-Interrupt wirst Du so nie bekommen, weil Du ihn nicht 
aktiviert hast (CCTL1 = 0). Stattdessen hast Du den Timer-Interrupt 
freigegeben (TACTL = (mode&0xFFCF) | TACLR; mit mode = 0x0212).
Da Du den Timer im 'Up-to-CCR0' betreibst, kommt dieser IRQ alle 
CCR0-Timercounts.

Wenn Du nun einen IRQ durch CCR1 auslösen willst, musst Du CCTL1 |= CCIE 
setzen. Allerdings kommt dieser IRQ dann alle CCR0/2, da Dein 
Übergabeparameter timer_MANCODE/2 ist!

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok dann habe ich das falsch verstanden aus dem Datenblatt. Ich dachte da 
sich der CCR1,CCR2 und der Timeroverflow-Interrupt einen Vektor teilen 
muss ich diesen dann auch aktivieren, sprich TACTL = (mode&0xFFCF) | 
TACLR; mit mode = 0x0212.
Werde das so mal ändern und hoffe das es klappt.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja und Nein :-)
TMR_A, CCR1 und CCR2 teilen sich zwar einen Vektor (Im Register TAIV 
steht dann die Interruptquelle) aber die Interrupts müssen einzeln 
freigegeben werden!

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok es funzt jetzt schon mal in der Richtung in der ich will. Das ganze 
dauert nur sehr lange. Wenn ich das gemessene mit dem was ich dann 
ausgebe vergleiche habe ich einen Unterschied von ca.3µs bei einer 
Frequenz von ca.4Mhz. Und das auch nur wenn ich den Timerinterrupt UND 
den compareinterrupt anschalte. Ohne Timerinterrupt komme ich nur auf 
die hälfte der Frequenz. Auch muss ich den Timer im Interrupt auf null 
setzten (TAR=0) Komme leider auch mit dem Userguide nicht so recht 
weiter.
hier noch mal mein aktueller code
........
init_TIMERA1(0x0212, 0x0010, timer_MANCODE/2);
.........


//------------------------------------------------------------------------------
// Timer A0 interrupt service routine
interrupt (TIMERA1_VECTOR) TIMER_A1(void)
//------------------------------------------------------------------------------
{
  TAR = 0;
  CCTL1 &= ~(CCIFG|COV);      // reset timer occured flag, for up mode
  TACTL &= ~TAIFG;
  
  run = 1;
  P1OUT ^= 0x10;  

  MANCHESTER_CODE[run] = (MANCHESTER_CODE[run] | (MAN_PIN & MAN_IN));
  MANCHESTER_CODE[run] <<= 1;
}

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, ich versteh' nur Bahnhof!
>habe ich einen Unterschied von ca.3µs bei einer
>Frequenz von ca.4Mhz. Und das auch nur wenn ich den Timerinterrupt UND
>den compareinterrupt anschalte. Ohne Timerinterrupt komme ich nur auf
>die hälfte der Frequenz.
???
Hälfte der Frequenz = 2MHz oder 1/(2*3µs) ?
Wie initialisierst Du jetzt Timer_A ???
Warum übergibst Du timer_MANCODE/2, wenn Du doch timer_MANCODE haben 
willst (zumindest hast Du gesagt dass CCR0 = timer_MANCODE)) ???

Beschreibe doch mal bitte eindeutig, was Du eigentlich machen willst!
Deine Erklärungen dazu sind zu ungenau!

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok dann fange ich mal von vorne an. Ich habe ein serielles Signal. Dies 
beinhaltet am Anfang ein Preamble durch welches ich mir die 
Periodendauer herauslese. Das mache ich mit den capture mode von 
TIMERA0. Um dann das Signal abzutasten initialisiere ich den TIMERA1 mit 
der hälfte der vorher gemessenen Periodendauer ca. die Mitte des 
gültigen Zustands zu erreichen. Nach erfolgreichen auslesen setze ich 
den Timer auf den gemessenen Wert um dann immer wieder auf die Mitte zu 
kommen. Um den Anfang der Übertragung zu erkennen wird ein langes high 
Signal gesendet und mit dem TIMERB0 ausgemessen. Darauf startet die 
Übertragung wie ich es vorher beschrieben habe. Das ist auf jeden Fall 
meine Theorie :)
Bei Verbesserungen/Veränderungen bitte raus damit. Das ganze wird auf 
einen MSP430x169 realisiert.

So um dann auf die anderen Unklarheiten zurückzukommen. Die Frequenz des 
MSP habe ich auf ca.4Mhz mit einem Uhrnquarz eingestellt. Wenn ich jetzt 
wie oben das Programm laufen lasse, bekomme ich immer einen Intterrupt 
bei ca.53µs es sollten aber nur 50µs sein. Wenn ich das ganze mit dem 
Interrup vom TIMERA0 realisiere ist das auch kein Problem. Nutze ich 
allerdings den CCR1 Interrupt, verlängert sich alles um sagenhafte 3µs 
was bei einer Taktfrequenz von ca.4MHz schon recht ordentlich ist.

Ich hoffe jetzt ist es etwas genauer und präziser formuliert.

mfg

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist das serielle Protokoll vorgegeben oder kannst Du es ändern?
Ich meine, die einfachste Art wäre natürlich die vorhandene UART im MSP 
zu nutzen, wenn das Protokoll das zulässt.
Ansonsten könntest Du auch weiterhin mit der Capture-Methode die 
Baudrate ermitteln (Falls diese unbekannt ist) und dann die UART 
entsprechend konfigurieren.
Zu der Timer-Problematik fällt mir jetzt so spontan auch nix ein.
Da muss ich noch mal in mich gehen :-)

Fragen zum Verständnis:
Preamble ist 01010101-Folge?
Capture auf beide Flanken? (ergibt Bit-Time)
Capture nur auf steigende oder fallende Flanke? (ergibt doppelte 
Bit-Time)
Nach Preamble Verzögerung um 1/2Bit, um in Bitmitte abzutasten,
danach Abtastrate mit Bit-Time?
Falls ja, ist das vom Prinzip her schon richtig, würde ich sagen.

Anmerkung:
Einmaliger DCO-Abgleich auf Uhrenquarz ist 'gefährlich', da DCO bei 
Temperatur- und Spannungsänderungen wegdriftet. Aber wenn Du Dich bei 
jeder Übertragung erneut auf die Preable synchronisierst, sollte das 
kein Problem sein!

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das protokoll ist vorgegeben und die UART kann ich leider nicht nehmen.
Preamble ist 8 bit Folge, 10101010.
Capture ist auf beide Flanken und wird über jedes Bit gemittelt.
Abtastung erst mit halber Zeit und dann mit ganzer, auch richtig.

DCO Abgleich sollte wie du schon sagtest kein Prob sein da ich ja nicht 
mit einer vorgegebenen Zeit arbeite sondern mich immer synchronisiere.

Bin auch erst mal weg, falls dir aber noch was einfällt bin ich Ohr.

danke erst mal!

Stephan

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu der Timer-Geschichte:

Durch das Capture hast Du in CCR0 den Wert der Bit-Time... gut!
Diesen Wert erstmal in eine Variable sichern, da wir CCR0 ändern müssen!

Jetzt willst Du 1/2Bit-Time Verzögerung, also:
- CCR0 auf 1/2 Wert setzen
- keinen Interrupt verwenden, sondern pollen:
  
     TACTL |=  TACLR;             // Timer nullen
     TACTL &= ~TAIFG;             // IRQ-Flag löschen
     TACTL |=  MC0;               // up-mode up to CCR0
     while(!(TACTL & TAIFG));     // warten bis Timer = CCR0,
                                  // d.h. 1/2Bit-Time ist um.
- CCR0 wieder auf volle Bit-Time setzen
- Timer_A Interrupt verwenden ( nur den!)
     TACTL |=  TACLR;             // Timer nullen
     TACTL &= ~TAIFG;             // IRQ-Flag löschen
     TACTL |=  TAIE;              // Timer_A IRQ freigeben
     TACTL |=  MC0;               // up-mode up to CCR0
Der Timer_A läuft jetzt von 0 bis CCR0 und bei jedem Übergang
von CCR0 -> 0 wird der IRQ ausgelöst.

Um Dich vollends zu verwirren (:-)) kannst Du anstatt des Timer_A 
IRQ's auch den CCR0-IRQ verwenden. CCR0-IRQ tritt auf, wenn Timer_A = 
CCR0 ist. Während der Timer_A IRQ beim Überlauf des Timers nach 0 
auftritt (also einen Takt nach CCR0-IRQ). Deshalb sollten man in dieser 
Konfiguration auch nicht CCR0 und Timer_A IRQ aktivieren, da beide 
fast gleichzeitig auftreten, die IRQ-Behandlung inkl. ISR aber mehr Zeit 
benötigt!
B.T.W.: IRQ-Latenz + IRQ-Return = 11 Taktzyklen. Bei 4MHz macht das 
2,75µs... vielleicht waren das Deine 3µs ?!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Äh.... ich korrigiere...
Du musst ja bei der ersten 1/2 Bit-Time Verzögerung auch sampeln.
Also hier auch mit Interrupt:

- CCR0 auf 1/2 Wert setzen
- Timer_A Interrupt verwenden ( nur den!)
     TACTL |=  TACLR;             // Timer nullen
     TACTL &= ~TAIFG;             // IRQ-Flag löschen
     TACTL |=  TAIE;              // Timer_A IRQ freigeben
     TACTL |=  MC0;               // up-mode up to CCR0

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So im großen und ganzen funktioniert es jetzt. Allerdings bin ich beim 
Einlesen von den Interrupts weg. Es dauert einfach zu lange. Jetzt polle 
ich auf das Overflow Flag, welches wesentlich schneller ist.
Zu meinen Problemen. Zwei sind es immer noch. Zur berechnung der Bitzeit 
ermittele ich den Mittelwert von 6 Bits des Preambles. Dazu wird im 
Interrupt (steigende und fallende Flanke) eine Variable aufaddiert. Will 
ich jetzt den Timer das erste mal setzen dann muss ich ja den Wert durch 
die Anzahl der Messungen teilen. Da dies eine 16bit Division ist dauert 
es seine Zeit. Und genau das ist mein Problem. Hier einfach mal der Code 
ausschnitt.
while(!(position_MANCODE == 16));
P1OUT ^= 0x10;                
TACTL |=  0x0200 | TACLR ;   // Timer setzen    
timer_MANCODE /= 6;
CCR0   = timer_MANCODE;
TACTL &= ~TAIFG;             // IRQ-Flag löschen
TACTL |=  0x0010;            // up-mode up to CCR0  
Im Interrupt sieht es folgendermaßen aus:
  if (++position_MANCODE & 0x01) 
    temp_MANCODE = CCR0;
  else if (CCR0 < temp_MANCODE)  // overflow occured
  {
    temp_MANCODE = ((65535-temp_MANCODE) + CCR0);  // calculate difference
    timer_MANCODE += temp_MANCODE;          
  }
  else               // no overflow occured
  {
    temp_MANCODE = (CCR0 - temp_MANCODE);      // calculate difference
    timer_MANCODE +=  temp_MANCODE;        
  }
Jetzt vielleicht jemand hier der da ne bessere Idee hat. Auf Mittelwert 
wollte ich eigentlich nicht verzichten.
Dann mein zweites Problem. Es ist eine einfache Codezeile, viel mehr ein 
Funktionsaufruf. Und zwar dieser:
init_TIMERA0(0x0200, 0xC110, 0);
Das gehört zu meiner Init am Anfang des Codes. Wenn ich dieses jetzt 
ausführe springt er schon in den Interrupt. Meiner Meinung nach ist der 
Timer dann doch noch ausgeschaltet und es sollte kein Interrupt 
ausgelöst werden. Hier dann noch die Funktion selber:
    TACTL = (mode&0xFFCF) | TACLR;  // set timer register, clear TAR

    CCTL0 = control;      // set control register
  if (control < 16384) 
    CCR0 = cycles;    // set compare register if compare mode selected    

    TACTL |= (mode&0x30);            // Start/stop TIMER_A 
Falls jetzt jemand ne Idee hat wär ich echt dankbar!

greetz
Stephan

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weiß jetzt nicht mehr wieviele Bits Deine Preamble hat, aber Du könntest 
anstatt über 6 Bits zu mittel auch 4 oder 8 Bits nehmen. Division ist 
dann einfach ein Rechts-Schieben der Summe um 2 bzw. 3 Stellen.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In
init_TIMERA0(0x0200, 0xC110, 0);
aktivierst Du den Interrupt für CCR0.
Wahrscheinlich läufst Du in den IRQ?!

Ich vermute, Du hast die verschiedenen Timer-Interruptquellen noch nicht 
so ganz verstanden. Es gibt zwei Interrupt-Vektoren, die zum Timer_A 
gehören:
#pragma vector=TIMERA0_VECTOR
__interrupt void CCR0_Interrupt (void)

#pragma vector=TIMERA1_VECTOR
__interrupt void TMRA_CCR1_CCR2_Interrupt (void)

Der erste gehört ausschließlich zum CCR0.
Der zweite wird von Timer-Overflow, CCR1 und CCR2 gemeinsam benutzt.
Daher muss man hier im TAIV-Register nachschauen, welche Quelle den IRQ 
ausgelöst hat!

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja das weiss ich, oder viel mehr so habe ich das auch schon verstanden. 
Nur verstehe ich nicht das ich einen IRQ bekomme wenn ich den Timer noch 
gar nicht laufen lasse. Meine Frage ist explicit warum ohne laufenden 
Timer der IRQ ausgelöst wird und das nicht nur einmal. Das Programm 
springt dann in die CCR0 Interrupt Routine.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, ich glaub ich weiß wo der Hund begraben ist... Tricky ;-)

Der CCR0-IRQ wird ausgelöst, wenn der Wert im CCR-Register mit dem 
Timer-Wert übereinstimmt. Du löscht den Timer, also TMR=0. Dann setzt Du 
CCR0 = cycles... und als cycles hast Du auch 0 übergeben -> Bingo!

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok das klingt logisch :) Damit wirst du auch recht haben!! Nun ein neues 
Problem :) Ich kann das TACCR0 Register aus meiner Funktion heraus nicht 
initialisieren. Bei TimerB geht das ohne Probleme und die Funktion ist 
die gleiche. Wenn ich dann später das TACCR0 Register setze funzt es 
ohne Probleme. Ich habe auch schon die Reihenfolge geändert aber beim 
Debuggen stelle ich immer wieder das gleiche fest. Wenn ich den 
Assembler Code anschaue sieht es auch richtig aus.
Denke langsam das irgendwie die Kombination vom MSPGCC und Eclipse die 
ich benutze nicht funzt.
Aber noch mal meinen C-Code damit das auch nachvollziehbar ist
.......
  init_TIMERA0(0x0200, 0xC910, 10);
  // initialise TIMERB, compare mode, SMCLK/1, capture/compare int 
  init_TIMERB0(0x0200, 0x0010, 40);  
  // initialise ADC0
//  init_ADC0();
  // initialise ports later than USART!!!
  init_PORTS();    
  // initialise LCD
  init_LCD();   
  // global interrupt enable 
  _EINT();          
//------------------------------------------------------------------------------    
  
  LED1_OFF;
  LED2_OFF;
  
  temp_tb = TBCCR0;
  temp_ta = TACCR0;
  TACCR0 = 1000;
  temp_ta = TACCR0;
.......
wenn ich nun step per step durchgehe (angefangen bei  temp_tb = TBCCR0;) 
stelle ich fest das temp_tb auch seinen Wert von 40 hat. temp_ta dann 
aber nicht 10 sondern 0 ist. Erst beim zweiten mal ist temp_ta den 
gesetzten Wert von 1000. Initialisierung ist die gleiche wie oben 
beschrieben.

Programmiere wirklich schon länger, allerdings das erste mal MSP, aber 
so was ist mir noch nie passiert.

Mfg
Steph

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Scherzkeks ;-)
Guck mal Deine Init an und überlege, was bei control = 0xC910 passiert!
  if (control < 16384) 
    CCR0 = cycles;    // set compare register if compare mode selected 

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah tschuldige, ein codeteil fehlt und zwar der:
else 
    TACCR0 = 10;
das habe ich eingefügt nachdem du das mit dem comparewert gesagt hast.
Das ganze Übel liegt aber woanders. Ich habe mal angefangen alles 
auszukommentieren mit dem Ergebnis das es an der Init vom LCD liegt. Das 
witzige ist auch, das der Fehler wenn er einmal aufgetaucht ist, nur 
durch ein abtrennen der Spannungsversorgung behoben werden kann. So war 
es auch nich einfach das herauszufinden.
Ich bin jetzt mal dran mit dem Debugger eins nach dem anderen 
auseinander zu nehmen. Ich meld mich wenn ich den Fehler hab.
Aber riesen dank noch mal das du dich so viel damit beschäftigst!!

mfg

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So nach fast 2 Tagen debuggen habe ich es endlich gefunden. Der Fehler 
trat leider ja immer nur sporadisch auf und ließ sich auch nur durch 
einen Power-on-Reset beheben, wie beschrieben. Das ganze hängt an der 
Init der Ports. Dieses erledige ich durch Defines aus der main.h. 
Irgendwie scheint es aber Fehler bei den Defines des Port1 zu geben. 
Defines wie folgt:
#define PORT1_DIR  0x10  // port1 direction 
#define PORT1_SEL  0x02  // port1 special function 
#define PORT1_IF  0x00  // port1 interrupt flag   
#define PORT1_IES  0x00  // port1 interrupt edge select
#define PORT1_IE  0x00  // port1 interrupt enable 
Init dann in einer Funktion wie folgt:
P1SEL = PORT1_SEL;    // Port1 I/O Function
P1DIR = PORT1_DIR;    // Port1 Direction    
P1IFG &= ~PORT1_IF;    // Port1 interrupt flag   
P1IES = PORT1_IES;    // Port1 interrupt edge select
P1IE  = PORT1_IE;    // Port1 interrupt enable  
Beim gesammten Code scheint auch noch nicht das letzte Wort gesprochen 
zu sein.

greetz

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan Plaschke wrote:

> Irgendwie scheint es aber Fehler bei den Defines des Port1 zu geben.
> Defines wie folgt:
> #define PORT1_IF  0x00  // port1 interrupt flag
> Init dann in einer Funktion wie folgt:
> P1IFG &= ~PORT1_IF;    // Port1 interrupt flag

Was soll das deiner Meinung nach bewirken?

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nichts! Es sind allgemeine Defines damit ich nicht immer in den 
Funktionen rumpfuschen musss.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meinte eher das Ver-Unden der Interrupt Flags. Der Befehlt hat 
keinen wirklichen Sinn, denn es bleibt alles, wie es ist. Allerdings 
sollte man beim manipulieren der Interrupt-Flags genau wissen, was man 
macht....

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal abgesehen davon, dass
> #define PORT1_IF  0x00  // port1 interrupt flag
> P1IFG &= ~PORT1_IF;     // Port1 interrupt flag
die Interrupt-Flags nicht löscht, wie Christian schon erwähnt hat...
... was ist den jetzt noch Dein Problem???

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Problem ist immer noch das der TimerA macht was er will. Ich setze 
die Register, steppe mich durch mein Programm und nach einem Durchlauf 
sind die Register anders gesetzt. Dies obwohl ich nur einmal den TimerA 
anfasse. Zum Beispiel wird das TACCR0 Register immer auf 0 gesetzt, 
angefasst wird es aber nicht...

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stoppst du den Timer, wenn du eines der Register veränderst? Wenn nicht, 
kann das zu seltsamen Verhalten führen. Außerdem muss man aufpassen, 
wenn man TACLR setzt (also Timer löschen), wird der Teilerfaktor und die 
Richtung des Timers ebenfalls zurückgesetzt. Sowas zu Debuggen ist 
schwierig...

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Verbesserung das TACCR0 wird nicht immer auf 0 sondern auf einen 
beliebigen Wert gesetzt. Das liegt daran das der Int ausgelöst wird wie 
ich jetzt gerade herausgefunden habe. Der Timer ist auf Capture gestellt 
und während der Init läuft im Hintergrund ein kontinuirlliches Signal. 
Da dann immer wieder der Capture ausgelöst wird erhalte ich einen 
Capture overflow. Es lag also nicht daran das ich einen compare int 
bekommen habe sondern einen capture overflow int.
Jetzt nur eine ganz allgemeine Frage:
Werden die Interruptquellen nicht mit der jeweiligen Peripherie 
gestartet?? Der Timer "läuft" ja noch nicht, nur die initialisierung 
wurde schon durchgeführt.

greetz

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interrupts werden immer durch das zugehörige Enable-Bit freigeschaltet.
Ob der Timer dabei läuft oder nicht ist wurscht... aber das hatten wir 
doch schon ;-)

Autor: Stephan Plaschke (steph0815)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann hatte ich es damals noch nicht verinnerlicht :)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.