PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Signalzustand senden



Reeper
16.08.2007, 21:08
Hallo,

schlage mich mal wieder mit C herum.
Nun habe ich das Problem, dass die Variable bPortD nicht korrekt gesendet wird.
Kann es daran liegen, dass dies eine int ist und das eine char gesendet wird?



#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>


int i;
uint8_t bPortD;



void string_senden (const char *string);
void usart_initial();

int main(void)
{
DDRD |= (1<<4) | (1<<5);
usart_initial();
while(1)
{
bPortD = PIND;
string_senden (bPortD);
string_senden ("\n\r");
if (PIND & (1<<PIND7)){
string_senden ("Taster nicht gedrueckt\r\n");
}
if ( !(PIND & (1<<PIND7))){
string_senden ("Taster gedrueckt\r\n");
}
for (i=0; i<100; i++)
{
_delay_ms(10);
}
}
}

//-----------------------------------------------------

void usart_initial()
{
UBRRH = 0;
UBRRL = 7;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}


//-----------------------------------------------------
void string_senden (const char *string)
{
while (*string)
{
while (!(UCSRA & (1<<UDRE)))
{}
UDR = *string++;
}
}

//-----------------------------------------------------

izaseba
16.08.2007, 21:19
Ja ist doch klar...
Gibt der Kompiler keine Warnung ?
Deine string_senden Funktion erwartet eine Zeiger auf const char
Du übergibst aber uint8_t oder unsigned char, das ist doch ein Unterschied oder ?
es müßte wirklich eine Warnung kommen...
mach das ganz einfach:

#include <stdlib.h>

irgendwo am Anfang von main

char puffer[5];

vor der ausgabe

itoa (bPortd,puffer,10);
stringsenden(puffer);

ond mach const weg.

Gruß Sebastian

Reeper
16.08.2007, 22:41
Vielen Dank, nun funktioniert es O:)

