Forum: Mikrocontroller und Digitale Elektronik Hardware-Interrupt R8C/13


von Peter (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein kleines Programm geschrieben, dass mir die Daten der 
UART0-Schnittstelle des µC R8C/13 liefert (Über "ri_u0c1").

Wie kann ich das Programm denn so schreiben, dass das Symbol "ri_u0c1" 
einen Interrupt auslöst ? Also etwa so.
1
void main (void)
2
{
3
while (1]
4
{
5
...tu was..
6
}
7
}
8
9
...
10
ri_u0c1 empfängt Daten:
11
Sprung auf:
12
13
Funktion_x //Interrupt wurde ausgelöst
14
{
15
...tu was anderes.
16
}


Ich habe im Datenblatt des µC etwas übder "INT0 interrupt control 
register" gefunden, werde aber nicht so wirklich daraus schlau.

Ich hoffe Ihr könnt mir helfen.

Gruss
Peter

von Peter (Gast)


Lesenswert?

Hat keiner eine Idee ???

Gruss

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Zumindest ich verstehe nicht, wie du mit ri_u0c1 arbeitest, also was du 
schon erfolgreich geschafft hast. Der Pseudocode oben von dem was du 
nicht weisst, hilft da nicht wirklich.

Klassisch kann man auf zwei Arten mit Interrupts arbeiten, die auch im 
Artikel Interrupt beschrieben sind:

1/ Die Zusatzarbeit wird direkt in der Interruptroutine abgearbeitet. 
Das ist nur sinnvoll, wenn die Zusatzarbeit gering ist und die 
Interruptbearbeitung nur unwesentlich verlängert wird. Keinesfalls 
sollte die Bearbeitung so lange dauern, dass Interrupts verloren gehen!

2/ Die Zusatzarbeit wird nicht in der Interruptfunktion abgearbeitet. 
Die Interruptfunktion setzt lediglich ein Flag und in einer periodisch 
abgearbeiteten Funktion/Schleife wird das Flag geprüft.

volatile char flag;

void meine_interrupt_funktion(void)
{
  flag = 1;
}

void main (void)
{
  while (1)
  {
    if (flag == 1)
    {
      flag = 0; // Zurücksetzen
      ...tu was anderes.. z.B. Funktion_x() aufrufen
    }
    else
    {
      ...tu was..
    }
  }
}

von gk (Gast)


Lesenswert?

Also der Innterrupt Handler muss erstmal als solcher deklariert werden.

#pragma interrupt Handler(vect=xx)  xx z.B. 18 für Uart0 Receive Int.

Hier der Handler

void Handler(void)
{
......Do something...

}

Dann muss noch eine Interrupt-Priorität vergeben werden, z.B

s0ric = 0x04;

Eventuell muss noch in irgendeinem Uart Register der Interrupt 
freigegeben werden.

Und dann müssen die Interrupts, zum Beispiel am Anfang des 
Hauptprogramms
freigeben werden:

asm("FST I");

gk

von Peter (Gast)


Lesenswert?

Vielen Dank, ich teste das mal.

von Peter (Gast)


Lesenswert?

Also, ich hab das mal durch getestet, leider ohne Erfolg. Ich hab jetzt 
folgendes mit eingebracht:

Vor der Main Funktion:
1
#pragma interrupt INT_UART0_Rx    // UART 0 Recive Serial interface


...dann die initialiesierung eines Timers und meines Interrupts:
1
void Init_Timer (void)
2
{
3
  asm("FCLR I");//Interrupt ausschalten
4
    /*-------------------------------------------------
5
    -  Setting main cycle timer                       -
6
    -  20 MHz * 1/32 * 1/50 * 1/250 => 50 Hz         -
7
    -------------------------------------------------*/
8
9
    txmr   = 0x00;    //Timer mode for Timer X
10
    prex   = 50-1;    //Set Prescaler X register to 50
11
    tx     = 250-1;  //Set Timer X register to 250         
12
    txck0  = 0;    //Timer Count source = f32
13
    txck1  = 1;
14
    txic  = 0x03;    //Timer interrupt priority level = 7
15
    s0ric   = 0x01;    //UART0 interrupt priority level = 1
16
    txs    = 1;    //Timer X count start flag -> start
17
18
  asm("FSET I");    //Interrupt einschalten
19
}


...und dann die Interruptfunktion als solches:
1
void INT_UART0_Rx (void)
2
{
3
  Out_3_1 = 1;
4
}


Eigentlich soll der µC nur den Port: Out_3_1 setzen, sobald er über den 
UART0_Rx etwas empfängt.  Hab ich vielleicht noch ein Startflag oder so 
etwas vergessen. Würde das denn überhaupt so einfach funktionieren ? Der 
µC empängt aufjedenfall was, weil ich mir die Daten die über die UART0 
kommen auf ein Array anzeigen lasse.

von Olaf (Gast)


Lesenswert?

Mal eine Gegenfrage:

Hast du eigentlich ein Problem damit ueberhaubt einen Interrupt zu 
verarbeiten, oder nur mit dem Interrupt deiner seriellen Schnittstelle?

Hast du z.b schonmal deinen Timer einen IRQ erzeugen lassen und hat der 
deine Funktion erfolgreich aufgerufen?

Olaf

von Peter (Gast)


Lesenswert?

Hallo Olaf,

zu deiner Frage. Ich habe nur das Problem den Interrupt über den UART 
auszulösen. Der Time-Interrupt den ich schon drin habe, funktioniert 
tadellos. Dieser inkementiert eine variable im 50Hz Takt, das kann ich 
beim debuggen beobachten.

Gruss

von Olaf (Gast)


Lesenswert?

> Ich habe nur das Problem den Interrupt über den UART
> auszulösen.

Dann musst du dein Problem selber loesen. :-)

