UART soll nach externem Interrupt senden (C, ATM.8)

OP (Firma: A.S.) #2733163
Lesenswert?

1
//---------------------INCLUDES---------------------------------
2
#define F_CPU 3686400UL
3
#include <avr/delay.h>
4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
#include <inttypes.h>
7
#include <avr/signal.h>
8
#include <avr/wdt.h>
9
//---------------------DEFINES---------------------------------
10
#define eDIP_IRQ PD2
11
#define Takt 3686400UL  //Controllertakt 3,4686 MHz
12
#define BAUD 9600UL    //Baudrate  
13

14
#include <UART\konsolfunc.h>
15
//-------------------INIT UART----------------------------------
16
//UCSRA:  RXC = INT wenn zeichen im empfänger angekommen. Wird gelöscht wenn Daten aus UDR gelesen werden.
17
//      TXC = INT wenn Zeichen aus dem sender geschickt wurde und Sendepuffer leer ist. Durch Interrupt-
18
//            annahme oder durch Einschreiben einer 1 wieder gelöscht.
19
//      UDRE = 1 wenn Puffer bereit für neue Datenübertragung.  (S.350)
20

21
//-------------------IRQ ausgelöst-------------------------//GIFR (Interrupt Flag = 01000000)
22
volatile double ISR_buffer;
23

24
//-------------------------FUNKTIONEN--------------------------------------------
25

26
//-------------------------Sendepuffer empfangen---------------------------------
27
int sendepuffer_empfangen()
28
{
29
  getch();
30

31
  switch(UDR)
32
  {
33

34
    case 0x01 : PORTB^=(1<<PB1);  //gelbe LED blinkt
35
    break;
36
    _delay_ms(50);
37

38
    case 0x02 : PORTB^=(1<<PB1);  //gelbe LED blinkt
39
    break;
40
    _delay_ms(50);
41

42
    default : PORTB^=((1<<PB1) | (1<<PB2));
43
    _delay_ms(50);
44
  }
45
  return(0);
46
}
47

48
//-------------------------Sendepuffer anfordern --------------------------------------
49
void sendepuffer_anfordern()
50
{
51

52
  initusart();
53
  _delay_ms(30);
54
  putch('0x12');   //<DC2>
55
  _delay_ms(1);
56
  putch('0x01');  //1(len)
57
  _delay_ms(1);
58
  putch('0x53');  //S
59
  _delay_ms(1);
60
  putch('0x66');  //66(bcc)
61
  _delay_ms(1);
62

63
  getch();    // Empfänger ein und auf Antwort des Displays warten
64

65
  if(UDR == '0x06')      //wenn "Ack" vom Display
66
  {
67
    PORTB=(1<<PB1);      // LED grün
68
    sendepuffer_empfangen;      
69
  }
70
else            //wenn "Nack" vom Display
71
  {
72
    PORTB=(1<<PB2);      //LED rot
73
  }
74
  for (int i=0; i<5; i++)
75
  {
76
    sendepuffer_anfordern;            //EVENTUELL SEPARAT !!!
77
  }
78

79
}
80

81
//-------------------------Daten senden--------------------------------------
82

83
// FÜR MENÜBEFEHLSROUTINE !!!
84

85
//-------------------------auf Daten warten--------------------------------------
86

87
int wait_for_data()
88
{
89
  ISR_buffer = PORTC  ;
90
  while(1)
91
  {PORTB=(1<<PB3);//DEBUGLEUCHTE
92
    if(ISR_buffer>0x00)              //prüfen ob Daten in Register
93
    {
94
      ISR_buffer = 0;          //Buffer zurücksetzen
95
      sendepuffer_anfordern;
96
      
97
    }
98

99
  }
100
  return(0);
101
}
102

103
//------------------------------------------------------------------------------
104
//-------------------------ISRs--------------------------------------
105

106
ISR (INT0_vect)          // SBUF Display hat Daten - jetzt abholen !
107
{  
108
  PORTC++;
109
//  GICR= (!(1<<INT0)) ;
110
}
111

112
//--------------------HAUPTPROGRAMM----------------------------
113

114
int main()                      
115
{
116
  wdt_reset();
117
  
118
  initusart();
119
  //---------------------INIT EXT INTERRUPT--------------------------
120

121
  MCUCSR |=(1<<ISC01);    //INT bei fallender Flanke an PIN D2
122

123
  GICR |= (1<<INT0) ;               // EXT INT aktiviert
124

125
  //------------------------------------------------------------------  
126

127
  //----------------------EIN/AUSGÄNGE festlegen----------------
128
  DDRB=0xff;
129
  DDRC=0xff;
130
  PORTD=0xff;  //PIN 2 EXT0 INTERRUPT Pullup
131
  //-----------------------------------------------------------
132
  sei();
133
  while(1)
134
  {
135

136
    PORTB^=(1<<PB0);    // Rote LED blinkt
137
    _delay_ms(50);  
138
    cli();      
139
    wait_for_data;
140
    sei();
141
  }
142
  // Arbeitsschleife Ende
143

144
}

