PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UART mit dem F330 von SiLabs



Mr Bean
03.06.2009, 15:27
Hallo

Ich hoffe ihr könnt mir weiter helfen. Ich möchte mit dem F330 von SiLabs eine RS232 Kommunikation aufbauen. Ich habe dazu folgendes Programm geschrieben:


#include <c8051F330.h>
#include <stdio.h>

#define SYSCLK 24500000
#define BAUDRATE 115200
#define RX_length 25

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

//bit TX_ready; //True = OK zur Übertragung
//char *TX_ptr; //pointer auf zu übermittelnden String

bit RX_ready; //True = string empfangen
char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen
unsigned char the_char; //zwischenspeicher

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void UART0_ISR (void);
void Print_String (char pstring[]);

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------

void main (void)
{
// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 0; //Interrupts global freigeben
ES0 = 1; //UART0 interrupt freigeben

while (1)
{

}
}


//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}

void UART0_ISR (void) interrupt 4 using 3
{
static unsigned char RX_index = 0; //receive buffer index
unsigned char the_char; //zwischenspeicher

Print_String ("In ISR..."); //Debugausgabe auf UART
RI0 = 0;
if (RI0=1)
{

the_char = SBUF0;
RX_buf[RX_index] = the_char; //Byte in array speichern


if(RX_index < (RX_length-2))
{
RX_index++;
}
else
{
RX_index = 0;
RX_ready = 1;
RX_buf[RX_index-1] = '\0';
}


}
}

void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring[i])
{
putchar(pstring[i++]);
}
}


Das Senden eines Strings funktioniert auch schon gut. Ich möchte nun aber auch einen String einlesen, speichern und je nach dem was für Kommandos angekommen sind eine Aktion ausführen.
Im Moment sieht es so aus als wenn der Controller nicht einmal in die UART ISR springt. Um das zu überprüfen gebe ich den Text "In ISR..." aus. Der Text wird ausgegeben wenn ich in main das Bit RI0 manuell setze. Eigentlich sollte das Bit automatisch gesetzt werden wenn ein byte vom PC empfangen wurde. :-k
Wie gesagt, das Senden von Text an den PC funtkioniert. Liegt also denke ich nicht an der Baudrate oder gleichen. Probier jetzt schon ne ganze Weile rum, komme aber nicht weiter. Hoffe ihr habt eine Idee.

Grüße!

Bean

sast
03.06.2009, 16:21
RI0 = 0;
if (RI0=1)
{ ...

wie soll da RI0 jemals 1 sein, wenn du es vorher auf 0 setzt? Außerdem ist in C der Vergleich ==

sast

edit:
Versuche es doch erst mal ohne Interrupt mit



sfr SBUF = 0x99;
sbit RI = 0x98;

char nb_getkey ()
{
char c;
int i;

while(!RI && i++<100);
if(RI)
{
c = SBUF;
RI = 0;
}
else
c = '\3';
return (c);
}
char b_getkey ()
{
char c;

while (!RI);
c = SBUF;
RI = 0;
return (c);
}


und Aufruf von b_getkey() oder nb_getkey() in der while(1){}. Ich bin mir nicht mehr sicher, ob du nicht auch EA=1 setzen musst. Ist schon mind. 4 Jahre her, dass ich was mit dem F300 gemacht hatte. Ich hoffe die defines stimmen, ansonsten anpassen.

Und das print würde ich aus der Interruptroutine nehmen.

johns
04.06.2009, 01:51
hallo,

ev. hilft das weiter:
http://read.pudn.com/downloads35/sourcecode/embed/109928/C8051F02X%E7%B3%BB%E5%88%97%E5%B8%A6%E6%B3%A8%E9%8 7%8AC%20%E4%BE%8B%E7%A8%8B/UART0_Int1/UART0_Int1.c__.htm ab zeile 194

lg

Mr Bean
04.06.2009, 07:19
Guten Morgen!

Danke für die Antworten!
@sast:
Ich setzte RI0 ja erst in der ISR wieder auf 0. Das muss ich ja auch weil das Bit ja nicht von der Hardware zurückgesetzt wird oder? In main warte ich in der whileschleife auf einen Interrupt. Wenn der kommt gehe ich zu UART_ISR. Dort setzte ich das Bit zurück. So war mal mein PLan. Du hast recht, so komme ich nie in die if Schleife, aber in die ISR sollte ich so schon kommen. Und den String gebe ich ja vor der if Schleife aus. Kann natürlich sein dass ich falsch liege.
EA hab ich auch auf 1 gesetzt.

@johns:
Danke für den Link, das Dokument kenne ich auch schon. Hat bei mir aber so auch nicht funktioniert, denke das liegt daran dass dieses C-Beispiel für einen anderen (kleineren) Prozessor von SiLabs ist.

Vielleicht habt ihr ja noch ein paar Ideen, ich versuch derweil mal weiter.

MFG

Bean

Peter1060
04.06.2009, 07:52
moin moin,

>>EA = 0; //Interrupts global freigeben
>> ES0 = 1; //UART0 interrupt freigeben

falsch, EA muß auch 1 sein, bei 0 wird gesperrt!

>>In main warte ich in der whileschleife auf einen Interrupt.
>>Wenn der kommt gehe ich zu UART_ISR

was soll denn das werden? Entweder Polling von RI und dann Zeichen von UART abholen oder die ISR schiebt das Zeichen von der UART in den Rx-Buffer.

>>Beispiel für einen anderen (kleineren) Prozessor
da alle 8051ziger bei UART gleich arbeiten spielt der Prozessor keine Rolle.

mfg
Peter

Mr Bean
04.06.2009, 08:06
Hallo

Ja da hast natürlich recht, die Interrupts muss ich mit 1 global freigeben. Da hat sich bei dem Rumprobieren wohl eine 0 eingeschlichen. Bringt aber auch keine Änderung. Außer dass ich, wenn ich die Interrupts global freigebe und danach ES0=1 setzte sofort in die ISR gesprungen wird. Das erkenne ich daran dass auf meinem Terminal ständig "In ISR...." ausgegeben wird. Kommentiere ich diese Zeile mit ES0 aus, passiert das nichtmehr, ich komme dann aber auch nicht in die ISR wenn ich ein Zeichen an den Controller schicke... :-k

Die SFR können doch schon von Controller zu Controller unterschiedlich sein oder?

Grüße!

Bean

Mr Bean
04.06.2009, 08:18
Was ich mir ja auch noch vorstellen könnte ist dass die interrupt quelle (interrupt 4 using 3) nicht passt. Das wurde nämlich von mir auch aus dem C-example übernommen. Wisst ihr da noch was?

Grüße!

Bean

Peter1060
04.06.2009, 08:46
moin moin,

SFR..nur wenn 2 UARTS drin sind.
Probiere mal eine reine Echofunktion.
Bin allerdings Assemblerfreak, in C muss nicht alles stimmen:

(all init)
loop:
while !(RI); //warte auf zeichen
Tx = 0; // Tx auf leer setzen
SBUF = SBUF; //umladen von Rx nach Tx und senden
goto loop;

Nun sollte alle Zeichen am Terminal als Echo erscheinen.

mfg
Peter

Peter1060
04.06.2009, 08:52
Nachtrag:
REN=1; // Set REN of SCON to Enable UART Receive

sast
04.06.2009, 11:11
Also dein interrupt 4 stimmt schon mal, wenn man dem Datenblatt (Seite 90)glauben kann. Mit dem using von Registerbanken kenne ich mich nicht aus, da nie benutzt.

Wie auch Peter geschrieben hat, noch mal der Hinweis, es erst mal ohne Interrupt zu versuchen. Taste dich langsam ran. Hab ja weiter oben den Code für meine F300 reingestellt.

Hast du überhaupt das Datenblatt zum F330 von Silabs? Da steht eigentlich alles drin was du wissen musst. Wenn nicht dann lad es dir von www.silabs.com mal runter. Ohne wirst du den nicht beherrschen.

Zu deinem Code vom Anfangscode ist mir noch was aufgefallen:

...else
{
RX_index = 0;
RX_ready = 1;
RX_buf[RX_index-1] = '\0';
...

Wieviel ist denn 0-1 bei unsigned char? So ein Controller arbeitet schön der Reihe nach durch, wenn er nicht gerade von einem Interrupt unterbrochen wird. Du solltest also zuerst den String abschließen und dann den Index zurücksetzen. Das ist genau wie bei deiner RI Abfrage. Wenn du immer vorher den Wert von Hand neu setzt musst du ihn doch danach nicht abfragen ;-)

sast

Mr Bean
04.06.2009, 13:50
hmm also ich hab jetzt nochmal folgenden Code ausprobiert:


#include <c8051F330.h>
#include <stdio.h>

#define SYSCLK 24500000
#define BAUDRATE 115200
#define RX_length 25

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

//bit TX_ready; //True = OK zur Übertragung
//char *TX_ptr; //pointer auf zu übermittelnden String

bit RX_ready; //True = string empfangen
char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen
unsigned char the_char; //zwischenspeicher

sfr SBUF = 0x99;
sbit RI = 0x98;

//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void UART0_ISR (void);
void Print_String (char pstring[]);
char nb_getkey ();
char b_getkey ();

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------

void main (void)
{
// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
//ES0 = 1; //UART0 interrupt freigeben

while(1)
{
nb_getkey ();
b_getkey ();
}
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}

/*
void UART0_ISR (void) interrupt 4
{
static unsigned char RX_index = 0; //receive buffer index
unsigned char the_char; //zwischenspeicher

Print_String ("In ISR..."); //Debugausgabe auf UART
//RI0 = 0;
if (RI0==1)
{

the_char = SBUF0;
RX_buf[RX_index] = the_char; //Byte in array speichern


if(RX_index < (RX_length-2))
{
RX_index++;
}
else
{
RX_index = 0;
RX_ready = 1;
RX_buf[RX_index-1] = '\0';
}


}
}
*/
void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring[i])
{
putchar(pstring[i++]);
}
}