Reeper
17.08.2007, 15:56
Nach langer Suche (nun weiß man nach was man suchen musste - ist viel dazu im Forum schon gewesen 8-[ ) eine weitere Frage:

verkürzter Code:

uint8_t bPortD;
char puffer[8];
.....
bPortD = PIND;
utoa(bPortD,puffer,2);
string_senden(puffer);

das funktioniert einwandfrei.

Da Variable "puffer" ein String (char Array) ist, müsste ich doch einfach wie auf dem PC auf den Inhalt zugreifen können und ausgeben.
Wieso funktioniert das nicht:

string_senden (puffer[5]);

Da kommt nur Mist heraus :-k

Gruß
Stefan

izaseba
17.08.2007, 16:10
Stefan,
liest Du überhaupt was man Dir schreibt?
Ich zitiere mich nochmal:


Deine string_senden Funktion erwartet eine Zeiger auf const char
Du übergibst aber uint8_t oder unsigned char, das ist doch ein Unterschied oder ?

und ? was ist bitte puffer[5] ?
Was meldet der Kompiler ?
Was möchtest Du erreichen ?
Oder anders gefragt, wenn Du ein uint8_t mit itoa/utoa behandelst, wieviel Platz wird im puffer belegt (mit '\0') und was steht sinnvolles bei puffer[5] ?
Dein String_senden erwartet ja einen Zeiger, also &puffer[5], aber Achtung, es wird solange was ausgegeben bis '\0' kommt ...

Gruß Sebastian

Reeper
17.08.2007, 16:35
Also gut,
in C bin ich ein Noob und versuche mich hinein zufinden. Denke es klappt so gaanz langsam. Mit Zeiger habe ich mich noch nicht beschäftigt, will hier ja"nur" den Inhalt lesen.

Der Compiler gibt mir nach erfolgreichen compilieren diese 3 Warnungen:


c:17: warning: function declaration isn't a prototype
c: In function `main':

c:41: warning: passing arg 1 of `string_senden' makes pointer from integer without a cast
c: At top level:

c:49: warning: function declaration isn't a prototype

Kompletter Code:

#include <avr/io.h>
#include <string.h>
#include <stdint.h>
#include <util/delay.h>
#include <inttypes.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>


int i;
uint8_t bPortd;
char puffer[8];


void string_senden (char *string);
void usart_initial();

int main(void)
{
DDRD |= (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
DDRA &= ~( (1<<PA0));
usart_initial();
while(1)
{
PORTD |= (1<<2) | (1<<3) | (1<<4) | (1<<6) | (1<<7);
bPortd = PIND;
utoa(bPortd,puffer,2);
string_senden(puffer);
string_senden ("\n\r");
if (PINA & (1<<PINA0)){
string_senden ("Taster nicht gedrueckt\r\n");
}
if ( !(PINA & (1<<PINA0))){
string_senden ("Taster gedrueckt\r\n");
}
for (i=0; i<100; i++)
{
_delay_ms(10);
}
string_senden (puffer[5]);
string_senden ("\n\r");
}
}

//-----------------------------------------------------

void usart_initial()
{
UBRRH = 0;
UBRRL = 7;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}


//-----------------------------------------------------
void string_senden (char *string)
{
while (*string)
{
while (!(UCSRA & (1<<UDRE)))
{}
UDR = *string++;
}
}

//-----------------------------------------------------

(Benutze AVR Studio)

Ziel:
Bei einem PC-Beispiel

#include <stdio.h>
#include <stdlib.h>

char vari[] = { "Hallo" };

int main(void) {
int i;
printf("%c", vari[0]); /* H */
printf("%c'", vari[3]); /* l */

return EXIT_SUCCESS;
}

Also will ich einen einzelnen Portzustand aus diesem String erhalten.
ZB. mit puffer[5]: PinD5


Falls ich total auf dem Holzweg bin, kann Kritik einstecken. Bin halt noch sehr am Anfang der Programmierung (Mechanik ist mein Lieblingsgebiet).

izaseba
17.08.2007, 18:38
Ok,
schön, jetzt weiß ich, was Du vor hast...
Ich find es auch gut, daß Du auf dem PC übst, so kommt man schneller ans Ziel, als nur mit dem µC.
Also was Dir fehlt, sind die Grundlagen(warum schreibt niemand einen tut!)
Fehler 1 Puffer ist zu klein!
Wenn Du ein uint8_t in Bits zerlegst, bekommst Du nach itoa/utoa ein Zeichenarray von 9 Bytes länge!
Beispiel
char puffer[] = {'0','0','0' ,'0' ,'0' ,'0' ,'0' ,'0' ,'\0'};
Man beachte dieses '\0' am Ende, damit wird signalisiert, daß der String zuende ist(deswegen 9 Bytes) klaro?

nun Deine sende_string Routine erwartet einen Zeiger auf ein char Array also übergibst Du der routine den Zeiger auf puffer[0].
puffer[0] ist aber kein Zeiger, sondern &puffer[0] wäre ein Zeiger und da sowas sehr oft bei C vorkommt kann man das ganze abkürzen und einfach puffer schreiben, klaro ?
was passiert jetzt in der sendestring Routine:


void string_senden (char *string)
{
while (*string)
{
while (!(UCSRA & (1<<UDRE)))
{}
UDR = *string++;
}
}
while(*string) bedeutet, solange ausführen bis das worauf string zeigt != 0 ist
wichtig ist hier * was bedeutet das worauf string zeigt (in diesem Fall puffer[0])
Dann wird das, worauf string zeigt in UDR geschrieben und Achtung der Zeiger um eins erhöht womit der Zeiger auf puffer[1] springt!
Zum Verständnis
UDR=*string++;
kann man auch
UDR=*string;
string++;
schreiben

Ich hoffe, jetzt wird klar, warum Dein vorhaben nicht funktionieren wird..
klar kannst Du
sende_string(&puffer[5]);
schreiben, was kommt dabei raus ?
Mein Vorschlag sende_string zegschlagen und zwar:


void string_senden (char *string)
{
while (*string)
sende_zeichen(*string++);
}
sende_zeichen(char zeichen){
while (!(UCSRA & (1<<UDRE)));
UDR = zeichen;
}

Damit kannst Du wie gewohnt mit string_senden("Hallo Welt");
Oder mit sende_zeichen(puffer[5]);
ein Zeichen senden, aber jetzt bitte keinen Zeiger!
Ich hoffe, daß Dir das weiterhilft...

Gruß Sebastian

P.S. Die andere Warnung kommt von dem Prototyp mit leeren Klammern schreib da ein void rein und weg ist die Warnung.
Puh.....

Reeper
18.08.2007, 16:11
Vielen Dank izaseba, dass hat mir sehr geholfen.

Habe nun string_senden und zeichen_senden. Das passt sehr gut.

void string_senden (char *string)
{
while (*string)
{
while (!(UCSRA & (1<<UDRE)))
{}
UDR = *string++;
}
}

void zeichen_senden(char zeichen)
{
while (!(UCSRA & (1<<UDRE)));
UDR = zeichen;
}

Gibt auch keine Fehler oder Warnungen O:)


Werde mich nun wieder in die Tutorials vergraben 8-[

Gruß
Stefan

izaseba
18.08.2007, 19:34
Es freut mich, daß ich alles nicht umsonst geschrieben habe (es ist nicht gerade einfach etwas in einem Post zu erklären, einfacher ist es am Schreibtisch bei einem Bier)
Spiel das am besten am PC durch, vor allem die Zeiger Geschichte...

Reeper
18.08.2007, 21:21
Ja.
Vor allem im Forum können sehr schnell Missverständnisse auftreten, man redet aneinander vorbei oder der Wissensstand ist einfach zu unterschiedlich ausgeprägt ...

Was ich noch falsch hatte:
für PIND5 muss ich puffer[2] auslesen,
da puffer mir 11011111 (Ausgabe ist ja logisch) ausgibt, wenn ich PIND5 auf low setze.