mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATtiny25 asynchronen Modus von Timer1 aktivieren


Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag,

ich versuche nun schon seit gestern den Timer1 des ATtiny 25 im 
asynchronen Modus mit 64Mhz zu betreiben. Durch das Datenblatt werde ich 
nicht schlauer. Im Datenblatt steht, dass PCKE in PLLCSR gesetzt sein 
muss, aber das habe ich ja.
Muss ich eventuell etwas an den Fusebits ändern? - momentan betreibe ich 
den ATtiny mit internen 8Mhz-

Es wäre echt klasse, wenn mir hier jemand einen entscheidenden Tipp 
geben kann.

Meine Timerinitialisierung:
// Timer 1 konfigurieren: 
TCCR1 |= (1<<CS10); 
PLLCSR |= (1<<PCKE);

//Overflow Interrupt Timer 1 aktivieren
TIMSK |= (1<<TOIE1);

// Global Interrupts aktivieren
sei();

Vielen Dank shconmal!

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:
> Im Datenblatt steht, dass PCKE in PLLCSR gesetzt sein
> muss, aber das habe ich ja.

Da steht aber noch mehr. Wie ich schon im anderen Thread (warum 
überhaupt ein neuer?) sagte, du musst anfangen genauer zu lesen. Nur 
einen flüchtigen Blick rein werfen reicht nun mal einfach nicht.

In der Beschreibung zu PCKE steht z.B. auch:
This bit can be set only if PLLE bit is set. It is safe to set this
bit only when the PLL is locked i.e the PLOCK bit is 1. The bit PCKE can
only be set, if the PLL has been enabled earlier.
Daraus ergibt sich eine einzuhaltende Folge von 3 Schritten.
Welche sind das?

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab einen enuen Thread aufgemacht, da sich mein Problem nun 
eingrenzen lies und ich dachte, dass es mit der genauernen Überschrift 
überischtlicher wird.

Mit den 3 Schritten müsste der code so aussehen?:
// Timer 1 konfigurieren: Clock = PCK 
TCCR1 |= (1<<CS10); 

//asynchronen Modus aktivieren (64Mhz)
PLLCSR |= (1<<PLOCK); 
PLLCSR |= (1<<PLLE);
PLLCSR |= (1<<PCKE);

//Overflow Interrupt Timer 1 aktivieren
TIMSK |= (1<<TOIE1);

Leider scheint irgend etwas immer noch nicht zu stimmen? - Mein Programm 
funktioniert zumindest noch nicht wie es soll...

Danke für deine Geduld mit mir ;) - ich hab an einer völlig falschen 
Stelle im Datenblatt gesucht.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und weiterhin machst du den Fehler nur flüchtig zu lesen.
Oder macht das Englisch dir Probleme?

Die drei Schritte sind:
1) PLL aktivieren
2) Warten bis PLL eingerastet
3) PCKE setzen

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Im Englischen bin ich zugegeben auch nicht besonders fit...

Wie realisiere ich denn das warten bis PLL einrastet ?

Also Schritt 1 ist:
PLLCSR |= (1<<PLLE);

Schritt 3 ist:
PLLCSR |= (1<<PCKE);

Falls ich das warten dadurch realisiere, dass ich das PLOCK bit setze 
ist Schritt 2:
PLLCSR |= (1<<PLOCK);

Allerdings funktioniert so das Programm acuh ncoh nciht...

Danke weiterhin

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:
> Falls ich das warten dadurch realisiere, dass ich das PLOCK bit setze

PLOCK ist Read-Only, das kannst du nicht selber setzen. Das wird von der 
Hardware gesetzt.

