Forum: Mikrocontroller und Digitale Elektronik Nebenuhrwerk "Digitalisieren" die zweite


von Sören K. (foxalem)


Lesenswert?

Hallöchen,

ich möchte zzt. ein Nebenurwerk (Bürk NU67) digitalisieren mit einem 
Atmega328P.

Ich hab an den besagten uC ein Quarzoszillator mit 16Mhz gehängt, sodass 
ich eine zuverlässige Frequenz habe. Allerdings bekomm ichs nicht hin 
mit meinen Ausgerechneten Werten eine Sekunde zu definieren.

Ich wollte über den Timer1 per CTC ein Signal von 1sek rausfiltern. 
Dieses Signal soll dann eben einen Sekundenzähler raufzählen und nach 60 
Sekunden einen Impuls von 800ms rausgeben.
Dieses Signal muss immer Wechseln, da ich das Uhrwerk per H-Brücke 
ansteuer, sodass die Polarität immer wieder geändert wird.

Ich musste schon den _delay_ms() "austricksen" indem ich sage das F_CPU 
4000000UL (4MhZ) ist, obwohl meine CPU_CLK bei 2Mhz liegen müsste (16MhZ 
mit Fuse DIV8)

Im Moment ist es so das ich am Ausgang 3 (PINB2) in einer Sekunde 4 
Impulse bekomme, obwohl dieser Sekündlich ausgelöst werden sollte (siehe 
funktion sekunde()).

Ich Danke schonmal für die Mühen.

Anbei mein Code:
1
/*
2
 * Nebenuhrwerk_Digitalisieren.cpp
3
 *
4
 * Created: 13.06.2014 11:24:10
5
 *  Author: h0d3nt3uf3l
6
 */ 
7
8
9
#include <avr/io.h>
10
#define F_CPU 4000000UL //16MhZ externer Oszillator
11
#include <util/delay.h>
12
#include <avr/interrupt.h>
13
#define Ausgang1 PINB0
14
#define Ausgang2 PINB1
15
#define Ausgang3 PINB2
16
#define Ausgang4 PINB3
17
18
int sekunden = 0;
19
bool wechsel_merker;
20
21
void minute();
22
void sekunde();
23
24
int main(void)
25
{
26
  
27
  //Ausgänge definieren
28
  DDRB |= (1<<Ausgang1) | (1<<Ausgang2) | (1<<Ausgang3) | (1<<Ausgang4);
29
  
30
  //Timer1 einstellen
31
  TCCR1B = (1<<CS10) | (1<<CS11) | (1<<WGM12); //Prescaler von 64 eingestellt, OCR1A wird auf null gesetzt
32
  OCR1A = 15624; //Errechnet für 1Hz = 15625 bei Prescaler von 64
33
  TIMSK1 = (1<<OCIE1A); //Compare-Interrupt aktivieren
34
  
35
  //Alle Interrupts aktivieren
36
  sei();
37
  
38
    while(1)
39
    {
40
        //TODO:: Please write your application code 
41
    }
42
  
43
}
44
45
void sekunde()
46
{
47
  sekunden++;
48
  
49
  if (sekunden >= 60)
50
  {
51
    sekunden = 0;
52
    minute();
53
  }
54
  
55
  PORTB |= (1<<Ausgang3);
56
  _delay_ms(10);
57
  PORTB &= ~(1<<Ausgang3);
58
  return;
59
  
60
}
61
62
void minute()
63
{
64
  if (wechsel_merker == false)
65
  {
66
    PORTB |= (1<<Ausgang1);
67
    _delay_ms(800);
68
    PORTB &= ~(1<<Ausgang1);
69
    wechsel_merker = true;
70
    return;
71
  } else if (wechsel_merker == true)
72
  {
73
    PORTB |= (1<<Ausgang2);
74
    _delay_ms(800);
75
    PORTB &= ~(1<<Ausgang2);
76
    wechsel_merker = false;
77
    return;
78
  }
79
}
80
81
ISR (TIMER1_COMPA_vect)
82
{
83
  sekunde();
84
}

von npn (Gast)


Lesenswert?

Stell mal den Prescaler von 64 auf 1024, dann dürfte das klappen.
Und als Takt hast du doch 16MHz anliegen, warum stellst du F_CPU auf 
4MHz?

von Sören K. (foxalem)


Lesenswert?

Danke für die schnelle Antwort.

Den Prescaler zu verändern hat keinen Sinn, trotzdem hab ichs gemacht 
und jetzt kommt der sekundenimpuls alle 4 sekunden.