Hallo !

Ich mach gerade meine ersten Gehversuche mit nem eDIP 160 Touchdisplay 
und nem ATmega 8. Das Display steckt auf einem EVA Board und der ATmega 
auf dem MyAVR MK2. Nun habe ich beides über RS232 verbunden und der UART 
funktioniert auch mit den gemachten Einstellungen.
Jetzt mein Problem: Das Display zeigt ja mit Low Level an PIN 20 an, 
dass Daten im Sendepuffer vorhanden sind. Also hab ich diesen mit dem 
ExtINT0 des uC vebunden. Die ISR spricht auch an sobal ich am Display 
eine Taste drücke, aber anscheinend bleibt der uC dann in der ISR hängen 
und geht nicht auf die Sendefunktion. Ich habe in der Sendefunktion PB3 
aktiviert, um mir das Ansprechen über eine LED anzeigen zu lassen - da 
tut sich nicht. Drücke ich den Reset des Display, wird die Puffermeldung 
gelöscht und ds Programm läuft in der Mainroutine weiter. Wie krieg ich 
es jetzt hin, dass nach dem INT0 mein Sendeprog startet ???
Gast #2733213
Lesenswert?

Alter das ist echt ne grosse Baustelle;)

  putch('0x12');   //<DC2>

Schwachsinn. Das geht in C nicht ohne massive Fehlermeldungen.
So macht man das.

  putch(0x12);   //<DC2>

Aus dieser Routine kommst du nie wieder raus.
1
int wait_for_data()
2
{
3
  while(1)
4
  {PORTB=(1<<PB3);//DEBUGLEUCHTE
5
    if(ISR_buffer>0x00)              //prüfen ob Daten in Register
6
    {
7
      ISR_buffer = 0;          //Buffer zurücksetzen
8
      sendepuffer_anfordern;
9
      
10
    }
11

12
  }
13
  return(0);
14
}



Na super erst mal alle Interrupts abschalten.

    cli();
    wait_for_data;
    sei();

Rekursiver Aufruf. Gute Idee!
1
//-------------------------Sendepuffer anfordern --------------------------------------
2
void sendepuffer_anfordern()
3
{
4
................
5
    sendepuffer_anfordern;            //EVENTUELL SEPARAT !!!
6

7
}
#2733254
Lesenswert?

Markus S. schrieb:
> Danke, das sind schonmal ein paar Dinge die ich angehen werde

Hier hast du noch weitere:

- Reichlich fehlende () bei Funktionsaufrufen.

- Nicht erreichbarer Code im switch.

Allgemein:
Das ist ein Haufen Code mit so vielen Fehlern darin, dass der mit 
Sicherheit noch nie richtig funktioniert hat. Du musst in kleinen 
Schritten programmieren und nach jedem Schritt ausführlich Testen. Und 
erst wenn es funktioniert, gehst du den nächsten Schritt an. Und noch 
bevor du mit diesen Schritten anfängst, musst du dir erst mal eine 
Struktur für dein Programm überlegen (denn die kann ich im Code oben 
auch nicht so wirklich erkennen).
OP (Firma: A.S.) #2733262
Lesenswert?

1
//---------------------INCLUDES---------------------------------
2
#define F_CPU 3686400UL
3
#include <avr/delay.h>
4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
#include <inttypes.h>
7
#include <avr/signal.h>
8
#include <avr/wdt.h>
9
//---------------------DEFINES---------------------------------
10
#define eDIP_IRQ PD2
11
#define Takt 3686400UL  //Controllertakt 3,4686 MHz
12
#define BAUD 9600UL    //Baudrate  
13

14
#include <UART\konsolfunc.h>
15

16
volatile double ISR_buffer;
17

18
//-------------------------FUNKTIONEN--------------------------------------------
19

20
//-------------------------Sendepuffer empfangen---------------------------------
21
int sendepuffer_empfangen()
22
{
23
  getch();
24

25
  switch(UDR)
26
  {
27

28
    case 0x01 : PORTB^=(1<<PB1);  //gelbe LED blinkt
29
    break;
30
    _delay_ms(50);
31

32
    case 0x02 : PORTB^=(1<<PB2);  //grüne LED blinkt
33
    break;
34
    _delay_ms(50);
35

36
    default : PORTB^=((1<<PB1) | (1<<PB2));
37
    _delay_ms(50);
38
  }
39
  return(0);
40
}
41

