PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeichen nibbeln



tholan
01.02.2006, 16:06
Hi,
bin neu in C- Programmierung und WinAVR.
Wollte mal fragen, ob's nen netten Menschen gibt, der mir
beim "Nibbeln" der ASCII-Werte eines Zeichenstrings
mal auf die Sprünge helfen kann. Ist für die
4-Bit Ansteuerung eines 4x27 LC-Displays.
Hab mir schon folgendes Gerüst für eine Unterfunktion
zurechtgebastelt:



void Textausgabe(void)
{
uint8_t UpperNibble,LowerNibble,count;
//Massstab: "0xxxxxxxx1xxxxxxxxx2xxxxxx7"
char Text[27]="0xxxxxxxx1xxxxxxxxx2xxxxxx7";
for(count=1;count<28;++count)
{
//Ein Zeichen holen, Typumwandlung uint8_t => char ??? (weiss nicht,ob's das Gleiche ist.)
//Unteres Nibbel von Text(count) mit &0xf0 "vernichten", Oberes Nibbel /16 => nach unten (weiss nicht, wie man 4 Bit auf einmal shiftet)
//Nibbel ausgeben
//Oberes Nibbel "vernullen" ( in Bit 4 und 5 liegen bei mir E1 und E2 des Displays), dann Byte ausgeben.
}

}

Belegung LCDisp. an ATMega8: D4 - D7 an PC0 - PC3, E1 an PC4, E2 an PC5, RS an PB0, R/W an Masse.
Wär wie gesagt toll, wenn ich da einen "Anschubser" bekäme.
Vielen Dank schonmal,
tholan

SprinterSB
01.02.2006, 16:31
Hi,
bin neu in C- Programmierung und WinAVR.
Wollte mal fragen, ob's nen netten Menschen gibt, der mir
beim "Nibbeln" der ASCII-Werte eines Zeichenstrings
mal auf die Sprünge helfen kann. Ist für die
4-Bit Ansteuerung eines 4x27 LC-Displays.
Hab mir schon folgendes Gerüst für eine Unterfunktion
zurechtgebastelt...


So was in der Richtung? Die Ausgabe hab ich jetzt nicht ausgeführt, das ist abhängig vom Displaytyp/Treiber.


#include <inttypes.h>

void Nibbleausgabe (const uint8_t nibble);
void Textausgabe (const uint8_t*);

// Massstab: "0xxxxxxxx1xxxxxxxxx2xxxxxx7"
char text[] = "0xxxxxxxx1xxxxxxxxx2xxxxxx7";

void Textausgabe (const uint8_t *tx)
{
// Zeiger tx läuft durch den String

while (1)
{
uint8_t nibble;
// Ein Zeichen holen, Typumwandlung uint8_t => char ??? (weiss nicht,ob's das Gleiche ist.)
// Zeichen aus RAM lesen, Zeiger eins weiter
uint8_t zeichen = *(tx++);

// zeichen == 0 --> Stringende
if ('\0' == zeichen)
break;

// Unteres Nibbel von Text(count) mit &0xf0 "vernichten",
// Oberes Nibbel /16 => nach unten
nibble = zeichen >> 4;
// high Nibbel ausgeben
Nibbleausgabe (nibble);

// Oberes Nibbel "vernullen"
// (in Bit 4 und 5 liegen bei mir E1 und E2 des Displays),
// dann Byte ausgeben.
nibble = zeichen & 0x0f;
// low Nibbel ausgeben
Nibbleausgabe (nibble);
}
}

void Nibbleausgabe (const uint8_t nibble)
{
}

PicNick
01.02.2006, 16:44
VIelleicht der Zusatz: SPrinter hat auf das "obere Nibble vernichten" verzichtet, da das
nibble = Zeichen >> 4
sowieso diese Bits löscht.

SprinterSB
01.02.2006, 16:59
Jau, dabei ist aber darauf zu achten, daß man die Zeichen als unsigned char (bzw. uint8_t) ausliest.

Ansonsten wird als oberes Bit beim Schieben nicht die 0 nachgeschoben, sondern das Vorzeichen. Bei Werten von 0x80..0xff bzw -128..-1 müsste man dann explizit noch mit einer Maske die oberen Bits löschen.

ogni42
01.02.2006, 17:02
dann noch:

while (*tx)

und man kann die if -abfrage sparen

Das ausmaskieren des oberen Nibbles ist nur dann nötig, wenn die Portpins anderweitig benutzt und in Nibbleausgabe nicht gesetzt werden.

PicNick
01.02.2006, 17:04
Na, dann noch ein's drauf: Es empfiehlt sich, das "Nibble löschen" gleich in die Nibble-Ausgabe zu verschieben, ein für allemal.