Ich bin mittlerweile vom 13er weg und nehme stattdessen den R8C/29. Ich 
habe gerade mal kurz das Datenblatt des R8C13 ueberflogen und fand das 
Bit das du setzen musst auch nicht auf Anhieb. Aber immerhin gab es 
irgendwo einen Nebensatz aus dem Hervorging das er es gundsaetzlich 
kann.

Hast du schonmal bei Renesas nach Applikationen gesucht? Die produzieren 
doch normaleweise eine Menge Papier und ich moechte wetten das es auch 
etwas ueber die serielle Schnittstelle gibt. Es kann auch sein das du 
die Infos bei anderen Typen wie R8C11, R8C15 oder so findest. Oder lies 
dir mal das Headerfile durch.

Die Vorgehensweise ist ja im prinzip so:

1. Ein Bit in einem Register finden das diesen ganz
   speziellen IRQ auswaehlt.

2. Freischaltung ueber Auswahl des IRQ-Level

3. Generell alle IRQs mit dem I-Bit freischalten.

4. Immer kucken ob es irgendwo ein PRC-Bit im Kleingedruckten gibt. :-)

Olaf

von gk (Gast)


Lesenswert?

Hallo Peter,
ich vermisse in Deinem Code die Definition des Interrupt Vectors.
Entweder musst Du das in der sect30.inc eintragen, was Du ja auch
für den Timerinterrupt getan hast oder durch die Angabe der
Vectornummer bei der Deklaration:

#pragma interrupt INT_UART0_Rx !!!!!! (vect=18) !!!!! siehe oben


Ein Bit zum Freischalten des RX Interrupts habe ich nicht
gefunden nur für das Senden. Stichwort ucon Register
gk

von Peter (Gast)


Lesenswert?

Hallo gk,

gk schrieb:
> Ein Bit zum Freischalten des RX Interrupts habe ich nicht
> gefunden nur für das Senden. Stichwort ucon Register
Dannach habe ich auch schon gesucht und nicht gefunden.


gk schrieb:
> ich vermisse in Deinem Code die Definition des Interrupt Vectors.
> #pragma interrupt INT_UART0_Rx !!!!!! (vect=18) !!!!! siehe oben

Ich hab den gesamten Code auf einen schon vorhandenen Beispielprogramm 
mit Time_X_Interrupt geschrieben, inkl. sect30.inc, und hatte damit 
natürlich zusätzlich keine Definition im Interrupt-Sektor für den UART 
geschrieben. Dies habe ich jetzt nachgeholt und siehe da, es 
funktioniert. Die Interrupt-Funktion reagiert promt auf ein Empfang den 
ich, an einem beliegen Zeitpunkt anstosse (z.B. BTM über Bluetooth 
verbinden, Antwort über UART0: 'Connect') und die Daten (aus dem 
Beispiel 'Connect') die Empfangen werden in einen Array beobachten kann.

Danke für den Tipp.

Gruß

von Peter (Gast)


Lesenswert?

Also, vielleicht habe ich mich doch ein bisschen zu früh gefreut. Das 
wesentliche, dass der UART0-Interrupt reagiert funkioniert ja jetzt. 
Jedoch ist es so als würde der zu langsam sein, da er das eine oder 
andere Zeichen "verschluckt" und nicht anzeigt. Wenn ich jetzt Zeichen 
sende und eine Antwort erwarte, habe ich es dazwischen mit Wartezeiten 
versucht. Dies klappt znur bedingt, da er dafür dann wiederum andere 
zeichen verschluckt.