•Bit 0 - PLOCK: PLL Lock Detector
When the PLOCK bit is set, the PLL is locked to the reference clock.
The PLOCK bit should be ignored during initial PLL lock-in sequence
when PLL frequency overshoots and undershoots, before reaching steady
state. The steady state is obtained within 100 µs. After PLL lock-in
it is recommended to check the PLOCK bit before enabling PCK for
Timer/Counter1.
PLOCK gibt also an, ob die PLL eingerastet ist, oder nicht. Allerdings 
soll man dieses Bit in der ersten Startphase der PLL ignorieren. Diese 
erste Startphase dauert 100µs. Daraus ergibt sich, dass dies
> Wie realisiere ich denn das warten bis PLL einrastet ?
wiederum aus zwei Schritten besteht:
1) 100µs warten
2) warten bis PLOCK 1 ist

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mein Code:
void initTimer1(void){
  //cs13:cs10 = 0010 for 125kHz
  //cs13:cs10 = 0001 for 250kHz
  //TCCR1 |= (1<<CTC1);    // Clear timer/counter on compare match
  TCCR1 |= (1<<PWM1A);    // Pulse width modulator A enable
  //TCCR1 |= (1<<COM1A1);    // comparator A mode select, 01 here
  TCCR1 |= (1<<COM1A0);
  //TCCR1 |= (1<<CS13);      // clock select, prescaler
  //TCCR1 |= (1<<CS12);      // 125kHz
  TCCR1 |= (1<<CS11);
  //TCCR1 |= (1<<CS10);

  //GTCCR = 0;
  //GTCCR |= (1<<PWM1B);      // enable PWM B
  //GTTCR |= (1<<COM1B1);      // comparator B mode select
  //GTTCR |= (1<<COM1B0);
  //GTTCR |= (1<<FOC1B);    // force output compare match
  //GTTCR |= (1<<FOC1A);    // force output compare match
  //GTTCR |= (1<<PSR1);      // Reset the prescaler

  OCR1A = 100;
  OCR1B = 0;
  OCR1C = 255;        // maximum value for pwm
  //TIMSK |= (1<<OCIE1A);    // Output compare match a interrupt enable
  PLLCSR |= (1<<PLLE);    // enable PLL before enabling it as source for timer1
  _delay_us(100);        // wait 100us for pll to stabilize
  //PLLCSR |= (1<<LSM);     // low speed mode

  // lock detection
  // Blocks until lock is detected, i.e. PLOCK = 1
  while(!(PLLCSR & (1<<PLOCK)))
      ;

  PLLCSR |= (1<<PCKE);    // enable PLL as timer1 clock source

  // init dead times
  //DTPS1 |= (1<<DTPS11);       // dead time prescaler
  //DTPS1 |= (1<<DTPS10);      // 00 = 1, 11 = 8
/*
  // amount of dead cycles coded in binary
  DT1A |= (1<<DT1AH3);
  DT1A |= (1<<DT1AH2);
  DT1A |= (1<<DT1AH1);
  DT1A |= (1<<DT1AH0);
  DT1A |= (1<<DT1AL3);
  DT1A |= (1<<DT1AL2);
  DT1A |= (1<<DT1AL1);
  DT1A |= (1<<DT1AL0);
*/
}

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
avion23 schrieb:
> Mein Code:

Genau. Da versucht man ihn dazu zu bringen es so weit wie möglich selber 
herauszufinden, nur damit dann doch wieder jemand vorbeikommt und ihm 
eine vorgekaute Fertiglösung hinspuckt.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank !

Nun bin ich auf jedenfall schon um einiges klüger.
Allerdings tut mein Programm immer noch nciht was es soll - Es soll eine 
rote LED immer heller faden.

Wwäre toll, wenn ihr nochmal über meinen gesamten Programmcode schauen 
könntet:
#ifndef F_CPU
#define F_CPU 8000000UL 
#endif

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

#define rot_an    PORTB |= (1 << PB1)
#define rot_aus    PORTB &= ~(1 << PB1)

// Variablen definieren
volatile uint8_t rot;
volatile uint16_t timer; 

uint16_t Helligkeit[64] = {  0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5,
              5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17,
              19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
              61, 68, 76, 85, 94, 105, 117, 131, 146, 162,
              181, 202, 225, 250, 279, 311, 346, 386, 430,
              479, 534, 595, 663, 739, 824, 918, 1023};

