Forum: Mikrocontroller und Digitale Elektronik Analoge Schnittstelle C167


von sneube (Gast)


Lesenswert?

Hallo,
ich habe den Mikrocontroller C167 von Infenion und möchte eine einfache 
Aufgabe schaffen.
Über den analogen Eingang am PIN 5.0 soll eine Analogspannung angelegt 
werden.
Diese soll dann gewandelt werden und der Spannungswert soll mit der 
printf -Funktion ausgegeben werden.

Die Wandlung geschieht in der Funktion messen. Der Rückgabewert soll aus 
dem Register ADDAT ausgelesen werden.
Mit der Funktion auswerten soll aus den Werten 0 ... 1023 wieder eine 
Spannung ausgegeben werden.
Leider funktioniert das überhaupt nicht und ich kann mir nicht erklären, 
woran das liegt.
Die Funktion init enthält die Parameter für die RS232 Schnittstelle, die 
habe ich weggelassen, da sie nur aus dem Beispiel Hello World ist, 
ausserdem funktioniert die printf - Funktion.

Hier der Code:

************************************************************************ 
**
int messen(int kanal){
ADCON = 0xf080 | kanal;
while(!ADCIR);
ADCIR = 0;
return  (ADDAT & 0x03ff);
}

float auswerten(wert){
unsigned int uein;
uein = wert*(5/1023);
return uein;
}

void main (void){
int wert;

float uein;
init();

while (1){
  wert = messen(0);
  uein = auswerten(wert);
  zeichen_senden('s');
  printf("Eingangsspannung ist: %f\n", uein);

  }
}
************************************************************************ 
**

Wäre super, wenn mir jemand helfen könnte

von Karl heinz B. (kbucheg)


Lesenswert?

> Leider funktioniert das überhaupt nicht und ich kann mir nicht erklären,
> woran das liegt.

Das liegt vielleicht an Syntax Fehlern in deinem Pgm