void Nibbleausgabe (const uint8_t nibble)
{
xxx = nibble & 0x0F;
.....
}

tholan
01.02.2006, 17:12
Super!
Ich denk, damit komm ich klar und weiter!
Bin halt ziemlich BASIC-versaut.
Zeichen mit Zeigern ausm RAM lesen und
Byte shiften gibts da halt nicht.
Danke nochmal,
tholan

SprinterSB
01.02.2006, 17:17
dann noch:

while (*tx)

und man kann die if -abfrage sparen.

Jo, damit spart man aber nur Quellcode, der erzeugte Code wird länger ;-)

tholan
01.02.2006, 18:44
Könnt ihr euch nochmal angucken, was ich jetzt verbrochen habe?


void Textausgabe(void)
{
const uint8_t *tx;
uint8_t nibble, zeichen;
char text[]="Lieber blau, als grau.";
while(1)
{
zeichen = *(tx++);
if ('\0' == zeichen)
break;
nibble = zeichen >> 4;
PORTC = nibble; //Zeichen anlegen...
Dat_tog_E1(); //und Feuer!
nibble = zeichen & 0x0f; //muss maskiert sein, wg. E1 / E2 an PC4 / PC5
PORTC = nibble;
Dat_tog_E1();
}
}

Der Compiler läuft durch und meckert nur noch, daß *tx evtl. nicht initialisiert ist
und das char text[] nicht benutzt wird (logisch).
Wie lasse ich jetzt *tx auf den String zeigen?
Der Cursor auf'm Display rutscht übrigens schon brav um eins weiter und malt
mir davor 'ne Hieroglyphe.
thx

PicNick
01.02.2006, 19:45
Kollege (*tadel*) tx is ja auch nicht initialisiert, das gibt stunk beim Ablauf

Muttu machen:
char text[]="Lieber blau, als grau.";
const uint8_t *tx = (uint8_t)&text; // addresse von text reinschreiben

Is ja wohl nur eine Testroutine ?

Zeichen mit Zeigern ausm RAM lesen und Byte shiften gibts da halt nicht.

Sag das nicht !

tholan
01.02.2006, 22:31
Is logischer Weise nur 'n Test (wo issn' hier der Rot-werd-Smiley?).
Hab halt mit C noch ganz schön zu kämpfen.
Das Display könnte ich langsam per Hand mit 'nem
Mäuseklavier (Schiebeschalterreihe) initialisieren.
Mit Basic (CC1 Basic und Qbasic am Parallelport)
hat die Ansteuerung jedenfalls schon gut geklappt.
Jetzt will ich mich aber schon noch mit 'ner "richtigen"
Programmiersprache (WinAVR) und 'ner "richtigen" MCU
(ATMegaxx) auseinandersetzen.
Danke nochma,
tholan

p.s.
Bei Qbasic gibts glaub ich sowas wie "varptr()", braucht man aber nich :) .

SprinterSB
02.02.2006, 11:04
Kollege (*tadel*) tx is ja auch nicht initialisiert, das gibt stunk beim Ablauf

Muttu machen:
char text[]="Lieber blau, als grau.";
const uint8_t *tx = (uint8_t)&text; // addresse von text reinschreiben


Nö, wenn überhaupt, is da ne Brezel (&) zu viel und es muss heissen

const uint8_t *tx = (const uint8_t*) text;

Ausserdem hatte ich ober für Textausgabe definiert

void Textausgabe (const uint8_t *tx) ...

damit die Routine nicht auf einen String festgenagelt ist. Sie bekommt den String (bzw Anfangsadresse) als Parameter. Aufruf:


const char text[] = "...";

int main()
{
....
Textausgabe (text); // Text ausgeben
Textausgabe ("Hallo"); // "Hallo" ausgeben
}

PicNick
02.02.2006, 11:10
Wenn du auf vielen Plattformen mit vielen verschiedenen Compilern arbeitest,gewöhnst du dir schnell an, eher zuviel als zuwenig Brezeln hinzuschreiben.
Aber der asteriks hat gefehlt, da hast du recht.

ogni42
02.02.2006, 11:46
Jo, damit spart man aber nur Quellcode, der erzeugte Code wird länger


Bei mir aber nur bei -O0, bei -O2 ist er gleich lang. (Aber vielleicht sollten wir die Disukssion besser im C-Forum führen :) )

tholan
03.02.2006, 18:07
Schätze,
werd mich wohl noch ein bischen intensiver
dem gcc widmen müssen (bischen rumreferenzieren üben).
C scheint doch nicht Basic zu sein :) .
thx,
tholan