Forum: Mikrocontroller und Digitale Elektronik ATmega168PA mit 32768Hz Quarz


von Marcus S. (marcus3967)


Lesenswert?

Hallo,

ich versuche auf einem STK600 einem ATmega168PA einen 1Hz Takt
abzugewinnen. Dazu habe ich auf dem STK600 den Jumper von
'32kHz' nach 'TOSC1' gesteckt (und kann die Frequenz dort auch
messen). Das Prg soll eine LED auf Port D im 1sec Takt blinken lassen.
Aber sie leuchtet nur ständig. Auch ohne den Jumper mit externem
32768Hz Quarz geht es nicht. Der Wahlschalter für den Takt habe ich
auf 'INT' gestellt. Ich kann auch einen 8MHz Takt an Port B0 messen
(CKOUT Fuse gesetzt). Das Programm ist wie folgt:

1
#include <avr/io.h>
2
#include <avr/sleep.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
#define F_CPU 8000000UL
7
 
8
void long_delay(uint16_t ms) {
9
    for (; ms>0; ms--) _delay_ms(1);
10
} 
11
 
12
 
13
//Prepare LED pin
14
void PortInit(void)
15
{
16
    //Initlally LED OFF
17
     PORTD&=~(1<<PD0);
18
    //PD0 as output
19
    DDRD|=(1<<PD0);
20
}
21
22
//Timer2 init acording datasheet
23
void RTCInit(void)
24
{
25
26
 
27
// Timer2 konfigurieren
28
 
29
        //Disable timer2 interrupts
30
    TIMSK2  = 0;
31
    //Enable asynchronous mode
32
    ASSR  |= (1<<AS2);
33
  long_delay(1000);
34
    //set initial counter value
35
    TCNT2=0;
36
    //set prescaler 128
37
    TCCR2B |= (1<<CS22)|(1<<CS20);
38
39
    //wait for registers update
40
    while (!(ASSR & ((1<<TCN2UB)|(1<<TCR2BUB))));
41
    //clear interrupt flags
42
    TIFR2  |= (1<<TOV2);
43
    //enable TOV2 interrupt
44
    TIMSK2  |= (1<<TOIE2);
45
  
46
}
47
48
//Overflow ISR
49
ISR(TIMER2_OVF_vect)
50
{
51
    //Toggle pin PD0 every second
52
PIND=(1<<PD0);
53
  
54
}
55
56
int main (void)
57
{
58
59
60
     PortInit();
61
    RTCInit();
62
    sei();
63
  
64
    while(1)
65
    {
66
  
67
    
68
    }
69
}

Die Fusebits wie folgt:
BOOTSZ = 1024W_1C00
BOOTRST = [ ]
RSTDISBL = [ ]
DWEN = [ ]
SPIEN = [X]
WDTON = [ ]
EESAVE = [ ]
BODLEVEL = DISABLED
CKDIV8 = [ ]
CKOUT = [X]
SUT_CKSEL = INTRCOSC_8MHZ_6CK_14CK_65MS

EXTENDED = 0xF9 (valid)
HIGH = 0xDF (valid)
LOW = 0xA2 (valid)

1. Warum kann ich den Takt an TOSC1 messen und trotzdem fkt. es nicht?
2. Warum fkt. es auch mit externem Quarz nicht?
3. Wie könnte man den Timer2 in dieser Betriebsart noch testen?

Danke & Gruß,
Marcus

von Stefan E. (sternst)


Lesenswert?

> 1. Warum kann ich den Takt an TOSC1 messen und trotzdem fkt. es nicht?

Vielleicht weil du es momentan auf externen Quarz (an TOSC1 und TOSC2) 
einstellst und nicht auf externen Takt (nur an TOSC1).

> 2. Warum fkt. es auch mit externem Quarz nicht?

Vielleicht weil deine "wait for registers update"-Zeile falsch ist.

von Marcus S. (marcus3967)


Lesenswert?

Hallo Stefan,

danke f.d. Hinweise!

Zu 1.:
Ich habe oben bei RTCInit folgendes eingefügt:
ASSR  |= (1<<EXCLK);
Die "wait for registers update" Zeile habe ich gleich gelassen. Dann hat
es funktioniert!

Zu 2.:
Mit einem externem Quarz geht es immer noch nicht (ASSR  |= (1<<EXCLK);
habe ich natürlich wieder entfernt). Wo könnte da der Fehler noch
genau liegen (also in der "wait for registers update" Zeile)?

Danke & Gruß,
Marcus

von Stefan E. (sternst)


Lesenswert?

Auf jeden Fall ist diese Zeile falsch, denn im Augenblick steht da:
Warte solange die Bits Null sind.

von Marcus S. (marcus3967)


Lesenswert?

So,

das Problem ist gelöst. Wer evtl. das gleiche Problem hat:

1. Ich habe folgendes Prg. benutzt:
1
# define F_CPU 8000000UL
2
# define __OPTIMIZE__
3
# define __DELAY_BACKWARD_COMPATIBLE__
4
5
#include <avr/io.h>
6
#include <avr/sleep.h>
7
#include <avr/interrupt.h>
8
#include <util/delay.h>
9
10
void long_delay(uint16_t ms) {
11
    for (; ms>0; ms--) _delay_ms(1);
12
} 
13
 
14
 
15
//Prepare LED pin
16
void PortInit(void)
17
{
18
    //Initlally LED OFF
19
     PORTD&=~(1<<PD0);
20
    //PD0 as output
21
    DDRD|=(1<<PD0);
22
23
}
24
//Timer2 init acording datasheet
25
void RTCInit(void)
26
{
27
28
// Timer2 konfigurieren
29
 
30
    //Disable timer2 interrupts
31
  TIMSK2  = 0;
32
    //Enable asynchronous mode
33
   ASSR  = (1<<AS2);
34
  long_delay(1000);
35
    //set initial counter value
36
    TCNT2=0;
37
    //set prescaler 128
38
    TCCR2B = (1<<CS22)|(1<<CS20);
39
40
    //wait for registers update
41
    while ((ASSR & 0b00010001) != 0) {};
42
  //clear interrupt flags
43
    TIFR2  |= (1<<TOV2);
44
    //enable TOV2 interrupt
45
    TIMSK2  = (1<<TOIE2);
46
  
47
}
48
//Overflow ISR
49
50
ISR(TIMER2_OVF_vect)
51
{
52
    //Toggle pin PD0 every second
53
PIND=(1<<PD0);
54
55
}
56
57
int main (void)
58
{
59
60
    PortInit();
61
    RTCInit();
62
    sei();
63
  
64
    while(1)
65
    {
66
    
67
    }
68
}

2. Den Quarz hatte ich zu Testzwecken direkt an die TOSC1/2 Pins 
gelötet.
3. Das Entscheidende war aber diese zwei Pins so noch oben zu biegen,
dass sie keinen Kontakt mehr mit dem Sockel (des STK600-DIP Adpater)
haben. Dieser Tipp kam von hier (S.9):
http://www.atmel.com/dyn/resources/prod_documents/doc8333.pdf

Gruß,
Marcus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.