Ich habs try-and-error mäßig auf 4mhz gestellt, weil so die exakten 
impulse rauskommen, ich hab keine ahnung warum.

Ich messe alles mit einem DS1052 von Rigol, sollte also schon hinhauen.

von Achim K. (aks)


Lesenswert?

>
> Den Prescaler zu verändern hat keinen Sinn, trotzdem hab ichs gemacht
> und jetzt kommt der sekundenimpuls alle 4 sekunden.
>

Wieso soll das keinen Sinn machen?
Egal, versuch es mit 256, liegt dazwischen :-).

Vielleicht läuft der MC doch auf 4MHz.

von npn (Gast)


Lesenswert?

Achim K. schrieb:
> Vielleicht läuft der MC doch auf 4MHz.

Kann sein, wenn die Clock-Fuses falsch eingestellt sind...
Allerdings schrieb er ja:
> Ich hab an den besagten uC ein Quarzoszillator mit 16Mhz gehängt

Also Sören, nochmal nachschauen! :-)

von Sören K. (foxalem)


Lesenswert?

Also, Fuse CKDIV8 ist gesetzt, hab jetzt sogar mal per Hand den 
Prescaler auf 4 gestellt:
1
  //Prescaler auf 4 stellen.
2
  CLKPR = (1<<CLKPCE) | (1<<CLKPS1);
So sollte ich wirklich 4MhZ haben.
F_CPU blieb auf 4 Mhz und der delay arbeitet nach wie vor hervorragend.
Den Prescaler vom Timer hab ich nun auf 256 gestellt und nun habe ich 
auch einen Sekündlichen ausschlag.
Aber diesen Prescaler bräuchte ich bei 8Mhz?

(CKSEL ist auf EXTCLK_6CK_14CK_65MS gestellt (Atmel Studio))

von Achim K. (aks)


Lesenswert?

Sören Kleer schrieb:
> Aber diesen Prescaler bräuchte ich bei 8Mhz?

Mein Excel meint:

15625 * 256 = 4000000

wie kommst Du also auf 8MHz?

von npn (Gast)


Lesenswert?

Sören Kleer schrieb:
> Also, Fuse CKDIV8 ist gesetzt, hab jetzt sogar mal per Hand den
> Prescaler auf 4 gestellt:  //Prescaler auf 4 stellen.
>   CLKPR = (1<<CLKPCE) | (1<<CLKPS1);
> So sollte ich wirklich 4MhZ haben.
> F_CPU blieb auf 4 Mhz und der delay arbeitet nach wie vor hervorragend.
> Den Prescaler vom Timer hab ich nun auf 256 gestellt und nun habe ich
> auch einen Sekündlichen ausschlag.
> Aber diesen Prescaler bräuchte ich bei 8Mhz?
>
> (CKSEL ist auf EXTCLK_6CK_14CK_65MS gestellt (Atmel Studio))

Ich meinte vorhin den Prescaler des Timers.
Bei 16MHz Systemtakt und Prescaler (Timer1) von 1024 kommst du mit OCR1A 
= 15624 auf 1s. Aber du hast ja den System-Prescaler noch gesetzt und 
außerdem CLKDIV8. Das wußte ich ja nicht. Hat das einen Grund?

von Sören K. (foxalem)


Lesenswert?

Deiner rechnung Stimme ich zu ;) allerdings dachte ich ich muss diese 
hier nehmen: f (OCnA) =  f clk/io / ( 2 x N x (1 + OCR1A))
Wobei N = der Prescaler ist.

So steht es zumindest im Datenblatt auf Seite 124.

Aber Okay, ist mir nun auch zu blöd :D es funktioniert.
Dankeschön

von npn (Gast)


Lesenswert?

Die Formel ist für das Toggeln des OCR-Pins gültig. Deswegen die "2". 
Wenn du eine ISR-Routine aufrufen willst, muß die 2 weg. Zum Toggeln des 
Pins gehören ja immer zwei Aufrufe (1x low-high und 1x high-low). 
Deswegen muß das Toggeln mit der doppelten Frequenz erfolgen wie der 
Aufruf der ISR.

von Sören K. (foxalem)


Lesenswert?

Mhh okay das macht Sinn.

Vielen Dank, wieder ein bisschen weniger Dumm :)

von Achim K. (aks)


Lesenswert?

> Quarzoszillator mit 16Mhz

Meinst Du einen Quarz und 2 Kondensatoren?

Oder ist das ein Oszillator mit einem Taktausgang, der dann
als Ext. Clock benutzt wird?

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.