-
Delay mittels Timer
Hallo,
ich versuche in folgendem Code eine Delay-funktion zu realisieren.
Leider funktioniert es nicht wirklich, kann vllt. von euch jemand erkennen, warum nicht im Sekundentakt gesendet wird, sondern viel schneller?
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
volatile uint8_t count;
void init_usart(void)
{
UBRRL |= 0b01100111;
UCSRB = (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}
void send_char(unsigned char s)
{
while (!(UCSRA & (1<<UDRE)));
UDR = s;
}
void send_string(char *s)
{
while(*s != '\0')
{
send_char(*s);
s++;
}
}
void waitms(uint16_t s)
{
uint16_t i;
uint8_t j;
TCCR0 |= (1<<CS01) | (1<<CS00); //Vorteiler 64
TIMSK |= (1<<TOIE0);
for(i=0;i<s;i++)
{
TCNT0 = 6; // Timer auf 6 vorladen, da (16000000/64)^-1 = 0.000004s
} // -> 1ms = 0.000004s*250
TIMSK |= (0<<TOIE0);
}
SIGNAL(SIG_OVERFLOW0)
{
count++;
TCNT0 = 6;
}
int main(void)
{
sei();
unsigned int i;
char a = "108:158#13#10";
i = 0;
init_usart();
do
{
send_string(a);
waitms(1000);
}
while (i == 0);
}
Gruß
Spurius
-
Re: Delay mittels Timer
Versuch mal sowas:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
volatile uint8_t count;
void init_usart(void)
{
UBRRL |= 0b01100111;
UCSRB = (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}
void send_char (unsigned char s)
{
while (!(UCSRA & (1<<UDRE)));
UDR = s;
}
void send_string (char *s)
{
while (*s++)
send_char(*s);
}
void init_timer0()
{
TCCR0 = (1<<CS01) | (1<<CS00); //Vorteiler 64
TIMSK |= (1<<TOIE0);
}
void waitms (uint16_t s)
{
while (s--)
{
uint16_t cnt;
cli();
count = 0;
TCNT0 = 6;
do
{
cli();
cnt = count;
sei();
}
while (cnt < 1000);
}
}
SIGNAL (SIG_OVERFLOW0)
{
TCNT0 = 6;
count++;
}
char a[] = "108:158#13#10";
int main(void)
{
init_usart();
init_timer0();
sei();
while (1)
{
send_string (a);
waitms (1000);
}
}
-
Hi,
bei deiner Version wird nur einmal gesendet :?:
Was ist bei mir denn konkret falsch? Hab ich nen Logikfehler oder eher was C-Spezifisches?
-
Sorry, count muss uint16_t sein, nicht uint8_t (zählt bis 1000). Und in der Schleife muss es heissen while(*s) { foo (*s++); }
Was bei dir konkret inkorrekt ist, ist schwer zu fprmulieren. Es geht eben nicht so. Interrupts hast du inaktiv und setzt in der Schleife nur s mal TCNT0 auf 6. Da müsste noch das Flag aus TIFR abgefrage/gelöscht werden, heisst glaub TOV0 oder so.
-
nimm diese hier, delay_us_(...) und delay_ms_(...):
#define delay_us_(us) _delayFourCycles_( ( ( 1*(F_CPU/4000) )*us)/2005)
static inline void _delayFourCycles_(uint16_t z)
{
uint16_t i;
for (i=0; i<z; i++)
asm volatile("nop");
}
static inline void delay_ms_(uint16_t z)
{
uint16_t i;
for (i=0; i<z; i++)
delay_us_(999);
}
-
Hallo,
danke für eure Hilfe, ich habs jetzt so gelöst:
Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
volatile uint8_t count = 0;
void init_usart(void)
{
UBRRL |= 0b01100111;
UCSRB = (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);
}
void send_char(unsigned char s)
{
while (!(UCSRA & (1<<UDRE)));
UDR = s;
}
void send_string(char *s)
{
while(*s != '\0')
{
send_char(*s);
s++;
}
}
void waitms(uint16_t s)
{
uint16_t i;
uint8_t j;
TCCR0 |= (1<<CS01) | (1<<CS00); //Vorteiler 64
TIMSK |= (1<<TOIE0);
for(i=0;i<s;i++)
{
count = 0;
TCNT0 = 6; // Timer auf 6 vorladen, da (16000000/64)^-1 = 0.000004s
while(count != 1)
{}
} // -> 1ms = 0.000004s*250
TIMSK |= (0<<TOIE0);
}
SIGNAL(SIG_OVERFLOW0)
{
count = 1;
}
int main(void)
{
sei();
unsigned int i;
char a = "Hallo Welt";
i = 0;
init_usart();
do
{
send_string(a);
waitms(1000);
}
while (i == 0);
}
Gruß
Spurius