PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Messwert-Variablen auf LCD 16x2 ausgeben, will nicht per ITOA klappen



oderlachs
12.02.2019, 18:07
Halle Freunde !

Vieleicht habe ich mich wieder selbst verrant, aber ich komme einfach nicht weiter.
Ich möchte Messwerte(Intergerwerte) auf einen Kontrolldisplay(Test mit 16x2) ausgeben. Aber das umwandlen der Integerwerte in einen String, den ich auf das LCD schreiben kann klappt nicht.
Vielleicht fasse ich die Sache auch komplett falsch an. zu Testzwecken habe ich den Integer einfach mal mit einem Wert 250 belegt. Hier mein Code:


/************************************************** ********************/
//
// Microchip MPLABX XC8 Compiler
//
/************************************************** *******************/

typedef unsigned char uChr;

/* ================================================== ================ */
/* */
/* LCD-Write uChar */
/* */
/* ================================================== ================ */

void Lcd_Write_Char(uChr a)
{
RS=1; // => RS = 1
PDAT=a ; // => Datenport = a
EN = 1; // => E = 1
__delay_ms(1);
EN = 0; // => E = 0
__delay_ms(1);
}

/* ================================================== ================ */
/* */
/* LCD-Write String */
/* */
/* ================================================== ================ */

void Lcd_Write_String(uChr *a)
{
while(*a) // bis Stringende( = 0)
{
Lcd_Write_Char( *a );
a++;
}
}

/************************************************** ********************/

void main(void)
{
Lcd_Init();

char Buffer[10];
int i = 250; // Vorgegebener Wert zum Test

itoa( i, Buffer, 10 );

Lcd_Write_String(Buffer);

while(1); // im Testmodus hier Halt
}

/************************************************** ********************/

Lcd_Write_String(Buffer) ist was immer bekrittelt wird vom Compiler : mein_lcd_16_2.c:71: warning: (357) illegal conversion of integer to pointer

Nun verstehe ich nicht das es auf einen Integer bezogen ist, wo doch Buffer ein Chararray bzw String ist.

Weiss wer bitte Rat ???

Ich habe mich da festgefahren :(

Gruss und Dank

Gerhard

Searcher
12.02.2019, 19:11
Hallo oderlachs,

Buffer ist vom Typ char. Die Funktion Lcd_Write_String erwartet aber ein Argument vom Typ uChr * da ja mit (uChr *a) deklariert.

Vielleicht geht die Warnung weg, wenn der Buffer auch vom Typ uChr ist.

Ich hab ja wenig Ahnung von C und gefunden hab ich das, als ich Deinen Code mit AVR Studio 4 kompiliert habe. Da kommt dann als Warnung:


../oderlachs.c:51:5: warning: pointer targets in passing argument 1 of 'Lcd_Write_String' differ in signedness [-Wpointer-sign]
../oderlachs.c:31:6: note: expected 'uChr *' but argument is of type 'char *'


Gruß
Searcher

seite5
12.02.2019, 19:11
evtl.: Lcd_Write_String(&Buffer[0]);
mfg
Achim

Edit: Kann's nicht sein - bringt nur 'ne warnung in AS

oderlachs
12.02.2019, 19:51
Hallo Searcher & seite5 !
Danke für Eure Teilnahme an meinem Problem !!

@Searcher Das AVR Studio war schon auf dem richtigem Wege uChar ist nicht Char !
Habe mal den Sourcode geändert und einen uChr Cast gemacht erst mal um zu testen :


************************************************** ***
int i = 12345;
itoa(Buffer,i, 10 );
Lcd_Write_String((uChr)Buffer);
************************************************** ***


Und nun geht es :) !
Ob es nun die "goldene Lösung " ist weiss ich nicht, aber ich kann erst mal mit dem gesamten Projekt weiter machen.
Ich bin auch noch beim X8 -Compiler etwas in den Startlöchern, da ist oft viel "Manual-Studium" angesagt... ;)
1-Wire und DS18B20 werden mir bestimmt auch noch Fallstricke um die Füsse binden... ;)

Gruss und Danke

Gerhard

PS: auch war die ITOA-Func. falsch, muss in den Unterlagen fehlerhaftig sein...integer und buffer waren in der Reihenfolge falsch....