42
//-------------------------Sendepuffer anfordern --------------------------------------
43
void sendepuffer_anfordern()
44
{
45

46
  _delay_ms(30);
47
  putch(0x12);   //<DC2>
48
  _delay_ms(1);
49
  putch(0x01);  //1(len)
50
  _delay_ms(1);
51
  putch(0x53);  //S
52
  _delay_ms(1);
53
  putch(0x66);  //66(bcc)
54
  _delay_ms(1);
55

56
  getche();    // Empfänger ein und auf Antwort des Displays warten
57

58
  if(UDR == 0x06)      //wenn "Ack" vom Display
59
  {
60
    PORTB=(1<<PB1);      // LED grün
61
    sendepuffer_empfangen;      
62
  }
63
else            //wenn "Nack" vom Display
64
  {
65
    PORTB=(1<<PB2);      //LED rot
66
  }
67

68
}
69

70
//-------------------------Daten senden--------------------------------------
71

72
// FÜR MENÜBEFEHLSROUTINE !!!
73

74
//*******************************************************************
75
//-------------------------ISRs--------------------------------------
76

77
ISR (INT0_vect)          // SBUF Display hat Daten - jetzt abholen !
78
{
79

80
  PORTC++;
81
  //GICR= (!(1<<INT0)) ;
82
}
83

84
//--------------------HAUPTPROGRAMM----------------------------
85

86
int main()                      
87
{
88
  wdt_reset();
89

90
  initusart();
91
  //---------------------INIT EXT INTERRUPT--------------------------
92

93
  MCUCSR |=(1<<ISC01);    //INT bei fallender Flanke an PIN D2
94

95
  GICR |= (1<<INT0) ;               // EXT INT aktiviert
96

97
  //------------------------------------------------------------------  
98

99
  //----------------------EIN/AUSGÄNGE festlegen----------------
100
  DDRB=0xff;
101
  DDRC=0xff;
102
  PORTD=0xff;  //PIN 2 EXT0 INTERRUPT Pullup
103
  //-----------------------------------------------------------
104
  sei();
105
  while(1)
106
  {
107

108
    PORTB^=(1<<PB0);    // Rote LED blinkt
109
    _delay_ms(50);  
110

111
    if(PORTC>0)              //prüfen ob Daten in Register
112
    {
113

114
      PORTB=(1<<PB3);        //DEBUGLEUCHTE
115
      PORTC = 0;          //Buffer zurücksetzen
116
      sendepuffer_anfordern;
117

118
    }
119
    return (0);
120
  }
121
  // Arbeitsschleife Ende
122

123
}

Ich hab jetzt schonmal die angesprochenen Fehler beseitigt. Der Compiler 
meckert ja auch nicht. Aber Du hast recht, wahrscheinlich muss ich 
nochmal in kleinen Schritten loslegen.
Habe mir aber vorher nen PAP erstellt, nur durch diverse Korrekturen 
sieht es schon etwas anders aus.
OP (Firma: A.S.) #2733399
Lesenswert?

1
//---------------------INCLUDES---------------------------------
2

3
#include <avr/delay.h>
4
#include <avr/io.h>
5
#include <avr/interrupt.h>
6
#include <inttypes.h>
7
#include <avr/signal.h>
8
#include <avr/wdt.h>
9
//---------------------DEFINES---------------------------------
10
#define eDIP_IRQ PD2
11
#define Takt 3686400UL  //Controllertakt 3,4686 MHz
12
#define BAUD 9600UL    //Baudrate  
13

14
#include <UART\konsolfunc.h>
15

16
volatile int SBUF_EDIP;
17
volatile int transfer_error;
18

19
//********************FUNKTIONEN******************************
20

21
//--------------------DATEN IM EDIP-PUFFER--------------------
22
int paket_fordern()
23

24
{
25
  putch(0x12);   //<DC2>
26
  putch(0x01);  //1(len)
27
  putch(0x53);  //S
28
  putch(0x66);  //66(bcc)
29
  _delay_ms(10);      
30
  return(0);
31
}
32
//--------------------DATENPAKET AUSWERTEN---------------------
33
int get_package()
34
{
35

36
  switch(UDR)
37
  {
38

39
    case 0x01 : PORTB^=(1<<PB0);  //rote LED blinkt
40
    break;
41
    _delay_ms(50);
42

43
    case 0x02 : PORTB^=(1<<PB2);  //grüne LED blinkt
44
    break;
45
    _delay_ms(50);
46

47
    default : PORTB^=((1<<PB1) | (1<<PB2));  //beide blinken
48
    _delay_ms(50);
49
  }
50
  return(0);
51
}
52
//--------------------ANTWORT AUF ACK PRÜFEN------------------ 
53

