mikrocontroller.net

Forum: Compiler & IDEs Progmem&uart


Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

Vorab einmal, ja ich habe die Suche benutzt und auch etwas gefunden.
Nur leider verstehe ich das noch nicht so ganz mit Progmem.

http://www.mikrocontroller.net/forum/read-2-94515.html#new

Diesen Thread habe ich mir mal zu Hilfe genommen.
Vielleicht würde ich ja damit ein Programm zum laufen bringen,
allerdings ist es das alleine nicht, ich möchte auch begreifen,
wesshalb das so gemacht werden muss.

Wesshalb kann ich zum Beispiel nicht einfach schreiben:

>const char SHOW0[] PROGMEM = "BRAUCHWASSER";
>lcd_puts(SHOW0);


Ich meine, wesshalb wird da noch so etwas wie strcpy_P (buf, SHOW[0]);
Verwendet?

Für meine Anwendung möchte ich vorerst nur einmal einen String als
Progmem
 speichern und diesen über den Uart ausgeben.
Die Funktion für den uart habe ich bereits und die funktioniert auch.
Unter anderem habe ich eine Funktion, die nur ein einzelnes Byte
sendet.

Die möchte ich in der art wie z.B.

UART_SendByte(daten[20]);
verwenden, um nur ein einzelnes byte zu senden.

Nun aber, wie bringe ich das nun hin, dass der string "daten"
eben ein als progmem definierter String ist und was muss ich eventuell
noch beachten?

Sorry für die Anfängerfragen, aber bis jetzt habe ich für etwa 4 Jahre
nur in Basic / Visual Basic
programmiert, da ist der Umstieg zu C schon nicht gerade einfach. :-(

mfg Nik

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, ich habs nun hinbekommen, die als progmem zu definieren und auch
auszulesen. Nur die bytes sind die falschen.
Nun habe ich in einem anderen Thread etwas über pointer gelesen...
Aber wie mache ich das mit diesem Pointer nun genau, wenn der progem
string bei mir so ausschaut:

PROGMEM char MUSIK[] = {
0xFF,0xE3,0x18,.....}

??

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mittlerweilen habe ich einiges schon selbst herausgefunden-ich hab
mir jetzt eine eigene Funktion gemacht die eigentlich mit Hilfe eines
Pointers die Werte auslesen sollte:

void send_prg(uint16 count, uint16 *zeiger)
{
  while (count--)
  {

     UART_SendByte(*zeiger);
    *zeiger++;
  }
}

Aufrufen tue ich das ganze zum Beispiel mit

send_prg(5, MUSIK);

wobei MUSIK der String vom obigen thread ist. Nun kriege ich trotz dem
Pointer aber immer noch falsche Werte, an was liegt denn das nun?

mfg Nik

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Dereferenzierung des Pointers 'zeiger' in dieser Zeile

     UART_SendByte(*zeiger);

weiss nicht, daß das ein progmem-Pointer ist; Du wirst hier eine der
Zugriffsfunktionen auf den Flash-Speicher verwenden müssen.

     UART_SendByte(pgm_read_byte(zeiger));

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
"undefined reference to 'pgm_read_byte'"
Und das, obwohl ich pgmspace.h included habe.

aber dennoch danke-gibts evtl noch eine andere Möglichkeit das mit
einem alten gcc(3.3.3) zu lösen? Denn ich kann kaum den ganzen Rest des
Programms ändern...

Autor: Tobias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe das vor einiger Zeit auch mal gemacht:
Nimm unten die Zeile mal als Basis.

PGM_P Pointer = (PGM_P)pgm_read_word((int)datensaetze +Index*
sizeof(PGM_P));

datensaetze ist als PGM_P datensaetze[15] PROGMEM {ersterstring, 2ter,
usw...}initialisiert.

ersterstring usw sind als "const prog_char" abgelegt.

In Pointer steht dann das Zeichen das du ausgelesen hast.

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.
   "undefined reference to 'pgm_read_byte'"
   Und das, obwohl ich pgmspace.h included habe.

Tja, was soll man da machen?

Was steht denn in Deiner Version von pgmspace.h drin? Und was hat das
mit der Version von gcc zu tun, das ist doch die avr-library, zu der
pgmspace.h gehört ...

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Tja, was soll man da machen?

Tja, das frage ich mich eben auch, pgmspace.h included progmem.h
Doch in progmem finde ich die funktion pgm_read_byte auch nicht
ansatzweise, heisst denn der befehl bei einer früheren libc version
anders?

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, PRG_RDB, wenn ich mich nicht irre.

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hey, danke, so scheints schon zu funktionieren, naja, jedenfalls fast
:)
Beim compilieren krieg ich nun keine fehlermeldung mehr, allerdings
kriege ich immernoch wirre Zeichen...

Meine Funktion sieht nun so aus:

void send_ascii(uint16 count, unsigned char *zeiger)
{
  while (count--)
  {
     UART_SendByte(PRG_RDB(*zeiger++));
        }
}


dann habe ich eine Variabel:

      PROGMEM char test[] = "hallo";

Und das ganze rufe ich dann so auf:

      send_ascii(5,test);

Ich empfange aber blos Datensalat, allerdings ist das Problem
reproduzierbar, auch nach einem Reset des uc erhalte ich genau
dieselben bytes.

Ein Problem mit dem Uart ist es aber nicht, denn wenn ich mit
 UART_SendByte(); direkt ein Byte sende, kommt dieses korrekt an...

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kein Wunder, daß das nicht funktioniert:

  UART_SendByte(PRG_RDB(*zeiger++));