char nb_getkey ()
{

char c;
int i;

Print_String ("In nb_getkey...");

while(!RI && i++<100);
if(RI)
{
c = SBUF;
RI = 0;
}
else
c = '\3';
return (c);
}
char b_getkey ()
{

char c;

Print_String ("In b_getkey...");

while (!RI);
c = SBUF;
RI = 0;
return (c);
}

Da wird wenn ich den Controller starte jeweils einmal in nb_getkey und einmal in b_getkey gesprungen. Ich lass mir das jeweils auf dem Terminal ausgeben. Aber Zeichen kann ich so nicht empfangen. :-k
Mit der Abfrage hast recht, das muss ich noch ändern.
Aber im Moment will ich eigentlich nur mal ein Zeichen aus Sbuf auslesen... 8-[

Grüße!

Bean

sast
04.06.2009, 14:57
Ich weiß nicht ob SBUF und RI bei dir die gleichen Register sind wie beim F300. Dazu musst du schon mal etwas in deiner Dokumentation schnüffeln. Im Datenblatt hatten die den UART0 auch immer mit RI0 betitelt (siehe Seite 90). Die Definition könnte auch in der Headerdatei zu deinem Kontroller stehen. Also nimm lieber die aus dem Header. Mein Code war nur als Beispiel gemeint.
sfr SBUF = 0x99;
sbit RI = 0x98;
sollten bei dir dann eigentlich nicht nötig sein.

nb_ bedeutet nicht blockierend und b_ logischerweise blockierend.
Du benötigst nur eins von beiden, je nach deiner Strategie.

Er läuft also in der main bis b_getkey und hängt dann dort für alle Ewigkeit bis das der Strom euch scheidet.

Das letzte was du siehst sollte also erst mal In b_getkey... sein.

Wenn du bis dahin kommst läuft dein Programm soweit. Die Funktionsrückgaben solltest du dann in der main in einem Print ausgeben.

Aber als erstes sollten deine SFR richtig zugewiesen sein. Sonst kommt da nie was an und natürlich muss auch hardwaremäßig an P0.5 was wackeln. Hast du das mal überprüft? Portseitig muss man da ja nichts weiter einstellen, wenn ich mich recht erinnere. Nur der Crossbar sollte passen. Das musst du aber alleine Überprüfen. Ich kann nur immer wieder betonen: Datenblatt lesen!

PS: es kann sein, dass es eine Funktion getkey() bereits gibt. Wenn ja dann sieh bitte dort mal nach, welche Register die genommen haben, das geht meist am schnellsten

sast

Mr Bean
04.06.2009, 15:40
Hallo
Ja die SFR hab ich schon kontrolliert. Das passt. Ich hab jetzt auch einfach für RI gleich RI0 geschrieben, dann brauch ich die Definition am Anfang ja nicht. SBUF0 passt auch mit 0x99.
Hab das Datenblatt schon gelesen. ;-) Das Problem liegt glaube ich eher in der Programmierung mit C.
Wie gebe ich die Funktionsrückgabe in main aus? Einfach mit printf(c); ?
Die Rückgabe ist doch c oder? In b_ steht ja "return (c);".
Pin 0.5 hab ich mit dem Oszi kontrolliert. Der wackelt.
Danke schonmal!

Grüße!

Bean

sast
04.06.2009, 17:35
Genau



...
unsigned char c;
...
while(1)
{
c = b_getkey();
printf("%c\n", c);//oder putchar(c);
}
...