Eine Idee?

Gruss

von Olaf (Gast)


Lesenswert?

> Jedoch ist es so als würde der zu langsam sein, da er das eine oder
> andere Zeichen "verschluckt" und nicht anzeigt.

Das geht nicht. Oder sagen wir mal lieber so, du bist schuld. :-)

Gib dem IRQ einen hohen Level. Im IRQ packst du alles was reinkommt in 
eine FIFO und das wars!
In deinem restlichen Programm kontrollierst du dann nur ab und an mal ob 
etwa in der Fifo steht und verarbeitest die Daten.

Olaf

von Peter (Gast)


Lesenswert?

Was ist den eine FIFO ?

Der Level liegt auf 1 (Timer-Interrupt auf 7) und die Daten werden jetzt 
direkt in der Interrupt-Funktion in die variable geschrieben. Direkter 
kann ich es doch gar nicht machen, oder ? Trotzdem verschluckt er das 
eine oder andere Char.

Gruss

von Peter (Gast)


Lesenswert?

Schau mal hier:

Vorab, ich sende alle zeichen einzeln.
Ich sende 'at', ein 'at' und dannach ein 'OK' kommen zurücken. Ich sende 
'atp?', ein 'atp?' kommt zurück, ein '0000' müsste auch zurückkommen, zu 
sehen ist aber nur eine '0' und dannanch das 'OK'.

    (Rx_Daten)[0]  97 'a'  000404
    (Rx_Daten)[1]  116 't'  000405
    (Rx_Daten)[2]  13  000406
    (Rx_Daten)[3]  13  000407
    (Rx_Daten)[4]  10  000408
    (Rx_Daten)[5]  79 'O'  000409
    (Rx_Daten)[6]  75 'K'  00040A
    (Rx_Daten)[7]  13  00040B
    (Rx_Daten)[8]  10  00040C
    (Rx_Daten)[9]  97 'a'  00040D
    (Rx_Daten)[10]  116 't'  00040E
    (Rx_Daten)[11]  112 'p'  00040F
    (Rx_Daten)[12]  63 '?'  000410
    (Rx_Daten)[13]  13  000411
    (Rx_Daten)[14]  48 '0'  000412
    (Rx_Daten)[15]  13  000413
    (Rx_Daten)[16]  10  000414
    (Rx_Daten)[17]  79 'O'  000415
    (Rx_Daten)[18]  75 'K'  000416
    (Rx_Daten)[19]  13  000417

Die UART-Interrupt-Funktion sind folgendermaßen aus:
1
void UART0_Rx_int (void)
2
{
3
    //Daten am Empfang (RX) abholen
4
//  while (!ri_u0c1);  //Warten bis Empfangspuffer voll
5
  
6
    Rx_Daten[Global_i] = u0rbl;
7
    RX_Error = u0rbh;  //löscht gleichzeitig ri_u0c1 !
8
    Global_i++;
9
}

von Peter (Gast)


Lesenswert?

Ein Verusch später, erkennt er alle nullen:

    (Rx_Daten)[0]  97 'a'  000404
    (Rx_Daten)[1]  116 't'  000405
    (Rx_Daten)[2]  13  000406
    (Rx_Daten)[3]  13  000407
    (Rx_Daten)[4]  10  000408
    (Rx_Daten)[5]  79 'O'  000409
    (Rx_Daten)[6]  75 'K'  00040A
    (Rx_Daten)[7]  13  00040B
    (Rx_Daten)[8]  10  00040C
    (Rx_Daten)[9]  97 'a'  00040D
    (Rx_Daten)[10]  116 't'  00040E
    (Rx_Daten)[11]  112 'p'  00040F
    (Rx_Daten)[12]  63 '?'  000410
    (Rx_Daten)[13]  13  000411
    (Rx_Daten)[14]  13  000412
    (Rx_Daten)[15]  10  000413
    (Rx_Daten)[16]  48 '0'  000414
    (Rx_Daten)[17]  48 '0'  000415
    (Rx_Daten)[18]  48 '0'  000416
    (Rx_Daten)[19]  48 '0'  000417
    (Rx_Daten)[20]  13  000418
    (Rx_Daten)[21]  10  000419
    (Rx_Daten)[22]  79 'O'  00041A
    (Rx_Daten)[23]  75 'K'  00041B
    (Rx_Daten)[24]  13  00041C
    (Rx_Daten)[25]  10  00041D

Wie kann das denn sein ?

von Peter (Gast)


Lesenswert?

Hab jetzt auch mal die Level-Prios geweechselt und den Timmer_Interrupt 
ganz aus dem Code genommen, doch er "verschluckt" nach wie vor Zeichen.

Hilfe.

von Peter (Gast)


Lesenswert?

Hallo ?

Keiner mehr da ?

von gk (Gast)


Lesenswert?

schon noch da. Habe aber keine Idee. Vielleicht beschreibst Du mal Deine 
verwendete Hardware, vielleicht liegt es jetzt ja daran. Welche 
Entwicklungsumgebung verwendest und welchen Debugger?
gk

von Olaf (Gast)


Lesenswert?

> Keiner mehr da ?

Als ich gelesen habe das du nicht wusstest was eine Fifo ist habe ich 
die Hoffnung verloren. .-)

void UART0_Rx_int (void)
{
    //Daten am Empfang (RX) abholen
//  while (!ri_u0c1);  //Warten bis Empfangspuffer voll

    Rx_Daten[Global_i] = u0rbl;
    RX_Error = u0rbh;  //löscht gleichzeitig ri_u0c1 !
    Global_i++;
}

Das ist ist zwar nicht optimal, grosse Gefahr eines Bufferueberlaufs, 
aber wenn du damit ueberhaubt ein paar Zeichen empfangen kannst, also 
der IRQ jetzt geht dann sollte das funktionieren.

Wenn ich dich richtig versteh dann empfaengst du alles was du empfangen 
willst, aber zusatzlich noch 0x00? Das geht eigentlich nur wenn der IRQ 
ausgeloesst wird wenn keine Daten kommen. Kann es sein das deine 
Hardware Stoerungen empfaengt? Ist das ganze ein Aufbau auf Breadboard 
mit lockeren Kabeln? Stimmen die eingestellten Schnittstellenparameter 
auf beiden Seiten? Also z.B 8N1? Hast du einen Quarz am Prozessor oder 
verwendest gar den internen RC-Oszillator?

Olaf

von Peter (Gast)


Lesenswert?

Olaf schrieb:
> Das ist ist zwar nicht optimal, grosse Gefahr eines Bufferueberlaufs,
> aber wenn du damit ueberhaubt ein paar Zeichen empfangen kannst, also
> der IRQ jetzt geht dann sollte das funktionieren.

Das funktioniert eben mit den Einschränkungen, dass er ein paar Zeichen 
"verliert".

> Wenn ich dich richtig versteh dann empfaengst du alles was du empfangen
> willst, aber zusatzlich noch 0x00?

Richtig, bis auf ein paar Zeichen die er zwischen drin "verliert". 
Zusätzlich sehe ich auch 0x10 und 0x13.

Der µC ist auf einer Euro-Platine gelötet. Der BTM ist auf der selben 
Platine mit Heisskleber befestigt. Die Anschlüsse des BTM's sind per 
Kupterlize an die Platine gelötet, soviel ich weiß habe ich auch 
Kondensatoren zur Entstörung eingebaut. Allerdings sind diese zwischen 
Kupferlitze und Platine, anders ist es nicht machbar (SMD). Also die 
Schnittstellenparameter stimmen auf alle Fälle, mit fehlerhaften 
Parametern bekomme ich nur fehler, schon ausprobiert. Bei den µC 
verwende ich den externen 20MHz-Quarz der mit auf der µC-Platine verbaut 
ist.

1
void UART0_Rx_int (void)
2
{
3
    //Daten am Empfang (RX) abholen
4
//  while (!ri_u0c1);  //Warten bis Empfangspuffer voll
5
6
    Rx_Daten[Global_i] = u0rbl;
7
    RX_Error = u0rbh;  //löscht gleichzeitig ri_u0c1 !
8
    Global_i++;
9
}

...was wäre denn taktisch kluger ???


Also ich hab mir jetzt erstmal damit geholfen, dass ich die Befehle 
(z.B. "atp?") in einer Schleife solange wiederhole, bis der µC in der 
Variable Rx_Daten, per String-Vergleich, ein "OK" findet. Findet er das, 
dann löscht er den Inhalt des Arrays und schickt den nächsten Befehl. 
Zwischen den Zeichen habe ich momentan 0,5s und zwischen einen ganzen 
Befehl 2s pause, damit der BTM etwas Zeit zum reagieren hat.

von Olaf (Gast)


Lesenswert?

> Bei den µC verwende ich den externen 20MHz-Quarz der mit
> auf der µC-Platine verbaut ist.

Ich weiss jetzt nicht welche Takteinstellungen beim R8C13 moeglich 
waren, aber kann es sein das Timer und Uart zwar mit 20Mhz laufen aber 
der Core stark untertaktet wird? Der Prozessor hat jedenfalls 
normalerweise keine Probleme schnell genug auf den Uart zu reagieren und 
sollte das koennen.

Was mir noch einfaellt, kann es sein das du deine Anwendung immer im 
Debugger laufen laesst und Softwarebreakpoints (rote Punkte) anstatt 
Hardwarebreakpoints (blaue Punkte) verwendest? Ich meine das macht den 
Prozessor auch langsamer.

Olaf

von Peter (Gast)


Lesenswert?

Olaf schrieb:
> Ich weiss jetzt nicht welche Takteinstellungen beim R8C13 moeglich
> waren, aber kann es sein das Timer und Uart zwar mit 20Mhz laufen aber
> der Core stark untertaktet wird?

Weiß ich nicht.


> Was mir noch einfaellt, kann es sein das du deine Anwendung immer im
> Debugger laufen laesst und Softwarebreakpoints (rote Punkte) anstatt
> Hardwarebreakpoints (blaue Punkte) verwendest? Ich meine das macht den
> Prozessor auch langsamer.

Ja das ist richtig, ich verwende die Softwarebreakpoints. Kann es dann 
daran liegen warum der µC Zeichen verschluckt ? Die Breakpoint verwende 
ich aber nicht immer, den Debugger schon. Zwischen den Zeichen sind 
genug Pausen eingebaut um die Entwicklung der Arrays zu beobachten.

Ich verwende den KD30-Debugger, integriet in der Entwicklungsumgebung. 
Ich werde mal gucken, ob es dort einen Hardwarebreakpoint gibt.

von gk (Gast)


Lesenswert?

Es könnte durchaus sein, dass der Debugger daran schuld ist, dass 
Zeichen verloren gehen, da er ja auch einen periodischen Interrupt 
benutzt und zum Beispiel die beobachten Variablen in der HEW updatet. 
0x10 und 0x13 ist das Zeilenende, welches Dein angeschlossenes Gerät 
sendet.
Ich würde jetzt mal ohne Debugger arbeiten und die empfangenen Zeichen 
auf UART1 wieder ausgeben und dies mit Hyperterminal, HTerm o.ä, 
beobachten.
gk

von Olaf (Gast)


Lesenswert?

> Es könnte durchaus sein, dass der Debugger daran schuld ist, dass
> Zeichen verloren gehen, da er ja auch einen periodischen Interrupt

Ich muss aber sagen das ich sehr viel mit Uarts entwickel und da 
normalerweise auch den Debugger laufen habe ohne das es jemals gestoert 
hat. Allerdings verwende ich immer Hardwarebreakpoint.
Mir hat aber mal jemand von Glyn erzaehlt das man Softwarebreakpoints
vermeiden sollte. Es kann aber sein das sich das auch nicht auf die
Geschwindigkeit des Programms auswirkt, sondern nur auf die 
Geschwindigkeit beim debuggen. Bei Softwarebreakpoints wuerde ich 
erwarten das der Prozessor jedesmal einen jsr in den Code reinmacht und 
darum oefters das Rom umflashen muss.

Olaf

von Peter (Gast)


Lesenswert?

Ok danke für die Tipps. Ich probier mal die Variante mit den 
zusätzlichen Hyperterminal.

Gruss

von Olaf (Gast)


Lesenswert?

Mir ist gerade noch eingefallen. Der Prozessor hat doch auch die 
Faehigkeit nach jedem Befehl den Debugger aufzurufen. Wenn das fuer 
Softwarbreakpoints genutzt wird, dann wird damit die Ausfuehrung des 
Programms natuerlich erheblich langsamer...

Olaf

von Henrik (Gast)


Lesenswert?

Für den R8C empfiehlt sich eigentlich auch eher diese Forum:
http://www.renesasrulz.com/index.jspa

Da gibts meist schnelle und kompetente Antworten.

von Olaf (Gast)


Lesenswert?

> Da gibts meist schnelle und kompetente Antworten.

DAs Problem ist nur das man da nicht wirklich sein will weil
die Software dort eine Katastrophe ist. Laeuft mit vielen
Browsern nicht richtig, ist total langsam und merkwuerdig
umstaendlich sowieso.

Olaf

von Peter (Gast)


Lesenswert?

Henrik schrieb:
> Für den R8C empfiehlt sich eigentlich auch eher diese Forum:
> http://www.renesasrulz.com/index.jspa
>
> Da gibts meist schnelle und kompetente Antworten.

Das ist ja komplett in Englisch. Ich hab schon schwierigkeiten das ganze 
Thema in deutsch zu verstehen und dann noch in englisch ? Ich kann zwar 
etwas englisch , aber das ist selbst mir zu viel.

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.