PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer / Interrupte in C



masr
27.05.2004, 00:40
Hi!

Hat jemand von euch vielleicht einen Timer für einen AVR Mikrocontroller,
der via Interrupts funktioniert, aber ohne PWM und alles andere?
Der soll natürlich in C geschrieben sein, nicht in Assembler.
Ich verstehe nämlich immer noch nicht, wieso meine Versuche bei
mir, einen Timer zu programmieren fast immer gescheitert sind.

Martin

recycle
27.05.2004, 02:40
C kann ich leider nicht und habe auch keine Beispiele.

Bei Bascom sind aber einige dokumentierte Beispielprogramme unter anderem auch für den Einsatz von Timern dabei.

Ist zwar Basic, aber wenn du C kannst verstehst du wahrscheinlich trotzdem worum, bzw. wie es geht.

Die Beispiele kannst du dir hier einzeln runteladen: http://www.mcselec.com/download/bascomlt/samples.zip

masr
27.05.2004, 08:48
Ich habe es mir angeschaut, aber Basic ist ganz anders als
C. Damit komme ich leider nicht zurecht.... Trotzdem danke für
den Tip. Hat jemand anderes vielleicht ein Beispielprogramm für solch
einen Timer?

Dino Dieter
27.05.2004, 08:55
Hallo

Hier mal ein kleines Testprogramm für den Timer0 Int.



/*
Kleines Testprogramm zum testen des TIMER0 im Mega8
Timer0 erzeugt ca alle 10ms einen Interrupt.

Bei 4 MHZ dauert ein Takt 250 ns d.h. für 10 ms müssen wir
nach 40000 Takten einen Overflow mit TIMER0 erzeugen. Da
TIMER0 aber nur bis 255 zählen kann und bei 255 --> 256 einen Overflow
INT erzeugt, haben wir ein Problem. Also setzen wir den Vorteiler
von TIMER0 auf 256. Damit ergibt sich 40000 / 256 = 156,25.

Da wir den Wert 156 schlecht abfragen können und der Overflow INT
nur bei 255 --> 256 auftritt, laden wir den TIMER0 mit 100 vor. ( 256 - 156)
Der Timer0 zählt dann von 100 aufwärts und löst damit, nach
156 * 256 Takten = 39936 * 250 ns = 9,984 ms einen Overflow INT aus.

In der Overflow INT Routine, müssen wir dann die ca 10 ms INT nur noch zählen
und entsprechend auswerten.

Chip Mega 8
Takt 4.00 MHz
Stand: Test, läft im Simulator
Verfasser: Dino Dieter */

#include <avr/io.h>
#include <stdlib.h>
#include<avr/interrupt.h>
#include<avr/signal.h>


//Definition einiger Datentypen, reine Geschmacksache
#define uchar unsigned char // 1 Byte ohne Vorzeichen 0 bis 255 erlaubt
#define uint unsigned int // 2 Byte ohne Vorzeichen 0 bis 65535 erlaubt

//Definition der Konstanten
#define reload 100 // Reload Wert für Timer0 256 - 100 = 156

// Defintion der globalen Variablen
volatile uchar count_10ms; // Zähler für die 10ms INT

// Timer0 Overflow Routinen, Aufruf alle 10 ms
SIGNAL (SIG_OVERFLOW0 )
{
TCNT0 = reload; //Timer0 neu einstellen auf 100
count_10ms++; //Zähler um 1 erhöhen

if(count_10ms >= 100) //Abfrage 1 Sekunde vorbei, 100 * 10 ms
{
//dann LED umschalten
if(bit_is_set(PORTB,1)) //PIN gesetzt ???
PORTB = 0x00;
else
PORTB = 0x01;

count_10ms = 0; //Zähler löschen
}
}

//Einstellen der Hardware des AVR +++++++++++++++++++++++++++++++++++++++++++++
void init(void)
{
//Port einstellen
DDRB = 0x01; //PortB.1 auf Ausgang

//TimerO einstellen
TIMSK = _BV(TOIE0); // Timer0 Overflow INT erlauben
TCNT0 = reload; // TIMER0 vorladen mit 100
TCCR0 = _BV(CS02) ; // Vorteiler auf 256, ab hier läuft der TIMER0

// Global Interrupts freigeben
sei();
}

//Hauptprogramm, hier startet der uC ++++++++++++++++++++++++++++++++++++++++++
void main (void)
{

init(); // Hardware einstellen gehen

for(;;) // Endlosschleife
{
}

}
MFG
Dieter

masr
27.05.2004, 09:20
Wodran kann es liegen, dass dieses Programm bei mir nicht funktioniert?
Das Lämpchen an PortB1 bleibt einfach an und blinkt nicht.
Ich habe es mit einem 1 MHz-Quarz und einem 8 MHz-Quarz ausprobiert.
Martin

27.05.2004, 09:31
Hallo

Das Programm schaltet die LED an PORTB PIN 0 um.

Ändere mal PORTB = 0x01 in

PORTB = 0x02 oder für ale PINs in PORTB = 0xff um.