Du musst dir nur verinnerlichen, dass das c aus der Funktion b_getkey() nicht das ist, welches global gilt. Deshalb hab ich es noch mal explizit in die Codetags mit aufgenommen.

sast

Mr Bean
05.06.2009, 07:04
Hmm wenn ich das so mache, bekomme ich einen Feher: "illegal pointer conversion". :-(
Dachte eigentlich auch so müsste das funktionieren... :-(

Grüße Bean

sast
05.06.2009, 08:09
Ja weil printf() als erstes Argument einen FormatString erwartet. Habs oben angepasst.

sast

PS: Falls du mit der Keil Software C51 arbeitest, gibts auch schon die _getkey() Funktion, die genau das selbe macht wie mein b_getkey().



_getkey
Summary: #include <stdio.h>
char _getkey (void);
Description: The _getkey function waits for a character to be received
from the serial port.
NOTE
This routine is implementation-specific, and its function may
deviate from that described above. Source is included for
the _getkey and putchar functions which may be modified to
provide character level I/O for any hardware device. Refer
to “Customization Files” on page 150 for more information.
Return Value: The _getkey routine returns the received character.

Mr Bean
05.06.2009, 08:48
Also mit:


while(1)
{
c= nb_getkey ();
putchar(c);
}

Bekomme ich wenn ich über das Terminal etwas sende auch etwas zurück. Aber meistens Leerzeichen oder anderen Datenmüll...
Aber das ist ja schonmal ein Anfang...
Ich verwende nicht den Keil, sondern die original IDE von SiLabs. Als Compiler hab ich den Keil aber eingebunden.
Was noch komisch ist, ist dass der Controller wohl ständig noch irgendwas sendet. Ich hab eine LED an Tx und die leuchtet eigentlich durchgehend.
Ich weiß aber nicht was das noch sein könnte... :-(

Grüße!

Bean

sast
05.06.2009, 09:00
Wenn du ständig putchar() aufrufst muss er ja auch was senden. Wie ich oben schon gesagt hatte, ist nb_getkey() nichtblockierend. Nutze doch einfach mal die stdio.h Funktion _getkey. Die ist blockierend und dein putchar() sendet nur noch wenn der RX auch was bekommt.

Wie hast du denn die LED angeschlossen? An TX und VCC?

sast

Mr Bean
05.06.2009, 09:21
Naja die LED ist irgendwie in meinem Interface zwischen USB und RS232 angeschlossen. Wie weiß ich nicht.
das mit _getkey versuch ich jetzt mal noch.
Danke schonmal!

Grüße!

Bean

sast
05.06.2009, 09:37
Wie?
Du kannst mit dem Oszi ein Signal messen, aber was auf der anderen Seite an der LED liegt kannst du nicht messen?
Verwirrt ich bin ;o)

sast

Mr Bean
05.06.2009, 09:56
Naja mit dem Oszi messe ich direkt ab dem Controller. Die Led sitzt in einem kleinen USB>>RS232 umsetzer. Da komm ich nicht ran ich seh sie nur ;-)

Die _getkey() funktion will bei mir nicht funktionieren. Ich muss jetzt mal blöd fragen was der Unterschied zwischen blockierend und nicht blockierend ist. Ich versteh nicht so ganz was da blockiert wird... :-(

Grüße!

Bean

sast
05.06.2009, 10:20
ok dann benutzt du die b_getkey()

blockierend heißt einfach, dass die Funktion solange wartet bis ein Zeichen über die UART Schnittstelle reinkommt. Bei der nichtblockierenden Funktion wird nach einer vorgegebenen Wartezeit die Funktion verlassen, auch wenn da nichts vom UART kam.

sast

Mr Bean
05.06.2009, 14:23
naja wenn ich b_getkey verwende, tut sich wieder gar nichts. Lediglich bei nb_getkey bekomme ich eine Antwort wenn ich etwas sende. Das sieht aber eher nach Datenmüll aus...
Wenn ich b_getkey verwende komme ich zwar in die Funktion:

char b_getkey ()
{

char c;
Print_String ("In b_getkey...");
while (!RI0);

c = SBUF;
RI0 = 0;
return (c);
}

In diesem Fall wird "In b_getkey..." einmal auf dem Terminal ausgegeben. Dann hänge ich denke ich in der folgenden while Schleife... :-(

Meine main sieht jetzt so aus:


void main (void)
{
unsigned char c;

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
//ES0 = 1; //UART0 interrupt freigeben

while(1)
{
c= b_getkey ();
putchar(c);
}
}

Was könnte das noch sein? Ich verzweifle so langsam... Mit den AtMegas hat das ganze irgendwie besser und einfacher funktioniert... ;-)

Grüße!

Bean

sast
05.06.2009, 17:25
Das er bis zum print_string(...) kommt ist doch schon mal gut. Anschließend kommt er zur while(!RI0); und wartet dort, bis du ihm ein Zeichen über RX fütterst.

Da du am Eingang P0.5 was gemessen hast, was wie ein gesendetes Zeichen aussieht und b_getkey() eigentlich funktionieren müsste, liegt jetzt nur noch der PIN I/O und die Crossbar dazwischen.

Kannst du nochmal den kompletten Code so wie er jetzt ist posten?

sast

Mr Bean
08.06.2009, 07:19
So, guten Morgen!

Also hier nun noch der komplette code:


#include <c8051F330.h>
#include <stdio.h>

#define SYSCLK 24500000
#define BAUDRATE 115200
#define RX_length 25

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

//bit TX_ready; //True = OK zur Übertragung
//char *TX_ptr; //pointer auf zu übermittelnden String

bit RX_ready; //True = string empfangen
char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen
unsigned char the_char; //zwischenspeicher

sfr SBUF = 0x99;


//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void UART0_ISR (void);
void Print_String (char pstring[]);
char nb_getkey ();
char b_getkey ();

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------

void main (void)
{
unsigned char c;

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
//ES0 = 1; //UART0 interrupt freigeben

while(1)
{
c= b_getkey ();
putchar(c);
}
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}

/*
void UART0_ISR (void) interrupt 4
{
static unsigned char RX_index = 0; //receive buffer index
unsigned char the_char; //zwischenspeicher

Print_String ("In ISR..."); //Debugausgabe auf UART
//RI0 = 0;
if (RI0==1)
{

the_char = SBUF0;
RX_buf[RX_index] = the_char; //Byte in array speichern


if(RX_index < (RX_length-2))
{
RX_index++;
}
else
{
RX_index = 0;
RX_ready = 1;
RX_buf[RX_index-1] = '\0';
}


}
}
*/
void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring[i])
{
putchar(pstring[i++]);
}
}

