32kHz Oscillator Interrupt

#3816150
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
}
#3816278
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren