Forum: Mikrocontroller und Digitale Elektronik C PRogramm verstehen (Interrupt RS232)


von Dan M. (luizaranha)


Lesenswert?

Hallo liebe Gemeinde,

Ich beschäftige mich gerade mit einem Demoprogramm (compact-c) mit dem 
compiler IDE für ein Projectboard MEGA32.
Ich würde gerne auch schon antworten auf ein paar Frage geben, aber ich 
bin noch unerfahren im uC-Bereich.

Bei folgendem Code hab ich schon zwei Fragen:
Wenn von einem Programm(z.B. Matlab) über die serielle Schnittstelle zum 
Zeitpunkt X ein Byte geschrieben wird, heisst das dann, das der 
Interrupt wieder neu bei der Funktion "Serial_Init_IRQ" beginnt, oder 
woher weiss ich wenn die Sache im Interrupt modus arbeitet, ab welcher 
Aktion der code wieder abgearbeitet wird.

Vielen Dank für eure Hilfe

gruss Luiz
1
#define PORT 0
2
//oimaul defina, dann isch s guat
3
4
// 35 bytes send + receive buffer + 6 bytes internal FIFO management
5
byte buffer[41];                                // Array declaration
6
7
8
//------------------------------------------------------------------------------
9
// Main program
10
//
11
void main(void)
12
{
13
    char Text1[40];                             // Arrays declaration
14
    char output[40];
15
    byte count;
16
    int sz;
17
18
    Text1="Test Text\r\n";
19
20
    //Initialize RS232: 19200 bps, 8 Bit, 1 Stop, NP
21
    // 20 bytes receive buffer - 15 bytes send buffer
22
    Serial_Init_IRQ(PORT,buffer,20,15,SR_8BIT|SR_1STOP|SR_NO_PAR,SR_BD19200);
23
24
    Serial_Write(PORT,'\r');                       // control character for carriage return is sent via RS232 interface
25
    Serial_Write(PORT,'\n');                       // control character for line feed is sent via RS232 interface
26
    Serial_WriteText(PORT,Text1);                  // output text via RS232 interface
27
28
29
    AbsDelay(10000);                             // 10 seconds waiting time
30
                                                 // Until receive buffer is full, all received data are buffered
31
32
33
    count=Serial_IRQ_Info(PORT,RS232_FIFO_RECV); // Investigates, how many characters have been received
34
35
    Msg_WriteWord(count);                       // The number of characters is displayed as message
36
    output=" Characters received by IRQ\r";
37
    Msg_WriteText(output);
38
39
    while(true)
40
    {
41
        sz=Serial_ReadExt(PORT);                // Get value out of receive buffer
42
        if(sz==0x100) break;                    // If the value is 0x100, the receive buffer is empty
43
        Msg_WriteChar(sz);                      // Display received character as message
44
        Serial_Write(PORT,sz);                  // Output received character on the RS232 interface
45
    }
46
    AbsDelay(500);                              // Wait for output to complete
47
                                               // Consider, sending data continues while interrupt is present
48
}

von Dan M. (luizaranha)


Lesenswert?

Hmmm.....wird eigentlich die schleife auch dann nochmal aufgerufen, wenn 
ich z.B. ne Stunde später auch nochmal n byte schicke.... weil das Ende 
Kriterium ja nur für ein Wort gilt ?????

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Daniel Mayr schrieb:

> Bei folgendem Code hab ich schon zwei Fragen:

Die Fragen zeigen, dass du nicht bei diesem Beispiel einsteigen 
solltest, sondern bei einfacheren Beispielen z.B. Serielle Übertragung 
mit Polling statt mit Interrupt.

> Wenn von einem Programm(z.B. Matlab) über die serielle Schnittstelle zum
> Zeitpunkt X ein Byte geschrieben wird, heisst das dann, das der
> Interrupt wieder neu bei der Funktion "Serial_Init_IRQ" beginnt,

Natürlich nicht. Dein Programm oben bewegt sich nach den 
Initialisierungen anwenderseitig innerhalb des Anweisungsblocks des 
while.

> oder
> woher weiss ich wenn die Sache im Interrupt modus arbeitet, ab welcher
> Aktion der code wieder abgearbeitet wird.

Der Interrupt unterbricht deine Anweisungen in der while-Schleife. Nach 
der Unterbrechung geht es aber an der gleichen Stelle weiter.

Während des Interrupts wird ein Empfangspuffer gefüllt, dessen Inhalt 
dann deine Anwesiungen im while lesen können.

