Forum: Mikrocontroller und Digitale Elektronik 32kHz Oscillator Interrupt


von Stefan S. (sschultewolter)


Lesenswert?

Hallo,

ich habe mir das Tutorial entsprechend durchgelesen
http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC
Jedoch nicht umbedingt das passende gefunden, was ich gesucht habe.

Ich würde gerne das der Attiny im Standby die Uhr weiterzählt.
100% genau wird das nicht laufen, deshalb lasse ich diese jeden Tag 
einmal mit einem DCF Modul abgleichen.

Nun zur Frage, wie kann ich das anstellen, dass ich den Ultra Low Power 
Oscillator auslese? Einen externen Takt habe ich in diesem Moment ja 
nicht, den ich an T0 o.ä. mit einem Interrupt zählen kann.

Gefunden habe ich derzeit nur die Prescaler Einstellungen im Datenblatt
1
CLKPR = (1 << CLKPS3);
1
/*
2
*  Project:  tiny841_blink.c
3
*  Created:  24.09.2014
4
*   Author:  sschultewolter
5
*  Hardware:  ATtiny841 3V3 8MHz
6
*
7
*
8
*                      VCC-1  T  14-GND
9
*  (PCINT8/ADC11/XTAL1/CLKI)        PB0-2  I  13-PA0 (PCINT0/ADC0/AREF/MISO)
10
*  (PCINT9/ADC10/XTAL2/INT0)        PB1-3  N  12-PA1 (PCINT1/ADC1/AIN00/TOCC0/TXD0/MOSI)
11
*  (PCINT11/ADC9/RESET/dW)          PB3-4  Y  11-PA2 (PCINT2/ADC2/AIN01/TOCC1/RXD0/SS)
12
*  (PCINT10/ADC8/CLKO/TOCC7/ICP2/RXD0)    PB2-5  8  10-PA3 (PCINT3/ADC3/AIN10/TOCC2/T0/XCK0/SCK)
13
*  (PCINT7/ADC7/TOCC6/ICP1/TXD0/SS)    PA7-6  4   9-PA4 (PCINT4/ADC4/AIN11/TOCC3/T1/RXD1/SCL/SCK)
14
*  (PCINT6/ADC6/ACO1/TOCC5/XCK1/SDA/MOSI)  PA6-7  1   8-PA5 (PCINT5/ADC5/ACO0/TOCC4/T2/TXD1/MISO)
15
*
16
*
17
*  ULPOSCSEL  = ULPOSC_32KHZ
18
*  BODPD    = BOD_DISABLED
19
*  BODACT    = BOD_DISABLED
20
*  SELFPRGEN  = [ ]
21
*  RSTDISBL  = [ ]
22
*  DWEN    = [ ]
23
*  SPIEN    = [X]
24
*  WDTON    = [ ]
25
*  EESAVE    = [ ]
26
*  BODLEVEL  = 2V7
27
*  CKDIV8    = [ ]
28
*  CKOUT    = [ ]
29
*  SUT_CKSEL  = INTRCOSC_8MHZ_6CK_16CK_16MS
30
*
31
*  EXTENDED = 0xFF | HIGH = 0xDD | LOW = 0xE2
32
*/
33
34
#include <avr/io.h>
35
#include <avr/interrupt.h>
36
37
#define RED    (1 << PINB0)
38
#define GREEN  (1 << PINB1)
39
40
volatile uint32_t millis;
41
42
ISR(TIMER0_COMPA_vect)
43
{
44
  millis++;
45
  
46
  // DEBUG ONLY
47
  if(!(millis % 1000)) PORTB ^= RED | GREEN;      // 1.0 Hz
48
  else if(!(millis % 500)) PORTB ^= GREEN;      // 0.5 Hz
49
  // END DEBUG ONLY
50
}
51
52
int main(void)
53
{
54
  // LEDS
55
  DDRB |= RED | GREEN;
56
  
57
  // MILLIS_TIMER
58
  TCCR0A = (1 << WGM01);          // CTC Mode
59
  TCCR0B |= (1 << CS01) | (1 << CS00);  // Prescaler 64
60
  OCR0A = 124;              // (F_CPU/PRESCALER)/1000-1
61
  TIMSK0 |= (1 << OCIE0A);        // Compare Interrupt
62
63
64
  // CLKPR = (1 << CLKPS3);
65
  // 32768[Hz] / 256 = 128Hz
66
67
  sei();  // Interrupts enable
68
  
69
  while(1)
70
  {
71
    // ...
72
  }
73
}

von Thomas E. (thomase)


Lesenswert?

Tu dir selbst den Gefallen und nimm einen Atmega48/88/168/328.

Der bringt von Haus aus alles mit, was du für eine Uhr brauchst.

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR#Timer2_im_Asynchron_Mode

mfg.

von Stefan S. (sschultewolter)


Lesenswert?

Warum immer die großen Teile? Atmega328P habe ich ein paar, aber die 
sind im Aufbau aufwendiger. Benötige da in der Regel externe 
Komponenten.

Edit ANFANG
Atmegax8P gibt es nicht als SOIC. DIP hab ich davon genug hier, die sind 
viel zu groß. QFN/TQFN wollte ich nicht, da ich dafür keine Platinen 
derzeit hab.
Edit ENDE


Der Attiny841 kann auch mit dem internen Oscillator problemlos am UART 
hantieren. Die Atmegas kenne ich gerade nur vom Hörensagen. Was mir 
einfach nur fehlt, wo ich den Takt der 32kHz abgreifen kann. Das soll 
wie folgt aussehen, ich lasse den internen 32KHz Takt mitzählen und der 
soll immer wenn er bei 255 und nach 0 wechselt einen Overflow Interrupt 
auslösen. Das entspricht 7,8125ms.

1
#ifdef TIMER_32KHZ
2
ISR(TIMER0_OVF_vect)
3
{
4
  s_128hz++;
5
  
6
  // DEBUG ONLY
7
  if(!(s_128hz % 64)) PORTB ^= GREEN;      // 0.5 Hz
8
  // END DEBUG ONLY
9
  PORTB = RED;
10
}
11
#endif
12
13
int main(void)
14
{
15
  // LEDS
16
  DDRB |= RED | GREEN;
17
  
18
  // MILLIS_TIMER
19
  /*
20
  TCCR0A = (1 << WGM01);          // CTC Mode
21
  TCCR0B |= (1 << CS01) | (1 << CS00);  // Prescaler 64
22
  OCR0A = 124;              // (F_CPU/PRESCALER)/1000-1
23
  TIMSK0 |= (1 << OCIE0A);        // Compare Interrupt
24
  */
25
26
  // 32KHZ_TIMER
27
  // Overflow Interrupt erlauben
28
  // Löst alle 1/128s aus
29
  TIMSK0 |= (1 << OCIE0A);
30
  // Global Interrupt erlauben
31
  sei();
32
  
33
  while(1)
34
  {
35
    // ...
36
  }
37
}

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.