Searcher
12.02.2019, 20:00
/************************************************** ********************/

void main(void)
{
Lcd_Init();

uChr Buffer[10];
int i = 250; // Vorgegebener Wert zum Test

itoa( i, Buffer, 10 );

Lcd_Write_String(Buffer);

while(1); // im Testmodus hier Halt
}

/************************************************** ********************/


Ich hatte mir das ja mit "uChr Buffer[10]; " vorgestellt. s.o. . Aber wenns auch so geht ...

Gruß
Searcher

oderlachs
13.02.2019, 10:24
Danke Searcher!.... das ich da nicht drauf gekommen bin...die einfachste Lösung...ja so ist es , wenn man sich mal festgefahren hat... ;)

Gruss
Gerhard

Edit:

Dank der "Probleme" konnte ich meine LCD-Routinen um eine weitere ergänzen:


void LCD_Write_Buff(char Buffer[])
{
int x;
int len;
len = strlen( Buffer);
for(x=0; x<= len;x++)
{
if(Buffer[x]==0)
return;
else
Lcd_Write_Char(Buffer[x]);
}
}


So haben Probleme auch noch was Gutes an sich... ;)

Ceos
13.02.2019, 11:30
deine Schleife ist irgendwie nicht richtig

strlen kann auch 0 zurück geben und dann knallt es in deiner Schleife weil er das erste Zeichen ausgeben will obwohl da keines ist
und wenn dein index = strlen erreicht rettet dich bestenfalls ein natürlich angehängter "0"-Terminator vor einem Pufferüberlauf :)

ich würde es eher mit x < len statt <= versuchen

Wen du ein Strign der größe 5 mit "12345" hast (also kein 0 Terminator) zum Beispiel, so würdest du dir auch dein if(Buffer[x]==0) sparen können, denn strlen sucht immer nach der letzten 0 und liefert die länge ohne Terminator zurück

oderlachs
13.02.2019, 11:38
Danke Ceos !

Muss ich mal überdenken, ...man ist ja lernwillig, .....stimmt das "if(Buffer[x]==0) " ist eigentlich hier überflüssig....

Klebwax
13.02.2019, 18:13
Halle Freunde !

Vieleicht habe ich mich wieder selbst verrant, aber ich komme einfach nicht weiter.
Ich möchte Messwerte(Intergerwerte) auf einen Kontrolldisplay(Test mit 16x2) ausgeben. Aber das umwandlen der Integerwerte in einen String, den ich auf das LCD schreiben kann klappt nicht.
Vielleicht fasse ich die Sache auch komplett falsch an. zu Testzwecken habe ich den Integer einfach mal mit einem Wert 250 belegt. Hier mein Code:


/************************************************** ********************/
//
// Microchip MPLABX XC8 Compiler
//
/************************************************** *******************/

typedef unsigned char uChr;

/* ================================================== ================ */
/* */
/* LCD-Write uChar */
/* */
/* ================================================== ================ */

void Lcd_Write_Char(uChr a)
{
RS=1; // => RS = 1
PDAT=a ; // => Datenport = a
EN = 1; // => E = 1
__delay_ms(1);
EN = 0; // => E = 0
__delay_ms(1);
}

/* ================================================== ================ */
/* */
/* LCD-Write String */
/* */
/* ================================================== ================ */

void Lcd_Write_String(uChr *a)
{
while(*a) // bis Stringende( = 0)
{
Lcd_Write_Char( *a );
a++;
}
}

/************************************************** ********************/

void main(void)
{
Lcd_Init();

char Buffer[10];
int i = 250; // Vorgegebener Wert zum Test

itoa( i, Buffer, 10 );

Lcd_Write_String(Buffer);

while(1); // im Testmodus hier Halt
}

/************************************************** ********************/

Lcd_Write_String(Buffer) ist was immer bekrittelt wird vom Compiler : mein_lcd_16_2.c:71: warning: (357) illegal conversion of integer to pointer

