Versuche, die char (8 bit) Werte vom ATMEGA per USARTz zu senden. Excel
soll die Werte einlesen.
Im Excel benötige ich die Werte und nicht die Zeichen. Besteht die
Möglichkeit, dass Excel die Umwandlung vornimmt. Das hätte auch den
Vorteil, dass nur ein Zeichen pro Wert übertragen wird.
Oder gibt es da einen C-Befehl der char-Werte in ASCI-Zeichen umwandelt?
Danach müsste man die Zeichenkette (3 Zeichen) für einen Wert per USART
senden.
Thanks im Voraus!
Hallo Jogibär!
Danke für deinen Tipp, aber leider funktioniert es nicht.
Sende ich den Integer-Wert 123 zum HyperTerminal, so bekomme ich dort
123115!
Zum senden verwende ich "usart_puts".
Ich vermute, weil >itoa< nur für 16Bit Integer geeignet ist. Oder mache
ich was falsch? Muss (kann) ich den INTEGER in eine CHAR-Wert umwandeln.
Bitte um Hilfe.
Hi,
itoa wandelt dir deinen integer Wert in ein Array um. Oder Quasi in eine
Char Variable, die müsstest du dann senden können.
Mache das mit meinem LCD Display am AVR auch.
In C sieht das dann so aus:
So ist das aber nichts.
1. Die auto-variable "lcd_wert" auf dem stack ist nach dem return nicht
mehr gültig.
2. Der return eines solchen strings sollte auch mit "char *" deklariert
sein.
3. Die Zuweisung "lcdstring = lcd_wert;" sollte eigentlich auch ein paar
Warnings geben. Darüberhinaus ist sie unnötig.
Gruß
Hi,
nunja, der Code läuft so.
1. Das war mir bewusst, wird sonst auch nirgendwo verwendet.
2. Bitte beschreib mir mal genauer, was du da meinst.
3. Warnungen gab es keine. Das sie nicht notwendig war, ist mir im
nachhinein auch bewusst.
Ist eins meiner ersten Programme.
MfG
Jens K. wrote:
> Hi,> nunja, der Code läuft so.
Mag sein, aber nicht sicher. Punkt 1. ist eine Zeitbombe, wenn dir da
ein Interrupt bis zur Verwendung der Variable im Aufrufer dazwischen
funkt wird Schrott ausgegeben.
>> 1. Das war mir bewusst, wird sonst auch nirgendwo verwendet.
Dann ist es ja gut;-)
>> 2. Bitte beschreib mir mal genauer, was du da meinst.
Nun, willst doch einen String in Form eines char-Arrays zurückgeben,
oder? So wie du es deklarierst ist es aber nur ein einzelnes Zeichen.
>> 3. Warnungen gab es keine.
Also hier (avr-gcc3.4.6) kommt:
"warning: assignment makes integer from pointer without a cast"
>> War eins meiner ersten Programme.
Kein Problem.
Gruß
Hi Harald,
Zum ersten Punkt, wie müsste ich mit der Variablen umgehen, dass sie
nicht verloren geht? Müsste ich ne globale Variable verwenden, die ich
im Unterprogramm verwende?
3. Habe es nochmal durchkompiliert und dabei habe ich auch deine besagte
Warnung bekommen. Wie müsste ich den Return-Wert abändern, dass er mir
dort diese Fehlermeldung nichtmehr ausgibt? Müsste ich an dieser Stelle
auch eine globale Variable verwenden? Oder im Allgemeinen, wenn ich aus
einem Unterprogramm einen Wert zurückgebe in ein anderes oder auch in
Main, muss es sich beim zurückgeben in Main immer um eine globale
Variable handeln und muss ich die Variable im Falle eines Aufrufs aus
einem anderen Unterprogramm auch in dem aufrufenden Unterprogramm
deklarieren, oder einfach in diesem Fall auch eine globale Variable
verwenden?
Sollte ich in solch kleinen Programmen vll komplett auf lokale Variablen
verzichten?
MfG
i.a. kann man in c mit chars genauso rechnen wie mit integer. je nach
compiler ist manchmal sogar ein char nur ein int mit 8 bit. deshalb gibt
es auch keinen unterschied in der übertragung ob nun 0x20, ' ' oder 32
gesendet wird - nur die darstellung ändert sich.
daher ist es dem controller auch egal ob nun chars oder bytes gesendet
werden. dadurch liegt das problem mit der darstellung als zahl oder als
buchstabe auch an excel.
Jens K. wrote:
> Hi Harald,>> Zum ersten Punkt, wie müsste ich mit der Variablen umgehen, dass sie> nicht verloren geht?
Bei Programmierung im PC-Bereich würde ich mir Speicher über "malloc"
(o. "new") holen und ihn beim Aufrufer wieder freigeben.
Bei Programmierung im uC-Bereich lege ich im Aufrufer den Speicher an,
und übergebe ihn. Der kann dann auch lokal sein.
> 3. Habe es nochmal durchkompiliert und dabei habe ich auch deine besagte> Warnung bekommen.
wusst' ich es doch;-)
> Wie müsste ich den Return-Wert abändern, dass er mir> dort diese Fehlermeldung nichtmehr ausgibt?
Wenn du ein char-Array zurückgeben willst, dann mit:
1
char*funktion()
2
{
3
char*lcdstring;
4
..
5
..
6
..
7
returnlcdstring;//Rückgabe als string
8
}
> Müsste ich an dieser Stelle> auch eine globale Variable Verwenden? Oder im Allgemeinen, wenn ich aus> einem Unterprogramm einen Wert zurückgebe in ein anderes oder auch in> Main, muss es sich beim zurückgeben in Main immer um eine globale> Variable handeln
nein. Es kommt darauf an ob du den Wert selbst zurück gibst, oder (wie
hier) eine Referenz.
> Sollte ich in solch kleinen Programmen vll komplett auf lokale Variablen> verzichten?
Würde ich nicht, lokale Variablen sparen statischen Speicher und sorgen
auch für Kapselung.
Gruß
Ok, vielen Dank schonmal bis hierhin.
Das mit dem Übergeben, wie meinst du das genau? Ich nehme mir einen
Wert, übergebe ihn an mein Unterprogramm, verändere ihn dann dort und
gebe den selben Wert wieder zurück? Oder Deklarierst du einen
Übergabewert hin und einen Zurückwert im aufrufenden Programm?
Wenn ich mir das so durchlese klingt die zweite Möglichkeit etwas zu
überdimensioniert, da ich den alten Wert danach ja eigentlich nichtmehr
benötige. Oder liege ich da falsch?
Ok nun zu dem Codeschnipsel. Habe ihn nun mal so verändert:
1
char*umwandlung()
2
3
{
4
inti=100;
5
char*lcd_wert[5];
6
7
8
i=lese();//Analogwert aus lese UP aufrufen
9
10
itoa(i,lcd_wert,10);//Umwandeln in Dezimalstring
11
12
13
14
15
returnlcd_wert;//rückgabe int als string
Bekomme dabei nun folgende Fehlermeldungen:
../int_to_string.c:14: warning: implicit declaration of function 'lese'
Diese Problem habe ich leider noch nicht so ganz duchschaut. Ich Rufe ja
meine Funktion lese auf, in welcher ich den Analogwert einlese. Müsste
ich mir im aufrufenden UP für diesen Wert noch eine Variable anlegen?
Diese Fehlermeldung war aber schon vor der Änderung da. Aber da wir ja
gerade dabei sind :=)
../int_to_string.c:16: warning: passing argument 2 of 'itoa' from
incompatible pointer type
Diese Fehlermeldung ist neu, kann aber mit dieser leider garnichts
anfangen.
../int_to_string.c:21: warning: return from incompatible pointer type
Auch diese ist neu, wird aber meiner Ansicht nach was mit der vorigen
Fehlermeldung zu tun haben.
../int_to_string.c:21: warning: function returns address of local
variable
Das ist ja das Problem, wo auch die erste Warnung drauf abzielt. Da
werde ich nochmal genauer schauen müssen.
Hier nochmal das ganze Unterprogramm. fällt dir damit sicher leichter,
als es dir nur vorzustellen.
1
#include<avr/stdlib.h> // für Befehl itoa einbinden
Hi,
habe den code nun mal abgeändert in folgenden:
1
#include<avr/io.h>
2
#include<avr/lcd_routines.h>
3
#include<util/delay.h>
4
5
6
7
8
9
10
intmain(void)
11
12
13
14
{
15
charlcd_wert[5];
16
unsignedchari;
17
18
19
lcd_init();//initialisieren LCD
20
21
22
23
24
while(1)
25
26
{
27
28
lcd_init();
29
i=lese();
30
i=123;
31
umwandlung(i,lcd_wert);
32
33
lcd_string(lcd_wert);//Ausgabe des Umgewandelten Analogwertes auf LCD
34
35
36
}
37
return0;
38
}
Bekomme aber leider immernoch folgende Warnmeldungen:
../main_ausgabe.c:30: warning: implicit declaration of function 'lese'
und
../main_ausgabe.c:32: warning: implicit declaration of function
'umwandlung'
Kannst du mir dazu noch etwas sagen?
MfG
Die Fehlermeldungen bedeuten, dass die besagten Funktionen dem Compiler
zum Zeitpunkt ihres Aufrufs nicht bekannt sind, weshalb der Compiler
denkt, Du willst sie an der Stelle deklarieren. Eine Funktion muss vor
ihrem ersten Aufruf mindestens deklariert werden.
Du solltest nebenbei noch eine Fehlermeldung der Art "Achtung! Zu viele
Leerzeilen im Quelltext" bekommen, und da der Compiler das nicht macht,
bekommst Du sie jetzt von mir...
Die Funktionen lese() und umwandlung() benötigen eine
Prototyp-Deklaration. Diese solltest du jeweils in einem Header-File mit
dem gleichen Namen der C-Datei, in welcher sich die Original-Funktion
befindet, jedoch mit der Endung .h unterbringen. Dieser Headerfile wird
dann dort, wo er benötigt wird, included.
Zum Ausprobieren reichts erst mal, das oberhalb von main() einzufügen.
Die Deklaration sollte aber identisch zur Originalfunktion sein. Da du
diese Funktionen hier noch nicht reingestellt hattest, kann ich nur
raten:
unsigned char lese();
void usart_puts(char *ptr);
Gruss, Bernd
:)
Ok, werde meinen zukünftigen Code etwas kompakter schreiben.
Nunja, hab ein wenig rumprobiert und bin wohl auf den Grund gestoßen,
warum er sie nicht finden kann. Aus Übersichtsgründen habe ich die
einzelnen Funktionen in seperate *.c Daeien gepackt, die ich dann links
neben im Projektbaum ( verwende AVR Studio mit GCC Plugin ) schön
einzeln öffnen kann.
Wenn ich nun diese einzelnen Funktionen nehme und schreibe sie in die
Datei wo sich auch mein main befindet, sind diese Fehlermeldungen weg.
So scheint es zumindest erstmal.
Gibt es eine Möglichkeit dem Compiler zu sagen, dass er aus mehr als nur
einer Datei besteht?
MfG
Hallo Bernd,
das heisst nun, dass ich die einzelnen C Dateien dann in h Dateien
umbenennen muss und sie dann oben include?
Das wäre ja sehr umständlich.
Dann noch eine Frage. Ich verwende ja nun die Standart Header Dateien.
Links im Projektbaum ( AVR Studio 4 mit GCC Plugin ) gibt es ja so eine
schöne Aufteilung. Kann ich die Headerdateien, die dort liegen nicht
auch irgendwie einfach einbinden?
Würde in meinen Augen den Sinn machen, dass ich dann das Projekt schön
zusammen in einem Verzeichnis hätte.
MfG
Nein, es gibt eine Originaldate mit den kompletten Funktionen und eine
Headerdatei mit den Prototypen, jedoch ohne Funktionsinhalt.
In die Datei "funktionen.h" kommt folgendes
Standard Headerfiles werden üblicherweise so eingebunden:
#include <stdio.h>
dabei fügt der Compiler seinen default-include-Pfad ein.
und deine header so:
#include "funktionen.h"
Diese Datei wird aus deinem Verzeichnis eingefügt.
Bernd
Alle Funktionsprototypen, welche irgendwann mal an anderer Stelle
benötigt werden könnten, in die Header-Datei. Genauso die globalen
Variablen und #defines.
Nun habe ich ein anderes Problem. Habe in die Headerdatei die Funktionen
eingetragen.
1
#include<avr/io.h>
2
#include<avr/lcd_routines.h>
3
#include<util/delay.h>
4
#include<avr/stdlib.h>
5
#include"funktionen.h"
6
7
intmain(void)
8
{
9
charlcd_wert[5];
10
unsignedchari;
11
12
13
lcd_init();//initialisieren LCD
14
15
while(1)
16
{
17
lcd_init();
18
i=lese();
19
i=123;
20
umwandlung(i,lcd_wert);
21
22
lcd_string(lcd_wert);//übergabe Wert an LCD
23
}
24
return0;
25
}
Nun kommen folgende Fehlermeldungen:
../main_ausgabe.c:7: error: expected '=', ',', ';', 'asm' or
'__attribute__' before 'int'
und
../main_ausgabe.c:25: error: expected '{' at end of input
Beim Draufklicken springt der Zeiger in die Zeile meiner Main Anweisung
bei der zweiten Springt er auf die geschweifte Klammer am Ende?
Wenn ich die funktion.h wieder rausnehme, funktioniert alles wie vorher.
MfG
Aber nun noch eine Frage. Wieso schreibe ich die Prototypen meiner
Funktionen sowie die globalen Variablen nocheinmal in eine extra
Headerdatei?
Die stehen ja eigentlich schon alle im Code. Oder liegt es an den vielen
Codedateien, die ich habe?
> Oder liegt es an den vielen Codedateien, die ich habe?
Ja, genau. Wenn der Compiler aufgerufen wird, wird das für genau eine
.c-Datei gemacht. Er sieht nur diese, und sonst nichts. Damit er weiß,
wie der Aufruf einer Funktion aussehen muß und welche Funktionen
überhaupt existieren, benötigt er in dieser Datei deshalb den Prototyp.
Damit man nun nicht in jeder einzelnen .c-Datei sämtliche Prototypen
hinschreiben muß, werden die in Headern zusammengefaßt, die dann per
#include vom Präprozessor in die .c-Datei eingebunden werden, bevor der
eigentliche Compiler sie dann sieht.
Die Header-Datei muss überall dort eingebunden werden, wo du eine der
Funktionen verwenden willst.
Selbst hier ist ein Prototyp notwendig, da funktion_b beim Aufruf noch
nicht bekannt ist:
Der Compiler legt eine Tabelle mit Funktionen, Variablen, Konstanten
usw. an. Beim Aufruf einer Funktion schaut der Compiler nach, ob und wie
diese deklariert ist. Bei Unklarheiten gibts eine Warnung oder Error.
Der Linker weist später jeder Funktion eine Adresse zu. Damit ist erst
dem Linker bekannt, wohin ein Aufruf/Sprung geht.
Bernd
Vielen Dank für die netten Erklärungen.
Diese grundlegenden Möglichkeiten mit der Headerdatei und das Einbinden
von Headerfiles, die neben im Projektverzeichnis sind, findet man leider
( oder ich habe sie noch nicht gefunden ) in keinem c Tutorial.
Mfg