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
voidmain(void)
2
{
3
while(1]
4
{
5
...tuwas..
6
}
7
}
8
9
...
10
ri_u0c1empfängtDaten:
11
Sprungauf:
12
13
Funktion_x//Interrupt wurde ausgelöst
14
{
15
...tuwasanderes.
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
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..
}
}
}
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
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.
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
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
> 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
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
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ß
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
> 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
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
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
> 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
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
voidUART0_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.
> 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
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.
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
> 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
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
> 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
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.