Nun verstehe ich nicht das es auf einen Integer bezogen ist, wo doch Buffer ein Chararray bzw String ist.
Du bist in eine böse Falle getapt. An deinem Code ist eigentlich alles ok. Dein eigener Typ uChr hat dir zusätzlich die Sicht versperrt, lass ihn einfach weg. Ein String besteht aus chars, das reicht. Und wenn dein Datenport mit 8-Bit unsigned angesprochen werden will, dann caste vor der Ausgabe den char zum Standarddatentyp uint8_t (PDAT = (uint8_t)a;).

Die Funktion itoa ist beim XC8 falsch implementiert. In den üblichen Dokumentationen kommt als Parameter zuerst der Integer und dann der String. Bei XC8 gehts genau anders herum. Daher hat er an erster Stelle bei deinem Aufruf von itoa einen Pointer erwartet, von dir aber einen Integer bekommen. Soweit ist die Fehlermeldung ok. Das Problem geht aber tiefer. Ich hab mal geschaut, ob diese Problem nicht anderswo erkannt worden ist und bin auf follgendes gestoßen XC8 Version 2.xx (https://www.microforum.cc/topic/5-i-used-to-use-to-locate-variables-but-since-xc8-20-this-is-no-longer-working/). Da itoa() in C99 nicht Pflicht ist, kommt das bei V2.00 und neuer von XC8 gar nicht mehr vor. du solltest also sprintf(Buffer, "%d", i); verwenden, das klappt dann auch mit den neuen Compilerversionen (ich bin bei V2.05).

MfG Klebwax

P.S. Noch etwas zu deiner Funktion void Lcd_Write_Char(uChr a). Daß du einfach char nehmen soltest, hab ich schon gesagt. Das Delay von einer Millisekunde ist viel zu groß, eine Mikrosekunde oder ein NOP() reicht da. Und nachdem EN auf low gesetzt wird, braucht man gar kein Delay. Die Zeit, die der Prozessor für das Return und den nächsten Funktionsaufruf braucht reicht da vollkommen. Die Funktion ist also rund zweitausend mal zu langsam.

Und solche Kommentare wie " RS=1; // => RS = 1" sollte man vermeiden. Erstens sagt er das gleiche wie der Code, ist also überflüssig. Schlimmer aber, wenn du den Code mal änderst, wirst du den Kommentar nicht ändern. Dann stehen da zwei sich wiedersprechende Aussagen und machen dir das Leben schwer. Kommentieren sollte man nur, was nicht offensichtlich ist.

oderlachs
16.02.2019, 09:08
Hallo Klebwax !

Danke für Deine ausfühlichen Ratschläge.
Leider will der XC8 Compiler nichts mit uint8_t zu tun haben. Das ist auch noch ein weiteres Problem, das gewohnte C-Programmcode hier oft daneben geht.
Auch bin ich , neben früheren "Ein Zwei Mal" Anwendungen, erst ab Ende vergangenen Jahres PIC- und MPLab-Aktiv geworden..da habe ich noch jede menge Lernbedarf
Aber für meine Freizeitbeschäftigungs-Programmierung und Hobby, will ich nicht noch sonst was investieren(Compiler, IDEs usw.).

Gruss und Dank

Gerhard

Klebwax
16.02.2019, 09:56
Leider will der XC8 Compiler nichts mit uint8_t zu tun haben.

Das hat mit XC8 nichts zu tun. Kein C-Compiler kennt das, auch wenn man den GCC für einen PC benutzt. Er kennt nur char und int. Um dem Compiler die modernen Bezeichnungen der Datentypen näher zu bringen, muß stdint.h includiert werden. Kipp einfach mal uint8_t in Google. Wenn ich ein ähnliches Problem habe, mach ich das so. Auch wenn ich eine Fehlermeldung nicht wirklich verstehe, ist der erste Versuch sie einfach in Google zu pasten.

In MPLABX muß man das noch nichtmal wirklich schreiben. Einfach "#in" und schon bietet es "#include" an. Dann "<" und schon bekommt man alle Systemincludes angeboten. Mit "std" hat man dann die Standardincludes wie stdio.h, stdbool.h oder auch stdint.h in der Auswahl

Es ist das Prinzip von C, daß der Compiler selbst wenig weiß und kann, außer zu compilieren. Das meiste, das er zum Compilieren braucht, kommt aus Headerfiles, so auch die internen Register des jeweiligen Chips (xc.h plus die Projekteinstellung des Prozessors). Und was das Programm zum funktionieren braucht, kommt aus Libraries, zu allererst aus der libc. Und auch die kennt der Compiler nicht, wenn man sie ihm nicht z.B. stdio.h oder string.h bekannt macht.

MfG Klebwax

P.S. "gewohnter C-Programmcode" ist ein etwas problematischer Begriff. Insbesondere für kleine µC gab und gibt es Compiler, die sich nicht vollständig an die C Standards halten. XC8, ehemals HighTech, wird da gerade aufgefrischt.

oberallgeier
16.02.2019, 10:00
.. Leider will der XC8 Compiler nichts mit uint8_t zu tun haben ..Hmmm, seltsam. Hast Du denn auch die <stdint.h> richtig eingebunden (#include ..) ? Denn


..
2.4.6 Sizes of TypesThe sizes of the basic C types, e.g., char, int and long, are not fully defined by the CCI. These types, by design, reflect the size of registers and other architectural fea-tures in the target device. They allow the device to efficiently access objects of this type. The ANSI C Standard does, however, indicate minimum requirements for these types, as specified in <limits.h>. If you need fixed-size types in your project, use the types defined in <stdint.h>, e.g., uint8_t or int16_t. These types are consistently defined across all XC compilers, even outside of the CCI.
..
2.4.6.3 MIGRATION TO THE CCI If you require a C type that has a fixed size, regardless of the target device, use one of the types defined by <stdint.h>
..

Und auch

..
2.4.1.1EXAMPLEThe following shows a string constant being defined that uses escaped characters.const char myName[] = "Bj\370rk\n";
..

Siehe z.B. diese Dokumentation (http://ww1.microchip.com/downloads/en/devicedoc/50002053g.pdf).

Puhhh - Klebwax war schneller . . .

HaWe
16.02.2019, 10:54
viele C libs können mit den stdint Datentypen int8_t oder uint8_t nichts anfangen, selbst wenn stdint #included ist, sie ewarten die "genuinen" Typen char oder int, je nachdem, was halt in den libs steht und verwednet wird.
Selbst unsigned char oder signed char sind auf Lib- und Compilerebene nicht von vornherein mit char kompatibel, sie sind "etwas anderes".
cstring arbeitet ausschließlich mit char, mit nichts anderem.
Wenn ein cstring benutzt wird, muss also ein array of char übergeben werdem.

Haben die eigenen Daten eine andere Struktur, musst du sie vorher oder hinterher entsprechend explizit casten, was oft sehr umständlich ist, besser also, man verwendet von vornherein das, was die Lib erwartet.



char is signed on Intel (edit: and AVR) and unsigned on ARM (the Pi
(edit: ) and ARM Cortex M0 + M3 + M4 e.g., Zero +Due, and ESP)).
You cannot explicitly use "signed char" or "unsigned char" which, though legal types, are both distinct from the "char" type that library functions expect.
The only option if the type of char is important (which it often is) is to use the "-funsigned-char" compiler option. All C compilers have similar options.
"uint8_t" etc will fail when library functions are used.

https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=233557&sid=8675df85aedc2a56b6068996b8fd0047#p1429279

Das gilt also entsprechend verschärft für int8_t oder uint8_t und erst recht für selber definierte ganz "neue" Datentypen wie das "uChr " bei dir.

oderlachs
16.02.2019, 13:27
Hallo und Danke für Eure Hilfe und Erklärungen !!
Wie gesagt mit PIC und MPLab betrete ich für mich noch "Neuland", von einigen "Testseitensprüngen" mal abgesehen. Ich google auch schon wenn was nicht so funzt, sonst wäre ich noch gar nicht so weit.
Habe da solch "altes PIC-Büchlein" : "Programmieren von PIC Mikrocontrollern" - Der leichte Einstieg mit dem 16F84A von Dieter Kothz, das hat mich erst bewogen micht auf die PIC Ebene zu wagen.
Dann bekam ich günstig dieses "EasyPIC-40" Bord und da versuche ich mich nun drann, neben dem AVR-Chips, meine Freizeit "sinnvoll" zu verkürzen.

Gerhard

@Oberall : der Tip mit der "<stdint.h>" war gut , hatte die nicht immer im include , ich Trottel :mad:;)