Forum: Mikrocontroller und Digitale Elektronik Externer Interrupt löst mit Verzögerung aus (ATMEGA32)


von Karl (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich habe ein Problem!

Ich habe eine Platine mit einem Atmega32 (16 MHz) der Soll DMX-Signal 
auswerten. Dazu benötige ich den externen Interrupt um das Reset-Signal 
zu ermitteln. Im Moment toggle ich nur einen Port-Pin um zu sehen, dass 
die ISR auslöst.

Auf dem Osziloskop ist unschwer zu erkennen, dass der Interrupt 25µs 
nach der Fallenden Flanke auslöst. Das DMX-Signal kommt aus einem 
SN75175 (RS485 -> TTL Wandler).

Folgende Lösungen habe ich schon probiert:
- Internen Pull-Up-Widerstände eingeschaltet
- Externer Pull-Up-Widerstand
- Externer Pull-Down-Widerstand

zum eintreten in die ISR benötigt der Atmega 12 Clocks die ISR selber 
(togglen) dauert 4 Clocks, wenn ich davon ausgehe, dass die Frequenz 
vorher nicht geteilt wird, dann ergibt sich eine Zeit von 1µs für das 
eintreten in die ISR und das abarbeiten dieser.

Hat vllt. schon jemand Erfahrung mit sowas gemacht und eine Lösung?
Hat sonst jemand eine Idee?



In der Angehängten Grafik seht ihr meine Schaltung.
IC1 ist der Wandler wichtig ist die Verbindung an Pin1 zum Atmega. Der 
ist verbunden mit Pin 14 (UART RX) und Pin 16 (Ext. Int. 0)

von Peter D. (peda)


Lesenswert?

Break-Erkennung macht man üblicher Weise so:
Datenbyte = 0x00 und Framing-Error-Bit gesetzt.


Peter

von Peter D. (peda)


Lesenswert?

Karl schrieb:
> zum eintreten in die ISR benötigt der Atmega 12 Clocks die ISR selber
> (togglen) dauert 4 Clocks

Hängt ganz von Deinem Assemblercode ab, den nur Du kennst.

Offiziell dauert der Eintritt in den Interrupt 6 Zyklen + Beenden der 
laufenden Instruktion.
Dazu kommt dann noch daß, was der Interrupthandler macht (Register 
sichern usw.).


Peter

von Karl (Gast)


Lesenswert?

So erst einmal vielen Dank für die schnell Antwort.

Habe das ganze nochmal begonnen. Jetzt ohne externen Interrupt (nur 
UART). Es werden nur 5 Byte eingelesen die Sinnlos erscheinen.

Das DMX Startbyte sollte 0x00
Die ersten Kanäle sollten:
0xFF 0xFF 0xAA 0xAA sein
das sind die Daten wie sie ankommen:
0x55 0x00 0xAA 0xAB 0x00

Hier der Code zur Initialisierung des UART Interrupts
1
#define UART_INT_ENABLE() UCSRB |= (1<<RXEN) | (1<<RXCIE)
2
// Initialisierung des UART RX Interrupts
3
void uart_rx_init()
4
{
5
  // UART konfigurieren
6
  UCSRB &= (0 << TXEN);// UART Transmit enable Bit löschen
7
  UCSRC |= (1 << USBS);// 2 Stopbits empfangen
8
  UCSRC |= (1 << UCSZ1) | (1 << UCSZ0);// 8 Bit Daten
9
  UCSRC &= (0 << UMSEL); // Asynchrone Übertragung
10
  
11
  UART_INT_ENABLE();// UART Interrupt aktivieren
12
13
  sei();
14
}
Hier die UART ISR
1
ISR(USART_RXC_vect)
2
{
3
  temp_data = UDR;
4
  frame_error = ((UCSRA & (1 << FE)) >> FE);
5
  ISR(USART_RXC_vect)
6
{
7
  temp_data = UDR;
8
  frame_error = ((UCSRA & (1 << FE)) >> FE);
9
  
10
  PORTA ^= (1<<PA1);
11
12
  if(temp_data == 0x00 && frame_error)
13
  {
14
    // Reset
15
    set_new_trans_data();
16
    start=1;
17
  }
18
  else
19
  {
20
    // Daten
21
    if(start == 1)
22
    {
23
      insert_data(temp_data);
24
    }
25
  }
26
}
27
28
29
  if(temp_data == 0x00 && frame_error)
30
  {
31
    // Reset
32
    set_new_trans_data();
33
    start=1;
34
  }
35
  else
36
  {
37
    // Daten
38
    if(start == 1)
39
    {
40
      insert_data(temp_data);
41
    }
42
  }
43
}
Die Variable start ist nur dazu, um sicher zu gehen, das ich nicht 
mitten im DMX Protokoll einsteige.

Den Pin A 1 Toggle ich um zu sehen, ob die ISR aufgerufen wird, das ist 
eben nicht der Fall zu mindest nachher nicht mehr.

Die Hardware ist in sofern geändert, das der Pin 16 des MC jetzt nicht 
mehr angeschloßen ist.

Woran kann es liegen, das Signal nicht sauber eingelesen wird? (Davon 
gehe ich mitlerweile aus)

von Karl (Gast)


Lesenswert?

Sorry oben habe ich die ISR zweimal rein kopiert hier nochmal neu damit 
es einfacher zulesen ist.
1
ISR(USART_RXC_vect)
2
{
3
  temp_data = UDR;
4
  frame_error = ((UCSRA & (1 << FE)) >> FE);
5
  
6
  PORTA ^= (1<<PA1);
7
8
  if(temp_data == 0x00 && frame_error)
9
  {
10
    // Reset
11
    set_new_trans_data();
12
    start=1;
13
  }
14
  else
15
  {
16
    // Daten
17
    if(start == 1)
18
    {
19
      insert_data(temp_data);
20
    }
21
  }
22
}

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.