// ***** Timer1-Overflow-Interrupt ****** --> PWM Frequenz = 8MHz/1023/256(Timer)/1(Prescaler) = 32 Hz
ISR (TIMER1_OVF_vect){ 
// zähle die Variable timer von 0-1023
timer++;
if (timer > 1023) {timer = 0;}
}

// ***** Timer0-Overflow-Interrupt ******
ISR (TIMER0_OVF_vect){ 
rot++;
if (rot > 64) {rot = 0;}
}

// ***** Hauptprogramm *****
int main(void){
// Variablen setzen
rot = 0;
timer = 0;

// PortB 345 zu Ausgängen und auf 0
DDRB |= (1<<DDB3)|(1<<DDB4)|(1<<DDB1);
PORTB &= ~(1<<PB3)|(1<<PB4)|(1<<PB1);
                
// Timer 1 konfigurieren: Clock = PCK 
TCCR1 |= (1<<CS10); 
//asynchronen Modus aktivieren (64Mhz) - dazu: 1) PLL aktivieren 2) Warten bis PLL eingerastet 3) PCKE setzen
PLLCSR |= (1<<PLLE);
  _delay_us(100); 
while(!(PLLCSR & (1<<PLOCK)))
      ;
PLLCSR |= (1<<PCKE);

//Overflow Interrupt Timer 1 aktivieren
TIMSK |= (1<<TOIE1);

// Timer 0 konfigurieren: Prescaler 1024
TCCR0B |= (1<<CS00)|(1<<CS02);
// Overflow Interrupt Timer 0 aktivieren
TIMSK |= (1<<TOIE0);

// Global Interrupts aktivieren
sei();

// ***** Endlosschleife *****
while(1){
if (timer < Helligkeit[rot]) {rot_an;}
else {rot_aus;}

} //eof while
} //eof main


Danke! Ihr rettet mir mein Wochenende :-)

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> Genau. Da versucht man ihn dazu zu bringen es so weit wie möglich selber
> herauszufinden, nur damit dann doch wieder jemand vorbeikommt und ihm
> eine vorgekaute Fertiglösung hinspuckt.

Oh Sorry. Ich habe den Thread nicht gelesen, ich habe nur gesehen, dass 
jemand ein Problem hat und wollte helfen.

@ jürgen

Du musst das leider selbst mache. Ich würde so vorgehen:
- testen ob pwm funktioniert mit 10, 100, 250 als werte
- überprüfen ob ISR aufgerufen wird, und wie oft, z.B. über led togglen.
und dann erst deinen Code.
Übrigens hilft es funktionierenden code in funktionen zu packen.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sobald ich den Timer 1 nicht im asynchronen Modus mit 64 Mhz betreibe 
sondern mit 8Mhz(interner Takt ohne Prescaler) funktioniert der code 
einwandfrei, die LED flackert nur sehr stark, da ja meine PWM Frequenz 
nur 8Mhz / 256(8bit-Timer1) /1024(Variable"timer") /1(Prescaler)= 30,5 
Hz beträgt.
Wenn ich es nun aber schaffe den Timer 1 mit 64 Mhz zu betreiben reicht 
die Frequenz und es sollte nciht mehr flackern?

Leider leuchtet die LED nun anscheinend durchgehend(volle Helligkeit) 
und die ISR scheint nicht aufgerufen zu werden. (Dies habe ich getestet 
indem ich in der ISR eine andere LED angeschaltet habe.)

Hier die Version meines funktionierenden codes(mit flackernder LED):
#ifndef F_CPU
#define F_CPU 8000000UL 
#endif

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

#define rot_an    PORTB |= (1 << PB1)
#define rot_aus    PORTB &= ~(1 << PB1)

// Variablen definieren
volatile uint8_t rot;
volatile uint16_t timer;