54
int pruefe_ack()
55
{
56

57
  if(UDR==0x06)
58
  {
59
    get_package;PORTB=(1<<PB3);
60
  }
61
  //hole Paket
62

63
else 
64
  {
65
    transfer_error++;
66
  }
67
  if(transfer_error>5){return false;}      // FEHLERPUFFER
68
  return(0);    
69
  
70
}
71

72
//-------------------------ISRs--------------------------------------
73

74
ISR (INT0_vect)          // SBUF Display hat Daten - jetzt abholen !
75
{
76
  SBUF_EDIP++;  
77
}
78

79
//**********************HAUPTPROGRAMM*********************************
80

81
int main()                      
82
{
83
  //---------------------INIT EXT INTERRUPT--------------------------
84

85
  MCUCSR |=(1<<ISC01);    //INT bei fallender Flanke an PIN D2
86

87
  GICR |= (1<<INT0) ;               // EXT INT aktiviert
88

89
  //------------------------------------------------------------------  
90

91
  //----------------------EIN/AUSGÄNGE festlegen----------------
92
  DDRB=0xff;
93
  DDRC=0xff;
94
  DDRD=0x00;
95
  PORTD=0xff;  //PIN 2 EXT0 INTERRUPT Pullup
96
  //-----------------------------------------------------------
97
  initusart();
98
  sei();
99
  while(1)
100
  {
101

102
    if(SBUF_EDIP>1)
103
    {
104
      paket_fordern();
105
    }
106

107
  else 
108
    {
109
      PORTB=(1<<PB1);  
110
    }
111

112
    pruefe_ack();              // Rückmeldung des Displays prüfen
113
    if(transfer_error==1)
114
    {
115
      paket_fordern;
116
    }
117
    // Wenn kein "ACK" kam, Paket neu anfordern
118

119
  }
120

121
}


SO- Bis hierhin hab ichs jetzt hinbekommen, das mit dem Interrupt und 
dem Auslesen des Datenpuffers vom Display funktioniert nun. Jetzt steh 
ich vor dem nächsten Problem - wie lege ich das ankommende Datenpaket 
ab, um es auswerten zu können. Der UDR speichert doch immer nur ein BYte 
richtig ? Das Display sendet aber immer mindestens "ESC,A,1,CODE" bis zu 
32Byte. Wie mach ich das ? mit nem FIFO ? Und wenn dann weiss ich nicht 
so richtig wie !
Gast #2733408
Lesenswert?

Sorry,aber das kann nicht funktionieren!
1
if(transfer_error==1) 
2
{ paket_fordern; } 
3
// Wenn kein "ACK" kam, Paket neu anfordern

Es fehlen immer noch Klammern für die Funktionsaufrufe .
Hab mir den Code nicht angesehen,steckt bestimmt noch mehr drin!
Gast #2733419
Lesenswert?

C hat eine recht konsequente logische Sprachdefinition, was zu einigen 
seltsamen Konstruktionen führt, die offiziell erlaubt sind, aber selten 
Sinn machen. GCC kann, wenn man ihn drum bittet, solche problematischen 
Ausdrücke
und Befehle anmeckern.

Ich empfehle "-Wall -Wextra -Werror" als Compiler-Optionen (ich nehme 
mal an, du benutzt einen GCC). Damit werden solche zweifelhafte 
Konstrukte angemahnt und als Fehler gemeldet.

Gerade mit deinem unsteten C-Wissen solltest du dann zu jeder 
Fehlermeldung die Ursache bestimmen und beheben. Und nicht schummeln! 
Die Warnungen/Fehler sind zu deinem Besten! Dadurch lernst du nämlich 
auch noch einiges.
#2733511
Lesenswert?

Weil ichs gerade gesehen hab und weil das der Compiler nicht anmeckern 
wird (demist das prinizipiell egal)


Du darfst UDR pro Zeichen nur ein einziges mal auslesen!
Nach dem ersten auslesen ist UDR futsch.


Und wenn du C nicht so gut kannst, warum lernst du es nicht erst mal und 
fängst mit etwas einfacherem an? Du machst den Kardinalfehler 
schlechthin: Viel zu viel Code, den du nicht getestet hast und dann 
weiußt du nicht, wo du mit Fehlersuche anfangen sollst, weil so gut wie 
überall, quer durch den ganzen Code Probleme sind.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren