PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer 1 nutzen bei einem Tiny26



danst
15.01.2006, 01:10
Hallo,

könnte mir mal jemand ganz kurz sagen wieso, der Timer 1 beim Tiny26 (und wahrscheinlich auch anderen) so nicht funktioniert?


TIMSK |= (1<<TOIE0) | (1<<TOIE1);
TIMSK &= ~(1<<OCIE1A) & ~(1<<OCIE1B);
TCCR0 = B00000001; // CK / 1 für Timer 0
PLLCSR &= ~(1<<PCKE); // CK als Timer 1 Clocksource
TCCR1A = 0;
TCCR1B = B00001110; // CK/8192 -> 3.8 mal pro Sek wird der Ovf aufgerufen
sei();

Der Timer scheint nicht anzugehen? Timer 0 funktioniert dagegen!

Vielen Dank und viele Grüße,

Daniel

H.A.R.R.Y.
15.01.2006, 15:40
Hm, woher weißt Du, daß der eine Timer arbeitet, der andere dagegen nicht? Um die Interrupts auszuwerten, müssen auch entsprechende Programmteile in die Vektoren eingehängt werden. Die finde ich in Deinem Code-Auszug nicht.

Falls Du den Simulator aus dem AVR-Studio verwendest: Schau in der Hilfe nach, dort steht bei welchen Chips welche Simulationen NICHT arbeiten. Betrifft aber nur die Simulation, die ICs selbst funktionieren.

danst
15.01.2006, 22:08
Oook Ich glaube der Interrupt geht doch nicht, das komplette Prog. sieht bist jetzt so aus:


#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <stdbool.h>
#include "binary.h"

#define EEPROM __attribute__ ((section (".eeprom")))
#define LED PA7
#define DDRLED B10000000
#define DDR1 B00000010

#define US1IN PA1
#define US1OUT PA0


uint8_t stop;
volatile uint16_t countUS1 = 0;
volatile uint8_t messungUS1 = false;
volatile uint16_t ergUS1 = 0;

SIGNAL(TIM1_OVF_vect)
{
//PORTA ^= (1<<LED); // LED Togglen
PORTA &= ~(1<<LED);

countUS1 = 0;
PORTA &= ~(1<<US1IN); // Senden
_delay_us(10); // Warten
PORTA |= (1<<US1IN);
messungUS1 = true;
}

SIGNAL(TIM0_OVF_vect)
{
// wird 31250 mal pro Sek aufgerufen also etwas mehr als 1 cm!
PORTA &= ~(1<<LED);
if (messungUS1)
{
if ((PINA & (1<<US1OUT)) == (1<<US1OUT)) // ist das Signal schon da?
{
// ja!
messungUS1 = false;
ergUS1 = countUS1;
}
else
{
countUS1++;
// cut bei theoretischen 4m
if (countUS1>730)
messungUS1 = false;
}
}
}


int main (void)
{
wdt_disable();
DDRA = DDRLED + DDR1;
DDRB = 0x0; // alle als Eingang
PORTB = 0xff; // Und Pullups
stop = false;
PORTA = 0xff;

TIMSK |= (1<<TOIE0) | (1<<TOIE1);
TIMSK &= ~(1<<OCIE1A) & ~(1<<OCIE1B);
TCCR0 = B00000001; // CK / 1 für Timer 0
PLLCSR &= ~(1<<PCKE); // CK als Timer 1 Clocksource
TCCR1A = 0;
TCCR1B = B00001110; // CK/8192 -> 3.8 mal pro Sek wird der Ovf aufgerufen
sei();
PORTA=0x0;
while(stop==false)
{
for (uint8_t i=0;i<10;i++)
_delay_ms(250);
PORTA ^= (1 << LED);
if (ergUS1!=0)
{
for (uint8_t i=0;i<20;i++)
_delay_ms(250);
PORTA |= (1 << LED);
for (uint16_t i=0;i<ergUS1;i++)
_delay_ms(250);
PORTA &= ~(1 << LED);
ergUS1 = 0;
}
}
return 0;
}

Auch mit den alten Vektorbezeichnungen funktioniert es Leider nicht...
Wenn ich jedoch das sei(); weglasse, blinkt zumindest die LED

Könnte mir jemand einen Tipp geben?

Vielen Dank,

Daniel Stengel

H.A.R.R.Y.
16.01.2006, 11:03
Ich bin nicht der Held was C angeht; ich programmiere lieber gleich in Assembler, also kann es sein, daß ich das eine oder andere falsch verstehe. Ich versuche Dir trotzdem mal zu helfen:



Wenn ich jedoch das sei(); weglasse, blinkt zumindest die LED

Also sowohl Deine beiden Interruptroutinen als auch die Hauptschleife manipulieren am Status der LED. Ohne SEI sind die Interrupts wirkungslos und nur noch Dein Hauptprogramm kontrolliert die LED. So läßt sich natürlich nicht herausfinden, welcher IRQ arbeitet und wer was macht.

Mein Vorschlag ist:
Lege das obige Programm beiseite und führe folgende Schritte durch:
Baue das einfachst mögliche Programm um die LED von Timer0-IRQ aus blinken zu lassen (Portinit, Timerinit, Deklaration der Interruptroutine, leere Schleife nach Inits und SEI). Sobald Deine LED blinkt, weißt Du was für Timer0 zu tun ist. Das Ganze wiederholst Du für Timer1, bis Du es auch dort hinbekommen hast. Wenn Du magst, kannst Du ja dann noch versuchen beides zu kombinieren: Timer0 schaltet die LED ein, Timer1 schaltet sie wieder aus - beide laufen mit leicht unterschiedlicher Frequenz, so das Du es auch blinken siehst. Dann sollte es möglich sein das obige Programm zu kontrollieren und zur Funktion zu bewegen - wenn der Fehler nicht ganz wo anders liegt.

Wird der Stack eigentlich vom Compiler verwaltet, oder muß der Stackpointer auch initialisiert werden?

Die Bezeichnungen der IRQ-Vektoren würde ich im interrupt.h vermuten. Wie erzeugt eigentlich delay.h die Verzögerung? Wenn der einen Timer verwendet, dann stört er Dich damit ganz gewaltig...

magic33
01.03.2007, 20:09
ich würde die register direkt setzen um den timer 1 8bit am tiny 26 direkt anzufahren

tccr1b zb 135 für prescale 64 dann läuft der timer

wenn tccr1a auf compare oder pulsmode
dann enable timer1 sonst läuft er nicht

auch timsk sollte den richtigen wert laut datenblatt erhalten

und zum testen dann mal orc1c auf 255
und mit ocr1b dagegen laufen dann sollte an portb.3 ein signal kommen