Forum: Mikrocontroller und Digitale Elektronik Uart/Itoa-Problem


von Dominik (Gast)


Lesenswert?

Hallo,

ich sitze derzeit an einem Problem mit meiner itoa- und puts-Funktion 
und komme einfach nicht weiter.

Ich nutze einen MSP430-F2274 und versuche Daten von einem Transciever 
über UART (USCI-Modul) auszugeben.

Die Daten einzulesen funktioniert und sie über UART auszugeben 
ebenfalls.
Nun wollte ich nur bestimmte Daten ausgeben lassen.
Also eine if-Bedingung eingefügt und es ging nichts mehr.
Also die Daten erstmal zwischenspeichern und schauen ob es dann 
funktionert (wundert euch deshalb bitte nicht über das große Array).

Und nun hänge ich an meinem Problem:
Die itoa-Funktion funktioniert eigentlich. Die Puffer-Arrays für die 
UART-Ausgabe werden korrekt gefüllt. Allerdings springt die Laufvariable 
nach dem Befehl "Buffer[i] = '\0';" auf einen Wert über 500. Da es erst 
nach diesem Befehl passiert und danach die Funktion verlassen wird, 
sollte es eigentlich nicht schaden; auch wenn es seltsam ist.

Nach der ersten UART-Ausgabe, wird aber mein zweites Puffer-Array an 
einer Stelle mit '\0' überschrieben, obwohl in der zwischenzeit 
keinerlei Schreibbefehle ausgeführt wurden.

Lasse ich die if-Abfrage weg, und gebe alle Werte direkt nach dem 
auslesen aus, so funktioniert die UART-Ausgabe tadellos. Die Probleme 
begannen mit der Überprüfung auf bestimmte werde, die zur Ausgabe 
weitergeleitet werden sollten.

Ich würde mich freuen, wenn ihr mir bitte helfen könntet.

1
#include <msp430.h>
2
#include "CC2500\cc2500.h"
3
#include "UART\uart.h"
4
5
6
const int THRESHOLD = -75;
7
8
//#define DEBUG
9
10
11
void t_itoa(int z, unsigned char* Buffer);
12
13
unsigned char RSSI_A[10] = { 0 };
14
unsigned char Channel[10]  = { 0 };
15
16
17
18
/*
19
 * main.c
20
 *
21
 */