char nb_getkey ()
{

char c;
int i;

//Print_String ("In nb_getkey...");

while(!RI0 && i++<100);
if(RI0)
{
c = SBUF;
RI0 = 0;
}
else
c = '\3';
return (c);
}
char b_getkey ()
{

char c;
Print_String ("In b_getkey...");
while (!RI0);

c = SBUF;
RI0 = 0;
return (c);
}


Ja kann natürlich sein dass das an der Crossbar liegt... :-k
Aber ich wüsste nicht woran... :-k

Grüße

Bean

Mr Bean
08.06.2009, 10:41
So, ich kann jetzt mit dem oben geposteten Code Zeichen an den Controller senden und bekomme diese auch wieder von dem Controller zurück. Es ist ein etwas seltsames Problem. Wenn ich das Programm über den grünen Knopf in der Silicon Labs IDE starte, dann tut sich gar nichts auf der Schnittstelle. Wenn ich dann aber nur die USB Verbindung meines Toolsticks trenne und wieder neu anstöpsel, also quasie ein Hardwarereset mache, dann funktioniert das ganze Spielchen... 8-[
Habt ihr mir da eine Idee woran das noch liegen kann? Jetzt will ich mich dann aber doch noch an der UART mit Interrupt versuchen...

Grüße und Danke!

Bean

sast
08.06.2009, 11:10
So na gut
gerade wollte ich dir noch ein paar Tipps geben, wie du deine Hardware checken musst, da ich in der Software nichts auffälliges gefunden hatte.

Der Programmieradapter kann natürlich das Verhalten des UART beeinflussen. Man kann auch sonst nicht einfach zwei Sender parallel am UART betreiben. Dafür müssen sie über Dioden getrennt werden.

Das mit dem Interrupt sollte eigentlich auch kein Problem sein, wenn du nicht vergisst den Interrupt auch einzuschalten.

Mal noch was zum PXMDIN wenn du ein bestimmtes Pin auf Null setzen willst, dann geht das nicht, in dem du einfach alle anderen auf 1 oderst. Du muss den Pin direkt auf Null setzen. Bei deinem P1.4 wäre das
P1MDIN &= ~0x40;// Configure P1.4 as analog input

sast

Mr Bean
10.06.2009, 14:42
Hallo

Ich wollte jetzt noch das mit dem Interrupt ausprobieren. Das funktioniert aber leider auch nicht... :-( Hab den meisten Code aus der AN122.
Ich hab so das Gefühl als wenn der Controlller gar nicht in die ISR kommt. Ich hab mir wieder so eine Debug Ausgabe gemacht. Aber auf dem Terminial sehe ich nichts... :-(

Hie mal mein jetziger Code:


#include <c8051F330.h>
#include <stdio.h>

#define SYSCLK 24500000
#define BAUDRATE 115200
#define RX_length 25

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

//bit TX_ready; //True = OK zur Übertragung
//char *TX_ptr; //pointer auf zu übermittelnden String

bit RX_ready; //True = string empfangen
char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen
unsigned char the_char; //zwischenspeicher

sfr SBUF = 0x99;


//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void UART0_ISR (void);
void Print_String (char pstring[]);
char nb_getkey ();
char b_getkey ();

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------
void main (void)
{
unsigned char c;

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
//ES0 = 1; //UART0 interrupt freigeben

while(1)
{
while (RX_ready == 0);

putchar(the_char);
}
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}


void UART0_ISR (void) interrupt 4 using 3
{

static unsigned char RX_index = 0; //zwischenspeicher
unsigned char the_char;



if(RI0 == 1)
{
Print_String ("In ISR..."); //Debugausgabe auf UART
RI0 = 0;
if(RX_ready != 1)
{
the_char = SBUF0;
if (the_char != '\#')
RX_buf[RX_index] = the_char;
if(RX_index < (RX_length -2))
{
RX_index++;
}
else
{
RX_index = 0;
RX_ready = 1;
RX_buf[RX_index-1] = '\0';
}
}
}

}


void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring[i])
{
putchar(pstring[i++]);
}
}

/*
char nb_getkey ()
{

char c;
int i;

//Print_String ("In nb_getkey...");

while(!RI0 && i++<100);
if(RI0)
{
c = SBUF;
RI0 = 0;
}
else
c = '\3';
return (c);
}
char b_getkey ()
{

char c;
//Print_String ("In b_getkey...");
while (!RI0);

c = SBUF;
RI0 = 0;
return (c);
}
*/

Kannst mir da auch noch irgendwie weiter helfen @sast? Alle Anderen dürfen natürlich auch helfen ;-)

Grüße!

Bean

sast
10.06.2009, 15:04
Moin,

zum Interrupt: Du musst natürlich ES0 auch wieder einschalten.

Das RI0 = 0; würde ich ganz zum Schluss in der Routine verwenden.

Hast du mal den letzten Teil meine letzten Beitrages durchgelesen.

sast

Mr Bean
10.06.2009, 15:20
Ja hab ich gelesen. Aber die KOnfiguration der Ports kommt so aus dem Config Tool von SiLabs raus. Darum hab ich das so genommen.

Du meinst ES0 direkt nach den globalen Interrupts freigeben?


Grüße

Bean

sast
10.06.2009, 15:46
Danach oder davor, wie du willst, hauptsache du erlaubst ihm den UART-Interrupt

Und du solltest dein rx_ready auch wieder auf 0 setzen nach dem Ausgeben, wenn du noch mehr empfangen willst.

PS: Vergiss nicht dein Programmieradapter

sast

Peter1060
11.06.2009, 20:16
moin moin,

also im Pollin-Modus geht senden und empfangen, im Interrupt-Modus gehts nicht.
Wenn Du das Datenblatt liest, wirst Du feststellen, der UART-Interrupt kommt dann wenn:
Ri: es wurde ein Zeichen empfangen
Ti: der Sendepuffer wurde leer
In der UART-ISR muss daher geprüft werden welches Ereignis den Interrupt ausgelöst hat. Senden willst Du ohne Interrupt, jedoch der Empfang soll in der ISR erfolgen. Die ISR muss dann so aussehen:
- ist Ti gesetzt gleich wieder raus
- ist Ri gesetzt, Ri löschen, Zeichen abholen und im Puffer ablegen.
Sende nicht innerhalb der ISR über Tx neue Zeichen, gebe lieber über einen Port mit LED den Zustand an.

Mit Gruß
Peter

sast
11.06.2009, 23:36
Hi Peter,

in der ISR fragt er ja schon nur den RI0 ab. Beim TI macht er gar nichts.

Mit der UART Ausgabe in der Routine gebe ich dir recht. Sollte da nicht rein. Vielleicht gehts ja jetzt schon. Oft erfährt man das ja dann zum Schluß nicht, weil das Interesse am Schreiben nachläßt, wenn man die Lösung hat.