Wie gesagt, das ist 1. nicht für Anfänger und 2. sieht man in deinem 
Programm nur ca. 50% des eigentlichen Programms. Viele Funktionen, die 
zum Verständnis hilfreich sind, hast du nicht aufgelistet.

von Dan M. (luizaranha)


Lesenswert?

Hi Stefan,

vielen Dank für die Antwort. Ich gebe offen zu, dass ich davon keine 
Ahnung hab, und das Beispiel eig. zu schwer ist. Aber die Schule lässt 
mir keine andere Wahl.
Deine Ausführungen haben mir schon sehr weiter geholfen.
Ich versteh jedoch nicht, welche Ausführungen fehlen sollen, das is ein 
Demoprogramm... also ein vollständiger Code?!
Hmm.....ich werde mal ein selber programmiertes Code Beispiel 
reinstellen.
1
// 35 byte Sende + Empfungspuffer + 6 byte interne FIFO Verwaltung
2
byte buffer[41]; // globale Variable buffer
3
float PID_output;
4
5
#define PORT 0
6
void InterruptServiceRoutine(void)%wie der Name schon sagt
7
{ int help;
8
  help=0;
9
 if(Serial_IRQ_Info(PORT, RS232_FIFO_RECV)!=0)//wieviele Bytes sind //angekommen?
10
 {
11
        help=Serial_ReadExt(PORT);//den Port auslesen
12
     
13
// Hier könnte COde für die Weiterverarbeitung des Interrupts stehen
14
15
}
16
}
17
byte buffer[41]; // globale Variable buffer
18
void main(void)
19
{
20
21
word data;
22
byte i;
23
i=0;
24
PID_output=0.8;
25
26
Serial_Init_IRQ(0,buffer,20,15,SR_8BIT|SR_1STOP|SR_NO_PAR,SR_BD19200);
27
while(true)
28
Timer_T1PWM(492,PID_output,PS_1);  // PWM starten mit PID_output als //On/off Verhältnis
29
}

3 Fragen:
1.) Wenn die main fkt verlassen wird, hat der uC sein Programm 
abgearbeitet?
2.) Die Pwm läuft jetzt in einer Endlosschleife mit dem Timer. Wenn 
jetzt der Interrupt kommt, springt der controller in die 
InterruptServiceRoutine.
Und dort kann er dann von der RS232 lesen, oder ?
3.) Du hattest gesagt, man frägt den Buffer ab. Könnte ich jetzt für das 
tastverhältnis in der PWM (PID_output) folgenden code schreiben
1
...
2
while(true)
3
PID_output=Buffer[0];
4
Timer_T1PWM(492,PID_output,PS_1);  
5
}
Würde jetzt PID_output immer bei einem empfangenen Byte seinen Wert 
ändern, wenn dieses Byte den Interrupt auslöst?


Danke schon mal für euere Hilfe!! Des hilft hier echt weiter!
gruss Luiz

von Karl H. (kbuchegg)


Lesenswert?

Daniel Mayr schrieb:

Vieles von deinem Code ist unverständlich.
Offensichtlich stützt du dich auf bereits vorhandene Funktionalität, die 
wir hier nicht kennen.

Aber macht nichts. Hier der Versuch deine Fragen so gut es geht zu 
beantworten.

> 1.) Wenn die main fkt verlassen wird, hat der uC sein Programm
> abgearbeitet?

Genau.
Und exakt dazu solltest du es nie kommen lassen. Was dann genau passiert 
kannst du nicht mehr beeinflussen

> 2.) Die Pwm läuft jetzt in einer Endlosschleife mit dem Timer. Wenn
> jetzt der Interrupt kommt, springt der controller in die
> InterruptServiceRoutine.
> Und dort kann er dann von der RS232 lesen, oder ?

So wie ich deinen Code interpretiere: Ja

> 3.) Du hattest gesagt, man frägt den Buffer ab. Könnte ich jetzt für das
> tastverhältnis in der PWM (PID_output) folgenden code schreiben
>
>
1
> ...
2
> while(true)
3
> PID_output=Buffer[0];
4
> Timer_T1PWM(492,PID_output,PS_1);
5
> }
6
>

niemand hindert dich daran. 'Können' tust du immer. Ob es das macht, was 
du erwartest, ist eine andere Frage.
Aber mangels Wissen darüber, was die Timer und RS232 Funktionen machen 
lässt sich das von hier nicht entscheiden.

