Archiv verlassen und diese Seite im Standarddesign anzeigen : Universale Timerfunktion
Salut,
haette gern eine Timerfunktion, der ich einen float-Wert uebergeben kann und die mir dann x Sekunden wartet, also universal fuer 0.0001 .. 65535 sec zu verwenden ist. Am PC schaff ich das auch problemlos, die Werte werden anscheinen einwandfrei gesetzt, nur am AVR gibts eine Endlosschleife...
Code folgt:
uint8_t prescalerValues[] = PRESCALER_VALUES;
uint8_t timerValues[] = TIMER_VALUES;
#define WAIT 1
uint8_t mode = 0;
uint8_t overflow = 0;
ISR ( _VECTOR(5) ) {
TCCR2 = 0;
if ( mode == WAIT ) overflow = 1;
}
void waitTime(float time) {
mode = WAIT;
uint8_t ctr;
for (ctr = 0; ctr < 5; ctr++) {
for (time; (uint8_t) time > 0; time--) {
TCNT2 = 65535 - timerValues[ctr];
TCCR2 = prescalerValues[ctr];
while ( !overflow ) {}
overflow = 0;
TCCR2 = 0;
}
time *= 10;
}
mode = 0;
}
void initTimers() {
TIMSK |= ( 1 << TOIE2 );
sei();
}
Aufzurufen einfach im Sinne
initTimers();
wait(n.m);
PRESCALER_VALUES und TIMER_VALUES beschreiben die Ticks, die der Timer fuer einen bestimmten Prescaler ablaufen muss, um 1, 0.1, 0.01 etc sec zu brauchen; das wird dann (int) time mal wiederholt und auf die naechste Nachkommastelle weitergerueckt.
Frage ich TOV2 direkt ab, funktionierts uebrigens genauso wenig.
Gruss und Danke im Voraus,
David
SprinterSB
09.03.2007, 17:26
overflow ist flüchtig. Schau dir in einem C-Buch/Tutorial an, was das Schlüsselwort 'volatile' bewirkt!
Anststt _VECTOR(5) solltest du den Namen der ISR verwenden und nicht irgendwelche magischen Zahlen oder internen Makros.
Wenn TOV2 nicht per Polling funktioniert hast du den Timer nicht korrekt initialisiert.
Im übrigen solltest du überlegen, wie du warten kannst, ohne deine komplette Anwendung lahmzulegen ;-) (Währed du wartest geht nix anderes mehr).
also ich kann dir jetzt überhaupt nicht folgen?
stell halt den timer so ein das er alle 10ms kommt und im TOV0 lässt du dann ne variable dekrementieren und wenn die bei 0 ist machst was in der hautschleife
volatile uint8_t ovrcount;
int main
{
//init timer, prescaler, interrupts
ovrcount = 0x0F;
while (1)
{
if (!ovrcount)
{
//zeit abgelaufen
}
}
}
ISR (SIG_OVERFLOW0)
{
if ( ovrcount != 0)
ovrcount--;
}
Hallo Leutz,
ich bin mal wieder am verzweifeln...
Kann mir jemand sagen was an diesem Code nicht stimmt (Code für RN-Control 1.4 ATMega32, also LED's auf PORTC ).
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER2_COMP_vect)
{
PORTC = ~PORTC; // umschalten
}
int main(void)
{
DDRC = 0xFF;
PORTC = 0x0F; // alles aus
TCCR1A = (1<<COM1A1) | (1<<COM1A0);
TCCR1B = (1<<CS12) | (1<<WGM12);
OCR1A = 0xFFFF;
TIMSK |= ( 1 << OCIE1A );
sei();
while(1);
}
Die Hinweise hier im Forum, die Wissenseite, auf www.mikrocontroller.net, die Hilfe auf der Robotik-Hardware-CD und auch das #*@#+* Datenblatt haben mir nicht geholfen. Jedenfalls komme ich nicht weiter....
Banzai
PS: Kann man nicht einen 'Banzai-stellt-dumme-Fragen'-Thread aufmachen, in dem schlaue Leute einem geistig abwesenden Schwachsinnigen wie mir die Dinge einfach erklärt?
SprinterSB
26.03.2007, 22:33
Du aktivierst eine Timer1-IRQ, implementierst aber für die ISR einer Timer2-IRQ.
Auf die Stirnhauvorlauterdummheit!
Den Baum vor lauter Wald nicht seh (oder war das andersherum... egal )
Danke!!!!!
Banzai
Hallo erstmal,
ich hab zwar jetzt den TIMER2_COMP_vect für den Timer1 geändert und das Vergleichsregister OCR1A mit 3000dez geladen, aber es geht immer noch nicht.
Der Java-Timer-Calculator-Link auf den Wissenseiten ist irgendwie tot und mir hat sich die Berechnung der Werte um einen Interrupt in einer bestimmten Zeit z.B. 1 Sekunde aufzurufen noch nicht erschlossen.
Klar, irgendwie die µC-Clock (ich denke mal das Quarz, wenn kein externer Zeitgeber angeschlossen ist) durch den Prescaler. In meinem Fall die 16000000Hz / 256 = 62500Hz, also Schwingungen pro Sekunde... oder?
Wenn ich jetzt 0xF424 ( 62500 ) in das OCR1A lade, müsste doch nach einer Sekunde ein Timer Compare Match Interrupt ausgelöst werden, oder sehe ich das Falsch (OCR1A ist doch 16bit breit, kann also bis 0xFFFF, 65535dez aufnehmen )??? Der CTC (WGM12) ist ja auch eingeschaltet.
Was kann jetzt noch sein (ausser mein µC ist anders als andere oder das RN-Control ist ein RN-Machtnix)???
Gleich noch eine Frage hinterher: Kann man im AVR-Studio 4.x mit Interrupts 'simuliert' debuggen?
thx4help
Banzai
SprinterSB
27.03.2007, 09:36
Zeig mal den Code.
Hast du das Wiki-Beispiel in den C-Quellen (Hallo welt...) mal angeschaut? Da ist ne Formel für die Berechnung drin.
AVR-Studio weiß ich net, ist mir zu klotzig und mit Similieren findet man eh nur Fehler, die man komfortabler mit Brain v0.9 findet.
thx Sprinter
der Code...
#include <avr/io.h>
#include <avr/interrupt.h>
ISR(TIMER1_COMP_vect)
{
PORTC = ~PORTC; // umschalten
}
int main(void)
{
DDRC = 0xFF;
PORTC = 0x0F; // alles aus
TCCR1A = (1<<COM1A1) | (1<<COM1A0);
TCCR1B = (1<<CS12) | (1<<WGM12);
OCR1A = 0x3000;
TIMSK |= ( 1 << OCIE1A );
sei();
while(1);
}
Der Wiki-Tip ist gut, da die Artikel schon etwas wild gestreut sind und man nach 10x Seitenblättern irgendwie den Anschluss verpasst.
OK... wo kriege ich Brain V0.9, wenn meine Version bei V0.3 stehengeblieben ist und das updaten so unheimlich schwer fällt ;o)
seeYa
SprinterSB
27.03.2007, 16:53
Das sollte beim Übersetzen mindestens eine Warnung geben, weil du einen ungültigen SIGNAL-Name verwendest.
https://www.roboternetz.de/wissen/index.php/Fallstricke_bei_der_C-Programmierung#Warnung_ignoriert
/* Interrupt vectors */
/* External Interrupt Request 0 */
#define INT0_vect _VECTOR(1)
#define SIG_INTERRUPT0 _VECTOR(1)
/* External Interrupt Request 1 */
#define INT1_vect _VECTOR(2)
#define SIG_INTERRUPT1 _VECTOR(2)
/* External Interrupt Request 2 */
#define INT2_vect _VECTOR(3)
#define SIG_INTERRUPT2 _VECTOR(3)
/* Timer/Counter2 Compare Match */
#define TIMER2_COMP_vect _VECTOR(4)
#define SIG_OUTPUT_COMPARE2 _VECTOR(4)
/* Timer/Counter2 Overflow */
#define TIMER2_OVF_vect _VECTOR(5)
#define SIG_OVERFLOW2 _VECTOR(5)
/* Timer/Counter1 Capture Event */
#define TIMER1_CAPT_vect _VECTOR(6)
#define SIG_INPUT_CAPTURE1 _VECTOR(6)
/* Timer/Counter1 Compare Match A */
#define TIMER1_COMPA_vect _VECTOR(7)
#define SIG_OUTPUT_COMPARE1A _VECTOR(7)
/* Timer/Counter1 Compare Match B */
#define TIMER1_COMPB_vect _VECTOR(8)
#define SIG_OUTPUT_COMPARE1B _VECTOR(8)
/* Timer/Counter1 Overflow */
#define TIMER1_OVF_vect _VECTOR(9)
#define SIG_OVERFLOW1 _VECTOR(9)
/* Timer/Counter0 Compare Match */
#define TIMER0_COMP_vect _VECTOR(10)
#define SIG_OUTPUT_COMPARE0 _VECTOR(10)
/* Timer/Counter0 Overflow */
#define TIMER0_OVF_vect _VECTOR(11)
#define SIG_OVERFLOW0 _VECTOR(11)
/* Serial Transfer Complete */
#define SPI_STC_vect _VECTOR(12)
#define SIG_SPI _VECTOR(12)
/* USART, Rx Complete */
#define USART_RXC_vect _VECTOR(13)
#define SIG_USART_RECV _VECTOR(13)
#define SIG_UART_RECV _VECTOR(13)
/* USART Data Register Empty */
#define USART_UDRE_vect _VECTOR(14)
#define SIG_USART_DATA _VECTOR(14)
#define SIG_UART_DATA _VECTOR(14)
/* USART, Tx Complete */
#define USART_TXC_vect _VECTOR(15)
#define SIG_USART_TRANS _VECTOR(15)
#define SIG_UART_TRANS _VECTOR(15)
/* ADC Conversion Complete */
#define ADC_vect _VECTOR(16)
#define SIG_ADC _VECTOR(16)
/* EEPROM Ready */
#define EE_RDY_vect _VECTOR(17)
#define SIG_EEPROM_READY _VECTOR(17)
/* Analog Comparator */
#define ANA_COMP_vect _VECTOR(18)
#define SIG_COMPARATOR _VECTOR(18)
/* 2-wire Serial Interface */
#define TWI_vect _VECTOR(19)
#define SIG_2WIRE_SERIAL _VECTOR(19)
/* Store Program Memory Ready */
#define SPM_RDY_vect _VECTOR(20)
#define SIG_SPM_READY _VECTOR(20)
MANY THX!
Jetzt klappts (auch mit dem Interrupt)
Eine Compiler-Warnung hätte mich ja stutzig hemacht, aber da kommt nix....
Entweder ist das doppelt und falsch belegt, oder der Compiler prüft den Wert nicht... muss ich noch schauen.
Somit steht einer erfolgreichen Timer-Programmierung nichts mehr im Wege, denk ich mal!
Vielen Dank für die Hilfestellung!
banzai
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.