MFG
Dieter

27.05.2004, 09:38
Noch was vergessen

Dann mußt du auch noch
if(bit_is_set(PORTB,1)) ändern in

if(bit_is_set(PORTB,2))

MFG
Dieter

27.05.2004, 09:51
Und noch was.

DDRB = 0x02;

sollte man auch ändern.

MFG
Dieter

masr
27.05.2004, 10:26
Ach, ich meinte eigentlich PortB0. Der ist bei meinem ATmega8 ganz links unten.
Hast du vielleicht einen coolen Emulator, den du mir empfehlen kannst?
Ist egal, ob der Emulator unter Windows oder Linux läuft.

Den simulavr habe ich schon ausprobiert. Er läuft unter Linux, kann aber
glaube ich keine Interrupts verarbeiten.

Martin

27.05.2004, 10:44
Hallo

Ich mache sowas alles mit dem AVRSTUDIO.

Klappt ganz gut.

MFG
Dieter

masr
27.05.2004, 11:28
Wie kann ich eigentlich mit dem AVRStudio ein C-Projekt erstellen?
Ich habe das nämlich gerade installiert. Das ist echt super. Beim Debuggen
von Assembler-Programmen habe ich das gesehen... Ich kann jedoch
Assembler fast garnicht. Nur zu 10% ungefähr.

Was findest du eigentlich besser für einen Mikrocontroller?
Assembler oder C?

Martin

Kjion
27.05.2004, 15:34
Wie kann ich eigentlich mit dem AVRStudio ein C-Projekt erstellen?
Naja, eigentlich braucht man das nicht. Bei dem AVRStudio Version 3.** konnte man noch externe Compiler einbinden und so das AVRStudio als GUI verwenden. Bei Version 4.** geht das nicht mehr.
Aber warum nicht das Programmers Notepad das bei WinAVR dabei ist benutzten ??
( siehe http://www.kreatives-chaos.com/index.php?seite=avrgcc )

Ich habe das nämlich gerade installiert. Das ist echt super. Beim Debuggen
von Assembler-Programmen habe ich das gesehen... Ich kann jedoch
Assembler fast garnicht. Nur zu 10% ungefähr.

Was findest du eigentlich besser für einen Mikrocontroller?
Assembler oder C?
Lässt sich so nicht beantworten. Nur wirst du um Assembler bei Mikrocontrollern irgendwann nicht mehr herum kommen. Auch für das Verständnis wie der Controller eigentlich funktioniert und was der Compiler für Code erzeugt helfen Assemblerkenntnise ungemeint. Von daher würde ich zu beidem Raten ;-) C zum programmieren, Assembler zum verstehen was gemacht wird...

Hier übrigens noch ein Timerbeispiel ( lässt LEDs an PortD blinken ):
Das Programm ist für einen ATmega32 mit einem Quarz mit 14.7456 Mhz ausgelegt. Wenn man eine andere Taktfrequenz verwenden will, so muss man nur die Werte für TCNT1H und TCNT1L bzw. evnt. den Prescaler anpassen...


#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

#define SYSCLK 14745600

void init(void);
void delay(unsigned int ms);

volatile unsigned char zaehler = 1, richtung = 0;

int main(void)
{
unsigned char i;

init();

sei();

i = 0;
while(1) {

}

return 0;
}

void init(void)
{
DDRD = 0xff;

// Timer1 aktivieren
TCNT1H = 0xc7;
TCNT1L = 0xc0;

TIMSK |= (1<<TOIE1);

TCCR1A = 0;
TCCR1B = (1<<CS12) | (1<<CS10); // Prescaler = 1024
}

SIGNAL(SIG_OVERFLOW1)
{
unsigned char i, k;
i = zaehler;
k = richtung;

PORTD = ~i;
if (k == 0)
i <<= 1;
else
i >>= 1;

if (i == 0x01)
k = 0;
else if (i == 0x80)
k = 1;

zaehler = i;
richtung = k;

TCNT1H = 0xc7;
TCNT1L = 0xc0;
}

MfG Kjion

masr
27.05.2004, 20:09
Hi!

ENDLICH !!! ES KLAPPT!

Ich weiß jetzt, wo der Fehler lag. Die Programme habe ich vorher immer
mit dem avr-gcc in Linux kompiliert:
avr-gcc -s -mmcu=atmega8 ./timer.c

Nun hab ich sie aber mit WINAVR kompiliert und den Makefile habe ich
generieren lassen. Den so kompilierten Code kann ich auf meinem
Mikrocontroller ausführen. Ich habe mich wirklich totgesucht, wo mein
Fehler im Programm war, dabei lag es aber an der Art zu kompilieren.
Sicher kann man auch mit dem Programm in Linux richtig kompilieren,
aber der vom Programm generierte Makefile hat mir einfach geholfen.

Auf diese Weise müsste auch das Programm von Dino Dieter funktionieren,
was vorher bei mir nicht funktioniert hatte.

Danke nochmal für eure Hilfe!
Jetzt kann ich endlich mal mit dem Programmieren anfangen *g*