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
> 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.
> 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?
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...
> Leider ist es noch das gleiche...
Dann solltest du mal sagen, was denn unter 'das gleiche' zu
verstehen ist.
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
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.
> 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?
Es kommen von ADC keine vernünftigen Werte. Es ist so, wie ich oben beschrieben habe
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; } **********************************************************
> 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.
Aber es müsste doch möglich sein, Werte aus dem Register in eine Variable zu schreiben und diese dann über printf auszugeben.
Habe es gerade ausprobiert, die Printf Funktion funktioniert überhaupt nicht. An was kann denn das jetzt liegen?
> 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.
Okay, aber trotzdem vielen Dank, jetzt weiss ich wenigstens, an was es liegt
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
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.
>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?
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 | }
|
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.