sloti
01.07.2008, 17:11
Hi,
ich habe wie gesagt ein Problem mit dem 8 bit Timer meines ATMega8. Ich betreibe ihn mit einem externen Quarz bei 3,6864 MHz. Der Timer soll einen Interupt bei einem Überlauf auslösen und das möglichst 1000 mal die Sekunde. Dafür habe ich mit dem RN-Tool rnAVR einen prescaler von 64 und einen preloader von 198 ausgerechnet (ist das richtig?). Nun hab ich allerdings das Problem, dass wenn ich eine Lampe immer bei der gleichen
Anzahl von Interrupts an bzw. ausschalte, immer ein Abstand von ca. drei Sekunden habe auch wenn ich den Wert von 255 auf z.B. 85 runtersetze. Zudem hab ich noch eine Frage die sich auf die Variable "countTimer2" bezieht: Die Variable müsste doch eigentlich, wenn die Berechnungen von rnAVR stimmen, nach 1 sek. den Wert 1000 haben, doch bei mir erreicht sie lediglich 255, also einen 8 bit Wert, aber die 8 bit beziehen sich doch nicht auf die Variable aus der ISR oder? Irgendwie läuft das ganze nicht so wie ich mir das Vorstelle. Hier ist noch mein Code. Nicht erschrecken das meiste ist für die Ansteuerung einses LCD nur die ersten drei Funktionen beziehen sich auf mein Timerproblem.
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#define CLOCK 3686400
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <avr\interrupt.h>
#include <avr/delay.h>
#include <stdlib.h>
//----------------------------------------------------------------------
volatile int countTimer2; // Speichert den aktuellen Zählerwert
SIGNAL (SIG_OVERFLOW2) // ISR
{
countTimer2++;
}
void init (void)
{
DDRB= 0x00; // PortB Eingang
DDRC= 0xFF; // PortC Ausgang
PORTB |= (1<<PB0); // PortB.0 Pull up
TCCR2 = 0x04; // Prescaler von 64
TCNT2 = 198; // Vorladen mit 198
TIMSK |= (1<<TOIE2); // Interrupts aktivieren und damit Timer starten
sei(); // interupts erlauben
}
int get_time(void) // gibt die Anzahl der Überläufe wieder
{
return countTimer2;
}
void reset_timer(void) // stellt den Timer wieder auf Null
{
countTimer2=0;
TIMSK |= (1<<TOIE2);
}
void wait_ms(int miliSec)
{
_delay_loop_2( 1*(CLOCK/(1000/4)) * miliSec); // 4 Zyklen warteschleife
}
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTD;
rs&=4;
// High-Teil senden
char tmp=data;
tmp&=0xf0;
tmp|=rs;
PORTD=tmp;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
// Low-Teil senden
tmp=data;
tmp&=0x0f;
tmp*=16;
tmp|=rs;
PORTD=tmp;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
// verarbeiten lassen
wait_ms(1);
}
//---------------------------------------------------------------------------
// lcd_cmd(..) - sendet ein Kommando an LCD
// PE: cmd=Kommando-Byte
//---------------------------------------------------------------------------
void lcd_cmd(char cmd)
{
cbi(PORTD,2); // RS löschen = Kommando
lcd_send(cmd); // senden
}
//---------------------------------------------------------------------------
// lcd_write(..) - sendet ein Zeichen (Daten) an LCD
// PE: text=Zeichen
//---------------------------------------------------------------------------
void lcd_write(char text)
{
sbi(PORTD,2); // RS setzen = Daten
lcd_send(text); // senden
}
//---------------------------------------------------------------------------
// lcd_write(..) - sendet eine Zeichenkette an LCD
// Die Zeichenkette muss mit 0x00 abgeschlossen sein
// PE: pText=Zeiger auf Zeichenkette
//---------------------------------------------------------------------------
void lcd_write(char* pText)
{
while(pText[0]!=0)
{
lcd_write(pText[0]);
pText++;
}
}
//---------------------------------------------------------------------------
// lcd_write(..) - sendet eine Zeichenkette an LCD
// PE: pText=Zeiger auf Zeichenkette
// count=Anzahl der zu sendenden Zeichen
//---------------------------------------------------------------------------
void lcd_write(char* pText, int count)
{
while(count!=0)
{
lcd_write(pText[0]);
pText++;
count--;
}
}
//---------------------------------------------------------------------------
// lcd_home(..) - Cursor auf Position 1,1
//---------------------------------------------------------------------------
void lcd_home()
{
lcd_cmd(0x02);
wait_ms(2); // warten
}
//---------------------------------------------------------------------------
// lcd_clear(..) - löscht die Anzeige im LCD
//---------------------------------------------------------------------------
void lcd_clear()
{
lcd_cmd(0x01);
wait_ms(2); // warten
}
//---------------------------------------------------------------------------
// lcd_on(..) - schaltet das LCD an
//---------------------------------------------------------------------------
void lcd_on()
{
lcd_cmd(0x0E);
}
//---------------------------------------------------------------------------
// lcd_off(..) - schaltet das LCD aus
//---------------------------------------------------------------------------
void lcd_off()
{
lcd_cmd(0x08);
}
//---------------------------------------------------------------------------
// lcd_goto(..) - setzt die Cursorposition
// PE: row = Zeile 1..2
// col = Spalte 1..16
//---------------------------------------------------------------------------
void lcd_goto(int row, int col)
{
row--; // Null-basierend
row&=0x01; // sicherheitshalber
row*=0x40; // Zeile nach Bit 6 bringen
col--; // Null-basierend
col&=0x0f; // sicherheitshalber
char tmp=row|col;
tmp|=0x80; // Cursor setzen
lcd_cmd(tmp); // senden
}
//---------------------------------------------------------------------------
// lcd_init(..) - Schaltet die Ports und Initialisiert das LCD
//---------------------------------------------------------------------------
void lcd_init()
{
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
TCCR1A=0xA1;
TCCR1B =0x02;
// Port D = Ausgang
DDRD=0xff;
PORTD=0;
// warten bist LCD-Controller gebootet
wait_ms(200);
// 4-BitModus einschalten
PORTD=0x20;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
wait_ms(5); // Zeit zum Umschalten lassen
// ab hier im 4-Bit-Modus
lcd_cmd(0x28); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit
//lcd_off();
lcd_cmd(0x06); // Entry Mode
lcd_on();
lcd_clear();
}
main ()
{
char string[3];
int time;
init();
lcd_init();
while(1)
{
if(get_time==255)
{
PORTC |=(1<<PC5);
}
else
{
PORTC &= ~(1<<PC5);
}
}
}
schon mal Danke im Vorraus ;)
mfg
Erik
ich habe wie gesagt ein Problem mit dem 8 bit Timer meines ATMega8. Ich betreibe ihn mit einem externen Quarz bei 3,6864 MHz. Der Timer soll einen Interupt bei einem Überlauf auslösen und das möglichst 1000 mal die Sekunde. Dafür habe ich mit dem RN-Tool rnAVR einen prescaler von 64 und einen preloader von 198 ausgerechnet (ist das richtig?). Nun hab ich allerdings das Problem, dass wenn ich eine Lampe immer bei der gleichen
Anzahl von Interrupts an bzw. ausschalte, immer ein Abstand von ca. drei Sekunden habe auch wenn ich den Wert von 255 auf z.B. 85 runtersetze. Zudem hab ich noch eine Frage die sich auf die Variable "countTimer2" bezieht: Die Variable müsste doch eigentlich, wenn die Berechnungen von rnAVR stimmen, nach 1 sek. den Wert 1000 haben, doch bei mir erreicht sie lediglich 255, also einen 8 bit Wert, aber die 8 bit beziehen sich doch nicht auf die Variable aus der ISR oder? Irgendwie läuft das ganze nicht so wie ich mir das Vorstelle. Hier ist noch mein Code. Nicht erschrecken das meiste ist für die Ansteuerung einses LCD nur die ersten drei Funktionen beziehen sich auf mein Timerproblem.
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#define CLOCK 3686400
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <avr\interrupt.h>
#include <avr/delay.h>
#include <stdlib.h>
//----------------------------------------------------------------------
volatile int countTimer2; // Speichert den aktuellen Zählerwert
SIGNAL (SIG_OVERFLOW2) // ISR
{
countTimer2++;
}
void init (void)
{
DDRB= 0x00; // PortB Eingang
DDRC= 0xFF; // PortC Ausgang
PORTB |= (1<<PB0); // PortB.0 Pull up
TCCR2 = 0x04; // Prescaler von 64
TCNT2 = 198; // Vorladen mit 198
TIMSK |= (1<<TOIE2); // Interrupts aktivieren und damit Timer starten
sei(); // interupts erlauben
}
int get_time(void) // gibt die Anzahl der Überläufe wieder
{
return countTimer2;
}
void reset_timer(void) // stellt den Timer wieder auf Null
{
countTimer2=0;
TIMSK |= (1<<TOIE2);
}
void wait_ms(int miliSec)
{
_delay_loop_2( 1*(CLOCK/(1000/4)) * miliSec); // 4 Zyklen warteschleife
}
void lcd_send(char data)
{
// aktuelles RS ermitteln
char rs=PORTD;
rs&=4;
// High-Teil senden
char tmp=data;
tmp&=0xf0;
tmp|=rs;
PORTD=tmp;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
// Low-Teil senden
tmp=data;
tmp&=0x0f;
tmp*=16;
tmp|=rs;
PORTD=tmp;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
// verarbeiten lassen
wait_ms(1);
}
//---------------------------------------------------------------------------
// lcd_cmd(..) - sendet ein Kommando an LCD
// PE: cmd=Kommando-Byte
//---------------------------------------------------------------------------
void lcd_cmd(char cmd)
{
cbi(PORTD,2); // RS löschen = Kommando
lcd_send(cmd); // senden
}
//---------------------------------------------------------------------------
// lcd_write(..) - sendet ein Zeichen (Daten) an LCD
// PE: text=Zeichen
//---------------------------------------------------------------------------
void lcd_write(char text)
{
sbi(PORTD,2); // RS setzen = Daten
lcd_send(text); // senden
}
//---------------------------------------------------------------------------
// lcd_write(..) - sendet eine Zeichenkette an LCD
// Die Zeichenkette muss mit 0x00 abgeschlossen sein
// PE: pText=Zeiger auf Zeichenkette
//---------------------------------------------------------------------------
void lcd_write(char* pText)
{
while(pText[0]!=0)
{
lcd_write(pText[0]);
pText++;
}
}
//---------------------------------------------------------------------------
// lcd_write(..) - sendet eine Zeichenkette an LCD
// PE: pText=Zeiger auf Zeichenkette
// count=Anzahl der zu sendenden Zeichen
//---------------------------------------------------------------------------
void lcd_write(char* pText, int count)
{
while(count!=0)
{
lcd_write(pText[0]);
pText++;
count--;
}
}
//---------------------------------------------------------------------------
// lcd_home(..) - Cursor auf Position 1,1
//---------------------------------------------------------------------------
void lcd_home()
{
lcd_cmd(0x02);
wait_ms(2); // warten
}
//---------------------------------------------------------------------------
// lcd_clear(..) - löscht die Anzeige im LCD
//---------------------------------------------------------------------------
void lcd_clear()
{
lcd_cmd(0x01);
wait_ms(2); // warten
}
//---------------------------------------------------------------------------
// lcd_on(..) - schaltet das LCD an
//---------------------------------------------------------------------------
void lcd_on()
{
lcd_cmd(0x0E);
}
//---------------------------------------------------------------------------
// lcd_off(..) - schaltet das LCD aus
//---------------------------------------------------------------------------
void lcd_off()
{
lcd_cmd(0x08);
}
//---------------------------------------------------------------------------
// lcd_goto(..) - setzt die Cursorposition
// PE: row = Zeile 1..2
// col = Spalte 1..16
//---------------------------------------------------------------------------
void lcd_goto(int row, int col)
{
row--; // Null-basierend
row&=0x01; // sicherheitshalber
row*=0x40; // Zeile nach Bit 6 bringen
col--; // Null-basierend
col&=0x0f; // sicherheitshalber
char tmp=row|col;
tmp|=0x80; // Cursor setzen
lcd_cmd(tmp); // senden
}
//---------------------------------------------------------------------------
// lcd_init(..) - Schaltet die Ports und Initialisiert das LCD
//---------------------------------------------------------------------------
void lcd_init()
{
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);
TCCR1A=0xA1;
TCCR1B =0x02;
// Port D = Ausgang
DDRD=0xff;
PORTD=0;
// warten bist LCD-Controller gebootet
wait_ms(200);
// 4-BitModus einschalten
PORTD=0x20;
// Schreibsignal
sbi(PORTD,3);
cbi(PORTD,3);
wait_ms(5); // Zeit zum Umschalten lassen
// ab hier im 4-Bit-Modus
lcd_cmd(0x28); // Funktions-Set: 2 Zeilen, 5x7 Matrix, 4 Bit
//lcd_off();
lcd_cmd(0x06); // Entry Mode
lcd_on();
lcd_clear();
}
main ()
{
char string[3];
int time;
init();
lcd_init();
while(1)
{
if(get_time==255)
{
PORTC |=(1<<PC5);
}
else
{
PORTC &= ~(1<<PC5);
}
}
}
schon mal Danke im Vorraus ;)
mfg
Erik