float auswerten(wert){

                ****
hier fehlt der Datentyp für 'wert'. Das hätte dir dein Compiler
aber eigentlich sagen müssen.


unsigned int uein;
uein = wert*(5/1023);

Dir ist bewusst, dass die Division 5 / 1023 immer 0 ergibt?
Da ich mal davon ausgehe, dass du genau das nicht wolltest:

     uein = wert * ( 5.0 / 1023.0 );

5/1023 : Da beide Partner in der Division, sowohl 5 als auch 1023
int sind, wird auch die Division selbst im int-Raum gemacht. Wenn
du das anders willst, muss mindestens einer der beiden, oder alle
beide, vom Typ double (oder float) sein.

von Karl heinz B. (kbucheg)


Lesenswert?

> float auswerten(wert){
> unsigned int uein;
> uein = wert*(5/1023);
> return uein;
> }

Bist du sicher, dass uein in dieser Funktion vom Typ unsigned
int sein sollte?

von sneube (Gast)


Lesenswert?

Hallo,
ich habe den Quellcode verändert, indem ich alle Variablen, ausser der 
Variable "Kanal" auf float gesetzt habe und bei der Division an den 
Zahlen .0 angehängt habe. Den Syntaxfehler aus der Funktion auswerten() 
habe ich auch rausgemacht.
Leider ist es noch das gleiche...

von Karl heinz B. (kbucheg)


Lesenswert?

> Leider ist es noch das gleiche...

Dann solltest du mal sagen, was denn unter 'das gleiche' zu
verstehen ist.

von sneube (Gast)


Lesenswert?

Wenn ich das Programm ausführe, erscheint nur der erste Buchstabe in der 
printf - Funktion ("Eingangspannung...") also nur E, sonst nichts, das 
wiederholt sich nach dem reseten

von Karl heinz B. (kbucheg)


Lesenswert?

Probier mal folgendes:

while (1){
  wert = messen(0);
  uein = auswerten(wert);
  zeichen_senden('s');
  printf("Eingangsspannung ist: %f (%d)\n", uein, wert);
}

und sieh nach, ob vom ADC überhaupt vernünftige Werte kommen.

von Karl heinz B. (kbucheg)


Lesenswert?

> Wenn ich das Programm ausführe, erscheint nur der erste Buchstabe in der
> printf - Funktion ("Eingangspannung...")

Sagtest du in deinem Eröffnungsposting nicht, dass printf
funktionieren würde?

von sneube (Gast)


Lesenswert?

Es kommen von ADC keine vernünftigen Werte.
Es ist so, wie ich oben beschrieben habe

von sneube (Gast)


Lesenswert?

Moment mal,
ist das überhaupt richtig so?
Ich glaube langsam das da das Problem liegt


********************************************************
void init(void){

 P3  |= 0x0400;
 DP3 |= 0x0400;

  DP3 &= 0xF7FF;

  S0TIC = 0x80;
  S0RIC = 0x00;
  S0BG  = 0x80;
  S0CON = 0x8011;

}

**********************************************************

von Karl heinz B. (kbucheg)


Lesenswert?

> Es kommen von ADC keine vernünftigen Werte.

Also: Wenn bei einem
  printf("Eingangsspannung ist: %f (%d)\n", uein, wert);

nur das 'E' auftaucht und sonst nichts, dann hat das erst mal
gar nichts mit dem ADC zu tun. printf ist unabhängig vom
ADC und gibt einfach nur Texte und Variableninhalte aus.
Wo die herkommen ist dem printf sch...egal.
Dein erstes Ziel muss es also mal sein, den printf tatsächlich
funktionsfähig zu kriegen. Alles andere ist stochern im
Nebel.

Dein Testpgm lautet:

int main()
{
  float t = 2.3f;

  while( 1 ) {
    printf( "Test: %f\n", t );
  }
}

und dazu kommt natürlich noch alles was du an Initialisierungen
so brauchst um printf lauffähig zu kriegen. Solange dieses
Programm auf deinem Ausgabemedium nicht immer wieder die
Zeile

  Test: 2.3000

(mit möglicherweise unterschiedlicher Anzahl an Nachkommastellen)
ausgibt, (mglw. steht da auch 2.29999 oder 2.30001) hat alles
andere keinen Sinn.

von sneube (Gast)


Lesenswert?

Aber es müsste doch möglich sein, Werte aus dem Register in eine 
Variable zu schreiben und diese dann über printf auszugeben.

von sneube (Gast)


Lesenswert?

Habe es gerade ausprobiert, die Printf Funktion funktioniert überhaupt 
nicht.
An was kann denn das jetzt liegen?

von Karl heinz B. (kbucheg)


Lesenswert?

> An was kann denn das jetzt liegen?

Das kann ich dir nicht sagen, da ich weder den C167, noch den
Compiler den du benutzt, kenne. Aber in der Doku zu deinem
Compiler, müsste ja beschrieben sein, wie du dem printf eine
Ausgabefunktion auf den UART unterjubelst.

von sneube (Gast)


Lesenswert?

Okay,
aber trotzdem vielen Dank, jetzt weiss ich wenigstens, an was es liegt

von sneube (Gast)


Lesenswert?

Hallo,
ich habe den Fehler gefunden.
Es war die falsche System Datei eingebunden, so hat die Kommunikation 
mit der RS232 Schnittstelle nicht funktioniert,
aber jetzt funktioniert es wunderbar

von Dennis (Gast)


Lesenswert?

Hi,

ich versuch gerade das ganze hier nachzuvollziehen, da ich sowas 
ähnliches vor habe. Leider bekomm ich immer ne Fehlermeldung je nachdem 
welche Klasse (h-Datei) einbinde.

Habe in dem Beispiel die XC161.h und die stdio.h eingebunden damit 
bekomm ich auch ganz normal ne Anzeige über die Serielleschnittstelle 
wenn ich was über printf ausgebe.
Leider funktioniert das mit der "Erweiterung" von diesem Beitrag noch 
nicht so ganz, bekomme wenn ich das einbinde eine Fehlermeldung. Habe 
schon die reg167.h probiert nur leider funktioniert es damit auch nicht. 
Weiß zufällig jemand welche h-Datei ich für den A/D benötige?

Danke im vorraus.

von Jörg S. (joerg-s)


Lesenswert?

>Leider funktioniert das mit der "Erweiterung" von diesem Beitrag noch
>nicht so ganz, bekomme wenn ich das einbinde eine Fehlermeldung.
Was bindest du ein? Den Code aus Beitrag 1?

von Dennis (Gast)


Lesenswert?

Hi,

ich nutze das MCB-XC167 Board von Keil und will über den A/D was einen 
Spannungswert einlesen und den über die serielle Schnittstelle ausgeben.

Habe schon folgenden Code zum testen als Beispiel - die Ausgabe an 
Port2.8 ist nur zum testen für mich, also nicht weiter beachten...

Nutze ich den unten angegeben Code, bekomm ich nichts über die 
Schnittstelle raus. Wandel ich aber das S0.. usw. in ASCO... um, dann 
bekomm ich was raus, bekomme aber dann beim einbinden des A/D in den 
Quellcode Fehlermeldungen, das sich die Headerdateien nicht "vertragen".

Für die ASC0.. brauche ich die XC161.h und für den A/D die reg167.h..

Vielleicht ist es ja ganz einfach, nur ich bekomm es irgendwie nicht 
hin.

Danke im vorraus.
1
#include <reg167.h>          // einbinden der 80C167 Header Datei
2
#include <stdio.h>          // Standard I/O Funktionen einbinden
3
4
sbit P2_8 = P2^8;          // deklaration des zu nutzenden Portpin
5
sbit DP2_8 = DP2^8;          // deklaration der Richtung
6
7
void wait (void) {          // wait Funktion
8
  unsigned long i;
9
  for (i=0; i<150000; i++) {;}  // Verzögerungsschleife    
10
}
11
        
12
void ser_init (void) {        // Initialisierungsfunktion für die serielle Schnittstelle
13
  
14
  P3 |= 0x0400;          // Port 3.10 auf Output latch (TXD) setzen
15
  DP3 |= 0x0400;          // Port 3.10 für Output konfigurieren (TXD output)
16
17
  DP3 &= 0xF7FF;          // Port 3.11 für Input konfigurieren (RXD input)
18
19
  S0TIC = 0x80;          // Transmit Interrupt Flag setzen
20
  S0RIC = 0x00;          // Receive Interrupt Flag löschen
21
//  S0BG = 0x80;          // Baudrate auf 9600 einstellen bei 40MHz
22
//  S0BG = 0x6A;          // Baudrate auf 9600 einstellen bei 33MHz
23
//  S0BG = 0x50;          // Baudrate auf 9600 einstellen bei 25MHz
24
  S0BG = 0x40;          // Baudrate auf 9600 einstellen bei 20MHz
25
  S0CON = 0x8011;          // Serial Mode setzen  
26
  S0TIR = 1;            // Sendebuffer freigeben
27
}
28
29
void main (void) {
30
  
31
  ser_init();            // Aufruf der Init-Funktion für serielle Schnittstelle
32
  
33
  DP2_8 = 1;            // Initialisierung der Richtung -> Ausgang
34
  
35
  while(1) {            // Endlosschleifen
36
    
37
    printf("Hello World\n");  // Ausgabe auf die Serielleschnittstelle  
38
39
    P2_8 = 0;          // Port 2.8 aus
40
    wait();            // Aufruf der wait Funktion
41
42
    P2_8 = 1;
43
    wait();            // Aufruf der wait Funktion
44
 }
45
}

von Jörg S. (joerg-s)


Lesenswert?

>Für die ASC0.. brauche ich die XC161.h und für den A/D die reg167.h..
Dann würde ich mal nachschauen wie in der XC161.h das ADC Control 
Register heisst. Ich tippe auf ADC_CON anstatt ADCON. Die XC161.h hält 
sich wohl an die Namensgebung des User Manuals vom XC167:
http://de.sitestat.com/infineon/infineon/s?infineon.Products.Microcontrollers.16-Bit.XC166_Family.XC167CI.DOCUMENTS.xc167_um_v2.0_2004_04_pdf.zip&ns_type=clickin&ns_url=http://www.infineon.com/dgdl/xc167_um_v2.0_2004_04_pdf.zip?folderId=db3a304412b407950112b41c85aa2e48&fileId=db3a304412b407950112b41c86012e49

Vermutlich kannst du daher Programme vom C167 nicht 1:1 für dich 
kopieren. Du musst auf die andere Namensgebung der Register aufpassen!

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.