Forum: Mikrocontroller und Digitale Elektronik Stringlänge von Zeichen und Buchstaben bestimmen


von Thorsten (Gast)


Lesenswert?

Hallo,

ich stehe grade vor dem Problem, dass ich über UART eine Telefonnummer 
zum Atmega 32 geschickt bekomme. Diese Telefonnummer wird dann auf 
Plausibilität überprüft und auf einem LCD ausgegeben.

Jetzt möchte ich allerdings für die weitere Verarbeitung die genaue 
Länge des Strings erfahren, weil der String ins EEProm geschrieben und 
dann später immer wieder geladen werden soll.

Auf dem LCD lass ich mir auch die Länge des Strings ausgeben, es wird 
aber nur Müll angezeigt. Wo liegt hier mein Fehler ?

Also die über UART empfangene Telefonnumemr wird korrekt angezeigt....
1
#include <avr/io.h>
2
#define F_CPU 4000000
3
#include <util/delay.h>
4
#include "com74hc595.h"
5
#include "com74hc595_lcd.h"
6
#include <avr/interrupt.h>
7
#include <avr/eeprom.h>
8
#include <string.h>
9
10
#define BAUD 9600UL      // Baudrate
11
#define UART_MAXSTRLEN 14
12
13
14
// Konstanten fuer die Baudrate aus der Taktfrequenz berechnen
15
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
16
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
17
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
18
19
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
20
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
21
#endif
22
23
volatile uint8_t uart_str_complete = 0;     // 1 .. String komplett empfangen
24
volatile uint8_t uart_str_count = 0;
25
volatile char uart_string[UART_MAXSTRLEN + 1] = "";
26
volatile char Buffer[20];
27
28
uint8_t eeFooTelefonnummer[15] EEMEM;
29
uint8_t eeFooLaenge[4] EEMEM;
30
31
//**********************************************************//
32
//******************Funktionen UART*************************//
33
//**********************************************************//
34
35
int uart_putc( unsigned char c )
36
{
37
  while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
38
    ;
39
40
  UDR = c;                      /* sende Zeichen */
41
  return 0;
42
}
43
44
uint8_t uart_getc(void)
45
{
46
    while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
47
        ;
48
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
49
}
50
51
uint8_t uart_getc_wait()
52
{
53
  // Warten, bis etwas empfangen wird
54
  while (!(UCSRA & (1 << RXC)))
55
    ;
56
57
  // Das empfangene Zeichen zurückliefern
58
  return UDR;
59
}
60
61
/* String senden */
62
void uart_puts( const char *s )
63
{
64
//  lcd_clear();
65
//  lcd_string(s);
66
  while (*s)
67
  {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
68
    uart_putc(*s);
69
    s++;
70
  }
71
}
72
73
//**********************************************************//
74
//******************UART-Verbindung*************************//
75
//**********************************************************//
76
77
    void initUART()
78
    {
79
      UCSRB |= (1<<TXEN) | (1<<RXEN)|(1<<RXCIE);      // UART TX/RX einschalten
80
      UCSRC |= (1<<URSEL) | (1 << UCSZ1) | (1 << UCSZ0);//| (3<<UCSZ0);      // Asynchron 8N1
81
82
      UBRRH = UBRR_VAL >> 8;               // Baudrate setzen
83
      UBRRL = UBRR_VAL & 0xFF;
84
    }