Im Moment sehe ich jedenfalls nicht, wo es noch hängen sollte.

Gute Nacht
sast

Mr Bean
16.06.2009, 07:49
Hallo

Vielen Dank für die Antworten! Die Lust am Schreiben hat noch nicht nachgelassen. Nur die Zeit hat gefehlt...
Leider funktioniert das ganze immernochnicht... :-( Ich habe das senden aus der ISR raus genommen. und habe in main jetzt nur noch stehen:


void main (void)
{

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
ES0 = 1; //UART0 interrupt freigeben
RI0=0;

while(1)
{
while (RX_ready == 0);

putchar(the_char);
the_char = 0;

}

}

Trotzdem will das ganze noch nicht so... so langsam weiß ich auch nichtmehr woran das noch liegen kann...
Habe auch schon versucht wie sich das ganze verhält wenn ich den Controller ohne das Interface betreibe. Das brachte leider auch kein anderes Ergebniss...

Grüße!

Bean

sast
16.06.2009, 08:57
Da du an verschiedenen Stellen Änderungen vornimmst, hat es wenig Sinn nur einen Teil des Codes zu posten. Leider kann ich nur theoretische Überlegungen anstellen, da mir die Hardware zum Testen fehlt. Aber wenn es ohne ISR ging dann muss es auch mit funktionieren.

Außerdem hatte ich dir ja weiter oben schon gesagt, dass du nicht vergessen sollst das RX_ready wieder auf 0 zu setzen wenn du putchar aufgerufen hast, sonst sendet der immer wieder the_char da RX_ready aus der ISR auf 1 gesetzt wurde.

Wenn du den restlichen Code noch so hast wie bisher, dann hast du auch 2 unabhängige Variablen the_char. Die in der ISR deklarierte ist nämlich eine andere als die globale. D.h. selbst wenn deine ISR mal funktioniert wirst du in the_char für das putchar nie was empfangenes drin haben. Verstehst du den Unterschied zwischen lokalen und globalen Variablen? Variablen die im normalen Programmablauf und in einer ISR verwendet werden müssen als volatile deklariert werden.

Pass das Programm mal an und reduziere die ISR auf das Setzen des RX_ready (wird auch im main() und in der ISR verwendet) und das RI0 rücksetzen und das SBUF0 in the_char Schreiben.

Die 3 Funktionen können auch erst mal weg. Da haben wir dann nur noch den relevanten Code und versuchen uns mal ranzutasten.
Ein Zeichen empfangen und zurücksenden mit RX-ISR

sast

Mr Bean
16.06.2009, 09:34
Hallo

Vielen Dank! Jetzt funktioniert es. Lag zum einen daran dass die Variable nicht als Volatile deklariert war #-o .
Darauf hätte ich auch kommen können. Zum anderen hab ich jetzt mal noch das mit dem Array aus der ISR genommen. Also wirklich nur die Variable the_char beschrieben.
Ich würde jetzt aber schon noch gerne mehrere Strings in ein Array schreiben bis ein bestimmtes Zeichen kommt. Werde das jetzt dann mal noch in Angriff nehmen. Werde dann wieder fragen... 8-[ :-)

Hier mal noch mein aktueller Code:

#include <c8051F330.h>
#include <stdio.h>

#define SYSCLK 24500000
#define BAUDRATE 115200
#define RX_length 25

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

//bit TX_ready; //True = OK zur Übertragung
//char *TX_ptr; //pointer auf zu übermittelnden String

bit RX_ready; //True = string empfangen
char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen

volatile unsigned char the_char; //zwischenspeicher


sfr SBUF = 0x99;


//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void UART0_ISR (void);
void Print_String (char pstring[]);
char nb_getkey ();
char b_getkey ();

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------
void main (void)
{

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
ES0 = 1; //UART0 interrupt freigeben
RI0=0;

while(1)
{
while (RX_ready == 0);

putchar(the_char);
RX_ready = 0;

}

}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}


void UART0_ISR (void) interrupt 4 using 3
{

static unsigned char RX_index = 0; //zwischenspeicher

if(RI0 == 1)
{
if(RX_ready != 1)
{
the_char = SBUF0;
/*if (the_char != '\#')
RX_buf[RX_index] = the_char;
if(RX_index < (RX_length -2))
{
RX_index++;
}
else
{
RX_index = 0;
RX_ready = 1;
RX_buf[RX_index-1] = '\0';
}*/
RX_ready = 1;

}
RI0 = 0;
}

}


void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring[i])
{
putchar(pstring[i++]);
}
}

Grüße!

Bean

Mr Bean
16.06.2009, 13:53
So, hallo ich bins nochmal.

Ich hab den Code jetzt etwas umgeändert um die Zeichen in ein Array zu schreiben. Das Schreiben scheint auch zu funktionieren, da ich über Debugausgaben herasugefunden hab dass er diese Schleife in der ISR abarbeitet. Allerdings soll der Inhalt des Arrays in main an den PC geschickt werden. Das funktioniert leider nicht... :-(

Hier mal mein aktueller Code für die Variante mit dem Array:


#include <c8051F330.h>
#include <stdio.h>

#define SYSCLK 24500000
#define BAUDRATE 115200
#define RX_length 25

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

//bit TX_ready; //True = OK zur Übertragung
//char *TX_ptr; //pointer auf zu übermittelnden String

bit RX_ready; //True = string empfangen

volatile char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen

volatile unsigned char the_char; //zwischenspeicher


sfr SBUF = 0x99;


//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void UART0_ISR (void);
void Print_String (char pstring[]);
char nb_getkey ();
char b_getkey ();

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------
void main (void)
{

int i;
// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
OSCILLATOR_Init (); // Initialize Oscillator
PORT_Init(); // Initialize Port I/O
UART0_Init (); // Initialize UART0

EA = 1; //Interrupts global freigeben
ES0 = 1; //UART0 interrupt freigeben
RI0=0;

while(1)
{
if (RX_ready != 0)
{
for(i=0;putchar(RX_buf[i])!='\0';i++);
RX_ready = 0;
}


}

}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}


void UART0_ISR (void) interrupt 4 using 3
{

unsigned char RX_index = 0; //zwischenspeicher

if(RI0 == 1)
{

if(RX_ready != 1)
{
the_char = SBUF0;

if(the_char != '\n' && ( RX_index < (RX_length-1)) )
{

RX_buf[RX_index] = the_char;
RX_index++;
RI0 = 0;
}
else
{
RX_buf[RX_index] = '\0';
RX_index = 0;
RX_ready = 1;
RI0 = 0;
}
}

}

}


Grüße!

Bean

sast
16.06.2009, 17:53
Dein RX_index wird bei jedem Interruptaufruf auf 0 gesetzt.
Und wenn du in den else Zweig kommst, wird zwar endlich mal RX_ready aufgerufen, aber du setzt ja vorher den String auf \0