22
void main(void) {
23
24
  volatile int rssi_value = 0;
25
  volatile unsigned char state = 0;
26
  volatile unsigned int i = 0;
27
  volatile int rssi_array[500] = {0};
28
29
  WDTCTL = WDTPW | WDTHOLD;  // Stop watchdog timer
30
31
  UART_INIT();
32
  SPI_INIT();
33
  cc2500_sendCmdStrobe(SRES);
34
  cc2500_init();
35
  P1DIR |= 0x01;
36
37
38
39
    P1OUT = 0x01;
40
41
    cc2500_sendCmdStrobe(CC2500_RX);
42
43
    for(;;)
44
    {
45
46
      for(i = 0; i <= 250; i++)
47
      {
48
        state = cc2500_readReg(MARCSTATE);
49
        while((cc2500_readReg(MARCSTATE) & 0x1F) != 0x0D);
50
        state = cc2500_readReg(MARCSTATE);
51
        rssi_value = cc2500_readRssi();
52
        cc2500_sendCmdStrobe(CC2500_IDLE);
53
        cc2500_writeReg(CHANNR, i);
54
        cc2500_sendCmdStrobe(CC2500_RX);
55
56
        rssi_array[i] = rssi_value;
57
      }
58
59
      cc2500_sendCmdStrobe(CC2500_IDLE);
60
61
      cc2500_writeReg(FREQ2, 0x5D);
62
      cc2500_writeReg(FREQ1, 0xF0);
63
      cc2500_writeReg(FREQ0, 0x10);
64
65
      cc2500_sendCmdStrobe(CC2500_RX);
66
67
      for(i = 0; i <= 247; i++)
68
      {
69
        while((cc2500_readReg(MARCSTATE) & 0x1F) != 0x0D);
70
        rssi_value = cc2500_readRssi();
71
        cc2500_sendCmdStrobe(CC2500_IDLE);
72
        cc2500_writeReg(CHANNR, i);
73
        cc2500_sendCmdStrobe(CC2500_RX);
74
75
        rssi_array[i + 251] = rssi_value;
76
      }
77
78
79
      cc2500_sendCmdStrobe(CC2500_IDLE);
80
      cc2500_writeReg(FREQ2, 0x5C);
81
      cc2500_writeReg(FREQ1, 0x4F);
82
      cc2500_writeReg(FREQ0, 0xBB);
83
      cc2500_sendCmdStrobe(CC2500_RX);
84
85
      for(i = 0; i <= 499; i++)
86
          {
87
            if(rssi_array[i] >= (-75))
88
            {
89
              t_itoa(i,&Channel[0]);        //funktioniert
90
              t_itoa(rssi_array[i],RSSI_A); //funktioniert
91
              uart_puts(&Channel[0]);       //funktioniert überschreibt aber RSSI_A teilweise
92
              uart_putc(':');
93
              uart_puts(&RSSI_A[0]);
94
              uart_putc('\n');
95
            }
96
          }
97
    }
98
}
99
100
void t_itoa(int z, unsigned char* Buffer)
101
{
102
  int i = 0;
103
  int j;
104
  char tmp;
105
  unsigned int u;
106
107
  //zahl negativ?
108
    if( z < 0 ) {
109
      Buffer[0] = '-';
110
      Buffer++;
111
      u = ( (unsigned int)(-(z+1))) + 1;
112
    }
113
    else {
114
      u = (unsigned int)z;
115
    }
116
117
    //Stellen berechnen
118
    do {
119
      Buffer[i++] = '0' + u % 10;
120
      u /= 10;
121
    } while( u > 0 );
122
123
124
    //spiegeln
125
    for( j = 0; j < i / 2; j++ )
126
    {
127
      tmp = Buffer[j];
128
      Buffer[j] = Buffer[i-j-1];
129
      Buffer[i-j-1] = tmp;
130
    }
131
132
    //Stringende einfügen
133
    Buffer[i] = '\0';
134
}
135
136
/////in uart.h definiert
137
void uart_putc(unsigned char data)
138
{
139
140
  while (!(IFG2&UCA0TXIFG));   // USCI_A0 TX buffer ready?
141
  UCA0TXBUF = data;      // write TX buffer
142
}
143
144
void uart_puts(unsigned char *data)
145
{
146
  volatile unsigned int i = 0;
147
148
  do
149
  {
150
    while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
151
    UCA0TXBUF = *(data + i++);  // write TX buffer
152
  }
153
  while(*(data + i) != '\0');
154
155
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Dominik schrieb:
> volatile int rssi_array[500] = {0};

Das geht auf einem Controller, der gerade mal 1024 Bytes RAM hat, 
ziemlich gnadenlos in die Hose.

von Dominik (Gast)


Lesenswert?

Immer dann, wenn man schon nach Hilfe gefragt hat, findet man den Fehler 
selber.

In der puts-Funktion wurde das "volatile" entfernt. Allerdings frage ich 
mich dennoch, warum dies zum Fehler geführt hat?

von Dominik (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Das geht auf einem Controller, der gerade mal 1024 Bytes RAM hat,
> ziemlich gnadenlos in die Hose.

Oh man, im Eifer des Gefechts überhaupt nicht darüber nachgedacht.
Danke für den Hinweis!

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Nicht das "volatile" führt zum Fehler, sondern Dein durch Dein 1000 Byte 
großes Array plattgemachter Stack.

von Dirk B. (dirkb2)


Lesenswert?

Dominik schrieb:
> In der puts-Funktion wurde das "volatile" entfernt. Allerdings frage ich
> mich dennoch, warum dies zum Fehler geführt hat?

Willst du wirklich die '\0' vom Stringende mitsenden?
Wenn nicht, dann musst du zuerst auf das Ende prüfen.

Und mach es ohne i.
1
void uart_puts(unsigned char *data)
2
{
3
  while(*data);
4
  {
5
    while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
6
    UCA0TXBUF = *data;  // write TX buffer
7
    i++; 
8
  }
9
}

von Dominik (Gast)


Lesenswert?

Also war es wohl Zufall, dass das Entfernen von "volatile" den Fehler 
behoben hat und es war Glück, dass es überhaupt noch soweit lief.
Sowas mit dem zu großen Array sollte wirklich nicht passieren.
Vielen Dank!

von Dominik (Gast)


Lesenswert?

Dirk B. schrieb:
> Willst du wirklich die '\0' vom Stringende mitsenden?

Mache ich doch gar nicht oder habe ich noch einen Denkfehler?
1
do
2
  {
3
    while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
4
    UCA0TXBUF = *(data + i++);  // write TX buffer
5
  }
6
  while(*(data + i) != '\0');

i erhöht sich doch nachdem ein Zeichen in den TXBuffer geschrieben wurde 
und zeigt somit bereits auf das nächste Element. Sollte dieses '\0' 
sein, bricht die Schleife doch ab und das Stringende wird nicht 
gesendet.
Es könnte höchstens passieren, dass ein leerer String übergeben wird 
aber darüber bin ich mir bewusst.

von Dirk B. (dirkb2)


Lesenswert?

Dominik schrieb:
> Es könnte höchstens passieren, dass ein leerer String übergeben wird
> aber darüber bin ich mir bewusst.

Ok. Trotzdem nicht fein, da man es umgehen kann.

Das i++; bei mir da oben soll natürlich ein data++; sein. (schäm)

von Dominik (Gast)


Lesenswert?

Hast du auch wieder recht und werde es noch dahingehend ändern, dass es 
in allen Fällen funktioniert. :)

von Karl H. (kbuchegg)


Lesenswert?

Und wenn du schon dabei bist.
Du hast eine Funktion uart_putc. Ein uart_puts funktioniert im Prinzip 
so, dass er alle Zeichen ausgibt. Ein Zeichen auszugeben ist aber die 
Domäne der Funktion uart_putc. Die weiss wie das geht und was es da 
alles zu beachten gibt. Das ist nichts worüber sich uart_puts Gedanken 
machen muss oder machen sollte (wie zum Beispiel irgendwann mal die 
Behandlung eines Handshakes)
1
void uart_puts(unsigned char *data)
2
{
3
  while( *data )
4
    uart_putc( *data++ );
5
}

fertig.

Du musst anfangen deine Funktionen als 'Build Blocks' zu sehen. 
'komplexere Funktionen' bedienen sich der Services, die 'simplere 
Funktionen' zur Verfügung stellen.


Genauso wie diese Sequenz in deinem Hauptprogramm
1
              t_itoa(i,&Channel[0]);        //funktioniert
2
              t_itoa(rssi_array[i],RSSI_A); //funktioniert
3
              uart_puts(&Channel[0]);       //funktioniert überschreibt aber RSSI_A teilweise
4
              uart_putc(':');
5
              uart_puts(&RSSI_A[0]);
6
              uart_putc('\n');

eine Zahl ausgeben zu können stinkt förmlich danach, dass es eine 
Basisfunktionalität darstellt, genauso wie die Ausgabe eines Strings 
förmlich danach gestunken hat.
Es wird daher sinnvoll sein, sich dafür eine eigene Funktion zu 
schaffen, die genau das kann: einen int ausgeben.
Die Funktion an sich ist trivial
1
void uart_puti( int value )
2
{
3
  char buff[7];    // -32768,   6 Zeichen + '\0'
4
5
  t_itoa( value, buff );
6
  uart_puts( buff );
7
}

aber sie vereinfacht dir die Sequenz im Hauptprogramm (und in weiterer 
Folge dann nicht nur diese) zu
1
              uart_puti( i );
2
              uart_putc( ':' );
3
              uart_puti( rssi_array[i] );
4
              uart_putc( '\n' );
und du brauchst dir hier schon wieder keine Gedanken darüber machen, 
dass du zur Ausgabe eines int einen char Buffer brauchst, der dann auch 
noch groß genug sein sollte - das alles weiß die Funktion uart_puti und 
befreit dich damit an dieser Stelle davon, dir darüber Gedanken machen 
zu müssen. Dafür kannst du dich hier darauf konzentrieren, was du 
eigentlich tun willst. Nämlich eine Zahl auszugeben, gefolgt von einem 
Doppelpunkt, gefolgt von einer weiteren Zahl und einem Zeilenvorschub. 
Genau das, und nur das, liest du aber hier im Code bzw. genau über diese 
Dinge hast du nachgedacht, als du die einfachere Sequenz geschrieben 
hast.

: Bearbeitet durch User
von Eric B. (beric)


Lesenswert?

Dirk B. schrieb:

>
1
> void uart_puts(unsigned char *data)
2
> {
3
>   while(*data);
4
>   {
5
>     while (!(IFG2&UCA0TXIFG));  // USCI_A0 TX buffer ready?
6
>     UCA0TXBUF = *data;  // write TX buffer
7
>     i++;
8
>   }
9
> }

Da sind mindestens 3 Fehlder drinne.
- Das ; nach dem while(*data) soll weg
- Das i++ nutzt nix
- data wird nicht erhöht

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Eric B. schrieb:
> Da sind mindestens 3 Fehlder drinne.

Danke.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.