85
86
87
88
int main(void)
89
{
90
91
  char Vergleich[]="+49";
92
  int StringVergleich = 0;
93
  int TelefonnummerLaenge;
94
95
    com74hc595_init();        // Porterweiterungen initialisieren
96
    com74hc595_lcd_init();      // Lcd initialisieren
97
98
    initUART();            // UART initialisieren BAUDRATE ist 9600 !!
99
100
   sei();
101
102
    while(1)
103
    {
104
105
    if( uart_str_complete == 1 )
106
    {
107
      com74hc595_lcd_clear();
108
      com74hc595_set_cursor(0,1);
109
110
      StringVergleich = strncmp(uart_string, Vergleich, 3);
111
      if ( StringVergleich == 0)
112
      {
113
         com74hc595_lcd_string(uart_string);
114
115
         TelefonnummerLaenge = strlen(uart_string);
116
         eeprom_write_byte(&eeFooLaenge,TelefonnummerLaenge);
117
         
118
         com74hc595_set_cursor(0,2);
119
         com74hc595_lcd_string(TelefonnummerLaenge);
120
         uart_str_complete = 0;
121
      }
122
      else
123
      {
124
        com74hc595_lcd_string("Fehler");
125
        uart_str_complete = 0;
126
      }
127
    }
128
129
    }
130
}
131
132
ISR(USART_RXC_vect)
133
{
134
  unsigned char nextChar;
135
136
  // Daten aus dem Puffer lesen
137
  nextChar = UDR;
138
  if( uart_str_complete == 0 ) {  // wenn uart_string gerade in Verwendung, neues Zeichen verwerfen
139
140
    // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
141
    if( nextChar != '\n' &&
142
        nextChar != '\r' &&
143
        uart_str_count < UART_MAXSTRLEN ) {
144
      uart_string[uart_str_count] = nextChar;
145
      uart_str_count++;
146
    }
147
    else {
148
      uart_string[uart_str_count] = '\0';
149
      uart_str_count = 0;
150
      uart_str_complete = 1;
151
    }
152
  }
153
}

von Sebastian H. (sebihepp)


Lesenswert?

Die Variable TelefonnummerLaenge ist ein Integer und kein String.

von as (Gast)


Lesenswert?

versuchs mal mit:
 " TelefonnummerLaenge = strlen( uart_string ); "

von Thomas E. (thomase)


Lesenswert?

Du schliesst doch deinen zusammengebauten String mit 0 ab. Damit hast du 
alles, wa du brauchst. Beim Auslesen musst du nur bis 0 lesen.
Wo ist das Problem?

> uint8_t eeFooLaenge[4] EEMEM;
Das brauchst du nicht. Wenn du 4 mit 0 terminierte Nummern 
hintereinander ablegst, gehst du einfach durch den Speicher durch, bis 
du die richtige gefunden hast. Die zweite Nummer beginnt hinter der 
zweiten 0, die anderen entsprechend. Das geht Ratz-Fatz da einmal 
durchzunageln. Da kannst du auch den ganzen E²PROM vollschreiben.

mfg.

von Sebastian H. (sebihepp)


Lesenswert?

Und ich sage es nochmal: TelefonnumerLaenge ist ein Integer und kein 
String. Du musst die Variable erst in einen String konvertieren, bevor 
du com74hc595_lcd_string() aufrufen kannst.

von Karl H. (kbuchegg)


Lesenswert?

... wobei man sich am sinnvollsten gleich eine Funktion
1
void com74hc595_lcd_int( int wert )
2
{
3
  char str[7];
4
  itoa( wert, str, 10 );
5
  com74hc595_lcd_string( str );
6
}
baut, anstatt erst in main da groß rumzupfriemeln. So eine int Ausgabe 
braucht man immer wieder.

Wie hast du (Thorsten), das hier
1
  com74hc595_lcd_string(TelefonnummerLaenge);
eigentlich durch den Compiler gebracht? Da muss es doch an allen Ecken 
und Enden Alarm geklingelt haben!

von Sebastian H. (sebihepp)


Lesenswert?

>Wie hast du (Thorsten), das hier
>>com74hc595_lcd_string(TelefonnummerLaenge);
>eigentlich durch den Compiler gebracht? Da muss es doch an allen Ecken
>und Enden Alarm geklingelt haben!

Nicht, wenn ein Integer die Größe eines Pointers hat. Wenn dann noch 
Warnungen ausgeschalten sind oder der Compiler etwas älter ist, dann 
wird trotzdem kompiliert.

von ich (Gast)


Lesenswert?

Thorsten schrieb:
> uint8_t uart_getc(void)
> {
>     while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
>         ;
>     return UDR;                   // Zeichen aus UDR an Aufrufer
> zurueckgeben
> }
>
ist für mich das gleiche (außer dem Funktionsnamen) wie:

> uint8_t uart_getc_wait()
> {
>   // Warten, bis etwas empfangen wird
>   while (!(UCSRA & (1 << RXC)))
>     ;
>
>   // Das empfangene Zeichen zurückliefern
>   return UDR;
> }

Wo ist der Unterschied zwischen beiden Funktionen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

ich schrieb:
> Wo ist der Unterschied zwischen beiden Funktionen?

Der liegt im Namen. Mehr Unterschied ist nicht.

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.