Forum: Mikrocontroller und Digitale Elektronik OCR0A wird nicht beachtet (atmega325, C)


von Dean W. (agassiz)


Lesenswert?

Hi,

vorab, bin ich neu in dem Gebiet und kenne mich mit dem AtmelStudio noch 
nicht so gut aus.

ich habe ein Problem mit dem OCR0A Register (denke ich).

Und zwar wird der Wert der drin steht nicht beachtet, obwohl TMISK0 
richtig gesetzt ist.

Mein atmega325 müsste doch mit 16MHz laufen wenn ich mich nicht irre? 
Kann ich das irgendwo im Atmel Studio einstellen? Oder nur durch 
prescaler beeinflussen?

Irgendwie passt das Ganze aber nicht - ich weiß nicht wo es hängt.

Es werden momentan lediglich ein paar LEDs gesetzt.

Ich hätte gern, dass sie sekündlich blinken,

aber mit dem unten stehenden Code blinken Sie nur alle 2 Sekunden.

Das wiederum würde bedeuten:

1000 Counts in 2000ms => 500Hz

Da das OCR0A register nicht beachtet wird, wird es doch bis 256 gezählt 
oder?

Das wären dann 500 * 256 = 128000

Dann noch den Prescaler dazunehmen:

128000 * 8 = 1.024.000  ~  1MHz

Das ist äußerst merkwürdig :/

Im Datenblatt des atmega325 steht er läuft mit 16MHz ?!

Wo hinkt mein Gedankengang?
Was mache ich falsch?

Vielen Dank für eure Hilfe.

Hier mal mein Code ist hier vielleicht ein Fehler drin? :

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdlib.h>
4
#include "Pins.h"
5
6
uint16_t millisecond;
7
uint8_t second;
8
uint8_t testing;
9
10
ISR (TIMER0_COMP_vect)
11
  {
12
    millisecond++;        
13
    if (millisecond == 1000){
14
      second++;
15
      millisecond = 0;      
16
    }
17
    
18
    testing = second%2;
19
    
20
    switch(testing){
21
      case 0: 
22
          DDRA = 0xff;
23
          PORTA = 0b10101010;
24
          break;
25
      case 1: DDRA = 0xff;
26
          PORTA = 0b01010101;
27
          break;
28
          
29
      default:break;
30
    }
31
    
32
    
33
34
  }
35
36
37
int main(void)
38
{
39
  
40
  
41
  
42
  TCNT0 = 0;
43
  TCCR0A = 0b0000010; //Prescaler 8
44
  OCR0A = 125-1; 
45
  TIMSK0 = 0b00000010;
46
47
  sei();
48
  
49
50
  
51
  
52
    while(1){}
53
}

: Verschoben durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dean Winchester schrieb:
> Mein atmega325 müsste doch mit 16MHz laufen wenn ich mich nicht irre?

Warum sollte er das tun? Solange Du nicht die Fuses korrekt setzt, 
läuft er AFAIK wie alle AVRs mit intern erzeugten 1 MHz.

von Karl H. (kbuchegg)


Lesenswert?

Dean Winchester schrieb:

> Mein atmega325 müsste doch mit 16MHz laufen wenn ich mich nicht irre?

'Müsste' ist immer schlecht.
Aber .. das kann man rausfinden

Testprogramm:
1
#define F_CPU 1000000UL
2
// #define F_CPU 16000000UL
3
 
4
#include <avr/io.h>
5
#include <util/delay.h>
6
 
7
// Hier die tatsächlich verwendeten Parameter angeben
8
 
9
#define LED_PORT    PORTA
10
#define LED_DDR     DDRA
11
#define LED_PIN     PA0
12
 
13
int main()
14
{
15
   LED_DDR |= 1 << LED_PIN;
16
 
17
   while (1)
18
   {
19
      LED_PORT ^= 1 << LED_PIN;
20
      _delay_ms(1000);
21
   }
22
 
23
   return 0;
24
}

Bei welcher Einstellung für F_CPU leuchtet die LED 1 Sekunde und ist 1 
Sekunde aus? (Compiler OPtimierung auf -Os stellen, wenn sie nicht schon 
darauf eingestellt ist!)

Ist es
#define F_CPU 1000000UL
dann läuft der µC auch tatsächlich mit 1Mhz

Ist es
#define F_CPU 16000000UL
dann läuft der µC tatsächlich mit 16Mhz

