Forum: Mikrocontroller und Digitale Elektronik Atmega8 interrupt signal erzeugen


von HaraldB (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

Ich steh gerade irgendwie auf dem Schlauch.

Ich möchte mittels Funkmodul und Atmega8 diverse Funksteckdosen 
ansteuern was auch soweit mit Delays schon funktioniert wobei das mit 
den Delays nicht sehr genau ist.

Nun habe ich es schon geschafft mit dem 8bit Timer0 alle 500us einen Pin 
zu togglen ich steh nun aber gerade voll auf dem schlauch.

Vllt. kann mir jemand auf die Sprünge helfen wie kann ich nun z.B. einen 
High Puls mit 500us einfach mehrmals hintereinander senden?

Gruß

Chris

von Karl H. (kbuchegg)


Lesenswert?

HaraldB schrieb:

> Vllt. kann mir jemand auf die Sprünge helfen wie kann ich nun z.B. einen
> High Puls mit 500us einfach mehrmals hintereinander senden?

Ich versteh, wo dein Problem liegt.

Wenn du es doch schon geschafft hast, eine ISR alle 500µs aurufen zu 
lassen, dann hast du doch deinen gewünschten Puls. Wenn du x Pulse 
brauchst, dann zählst du halt einfach in einer Variablen mit und wenn 
die ISR dann eben 2*x mal aufgerufen wurde, dann machst du einfach 
nichts mehr am Pin.

von HaraldB (Gast)


Angehängte Dateien:

Lesenswert?

Das dacht ich eben auch hat aber nicht funktioniert deshalb dacht ich 
mir evtl. geht es doch nicht so einfach.

Hatte die ganze Zeit schon viele mögliche Varianten Ausprobiert und ein 
"volatile int count" hat mein Problem nun gelöst denn es funktioniert 
nun :)

Alle 8 Bit werden nun korrekt Übertragen.

Auszug Main:
1
volatile int count = 0;
2
volatile int send;
3
volatile int data[10];
4
5
int main(void)
6
{
7
8
// PortB1 Output
9
PORTB &= ~(1<<PB1); // Low
10
DDRB = (1 << PB1);
11
12
// Prescaler 64
13
TCCR0 |= (1<<CS01) | (1<<CS00);
14
15
// Enable Timer0 Overflow Interrupt
16
TIMSK |= (1<<TOIE0);
17
18
// Allow Interrupts
19
sei();
20
21
// set prescaler to 64 and start timer
22
TCCR2  |= (1<<CS21);
23
24
data[0] = 1;
25
data[1] = 0;
26
data[2] = 1;
27
data[3] = 0;
28
data[4] = 0;
29
data[5] = 1;
30
data[6] = 0;
31
data[7] = 1;
32
33
while(1)
34
{
35
    if(data[count] == 1)
36
    {
37
      send = 1;
38
    } else if(data[count] == 0)
39
    {
40
      send = 0;
41
    }
42
    
43
    if(count == 9)
44
    {
45
      count = 0;
46
    }
47
}

ISR:
1
ISR(TIMER0_OVF_vect)
2
{  
3
  TCNT0 = 131; // 500us
4
5
  if(send == 1)
6
  {
7
      PORTB |= (1<<PB1); // High
8
  } else if(send == 0)
9
  {
10
      PORTB &= ~(1<<PB1); // Low
11
  }
12
13
  count++;
14
  
15
  //PORTB ^= (1<<PB1);
16
}

von Hmm (Gast)


Lesenswert?

Ich halte das für unsauber, count an zwei Stellen zu verändern. Nimm den 
modulo 10 besser noch in den Interrupt.
Im übrigen spräche aus meiner Sicht nichts dagegen die Ausgabe und den 
Zugriff auf data auch im Interrupt zu machen.

von HaraldB (Gast)


Lesenswert?

Ich hab nun alles in die ISR gepackt jetzt ist die Pulselänge immer 1-2 
us zu lang/kurz.

Evtl. doch nicht ganz so Optimal.

von Karl H. (kbuchegg)


Lesenswert?

HaraldB schrieb:

> Auszug Main:

Tu dir selbst ein paar Gefallen

> volatile int count = 0;
> volatile int send;
> volatile int data[10];

wenn Variablen per Design keine größeren Werte als 255 haben können und 
auch nie haben werden, dann bürde dem µC keine 16-Bit Airthmetik auf.
Mal abgesehen davon, löst sich dann auch das Problem des atomaren 
Zugriffs in Luft auf, sobald ISR mit dieser Variable im Spiel sind. 8 
Bit pro Variable tuns auch:

volatile uint8_t count = 0;
volatile uint8_t send;
volatile uint8_t data[10];


>     if(data[count] == 1)
>     {
>       send = 1;
>     } else if(data[count] == 0)
>     {
>       send = 0;
>     }

tus nicht.
data KANN bei dir per Design nur 0 oder 1 sein. Andere Werte gibt es 
nicht. Wenn data[count] nicht 1 ist, dann KANN es daher nur 0 sein. Das 
muss man nicht testen. Jedes Wort, dass du unnötig schreibst, ist eine 
potentielle Fehlerquelle.


>   if(send == 1)
>   {
>       PORTB |= (1<<PB1); // High
>   } else if(send == 0)
>   {
>       PORTB &= ~(1<<PB1); // Low
>   }

selbiges.
Wenn send nicht 1 ist, dann kann es per Definition nur 0 sein.



Wozu eigentlich der ganze komplizierte Umweg über send? Wickle doch 
gleich alles komplett in der ISR ab, anstatt die Logik quer über das 
ganze Programm zu verstreuen.

von Hmm (Gast)


Lesenswert?

Oops. Sorry. Aber gleich 2us? Hmm. Naja. Dann lass es lieber. Vielleicht 
nur den Modulus im Int.

von Karl H. (kbuchegg)


Lesenswert?

HaraldB schrieb:
> Ich hab nun alles in die ISR gepackt jetzt ist die Pulselänge immer 1-2
> us zu lang/kurz.
>
> Evtl. doch nicht ganz so Optimal.

Kann nicht sein.
1
ISR( ... )
2
{
3
  TCNT0 = 131; // 500us
4
5
  if( data[count] )
6
    PORTB |= (1<<PB1); // High
7
  else
8
    PORTB &= ~(1<<PB1); // Low
9
10
  count++;
11
  if( count == sizeof( data ) )
12
    count = 0;
13
}

und mach deine Variablen uint8_t

von Hmm (Gast)


Lesenswert?

Wenn Du da noch 1-2us Verzögerung hast, dann ist was anderes faul.

von HaraldB (Gast)


Lesenswert?

Danke euch :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.