sast

Mr Bean
17.06.2009, 07:23
Hmm... ja stimmt. Ich will eigenltich als letztes Zeichen nach dem String \0 eintragen. Aber das funkioniert ha nicht wenn ich RX_index immer auf 0 setze. Hab das geändert.

Wie kann ich den Inhalt eines Arrays ausgeben? Funktioniert das mit printf("%c\n",RX_buf); ? Oder muss ich das in einer Schleife mit putchar machen?

Grüße!

Bean

sast
17.06.2009, 07:54
Also die einfachen Sachen solltest du schon allein hinbekommen. Wegen den Formatparametern kannst du ja auch mal ins C51.pdf schauen, was sicher deinem Keilkompiler beiliegt.

Ansonsten tuts auch nicht weh, wenn man mal was ausprobiert, was dann nicht geht. So schnell kann man die Dinger nicht kaputtprogrammieren ;o)

sast

Mr Bean
18.06.2009, 11:31
Hallo

Also ich hab das jetzt alles soweit hin bekommen. Und kann die Eingaben jetzt auch in dem Array (RX_buf) speichern und mit strtok separieren. Ich will die einzelnen Strings die ich mit strtok separiert hab jetzt jeweils in eine eigene Variable speichern. Habt ihr mir da einen Tipp wie ich das hin bekomme? Hier fehlt mir schon eine grundlegende Idee... :-(

Hier mal noch der entsprechende Code:


if (RX_ready != 0)
{
char * pch;
pch = strtok (RX_buf," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ");
RX_ready = 0;
}

Vielen Dank schonmal!

Grüße!

Bean

sast
18.06.2009, 12:34
Gibt es eine maximale Länge der Teilstrings?
Oder sind es am Ende sogar Werte, die in andere Typen gespeichert werden sollen?

Mr Bean
18.06.2009, 14:09
Genau das ist mein Problem, am Ende wird soetwas auf das UART übertragen:

11 g temp

Das steht dann wieder für <Adresse> <g=get> <temp=temperatur>.
ich muss diese 3 Strings also irgendwie separieren und entsprechend abfragen.
Mit strcmp ist es mir jetzt schon gelungen zwischen get und set zu unterscheiden... aber ich kann die drei einzelstrings noch nicht in eigene Variablen abspeichern.



if (RX_ready != 0)
{
char *pch;
pch = strtok (RX_buf," ");

while (pch != NULL)
{
if(strcmp(pch, "g")==0)
{
printf("getmethode");
}
else if (strcmp(pch, "s")==0)
{
printf("setmethode");
}
else
printf("keine bekannte Methode");

printf ("%s\n",pch);
pch = strtok (NULL, " ");
RX_ready = 0;
}
}

Grüße

Bean

sast
18.06.2009, 14:50
Naja eine zufriedenstellende Antwort auf meine Frage war das zwar nicht, aber ich spinne mir mal was zusammen.

g und s hast du ja sozusagen schon raus. Wenn wir mal davon ausgehen, das du jeden Parameter einzeln überträgst, dann könnte man von 3 bzw 4 Strings ausgehen Adresse, SET/GET, Befehl, <Wert>. Also nehmen wir 3 Arrays
uint8_t s1[MAX_STRLEN], s2[MAX_STRLEN], s3[MAX_STRLEN];

Dort wirfst du dann die pch rein, die nicht g oder s sind. Wir gehen jetzt davon aus, das nicht ununterbrochen über den UART was reinkommt.
Bei g oder s setzt du eine Bitvariable(Boolean) auf 1 oder 0.
in s1 bis s3 schreibst du entweder mit ner while char für char oder mit strcpy().
So und nun kannst du mit s1 bis s3 wie mit nem Ringpuffer umgehen und mit Hilfe von 2 Variablen (einmal was lese ich gerade und zum anderen wo schreibe ich gerade) zugreifen.
Kannst auch zum besseren Indizieren gleich ein s1_3[3][MAX_STRLEN] basteln.
Wenn du eine feste Befehls-/Parameterliste hast, geht das auch wieder ohne extra String ähnlich zu g und s. Da bleiben dann nur noch Adresse und Wert übrig. Ich z.B. verwende bei Adresse immer einen ":" vor der Adresse, damit kannst du ganz einfach zwischen Adresse und Wert unterscheiden und kommst sogar ganz ohne extra String aus. Ausser der Wert ist auch mal ein String.

Hoffe das war verständlich.

Übrigens reicht es, wenn du RX_ready am Ende der IF auf 0 setzt, sonst machst du das bei jedem separierten Teilstring.

sast

Peter1060
18.06.2009, 14:51
moin moin,

gib doch mal eine Übersicht, was Du eigendlich willst.
So einen ganz altmodischen PAP.

Einen ProgrammAblaufPlan.

Da kannst du dann auch Infos zu den benutzten Zeichenketten eintragen.
3 Zeichenketten in 1 Variablen geht.

Mit Gruß
Peter

Mr Bean
24.06.2009, 08:18
Hmm also was ich machen will ist eigentlich gleich erklärt, ich will eine Busverbindung zwischen mehreren Controllern aufbauen. Im Moment versuche ich das eben vom PC zu einem Controller über RS232. Später soll das ganze dann über RS485 laufen.

Es muss also ein Protokoll aufgebaut werden und Befehle definiert werden die die einzelnen Busteilnehmer verstehen.

Außerdem muss definiert werden wie ein Frame aussieht. Das hab ich eigentlich schon alles gemacht. Ein Frame startet immer mit der Adresse eines Slaves. Dieser muss daraufhin entscheiden ob die Nachricht für ihn oder einen anderen Busteilnehmer bestimmt ist. Danach folgt ein Befehl (get oder set) und danach das Objekt. Also z.B. "temp" für Temperatur. Jetzt muss ich mit meiner Software einen Weg finden um den String zu separieren (funktioniert ja schon). Und dann entsprechend des Inhalts dieses Strings zu reagieren. Hier fehlt mir noch eine gute Idee. Ich versuche das gerade mit if/else Schleifen. Aber das wird ziemlich unübersichtlich und es wird aufwendig dort später noch einmal Befehle einzufügen. Jetzt hatte ich die Idee mir mit "Struct" eine Variable anzulegen die die einzelnen Frameinhalte beinhaltet. Und dann über ein Array und einen Funktionszeiger auf einzelne Funktionen zu springen, je nach dem wleche Kombination über die Schnittstelle angekommen ist. Aber das bekomme ich noch gar nicht hin... :-(
Werde ich wohl noch einiges probieren müssen... :-(
Aber trotzdem nochmal Danke für die bisherige Hilfe!

Grüße!

Bean

sast
24.06.2009, 08:32
Hast du denn Rahmenbedingungen zu deinem Frame festgelegt? Z.B. Adresse ist 1Byte oder 2Byte usw. So ein PAP kann wirklich helfen.

sast

Peter1060
24.06.2009, 09:59
moin moin,

ein Frame sollte immer mit einem Startzeichen beginnen und mit einem Stopzeichen enden. Diese dürfen im Frame nicht in der Form vorkommen. Somit kann jeder Hörer bei Datenverlust neu synchronisieren.
Den Datensatz würde ich so aufbauen:
Start
Adresse
Befehl
(nun können noch Daten zu diesem Befehl kommen)
Prüfsumme
Stop

Die Antwort wäre dann so:
Start
Adresse
Echo (was der Befehl zurückliefert)
Prüfsumme
Stop

Warum willst Du Strings separieren? Als Befehl reicht doch oft ein Byte.
Und in C sollte es Zeichenkettenvergleiche geben.

MfG
Peter

Mr Bean
27.06.2009, 09:34
Hallo

Sorry dass ich so still war. ;-)
Die Rahmenbedingungen hab ich festgelegt. Also wie groß die einzelnen Frameinhalte sind. Ich denke das bekomm ich jetzt auch hin. Hab im Moment noch ein anderes "komisches" Problem.
Und zwar möchte ich zwei Ports mit

sbit fuse = P1^6
sbit relais_on = P1^7
ansteuern. Das funktioniert auch. Ich kann die Ports EIN und AUS schalten. Wenn ich dann aber den Zustand eines Ports als Bedingung in einer if Schleife verwenden will, dann funktioniert es mit fuse nicht und mit relais_on funktioniert es. Also ich schalte beide Ports auf 1 und dann frage ich ab:



if(relais_on==1)
{
.
.
.
}

Hier springt der Controller in die if Schleife


if(fuse==1)
{
.
.
.
}

Hier springt der Controller nicht in die Schleife. Und ich hab keine wirkliche Ahnung warum. Ich vermute dass es daher kommt dass hinter sbit fuse ja eigentlich eine Adresse steht aber kein Zustand.

Hier mal noch der komplette Code. Ist für meine Verhältnisse schon ganz schön angewachsen....


// FID: 33X000032
// Target: ToolStick C8051F330
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Command Line: None
//
//
// Release 1.0
// -Initial Revision (PD/GV/GP)
// -06 AUG 2006
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------

#include <C8051F330.h> // SFR declarations
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F33x
//-----------------------------------------------------------------------------

sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
sfr16 ADC0 = 0xbd; // ADC Data Word Register

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define BAUDRATE 115200 // Baud rate of UART in bps
#define TIMER2_RATE 1000 // Timer 2 overflow rate in Hz
#define RX_length 25 //Länge des UART empfangsarrays definieren
//#define adress 10 //Adresse der Sicherung (benötigt für Buskommunikation)

sbit fuse = P1^6; //fuse wird mit fuse=1 eingeschaltet
sbit relais_on = P1^7; //relais wird mit relais_on = 1 eingeschaltet

#define TRUE 1
#define FALSE 0


//-----------------------------------------------------------------------------
// current Sensor Calibration Parameters
//-----------------------------------------------------------------------------

#define CURRENT_SENSOR_GAIN 185000 //Current Sensor Gain in (uV / A). Value obtained from datasheet
#define VREF 3370 //ADC Voltage Reference (mV)
#define FUSE_VALUE 100 //Nennstrom der Sicherung

//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------

int ADC_offset;
bit RX_ready; //True = string empfangen

volatile char RX_buf[RX_length]; //Array als Eingangsbuffer anlegen
volatile unsigned char the_char; //zwischenspeicher


//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------

void OSCILLATOR_Init (void);
void ADC0_Init (void);
void UART0_Init (void);
void PORT_Init (void);
void TIMER2_Init (int);
char UART_ISR (void);
void Print_String (char pstring[]);
int Get_Current (void);
unsigned int Measure_current (void);
void Wait_One_Second (void);
void Print_current (unsigned int);


#define BIT0 1<<0
#define BIT1 1<<1
#define BIT2 1<<2
#define BIT3 1<<3
#define BIT4 1<<4
#define BIT5 1<<5
#define BIT6 1<<6
#define BIT7 1<<7

#define P1_6 P1&BIT6
#define P1_7 P1&BIT7

//-----------------------------------------------------------------------------
// main Routine
//-----------------------------------------------------------------------------

void main (void)
{
unsigned int current; // Stores last measurement
int messung=0;
//Adresse = 11;

// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable)
PORT_Init(); // Initialize Port I/O
OSCILLATOR_Init (); // Initialize Oscillator
TIMER2_Init (SYSCLK/TIMER2_RATE); // Init Timer 2
UART0_Init ();

AD0EN = 1; // Enable ADC
fuse = 0; //Sicherung ausschalten
Wait_One_Second();
ADC0_Init (); // Init ADC0

EA = 1; //Interrupts global freigeben
ES0 = 1; //UART interrupt freigeben
RI0 = 0;

relais_on = 0;

while (1)
{
if(fuse==1)
{
printf("Gebe Strommessung aus:\t");
current = Get_Current ();
Print_current(current);
}
else{
printf("P1_6 = 0x%x \t",P1_6);
printf("P1_7 = 0x%x\t", P1_7);
if(P1_6 == P1_7){
printf("P1_6 == P1_7 (%x)\t", P1_6 & P1_7);
}
printf("\r");

}

if(current > FUSE_VALUE)
{
fuse = 0;
Print_String ("Warning: overload\n");
Wait_One_Second();
messung = 0;
}

if (RX_ready != 0)
{
char *pch;
pch = strtok (RX_buf," ");

while (pch != NULL)
{

if(strcmp(pch, "g")==0)
{
Print_String("getmethode");
}

else if (strcmp(pch, "s")==0)
{
Print_String("setmethode");
}

else if(strcmp(pch, "temp")==0)
{
Print_String("temperaturausgeben");
}
else if(strcmp(pch, "on")==0)
{
relais_on = 1; //relais einschalten
fuse = 1; //Sicherung einschalten
Wait_One_Second();
}
else if(strcmp(pch, "off")==0)
{
fuse = 0;
relais_on = 0;
Wait_One_Second();
}
else
{
Print_String("keine bekannte Methode");
}
printf("%s\n",pch);
pch = strtok (NULL, " ");
}
RX_ready = 0;
}
}
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// P0.4 digital push-pull UART TX
// P0.5 digital open-drain UART RX
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0SKIP |= 0x01; // Skip P0.0 for external VREF
P1MDIN |= 0xEF; // Configure P1.4 as analog input.
P0MDOUT |= 0x10; // enable UTX as push-pull output
XBR0 = 0x01; // Enable UART on P0.4(TX) and P0.5(RX)
XBR1 = 0x40; // Enable crossbar and weak pull-ups

P0MDIN = 0xFE;
P1MDIN = 0xEF;
P0SKIP = 0x4D;
XBR0 = 0x07;
XBR1 = 0x40;

}

//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
OSCICN |= 0x03; // Configure internal oscillator for
// its maximum frequency
RSTSRC = 0x04; // Enable missing clock detector
}

//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure ADC0 to use ADBUSY as conversion source, and to sense the output
// of the temp sensor. Disables ADC end of conversion interrupt. Leaves ADC
// disabled.
//
//-----------------------------------------------------------------------------

void ADC0_Init (void)
{
ADC0CN = 0x40; // ADC0 disabled; LP tracking
// mode; ADC0 conversions are initiated
// on a write to ADBusy
AMX0P = 0x0C; // P1.4 selected at + input
AMX0N = 0x11; // Single-ended mode

ADC0CF = (SYSCLK/3000000) << 3; // ADC conversion clock <= 3MHz

ADC0CF &= ~0x04; // Make ADC0 right-justified
REF0CN = 0x0e; // enable temp sensor, VREF = VDD, bias
// generator is on.
AD0EN = 1; // Enable ADC0
ADC_offset = 0;
ADC_offset = Measure_current(); // Nullpunkt Offset messen

EIE1 &= ~0x08; // Disable ADC0 EOC interrupt
}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configure the UART0 using Timer1, for <BAUDRATE> and 8-N-1.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
SCON0 = 0x10; // SCON0: 8-bit variable bit rate
// level of STOP bit is ignored
// RX enabled
// ninth bits are zeros
// clear RI0 and TI0 bits
if (SYSCLK/BAUDRATE/2/256 < 1) {
TH1 = -(SYSCLK/BAUDRATE/2);
CKCON &= ~0x0B; // T1M = 1; SCA1:0 = xx
CKCON |= 0x08;
} else if (SYSCLK/BAUDRATE/2/256 < 4) {
TH1 = -(SYSCLK/BAUDRATE/2/4);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 01
CKCON |= 0x09;
} else if (SYSCLK/BAUDRATE/2/256 < 12) {
TH1 = -(SYSCLK/BAUDRATE/2/12);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 00
} else {
TH1 = -(SYSCLK/BAUDRATE/2/48);
CKCON &= ~0x0B; // T1M = 0; SCA1:0 = 10
CKCON |= 0x02;
}

TL1 = TH1; // Init Timer1
TMOD &= ~0xf0; // TMOD: timer 1 in 8-bit autoreload
TMOD |= 0x20;
TR1 = 1; // START Timer1
TI0 = 1; // Indicate TX0 ready
}