Kurz und gut, das _delay_ms liefert nur dann korrekte Zeiten, wenn der 
Wert von F_CPU mit der Realität übereinstimmt.


> Im Datenblatt des atmega325 steht er läuft mit 16MHz ?!

Nö-
Da steht drinnen, dass er mit 16Mhz laufen KANN.
'Kann' ist nicht dasselbe wie 'er tut es'.

von Dean W. (agassiz)


Lesenswert?

Alles klar danke für den Hinweis - der atmega325 läuft nun mit 8MHz 
(nicht 16 - sry) hatte das CKDIV8 fusebit gesetzt gehabt.

so, nun hab ich es soweit abgeändert, dass ich durch 64 Teile anstatt 8. 
Das Funktioniert nun aber ähnlich. d.h. die LEDs blinken immernoch im 2 
sekunden takt.

warum wird das register einfach nicht beachtet? ich verstehs nicht :(
1
  TCNT0 = 0;
2
  TCCR0A = 0b0000011; //Prescaler 64
3
  OCR0A = 125-1; 
4
  TIMSK0 = 0b00000010;

von Peter D. (peda)


Lesenswert?

Dean Winchester schrieb:
> warum wird das register einfach nicht beachtet?

Es wird beachtet, sonst kämen ja keine Interrupts.

Vermutlich willst Du aber, daß es auch verkürzend wirkt. Dann mußt Du 
auch den entsprechenden Timer-Mode einstellen.

von Karl H. (kbuchegg)


Lesenswert?

Dean Winchester schrieb:
> Alles klar danke für den Hinweis - der atmega325 läuft nun mit 8MHz
> (nicht 16 - sry) hatte das CKDIV8 fusebit gesetzt gehabt.
>
> so, nun hab ich es soweit abgeändert, dass ich durch 64 Teile anstatt 8.
> Das Funktioniert nun aber ähnlich. d.h. die LEDs blinken immernoch im 2
> sekunden takt.
>
> warum wird das register einfach nicht beachtet? ich verstehs nicht :(
>
>
1
>   TCNT0 = 0;
2
>   TCCR0A = 0b0000011; //Prescaler 64
3
>   OCR0A = 125-1;
4
>   TIMSK0 = 0b00000010;
5
>


Hör bitte mit dem Müll auf, da alle Angaben in Binärschreibweise zu 
machen. Atmel hat dir in den Header Files entsprechende #defines 
mitgegeben, so dass du zb schreiben kannst

TIMSK0 = ( 1 << OCIE0 );


Natürlich wird der beachtet. Sonst würde ja die ISR gar nicht aufgerufen 
werden.
Aber: was erwartest du?
Du betreibst den Timer im ganz normalen Modus! d.h der zählt von 0 bis 
255.

Schau:
Was du gemacht hast ist, du hast einen Compare Match aufgesetzt. Im 
Prinzip hast du folgendes getan: Du hast eine Uhr genommen und an den 
Sekundenzeiger einen Kontakt gepfriemelt. Wenn der Sekundenzeiger bei 20 
steht, dann löst du eine Aktion aus. Aber: Das ändert ja nichts daran, 
dass der Sekundenzeiger nach wie vor seine Runden dreht. Verschiebst du 
den Kontakt auf 40, dann kommt das Signal zu einem anderen Zeitpunkt. 
Aber es kommt noch wie vor alle 60 Sekunden. Denn solange braucht der 
Zeiger für eine Runde.
Würdest du den Zeiger nach auslösen des Kontaktes sofort auf 0 
zurückstellen, dann sieht die Sache anders aus. Dann würden die Signale 
tatsächlich alle 20 bzw. 40 Sekunden kommen. Aber das tust du ja nicht. 
Mittels

   TCCR0A = 0b0000011; //Prescaler 64

stellst du einen ganz normalen Zählmomdus ein.
Du wolltest vielleicht den CTC-Modus benutzen. Du hast sogar damit 
gerechnet. Aber du hast es nicht getan. Und durch die bescheuerte 
Binärschreibweise muss man auch noch 3 mal ganz genau hinsehen, um das 
zu sehen.

von Dean W. (agassiz)


Lesenswert?

Oh man Leute - Kommando zurück! -.-"

Mein Problem war, dass ich im TCCR0 das WGM01 bit nicht gesetzt hatte, 
bzw es auf "0" war.

Damit wurde der Timer nicht zurückgesetzt nachdem er erreicht wurde.

Ihr habt mir sehr geholfen.
Vielen, vielen Dank :)

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.