Du lässt immer noch den Compiler den Pointer dereferenzieren, und das
geht in die Hose. PRG_RDB will aber -ebenso wie das neuere
pgm_read_byte- einen Pointer als Argument übergeben bekommen.

Lass' in der Zeile mal den '*' weg und sieh' Dir das Macro PRG_RDB
genau an, ob es sich mit dem ++-Operator verträgt. Bei Unklarheiten
solltest Du das sicherheitshalber so schreiben:

  UART_SendByte(PRG_RDB(zeiger));
  zeiger++;


Wird's klarer?

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oho, schon viel besser :P
Nur ein Problem habe ich noch:

Originaldaten:
0xFF,0xE3,0x18,0xC0,0x00,0x00,0x00,0x03,0x48,0x01,0x80,0x00,0x00,0xFF,0x 
0C,0x5E...

empfangene Daten:

0xFF 0x18 0x00 0x00 0x48 0x80 0x00 0x0C 0x02 0x00 0x00 0x54 0xFC 0x10
0x60 0x30

es scheint, als ob der pointer irgendwie immer um 2 inkrementiert
wird,
ich bekomme einfach nur immer jedes zweite byte-doch wesshalb?

>UART_SendByte(PRG_RDB(zeiger));
>  zeiger++;


>Wird's klarer?

Ja allerdings, nur verstehe ich noch nicht ganz wesshalb
man den stern dann auch weglassen muss-?

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Stern musst Du weglassen, weil der der Operator zur
Pointerdereferenzierung ist. Und genau die kann der Compiler mit
ROM-Pointern nicht durchführen.
Du weißt nicht, was eine Pointerdereferenzierung ist? ->K&R lesen.

Das mit dem "zwei Bytes weiterspringen" wird wohl an der 16 Bit
breiten Organisation des Flash liegen; hier kann ich nur auf die
Dokumentation der avr-libc verweisen und Dir außerdem ein Update auf
die aktuelle Version nahelegen; mich wundert, daß das noch kein anderer
getan hat.

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>16 Bit
breiten Organisation des Flash liegen

DANKE :D es war zwar nicht dies, aber ich war zu blöd den Pointer 16
bit breit anzulegen...

zuerst hatte ich (uint16 *zeiger)

so funktionierts aber:

void send_hex(uint16 count, uint8 *zeiger)
{
..
}

ich verstehe allerdings nicht wirklich wesshalb, die adresse wird ja
wohl höher sein als nur 8bit also höher als 0xff.
Naja, wenigstens funktioniert es einmal :)

Vielen Dank Rufus-ich werd dann mal versuchen das
ganze über spi statt den uart zu senden-und zwar an einen vs1001k...

mfg Nik

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
.

   "zuerst hatte ich (uint16 *zeiger)

   so funktionierts aber:

   (uint8 *zeiger)

   ich verstehe allerdings nicht wirklich wesshalb, die adresse
   wird ja wohl höher sein als nur 8bit also höher als 0xff."

Das ist Grundlagenwissen in C. Ein Pointer, der auf einen bestimmten
Datentyp verweist, wird beim Inkrementieren mit ++ um die Anzahl an
Bytes erhöht, die ein Objekt des Datentyps im Speicher belegt.

Also:
sizeof (uint16) == 2, ++ erhöht den Pointer um zwei.
sizeof (uint8) == 1, ++ erhöht den Pointer um eins.
sizeof (uint32) == 4, ++ erhöht den Pointer um vier.

Die Pointer selbst sind alle gleich groß, egal, auf was für Datentypen
sie verweisen.

Literaturhinweis: K&R, Programmieren in C, zweite Auflage, Hanser
Verlag.

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Also:
>sizeof (uint16) == 2, ++ erhöht den Pointer um zwei.
>sizeof (uint8) == 1, ++ erhöht den Pointer um eins.
>sizeof (uint32) == 4, ++ erhöht den Pointer um vier.

vielen dank, ich denke ich hab das mit den pointern endlich begriffen
lol

Wenn das alles in dem Buch steht, ist das sicherlich eine Anschaffung
Wert:P

Tja, ich muss sagen, ich krieg langsam Freude an C, das erste mini mp3
file (5sekunden) mit progmem läuft :D
Jetzt fehlt "nur" noch ata und fat...hmpf
Das ganze soll am Schluss so werden wie yampp, nur möchte ich dabei das
Programm auch verstehen und ein bisschen mehr machen, als harware
zusammenlöten und fertig ists...
Falls ich das alles mal geschafft habe möchte ich auch noch mit einem
iim7000a eine netzwerkanbindung machen-aber das ist wohl noch ein
langer weg ;-)

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mist, ich habe mal nach dem buch gesucht, allerdings auch im internet
nicht allzuviel gefunden, hättest du vielleicht die isbn nummer gerade
zur hand? :)

Autor: Volkmar (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einmal bei amazon.de nach 'Programmieren in C' gesucht und gleich
gefunden:
http://www.amazon.de/exec/obidos/ASIN/3446154973/q...

Volkmar

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.lob.de/cgi-bin/work/outputexpert?id=42b...

Vorteil von Lehmanns: Lieferung in Deutschland ohne Versandkosten.

Autor: Nik Bamert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hehe danke, ich habs nun auch gefunden(bei www.books.ch) da ich aus CH
bin würde ich allerdings dennoch versandkosten haben bei Lehmanns.
Naja dann hol ichs eben im Laden, dann hab ich auch keine Versandkosten
;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.