//-----------------------------------------------------------------------------
// TIMER2_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) int counts - number of milliseconds of delay
// range is postive range of integer: 0 to 32767
//
// Configure Timer2 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
//-----------------------------------------------------------------------------
void TIMER2_Init (int counts)
{
TMR2CN = 0x00; // STOP Timer2; Clear TF2H and TF2L;
// disable low-byte interrupt; disable
// split mode; select internal timebase
CKCON |= 0x10; // Timer2 uses SYSCLK as its timebase

TMR2RL = -counts; // Init reload values
TMR2 = TMR2RL; // Init Timer2 with reload value
ET2 = 0; // Disable Timer2 interrupts
TR2 = 1; // Start Timer2
}

//-----------------------------------------------------------------------------
// Measure_current
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
//-----------------------------------------------------------------------------
unsigned int Measure_current (void)
{
unsigned i; // Sample counter
unsigned long accumulator = 0L; // Where the ADC samples are integrated

unsigned int currval;

AD0INT = 0; // Clear end-of-conversion indicator
AD0BUSY = 1; // Initiate conversion

// read the ADC value and add to running total
i = 0;
do
{
while (!AD0INT); // Wait for conversion to complete
AD0INT = 0; // Clear end-of-conversion indicator

currval = ADC0; // Store latest ADC conversion
AD0BUSY = 1; // Initiate conversion
accumulator += (currval); // Accumulate
i++; // Update counter
} while (i != 20);


return (unsigned int) (accumulator);
}

