PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ISR(SIG_OUTPUT_COMPARE0B){} und TCNT0 Problem



Kostja20
24.02.2007, 20:32
Hallo das habe ich soweit zusammen. Ein Problem habe ich aber noch und
zwar wen das Programm ISR(SIG_OUTPUT_COMPARE0B){} startet wird der TCNT0
Register nicht angehalten so das wen ich den wert von OCR0B ändere das
kein Einfluss auf die Frequenz hat! habe ich da was vergessen?

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

volatile uint16_t ImpulsZaehler1=0;
uint16_t a=50; //mitte 1,6ms


// Timer interrupt 4000Hz (4Mhz Quarz)
void Teimer0B_ON(void){
TCCR0B |= (1<<CS00) | (1<<WGM02);
OCR0B = 1;
TIMSK |= (1<<OCIE0B);
sei();
}


ISR(SIG_OUTPUT_COMPARE0B){
if (ImpulsZaehler1<100){
ImpulsZaehler1++;
}
if(ImpulsZaehler1==100){
ImpulsZaehler1=0;
}
}



int main(void){
Teimer0B_ON();
DDRD = (1 << DDB6);
while(1){
if ( ImpulsZaehler1<a ) {
PORTD &= ~(PIND ^ ( 1 << PD6) );
}
else{
PORTD = PIND ^ ( 1 << PD6 );
}
/*if ( PINB & (1<<PB0) ) {
a=42; //1,05ms min
}*/
}
}

SprinterSB
24.02.2007, 20:47
Der Zähler wird auch nicht angehalten, sonder nur zurück auf 0 gesetzt und läuft dann weiter.

Ausserdem: lies mal

https://www.roboternetz.de/wissen/index.php/Fallstricke_bei_der_C-Programmierung#Nicht-atomarer_Code

Ist etwas versteckt das Thema. Wenn wieder Muße habe, wird's ein eigener Artikel.

Bei dir schlägt das voll zu, weil OCR1B = 1 ist und damit nach *jeder* Instruktion eine IRQ ausgelöst wird! Die ISR wird also krass seltener durchlaufen, als es IRQs gibt.

Du willst den Port hin-herschalten?

Das geht zB so:



PORTD ^= 1 << PD6;


Auch wenn es geht, wird das den Port sehr schnell schalten, so daß du mit bloßem Auge nix erkennst, zB wenn du ne LED am Port hast um zu schauen was der Kamerad so treibt.

Kostja20
24.02.2007, 21:24
hallo, danke für den Link leider hat er mir nicht weiter geholfen, ich messe mit einem Oszilloskop und mit einen Frequenzmessgerät, ob ich OCR1B = 1 oder OCR1B = 100 oder auf OCR1B = 256 setze das Oszilloskop zeigt die selbe Frequenz.

SprinterSB
24.02.2007, 21:28
Wie sieht dein Code denn jetzt aus?

[code]-Tags wären angenehm. Der konkrete Controller-Typ unterliegt offenbar der Geheimhaltung.

Kostja20
24.02.2007, 21:33
nein, ist ein ATTiny2313, ist nur das was oben sehet mehr habe ich nicht.

SprinterSB
24.02.2007, 21:44
DS pp. 75:

Du betreibst Timer0 in Mode #4 (Reserved, also ungültig) anstatt in Mode #2 (CTC):



// Mode #2 (CTC)
TCCR0B = (1 << CS00) | (1 << WGM01);

Kostja20
24.02.2007, 21:56
danke, hat aber den selben Effekt, der TCNT wird nicht zurückgesetzt!

SprinterSB
24.02.2007, 22:10
oopps, habe mein post von eben überheinert. Antwort steht oben.

SprinterSB
24.02.2007, 22:11
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

volatile uint16_t ImpulsZaehler1;
uint16_t a = 50; //mitte 1,6ms


// Timer interrupt 4000Hz (4Mhz Quarz)
void Timer0B_ON (void)
{
// Mode #2 (CTC)
TCCR0B = (1 << CS00) | (1 << WGM01);
OCR0B = 200;
TIMSK |= (1 << OCIE0B);
}


ISR (SIG_OUTPUT_COMPARE0B)
{
if (++ImpulsZaehler1 >= 100)
{
ImpulsZaehler1 = 0;
}
}

int main(void)
{
Timer0B_ON();
DDRD = (1 << PD6);

sei();

while(1)
{
uint16_t iz;

// atomic
cli();
iz = ImpulsZaehler1;
sei();

if (iz < a)
{
PORTD &= ~(1 << PD6);
}
else
{
PORTD |= (1 << PD6);
}
} // while (1)
} // main

SprinterSB
24.02.2007, 22:13
Das ganze kann aber nur funzen, wenn OCR0B größer ist als die Anzahl der Ticks, die du in der ISR brauchst. Die ISR sollte also noch kürzer werden.

Kostja20
27.02.2007, 21:25
hallo,
ein großes Dankeschön an SprinterSB =D> .
Habe das hingekriegt jetzt tut es das was es soll!