Übrigens: Du solltest die PWM nur dann neu setzen, wenn du auch wirklich 
ein Zeichen empfangen hast.

> Würde jetzt PID_output immer bei einem empfangenen Byte seinen Wert
> ändern, wenn dieses Byte den Interrupt auslöst?

So siehts wohl aus.

Es ist aber sicher nicht schlau, sich das Zeichen aus buffer zu holen. 
So wie ich das sehe, ist buffer Teil einer FIFO Veraltung. Wo daher 
genau das neue Zeichen gespeichert wird, weißt du nicht.

Aber wenn ich das richtig sehe, dann holt ja Serial_ReadExt(PORT); das 
neue Zeichen ab. Du musst es dir nur noch zurechtlegen, dass es an die 
PWM übergeben werden kann.

von Klaus W. (mfgkw)


Lesenswert?

Wieso nicht einfach hier das gcc-Tutorial durchackern?
Danach sollte man das mit RS232 und Interrupt eigentlich verstanden 
haben.

von Dan M. (luizaranha)


Lesenswert?

Hallo zusammen,
danke für den Tip, werd ich machen.....aber leider drängt die 
Zeit....und deshalb wird s wahrscheinlich noch ein paar dümmere Fragen 
geben.
(Außerdem hab ich daheim nur die Entwicklungsumgebung, und nicht den 
Controller, der steht leider in der Schule... deswegen is des ein bissl 
schwierig.

von Karl H. (kbuchegg)


Lesenswert?

Karl heinz Buchegger schrieb:

> Aber wenn ich das richtig sehe, dann holt ja Serial_ReadExt(PORT); das
> neue Zeichen ab. Du musst es dir nur noch zurechtlegen, dass es an die
> PWM übergeben werden kann.

Wobei ich mich frage, was denn nun das Problem ist.
So wie es aussieht, ist doch im Programm im Eröffnungsposting ohnehin 
schon alles enthalten. Dieses Programm schickt ein erhaltenes Zeichen 
zurpck, du willst es jetzt zum Verstellen einer PWM benutzen. Wo liegt 
jetzt da das Problem?

von Dan M. (luizaranha)


Lesenswert?

das problem liegt darin, dass die Anpassung der PWM nicht funktioniert 
und weiterhin:
Der Controller wird über usb als emultierter COM port betrieben. Wenn 
ich nun im Debug modus bin, kann ich natürlich nicht mit matlab auf den 
gleichen Comport zugreifen, weil der ja durch den Compiler belegt ist.
Und jetzt steh ich vor dem Problem, dass ich als Anfänger meine Zeichen 
von Matlab senden kann, aber natürlich nicht debuggen kann, um zu sehen, 
wie er die zeichen verarbeitet bzw. wie der interrupt läuft...

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Dann musst du dir andere Debugmethoden ausdenken - das ist ein übliches 
Geschäft. Und soviel wie möglich des Debuggens auf dem AVR durch 
Planung/Vordenken beim Programmieren und Simulation auf dem PC ersetzen.

Anderes Debuggen kann im einfachen Fall heissen, ein paar IO-Pins als 
Status-LEDs zu "opfern" und sich dort Debuganzeigen ausgeben zu lassen. 
Eine Anzeige könnte z.B. sein, dass alle Sendungen von Mathlab aus mit 
bestimmten Werten beginnen und/oder enden. Dein AVR prüft auf diese 
Werte und schaltet eine Erfolg-LED oder eine Fehler-LED. Ob sich der AVR 
in der ISR befindet kann man ebenfalls durch eine LED anzeigen lassen. 
Hier kann es dann sinnvoll die Baudrate zu verkleinern, damit das 
Flackern der LED gut sichtbar ist/bleibt.

Wenn du mehr Pins zur Verfügung hast, kann es sich lohnen ein LCD für 
Debugmeldungen anzuschliessen. Ich weiss aber nicht so recht, ob ich dir 
das empfehlen soll, weil du jetzt schon knapp an Zeit bist und 
anscheinend große Teile des Tutorials noch nicht kennst.

von Dan M. (luizaranha)


Lesenswert?

Ja danke mal für die ganzen tollen Antworten, ich bin jetzt mal mit ein 
paar hilfen von der ganzen seite am Programmieren, werde das schon 
irgendwie lösen, die Nacht geht heute drauf und dann meld ich mich 
morgen nochmal.

DANKE und  frohe Weihnachten

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.