//-----------------------------------------------------------------------------
// Get_Current
//-----------------------------------------------------------------------------
//
// Return Value : int - returns the current in hundredths of degrees
// Parameters : None
//
//-----------------------------------------------------------------------------
int Get_Current (void)
{
long result;

result = Measure_current ();
result = result - ADC_offset;
result = result / 20;

result = result * 7580;
result = result / 1024;
return (int) result;
}

//-----------------------------------------------------------------------------
// Support Functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Print_String
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters :
// 1) char pstring[] - null terminated character string
//
// Prints the strings stored in pstring to the UART.
// This function is used instead of printf() because printf() consumes
// a considerable amount of code space.
//
//-----------------------------------------------------------------------------

void Print_String (char pstring[])
{
unsigned char i = 0;
while (pstring[i])
{
putchar(pstring[i++]);
}
}

//-----------------------------------------------------------------------------
// Wait_One_Second
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This routine uses Timer2 to insert a delay of approximately one second.
// Timer 2 overflows <TIMER2_RATE> times per second.
//
//-----------------------------------------------------------------------------
void Wait_One_Second (void)
{
unsigned int count;
TF2H = 0; // Clear Timer2 overflow flag
TR2 = 1; // Start Timer2

for (count = TIMER2_RATE; count != 0; count--)
{
while (!TF2H); // Wait for overflow
TF2H = 0; // Clear overflow indicator
}

TR2 = 0; // Stop Timer2
}


void Print_current (unsigned int current)
{
Print_String ("Current = ");

// This method of printing the current is an alternative to using
// printf() and its capabilities

EA = 0;
putchar ((current / 1000) + 0x30); // Tens digit
putchar (((current / 100) % 10) + 0x30); // Ones digit
putchar ('.');
putchar (((current / 10) % 10) + 0x30); // Tenths digit
putchar ((current % 10) + 0x30); // Hundredths digit
EA = 1;

Print_String (" A\n");

}

//-----------------------------------------------------------------------------
// Interrupt service routines
//-----------------------------------------------------------------------------
void UART0_ISR (void) interrupt 4 using 3
{

static unsigned char RX_index; //zwischenspeicher

if(RI0 == 1)
{

if(RX_ready != 1)
{
the_char = SBUF0;

if(the_char != '\r')
{
RX_buf[RX_index] = the_char;
RX_index++;
RI0 = 0;
RX_buf[RX_index] = '\0';
}
else
{
RX_buf[RX_index] = '\0';
RX_index = 0;
RX_ready = 1;
RI0 = 0;
}
}
}
}
//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------