uint16_t Helligkeit[64] = {  0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5,
              5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17,
              19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
              61, 68, 76, 85, 94, 105, 117, 131, 146, 162,
              181, 202, 225, 250, 279, 311, 346, 386, 430,
              479, 534, 595, 663, 739, 824, 918, 1023};

// ***** Timer1-Overflow-Interrupt ****** --> PWM Frequenz = 8MHz/1023/256(Timer)/1(Prescaler) = 32 Hz
ISR (TIMER1_OVF_vect){ 
// zähle die Variable timer von 0-1023
timer++;
if (timer > 1023) {timer = 0;}
}

// ***** Timer0-Overflow-Interrupt ******
ISR (TIMER0_OVF_vect){ 
rot++;
if (rot > 64) {rot = 0;}
}

// ***** Hauptprogramm *****
int main(void){
// Variablen setzen
rot = 0;
timer = 0;

// PortB 345 zu Ausgängen und auf 0
DDRB |= (1<<DDB3)|(1<<DDB4)|(1<<DDB1);
PORTB &= ~(1<<PB3)|(1<<PB4)|(1<<PB1);
                
// Timer 1 konfigurieren: Clock 8Mhz
TCCR1 |= (1<<CS10);

//Overflow Interrupt Timer 1 aktivieren
TIMSK |= (1<<TOIE1);

// Timer 0 konfigurieren: Prescaler 1024
TCCR0B |= (1<<CS00)|(1<<CS02);
// Overflow Interrupt Timer 0 aktivieren
TIMSK |= (1<<TOIE0);

// Global Interrupts aktivieren
sei();

// ***** Endlosschleife *****
while(1){
if (timer < Helligkeit[rot]) {rot_an;}
else {rot_aus;}

} //eof while
} //eof main


Da ich ja nur die Frequenz von Timer 1 ändere (und nicht die von Timer 
0!) verstehe ich nciht, warum es nciht Funktioniert, wenn doch nun die 
Timerinitialisierung richtig seien sollte.

Grüße
Jürgen

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
- clkdiv 8 fuse deaktiviert? default ist an, dann werden aus deinen 8MHz 
1MHz
- avr entkoppelt mit ~100nF Keramik?
- Versorgungsspannung 5V?
- _delay_us(100) mal auf _delay_ms(1) stellen und testen.
- nicht 64 mhz sondern 32mhz verwenden. da gibt's ein bit mit dem du auf 
den slow modus umschalten kannst o.ä.

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
- clkdiv 8 fuse ist deaktiviert
- _delay auf 1ms bringt nichts
- 32Mhz eingestellt, also das LSM bit gesetzt und es geht
- Habe den Attiny nicht mit einem Kondensator entkoppelt und würde mir 
dies auch gerne sparen - könnte ich damit denn die 64 Mhz fahren? - wie 
wird der Kondesnator angeschlossen?

Danke nochmal!

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen schrieb:
> - 32Mhz eingestellt, also das LSM bit gesetzt und es geht
D.h. Problem ist im Prinzip gelöst? Ursache dafür kann sein:
- zu niedrige Versorgungsspannung. Takt gegen Spannung steht im 
Datenblatt. Ab wann schafft er denn die PLL mit 64MHz?
- kein Kondensator. Wie das geht steht in einer application note von 
atmel, im rn-wissen wiki sehr anschaulich und überall sonst im internet

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
- Die Versorgungsspannung beträgt 5Volt (über 7805)
- Die 64 Mhz sollte er laut Datenblatt ab 2,7 Volt schaffen glaube ich

Bis jetzt hab ich es noch nciht geschafft, dass es mit 64Mhz geht.

Ich werde mich nun noch über den Kondensator schlau lesen.

Autor: avion23 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
<Nekrophilie>
Es ist mit Sicherheit der Kondensator gewesen. Das habe ich 
herausgefunden, weil bei mir der 100nF nicht richtig verlötet war. Ohne 
die 100nF resetet er oder stürzt mitten im Programm ab. Alles nicht 
reproduzierbar und sehr frustrierend.
</Nekrophilie>

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.