Forum: Mikrocontroller und Digitale Elektronik ISR Problem beim Tiny 2313


von Max (Gast)


Lesenswert?

Hallo Leute,
ich hab eine kleines Problem mit einer ISR beim Tiny2313.
Und zwar soll mein Tiny wenn er eine Low-Flanke an INT1 detektiert in 
der ISR ein Zeichen per Uart Empfangen und dieses in eine globale 
Variable schreiben danach soll er wieder zum Hauptprogramm wechseln. Das 
anspringen der ISR klappt aber komischerweise liest er immer erst 4 
Zeichen ein bevor er wieder raussüringt.

Kann eventuell jemand was zu meinem Code sagen ,weil ich finde den 
Fehler einfach nicht.
1
#include <avr/io.h>
2
#include <avr/wdt.h>
3
#include <inttypes.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
#include <avr/sleep.h>
7
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
11
#define BAUD 115200L
12
13
void init_mcu (void);
14
15
int main (void)
16
{
17
  init_mcu();
18
  while(1)
19
  {
20
    
21
    PORTB |= (1<<PB4);//LED AUS
22
    
23
  }
24
25
return 0;
26
}
27
28
void init_mcu (void)
29
{
30
31
  DDRB =0b11111111;
32
  PORTB=0b11100000;
33
  DDRD =0b01100000;
34
  PORTD=0b00000000;
35
  UCSRB = 1<<TXEN | 1<<RXEN;              // UART TX einschalten   UART RX einschalten
36
  UCSRC = 1<<UCSZ1 | 1<<UCSZ0;           // Asynchron 8N1
37
  UBRRH = UBRR_VAL >> 8;
38
  UBRRL = UBRR_VAL & 0xFF;
39
  MCUCR |=(1<<ISC10)|(1<<ISC11);
40
  GIMSK |=(1<<INT1);
41
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
42
  //_delay_ms(30000);
43
  sei();
44
}
45
46
ISR(INT1_vect)
47
{
48
  
49
50
  PORTB &= ~(1<<PB4);
51
  in=uart_getc();
52
  uart_putc(in);
53
}

Falls sich jemand nach dem Sinn fragt : Dies ist erstmal nur ein Test ob 
das rein und rausspringen klappt.Es geht hinterher darum ein 
Steuerzeichen zu empfangen was von einem Linux Router kommt,wobei dessen 
RS232 Schnittstelle aber nicht explizit frei ist für diese eine Aufgabe.

MfG

Max

von Max (Gast)


Lesenswert?

Oh hab ich vergessen in ist natürlich mit volatile char in='Y' 
definiert.
Sorry.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Es ist IMHO wahrscheinlich nicht "komischerweise liest er immer erst 4
Zeichen ein bevor er wieder raussüringt" sondern die ISR(INT1_vect) wird 
viermal hintereinander aufgerufen.

Wenn das Eingangssignal ein "Steuerzeichen" von einer RS232-Leitung ist, 
können sich darin mehrere steigende Flanken verstecken 
(http://www.mikrocontroller.net/articles/RS-232 => Startbit + Nextframe 
+ Anzahl 1-0 Wechsel im Steuerzeichen?)

1/ Hast du eine Möglichkeit das Signal am externen Interrupteingang zu 
oszilloskopieren?

2/ UART-Aktionen innerhalb der ISR(INT1_vect) wären für mich ein No-Go. 
Lieber in der ISR ein globales, volatile Flag setzen und das im 
Userprogramm (main) abfragen und behandeln.

von Max (Gast)


Lesenswert?

Sorry diese Möglichkeit habe ich leider nicht.Aber ich glaube ich habe 
mich falsch ausgedrückt. Die UART ist mit den RX/TX Leitungen des 
Routers verbunden.Und ein GPIO Pin des Routers Schaltet kurz die Tiny 
INT1 Leitung auf high und anschliessend sofort wieder auf low.Nun sendet 
der Router erst das Uart Zeichen da der Tiny nach dem Pin Wechsel in der 
ISR bei uart_getc() stehen sollte.So sollte der Ablauf zumindest sein.

von Stefan E. (sternst)


Lesenswert?

Max schrieb:
> Nun sendet
> der Router erst das Uart Zeichen da der Tiny nach dem Pin Wechsel in der
> ISR bei uart_getc() stehen sollte.So sollte der Ablauf zumindest sein.

Und wo kommt dieses uart_getc her? Vielleicht aus der Fleury-Lib? Das 
uart_getc dort wartet nämlich nicht auf ein Zeichen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1
#include <avr/io.h>
2
#include <avr/wdt.h>
3
#include <inttypes.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
#include <avr/sleep.h>
7
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
9
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
10
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
11
#define BAUD 115200L
12
13
#define DEBUG 1
14
15
volatile unsigned char num_ints;
16
17
ISR(INT1_vect)
18
{
19
  num_ints += 1;
20
}
21
22
void init_mcu (void)
23
{
24
  // I/O Init
25
  DDRB =0b11111111;
26
  PORTB=0b11100000;
27
  DDRD =0b01100000;
28
  PORTD=0b00000000;
29
30
  // UART Init
31
  UCSRB = 1<<TXEN | 1<<RXEN;   // UART TX und RX einschalten
32
  UCSRC = 1<<UCSZ1 | 1<<UCSZ0; // Asynchron 8N1
33
  UBRRH = UBRR_VAL >> 8;
34
  UBRRL = UBRR_VAL & 0xFF;
35
36
  // INT1 Init
37
  MCUCR |= (1<<ISC10)|(1<<ISC11); // steigende Flanke
38
  GIMSK |= (1<<INT1);
39
40
  // für später?
41
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
42
  //_delay_ms(30000);
43
 
44
  sei();
45
}
46
47
int main (void)
48
{
49
  init_mcu();
50
51
  while(1)
52
  {
53
    if (num_ints)
54
    {
55
      unsigned char i = num_ints;
56
      char in;
57
58
      // Arbeitsroutine
59
      in = uart_getc();
60
      uart_putc(in); 
61
      num_ints = 0;
62
63
#if DEBUG
64
      // DEBUG: Wieviele INT1s waren es?
65
      do
66
      {
67
        PORTB &= ~(1<<PB4); //LED AN
68
        _delay_ms(200);
69
        PORTB |= (1<<PB4);  //LED AUS
70
      } while(--i);
71
#endif /* DEBUG */
72
    }
73
  }
74
75
  return 0;
76
}

von Max (Gast)


Lesenswert?

Oh die hab ich vergessen.Das ist das getc hier aus dem AVR-GCC Tutorial.
1
uint8_t uart_getc(void)
2
{
3
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
4
        ;
5
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
6
}

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.