Forum: Mikrocontroller und Digitale Elektronik char Buffer[7] Resetten, löschen.


von mcnanuk (Gast)


Lesenswert?

Ich habe ein Programm das empfängt über ein Terminal Zeichen vom PC. Das 
wird in einen char Buffer[7] geschrieben.

Soweit so gut.

Wenn jetzt nur 3 Zeichen übertragen werden, dann bleiben 4 Plätze übrig.

Ich mach mal ein Beispiel:
1
Anzeige        Terminal
2
3
1|2|3|||||     Terminal sendet 123
4
1|2|3|4|5|6||  Terminal sendet 456
5
8|||||||       Terminal sendet 78

Ich hab jetzt schon vieles Versucht, aber nix fruchtet. In Java würde 
ich array[] = new Array() schreiben und das wäre gelöst. Wie löse ich 
sowas in C?

1
int len = strlen(Buffer);  
2
  unsigned int ibuff = atoi(Buffer);    
3
  if(ibuff< 100)
4
    {
5
  lcd_clrscr();
6
  lcd_puts(Buffer);
7
    lcd_puts("\n");
8
     lcd_puts("Kleiner 100");
9
10
  Buffer[len]='\0';
11
  getch(Buffer);
12
  
13
14
    } else {
15
  lcd_clrscr();
16
  lcd_puts(Buffer);
17
    lcd_puts("\n");
18
        lcd_puts("Bigger 100");
19
  Buffer[len]='\0';
20
21
    }

von Peter (Gast)


Lesenswert?

einfach ein

> Buffer[0]= '\0';

und schon ist der String 0 byte lang. Aber damit wird der Speicher nicht 
freigebenen, es wird noch die der String abgeschlossen.

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:

> Ich hab jetzt schon vieles Versucht, aber nix fruchtet. In Java würde
> ich array[] = new Array() schreiben und das wäre gelöst. Wie löse ich
> sowas in C?

Indem du das Array überhaupt nicht löscht, und dich daran erinnerst, das 
in C ein String dort aufhört, wo das '\0' Zeichen ist.

http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

hast du also in C ein Array

char Buffer[200];

und willst du ausdrücken, dass dort drinnen ein String mit 0 Zeichen 
Länge beheimatet ist, dann platzierst du das \0 Zeichen so, dass sich 
ein String mit 0 Zeichen Länge ergibt

  Buffer[0] = '\0';

von mcnanuk (Gast)


Lesenswert?

Das funktioniert nicht.

Wenn ich diese zeile in die IfElse Abfrage oder danach setze, dann wird 
nix im LCD geschrieben und die Abfrage landet immer bei "Kleiner 100"

von Jean Player (Gast)


Lesenswert?

...Oder er benutzt "malloc" und "free".

Gruß

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:
> Das funktioniert nicht.

Doch, das funktioniert.
Siehe deinen Originalthread.

Dein Problem ist, dass du ein massives Verständnisproblem bei ganz 
anderen Dingen hast.

von Link zu (Gast)


Lesenswert?

mcnanuk schrieb:
> Wenn ich diese zeile in die IfElse Abfrage oder danach setze, dann wird
> nix im LCD geschrieben und die Abfrage landet immer bei "Kleiner 100"
Du hast den Quellcode vergessen. ;-)
Wo kommt eigentlich lcd_puts() her?
Reagieren deine LCD-Funktionen wirklich auf \n?

Karl heinz Buchegger schrieb:
> Siehe deinen Originalthread.
Wie? Habe ich mal wieder was verpasst?

von Karl H. (kbuchegg)


Lesenswert?

Link zu schrieb:

>> Siehe deinen Originalthread.
> Wie? Habe ich mal wieder was verpasst?

Beitrag "Atmega644 UART - Komische Ausgabe"

aber auch dort schlägt man sich laufend mit unvollständigem Code herum 
:-)

von mcnanuk (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Doch, das funktioniert.
> Siehe deinen Originalthread.
>
> Dein Problem ist, dass du ein massives Verständnisproblem bei ganz
> anderen Dingen hast.

Das will ich nicht bestreiten, wobei ich meine es so in etwa zu 
verstehen. Nur wie soll man lernen, wenn man nicht anhand von Beispielen 
sich voranhangelt.
ich verstehe auch was bei   Buffer[0] = '\0'; passiert.

Die verständnisfragen werden immer weniger, wenn auch noch genug übrig 
sind. Wobei ich mir eigentlich recht sicher bin, bei dem was ich da 
fabriziert habe.


Nur hier an der Stelle sehe ich absolut keine Lösung. Direkt nach dem 
Einschalten des Boards klappt ja auch alles einwadnfrei. Eben aber nur 
beim ersten Mal, danach fehlt besagter reset.

von Link zu (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Link zu schrieb:
>>> Siehe deinen Originalthread.
>> Wie? Habe ich mal wieder was verpasst?
> Beitrag "Atmega644 UART - Komische Ausgabe"
Ach so.
Reagiert die Fleury-Lib wirklich auf '\n' wie man so erwarten würde? 
In der Online-Doku finde ich nichts dazu...

von Peter D. (peda)


Lesenswert?

Also ich mache das einfach so:
1
uint8_t data = UDR;
2
switch( data ){
3
  case '\n':
4
  case '\r': data = 0;
5
             command_received = 1;
6
  default: *data_ptr++ = data;
7
}
und dann ist der String immer richtig.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Link zu schrieb:

> Reagiert die Fleury-Lib wirklich auf '\n' wie man so erwarten würde?
> In der Online-Doku finde ich nichts dazu...

Sein Problem ist erst mal nicht das LCD an sich, sondern das 
Verständnis, dass über die UART erst mal nur einzelne Zeichen 
eintrudeln, die er zu einem String zusammensetzen muss, ehe er dann 
irgendetwas sinnvolles damit anstellen kann.

Es wäre schon viel gewonnen, wenn er sich endlich einmal mit sich selbst 
einigen könnte, wie er nun die UART bedienen will.
Mit eigenem Code oder mit der Fleury Library.

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:

> Nur hier an der Stelle sehe ich absolut keine Lösung. Direkt nach dem
> Einschalten des Boards klappt ja auch alles einwadnfrei. Eben aber nur
> beim ersten Mal, danach fehlt besagter reset.

Dann frag dich doch mal, woher deine Add Funktion, genauer gesagt die 
Variable LastCharInBuffer, wissen soll, dass es jetzt wieder von vorne 
im Buffer losgeht.

Im übrigen:
Von deinem Code schwirren mitlerweile mindestens 3 grundverschiedene 
Versionen durchs Forum. Kein Mensch weiß mitlerweile mehr, wie dein Code 
zur Zeit in seiner vollen Pracht aussieht, ob du die Fleury Lib noch 
benutzt, etc.
Es ist schwierig, auf Fehler im Code hinzuweisen, bzw. auf 
Verständnisprobleme einzugehen, wenn der zugrundeliegende Code nicht 
bekannt ist.

Das sollte dir einen kleinen Denkanstoss geben.

von mcnanuk (Gast)


Lesenswert?

Ich danke Euch.... ich habe extra einen neuen post aufgemacht, da der 
alte Thread doch schon sehr gewachsen war.

Ich glaube geschrieben zu haben, dass ich verstanden habe wie Uart Daten 
sendet. Zuerst hat es mich irritiert, aber als ich wusste, das es Ascii 
ist, war es mir klar.

Ich verwende im Moment die Libary von Fleury, da mein eigener Ansatz 
zwar an sich funktioniert, aber eben dort ein Fehler steckt, den ich 
nicht finde.
Aber lassen wir das mal weg.


Dein Einwand mit der Add Funktion ist natürlich absolut berechtigt, und 
ist mir absolut nicht aufgefallen. Wie eigentlich immer wenn man 
Stundenlang davor sitzt.


Ich entschuldige mich mal für die Verwirrung die ich gestiftet habe, 
obwohl ich mich eigentlich bemüht habe immer übersichtlich zu posten. 
Das heisst auch das wegzulassen was weiter oben schon stand. Aber war 
wohl der falsche Weg :)

Der Hund liegt tatsächlich in der Add Methode begraben. Werde mir das 
jetzt mal anscheun und versuchen das Problem zu lösen.

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:

> Ich verwende im Moment die Libary von Fleury, da mein eigener Ansatz
> zwar an sich funktioniert, aber eben dort ein Fehler steckt, den ich
> nicht finde.
> Aber lassen wir das mal weg.

Nein.
Das können wir nicht weg lassen.

Falls du es immer noch nicht begriffen hast. Hier nochmal. Diesmal in 
aller Deutlichkeit:

  P O S T E     D E I N E N     A K T U E L L E N     C O D E  !

      U N D    Z W A R     K O M P L E T T  !

Jetzt verstanden?

> Der Hund liegt tatsächlich in der Add Methode begraben.

Der Hund ist auch dort begraben, dass dir Stringverabreitung an sich 
noch nicht klar ist. Im anderen Thread hast du einen Code gepostet, der 
von der Fleury Lib weggegangen ist. Die Teile die du geklaut hast, sind 
alle korrekt. Aber in den Teilen, die du dazugeschrieben hast, wimmelt 
es nur so von String-Verständnisfehlern. Daher die Aufforderung: Poste 
kompletten Code!

Deine Probleme lassen sich nicht an einer Stelle dingfest machen. Deine 
Probleme ziehen sich über deinen ganzen Code hin.

von Hc Z. (mizch)


Lesenswert?

> Nur wie soll man lernen, wenn man nicht anhand von Beispielen
> sich voranhangelt.

Nein.  Beispiele sind gut, um zu Lernendes zu illustrieren, aber nicht, 
um sich daran entlang zu hangeln.  Entlang hangeln solltest Du Dich an 
den Grundlagen und die Beispiele zu deren Verdeutlichung nehmen.  Sonst 
landest Du bloß bei der Herumprobiererei, die wir gerade sehen.

Dann wüsstest Du, dass ein C-String an \0 endet und alles, was danach 
kommt, völlig egal ist - auch wenn es vom Speicherplatz her noch zum 
String-Array gehört.  Wenn der erste Platz im String-Array, also 
string[0], '\0' enthält, ist der String also 0 Zeichen lang.

von mcnanuk (Gast)


Lesenswert?

MainKlasse: Unverändert nutze ich die LCD Libary und UART Libary von 
Peter Fleury.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
#include <avr/pgmspace.h>
6
#include <util/delay.h>
7
#include <string.h>
8
9
#include "lcd.h"
10
#include "uart.h"
11
12
13
/* define CPU frequency in Mhz here if not defined in Makefile */
14
15
#define F_CPU 3686000UL
16
17
18
/* 9600 baud */
19
#define UART_BAUD_RATE      9600
20
21
unsigned char Buffer[7];
22
23
unsigned char LastCharInBuffer;
24
        
25
void Add( char Neu )
26
{
27
      Buffer[LastCharInBuffer++] = Neu;
28
      Buffer[LastCharInBuffer] = '\0';
29
}
30
31
32
int main(void)
33
{
34
    unsigned int c;
35
    char buffer[7];
36
 
37
38
     lcd_init(LCD_DISP_ON);
39
40
    /*
41
     *  Initialize UART library, pass baudrate and AVR cpu clock
42
     *  with the macro 
43
     *  UART_BAUD_SELECT() (normal speed mode )
44
     *  or 
45
     *  UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode)
46
     */
47
    uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
48
49
    /*
50
     * now enable interrupt, since UART library is interrupt controlled
51
     */
52
    sei();
53
    
54
    for(;;)
55
    {
56
        /*
57
         * Get received character from ringbuffer
58
         * uart_getc() returns in the lower byte the received character and 
59
         * in the higher byte (bitmask) the last receive error
60
         * UART_NO_DATA is returned when no data is available.
61
         *
62
         */
63
        c = uart_getc();
64
    
65
        if ( c & UART_NO_DATA )
66
        {
67
            /* 
68
             * no data available from UART 
69
             */
70
        }
71
        else
72
        {
73
            /*
74
             * new data available from UART
75
             * check for Frame or Overrun error
76
             */
77
            if ( c & UART_FRAME_ERROR )
78
            {
79
                /* Framing Error detected, i.e no stop bit detected */
80
                uart_puts_P("UART Frame Error: ");
81
            }
82
            if ( c & UART_OVERRUN_ERROR )
83
            {
84
                /* 
85
                 * Overrun, a character already present in the UART UDR register was 
86
                 * not read by the interrupt handler before the next character arrived,
87
                 * one or more received characters have been dropped
88
                 */
89
                uart_puts_P("UART Overrun Error: ");
90
            }
91
            if ( c & UART_BUFFER_OVERFLOW )
92
            {
93
                /* 
94
                 * We are not reading the receive buffer fast enough,
95
                 * one or more received character have been dropped 
96
                 */
97
                uart_puts_P("Buffer overflow error: ");
98
            }
99
  
100
      uart_putc((c & 0x00ff));
101
102
      Add((c & 0x00ff));
103
104
      unsigned int ibuff = atoi(Buffer);    
105
      if(ibuff< 100)
106
        {
107
        lcd_clrscr();
108
        lcd_puts(Buffer);
109
        lcd_puts("\n");
110
         lcd_puts("Kleiner 100");
111
        } else {
112
        lcd_clrscr();
113
        lcd_puts(Buffer);
114
        lcd_puts("\n");
115
          lcd_puts("Bigger 100");
116
        }
117
        //Buffer[0]='\0';
118
      
119
     }//end else
120
     
121
    }//end for
122
    
123
}//End main

von Karl H. (kbuchegg)


Lesenswert?

OK.

Als erstes bauen wir da gleich mal eine Funktion, die einen String von 
der UART empfängt. Als Konvention soll gelten: Die Übertragung, und 
damit der String, soll dann beendet sein, wenn von der Gegenstelle ein 
'\n' daherkommt.
Irgend so eine Konvention muss es geben, weil dein Programm ja nicht 
wissen kann, ob die Übertragung '1' '8' schon alles war (und du 18 
getippt hast) oder ob da noch was kommt (und du zb 183 getippt hast).

Die UART Library ist so aufgebaut, dass uart_getc nicht darauf wartet, 
dass ein Zeichen reinkommt. Das erleichtert den Einsatz, wenn asynchron 
noch andere Dinge passieren sollen. Fürs erste will ich aber genau die 
Umkehrung haben: Eine Funktion, die auf ein Zeichen wartet, falls keines 
vorhanden ist (die Lib speichert zwischenzeitlich eingehende Zeichen 
selbst zwischen).

Fehlerbehandlung wie Frame Fehler u. dgl. lass ich erst mal weg.
1
char uart_getc_wait()
2
{
3
  unsigned int c;
4
5
  do {
6
    c = uart_getc();
7
  } while( c & UART_NO_DATA );
8
9
  uart_putc( (c & 0x00ff) );
10
11
  return c;
12
}
13
14
15
void uart_gets( char * Buffer )
16
{
17
  char c;
18
  int  nextCharPos = 0;
19
20
  c = uart_getc_wait();
21
  while( c != '\n' ) {
22
    Buffer[ nextCharPos++ ] = c;
23
    c = uart_getc_wait();
24
  }
25
26
  Buffer[ nextCharPos ] = '\0';
27
}

Die Funktion uart_gets bekommt einen Buffer (ein char Array) übergeben, 
in dem sie die einzelnen Zeichen ablegen soll. Auch hier wieder eine 
Vereinfachung: Der Buffer muss vom Aufrufer gross genug zur Verfügung 
gestellt werden! Der Code sollte hier noch geändert werden, in dem man 
der Funktion die Größe des Buffers mitgibt und die Funktion in die Lage 
versetzt, sich davor zu schützen ausserhalb des zulässigen Speichers zu 
schreiben. Das verkompliziert allerdings den Code und lenkt von den 
wesentlichen Dingen ab. Daher hab ich es erst mal weg gelassen.

Mit der Funktion uart_gets() ist es nun möglich ein Hauptprogramm zu 
schreieben, welches auf einen kompletten String wartet, diesen String in 
einen int umwandelt und abhängig vom Zahlenwert etwas auf dem LCD zu 
machen
1
int main(void)
2
{
3
  char buffer[30];    // nicht kleckern, klotzen!
4
  char temp[20];
5
  int  Zahl; 
6
7
  lcd_init(LCD_DISP_ON);
8
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
9
10
  sei();
11
12
  while( 1 ) {
13
    uart_gets( buffer );
14
15
    Zahl = atoi( buffer );
16
17
    lcd_clrscr();
18
    lcd_puts( "Als String: *" );
19
    lcd_puts( buffer );
20
    lcd_puts( "*\n");
21
22
    lcd_puts( "Als Zahl: " );
23
    itoa( Zahl, temp, 10 );
24
    lcd_puts( temp );
25
26
    if( Zahl > 100 )
27
      lcd_puts( " gross" );
28
  }
29
}

von mcnanuk (Gast)


Lesenswert?

Danke Dir... ich werds mal testen.

von Karl H. (kbuchegg)


Lesenswert?

Ich muss allerdings sagen.
Ich habs hier im Editor direkt getippt und noch nicht durch einen 
Compiler gejagt. Da mag noch der eine oder andere kleine Fehler drinnen 
sein. Das Grundprinzip ist aber ok.

von mcnanuk (Gast)


Lesenswert?

Was schonmal funktioniert: Das Programm reagiert auf die Eingabe im 
terminal... musste da LF(\n) als Endsymbol einstellen.

Aber der buffer ist leer, und damit die Zahl 0.
Auch wird nix ans Terminal zurückgegeben.

von Hc Z. (mizch)


Lesenswert?

> Aber der buffer ist leer, und damit die Zahl 0.
> Auch wird nix ans Terminal zurückgegeben.

Du hattest mal ein Programm vorgezeigt, in dem sowohl eine ISR für den 
UART drin war als auch eine direkte Abholung außerhalb.  Da das wohl 
Dein allerkleinstes Problem zu dieser Zeit war, habe ich auf einen 
Kommentar verzichtet.  Nun hast Du uns zwar das angeblich komplette 
Programm gezeigt -- aber uart_init() war nicht dabei.

Daher: ist darin immer noch diejenige uart_init(), die RXCIE setzt und 
bei der eventuell sogar noch die ISR für den Empfangsinterrupt dabei 
ist?

von mcnanuk (Gast)


Lesenswert?

1
#elif defined(__AVR_ATmega644__)
2
 /* ATmega with one USART */
3
 #define ATMEGA_USART0
4
 #define UART0_RECEIVE_INTERRUPT   SIG_USART_RECV
5
 #define UART0_TRANSMIT_INTERRUPT  SIG_USART_DATA
6
 #define UART0_STATUS   UCSR0A
7
 #define UART0_CONTROL  UCSR0B
8
 #define UART0_DATA     UDR0
9
 #define UART0_UDRIE    UDRIE0
1
/*************************************************************************
2
Function: uart_init()
3
Purpose:  initialize UART and set baudrate
4
Input:    baudrate using macro UART_BAUD_SELECT()
5
Returns:  none
6
**************************************************************************/
7
void uart_init(unsigned int baudrate)
8
{
9
    UART_TxHead = 0;
10
    UART_TxTail = 0;
11
    UART_RxHead = 0;
12
    UART_RxTail = 0;
13
    
14
#if defined( AT90_UART )
15
    /* set baud rate */
16
    UBRR = (unsigned char)baudrate; 
17
18
    /* enable UART receiver and transmmitter and receive complete interrupt */
19
    UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
20
21
#elif defined (ATMEGA_USART)
22
    /* Set baud rate */
23
    if ( baudrate & 0x8000 )
24
    {
25
       UART0_STATUS = (1<<U2X);  //Enable 2x speed 
26
       baudrate &= ~0x8000;
27
    }
28
    UBRRH = (unsigned char)(baudrate>>8);
29
    UBRRL = (unsigned char) baudrate;
30
   
31
    /* Enable USART receiver and transmitter and receive complete interrupt */
32
    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
33
    
34
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
35
    #ifdef URSEL
36
    UCSRC = (1<<URSEL)|(3<<UCSZ0);
37
    #else
38
    UCSRC = (3<<UCSZ0);
39
    #endif 
40
    
41
#elif defined (ATMEGA_USART0 )
42
    /* Set baud rate */
43
    if ( baudrate & 0x8000 ) 
44
    {
45
       UART0_STATUS = (1<<U2X0);  //Enable 2x speed 
46
       baudrate &= ~0x8000;
47
     }
48
    UBRR0H = (unsigned char)(baudrate>>8);
49
    UBRR0L = (unsigned char) baudrate;
50
51
    /* Enable USART receiver and transmitter and receive complete interrupt */
52
    UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
53
    
54
    /* Set frame format: asynchronous, 8data, no parity, 1stop bit */
55
    #ifdef URSEL0
56
    UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
57
    #else
58
    UCSR0C = (3<<UCSZ00);
59
    #endif 
60
61
#elif defined ( ATMEGA_UART )
62
    /* set baud rate */
63
    if ( baudrate & 0x8000 ) 
64
    {
65
      UART0_STATUS = (1<<U2X);  //Enable 2x speed 
66
      baudrate &= ~0x8000;
67
    }
68
    UBRRHI = (unsigned char)(baudrate>>8);
69
    UBRR   = (unsigned char) baudrate;
70
71
    /* Enable UART receiver and transmitter and receive complete interrupt */
72
    UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
73
74
#endif
75
76
}/* uart_init */

Hier meine init Methode... direkt aus der Fleury Libary...

Ich will jetzt nicht in meinem eigenen versuch kruschteln, um keine 
Verwirrung, speziell bei mir hervorzurufen :)

von Hc Z. (mizch)


Lesenswert?

Ja, das ist genau das, was ich meinte.  Das kommt davon, wenn man sich 
aus verschiedenen Quellen Beispiele zusammenstoppelt, ohne die 
Grundlagen zu haben, sie zu verstehen.

Mach aus
1
    UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
neu
1
    UART0_CONTROL = _BV(RXEN)|_BV(TXEN);

von mcnanuk (Gast)


Lesenswert?

Wiso verschiedene Quellen.... kommt doch alles aus der Hand von Herrn 
Fleury...

Wie gesagt das was mein erster Anstz.... später hab ichs dann selbst 
versucht. Hier in diesem thread oben der Code basiert komplett auf der 
Libary. Die kommunikation klappt auch, nur mit der Verarbeitung der 
empfangenen Daten habe ich Schwierigkeiten.

Aber da ich dort nicht weiterkomme, und ich seit Tagen versuche eine 
Lösung zu erstellen, versuche ich es nochmals mit dem Ansatz von Karl 
heinz Buchegger.
Es war aber sehr lehrreich, da ich in den letzen 2 Tagen mehr über C 
gelernt habe, als in den 2 Monaten zuvor.

von Hc Z. (mizch)


Lesenswert?

Nein.  Karl Heinz hat Dir eine Empfangsroutine vorgeschlagen, die mit 
einer Interrupt-erlaubenden Initialisierung nicht zusammenarbeitet.  Da 
Du aber trotz Aufforderung, den KOMPLETTEN Code zu posten, diese 
Initialisierung nicht gezeigt hast, konnte er davon nichts wissen.

Es war Zufall, dass mir das ein paar Stunden vorher schon aufgefallen 
war.  Und es wäre Deine Verantwortung als Zusammensteller gewesen, 
Konflikte mit Teilen, die Du zufügst, zu erkennen.

> Die kommunikation klappt auch

Oooch komm.  Du setzt RXCIE, holst aber die Rx-Daten nicht 
interruptgesteuert ab, und willst mir erzählen, dass die Kommunikation 
klappt?  Gut möglich, dass es trotz Wegnehmen von RXCIE immer noch nicht 
klappt.  Das liegt aber dann nicht daran, dass RXCIE gar kein Fehler 
gewesen wäre, sondern daran, dass Du noch andere solche Würmer drin hast 
(was mich gar nicht wundern würde).

von Null Ahnung von Nichts (Gast)


Lesenswert?

Wenn man anfängt zu programmieren ist es ohnehin nicht ratsam, auf eine 
Unmenge an Libraries zurückzugreifen. Zuerst ist es mal wichtig, sein 
eigenes Geschreibsel richtig zu verstehen.
Du hast in deinem Code Libs für LCD und Uart eingefügt. Während LCD 
sicher etwas fortgeschrittener ist, ist der UART sehr einfach zu 
initialisieren und konfigurieren. Wenn du dies selber machst, lernst du 
auch den Umgang mit den diesbezüglichen Registern und kannst so 
obgenannte Fehler ausschließen.
Auch wenn du nun zig Libraries zusammenwürfelst und das Programm am Ende 
sogar noch funktioniert, hast du trotzdem keine wirkliche Ahnung was da 
eingelicht abläuft.

"Learning by doing" ist absolut ok. Aber "Learning by looking other 
people doing" eben nicht

von Karl H. (kbuchegg)


Lesenswert?

Hc Zimmerer schrieb:

> war.  Und es wäre Deine Verantwortung als Zusammensteller gewesen,
> Konflikte mit Teilen, die Du zufügst, zu erkennen.

Moment.
Ich geh davon aus, dass die Fleury Lib unverändert benutzt wird.
Und soweit ich mich erinnern kann, klappt die auch problemlos 
interruptgesteuert.

> Oooch komm.  Du setzt RXCIE, holst aber die Rx-Daten nicht
> interruptgesteuert ab

Wovon sprichst du?
DIe Fleury Funktionen enthalten die ISR. Von der ISR werden die Daten in 
einen Ringbuffer gestellt, von wo sie wiederrum uart_getc abholt.

von mcnanuk (Gast)


Lesenswert?

Wenn ich den gesamten Code gepostet hätte, dann hätte ich hier mehr als 
2000 Zeilen Code gepostet.
Nunja es liegt mir sehr fern mich hier zu streiten, auch kann ich nicht 
für alles geradestehen, was in meinem Code stand. Ich bin nunmal noch 
kein Spezialist im µC Bereich und in der C Welt.

Ich habe einige Jahre Java, Phython, Scheme, ... Erfahrung. In die 
Embedded Welt stürzte ich mich erst seit kurzem. Ich finde das alles 
sehr Spannend, und bin denjenigen sehr Dankbar, die sich die Zeit 
nehmen, mich auf meine Fehler hinzuweisen und mir Tipps geben.
C-Bücher habe ich hier liegen, aber bringen mich nur bedingt weiter. 
Heute und gestern bin ich an meine Grenzen gestoßen, was die logik 
hinter C angeht. Aber aus Fehlern lernt man.

Jedenfalls back on Topic:

Ich hab den Fehler gefunden im Code von Karl Heinz:
Aber wie ich sehe, hat er es schon reineditiert... :)

Naja wenigstens weiss ich worauf zu achten ist :)

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:
> Was schonmal funktioniert: Das Programm reagiert auf die Eingabe im
> terminal... musste da LF(\n) als Endsymbol einstellen.
>
> Aber der buffer ist leer, und damit die Zahl 0.

OK.

> Auch wird nix ans Terminal zurückgegeben.

Den sntsprechenden putc hab ich nachträglich noch ergänzt.
1
char uart_getc_wait()
2
{
3
  unsigned int c;
4
5
  do {
6
    c = uart_getc();
7
  } while( c & UART_NO_DATA );
8
9
  uart_putc( (c & 0x00ff) );
10
11
  return c;
12
}


Zum ersten Problem:
Ich hatte tatsächlich nach dem Absenden des Codes noch einen 
'Problemfall', ein vergessenens ++
Hast du das so
1
void uart_gets( char * Buffer )
2
{
3
  char c;
4
  int  nextCharPos = 0;
5
6
  c = uart_getc_wait();
7
  while( c != '\n' ) {
8
    Buffer[ nextCharPos++ ] = c;
9
    c = uart_getc_wait();
10
  }
11
12
  Buffer[ nextCharPos ] = '\0';
13
}

von mcnanuk (Gast)


Lesenswert?

Null Ahnung von Nichts schrieb:
> "Learning by doing" ist absolut ok. Aber "Learning by looking other
> people doing" eben nicht

Nunja kommt ja ganz auf die Person an, und wie sie damit umgeht.
Als ich angefangen habe UART zu nutzen, wusste ich nicht was es war. Da 
kam mir die libary vom Fleury gelegen, da ich gute Erfahrungen mit der 
LCD Libary gemacht hatte.
Die Uart Schnittstelle ist leider eine last Minute Anforderung, die ich 
noch einbauen musste.

Aber generell arbeite ich auf, was ich so hernehme. Und das Datenblatt 
liegt sowieso immer neben mir aufm Tisch.

von Hc Z. (mizch)


Lesenswert?

[Karl Heinz]
> Wovon sprichst du?

Karl Heinz, da muss ich Dir Abbitte tun.  Ich habe beim Drübergucken 
Dein uart_getc_wait() für eine direkte Abholroutine gehalten, die 
außerhalb des Interrupts arbeitet.  Erst jetzt habe ich gesehen, dass Du 
Fleurys Buffer-Abholroutine darin verwendest.  Sorry.

von Karl H. (kbuchegg)


Lesenswert?

Hc Zimmerer schrieb:
> [Karl Heinz]
>> Wovon sprichst du?
>
> Karl Heinz, da muss ich Dir Abbitte tun.

Kein Problem.
Solange wir das Misverständnis ausräumen können.

von mcnanuk (Gast)


Lesenswert?

jep ... Danke Dir...
Die Feinheiten werde ich noch einbauen, wobei Die Schnittstelle sehr 
einfach gehalten werden soll... Irgendwann muss ich sie Ausbauen, aber 
momentan tut sie genau das was ich brauche.
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <avr/signal.h>
5
#include <avr/pgmspace.h>
6
#include <util/delay.h>
7
#include <string.h>
8
#include "lcd.h"
9
#include "uart.h"
10
11
12
/* define CPU frequency in Mhz here if not defined in Makefile */
13
14
#define F_CPU 3686000UL
15
16
17
/* 9600 baud */
18
#define UART_BAUD_RATE      9600
19
20
char uart_getc_wait()
21
{
22
  unsigned int c;
23
24
  do {
25
    c = uart_getc();
26
  } while( c & UART_NO_DATA );
27
28
  return c;
29
}
30
31
void uart_gets( char * Buffer )
32
{
33
  char c;
34
  int  nextCharPos = 0;
35
36
  c = uart_getc_wait();
37
  uart_putc(c);
38
  while( c != '\n' ) {
39
    Buffer[ nextCharPos++ ] = c;
40
  c = uart_getc_wait();
41
  uart_putc(c);
42
    
43
  }
44
45
  Buffer[ nextCharPos ] = '\0';
46
}
47
48
49
50
int main(void)
51
{
52
char buffer[30];    // nicht kleckern, klotzen!
53
  char temp[7];
54
  int  Zahl; 
55
56
  lcd_init(LCD_DISP_ON);
57
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
58
59
60
  sei();
61
62
  while( 1 ) {
63
    uart_gets( buffer );
64
65
    Zahl = atoi( buffer );
66
67
    lcd_clrscr();
68
    lcd_puts( "String: *" );
69
    lcd_puts( buffer );
70
    lcd_puts( "*\n");
71
72
    lcd_puts( "Zahl: " );
73
    itoa( Zahl, temp, 10 );
74
    lcd_puts( temp );
75
76
  if( Zahl > 100 )
77
      lcd_puts( " gross" );
78
79
  }
80
81
    
82
}//End main

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:

> Als ich angefangen habe UART zu nutzen, wusste ich nicht was es war. Da
> kam mir die libary vom Fleury gelegen, da ich gute Erfahrungen mit der
> LCD Libary gemacht hatte.

Ich habe zwar die UART LIb von ihm auch noch nie irgendwo eingesetzt. 
Ich schätze sie aber trotzdem, weil sie grundsätzlich delay-freies 
arbeiten erlaubt. Man muss nicht zwangsweise auf ein Zeichen warten, 
kann das aber leicht 'umrüsten'. Anders rum ist das nicht so einfach 
möglich.

von Karl H. (kbuchegg)


Lesenswert?

mcnanuk schrieb:

> void uart_gets( char * Buffer )
> {
>   char c;
>   int  nextCharPos = 0;
>
>   c = uart_getc_wait();
>   uart_putc(c);
>   while( c != '\n' ) {
>     Buffer[ nextCharPos++ ] = c;
>   c = uart_getc_wait();
>   uart_putc(c);
>
>   }
>
>   Buffer[ nextCharPos ] = '\0';
> }


Normalerweise mach ich solche Sachen ungern mit Index-Variablen. Lieber 
direkt mit Pointermanipulation. Dann muss man keineen Datentyp für die 
Indexvariable festlegen. Reichen 8 Bit, oder sollen es doch 16 Bit sein. 
Mit Pointern stellt sich die Frage nicht.

Da die Funktion allerdings sowieso noch ausgebaut werden müsste
1
void uart_gets( char * Buffer, int BufferSize )

um der Funktion die Möglichkeit der Verhinderung eines Bufferüberlaufs 
zu geben, kommt dieser Index dann sehr gelegen.

> jep ... Danke Dir...
> Die Feinheiten werde ich noch einbauen, wobei Die Schnittstelle sehr
> einfach gehalten werden soll...

Wer sitzt am anderen Ende?
Ein Mensch oder ein anderes Programm?

Für einen Menschen solltest du noch zumindest eine rudimentäre 
Editiermöglichkeit über 'Backspace' (die große Pfeil Links Taste über 
Return) einbauen. Das geht ziemlich trivial: du kriegst ein '\b' Zeichen 
über die Schnittstelle und wenn du selber eines wegschickst, dann 
schiebt das Terminal den Cursor ein Zeichen nach links.
1
void uart_gets( char * Buffer )
2
{
3
  char c;
4
  int  nextCharPos = 0;
5
 
6
  while( ( c = uart_getc_wait() ) != '\n' ) {
7
8
    if( c == '\b' ) {
9
      if( nextCharPos > 0 ) {
10
        nextCharPos--;
11
        uart_putc( '\b' );
12
        uart_putc( ' ' );
13
        uart_putc( '\b' );
14
      }
15
    }
16
17
    else {
18
      uart_putc( c );
19
      Buffer[ nextCharPos++ ] = c;
20
    }
21
  }
22
 
23
  Buffer[ nextCharPos ] = '\0';
24
25
  uart_putc( '\n' );
26
}

von mcnanuk (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wer sitzt am anderen Ende?
> Ein Mensch oder ein anderes Programm?

Hehe die Frage ist einfach: Ich ! :)
Es soll auch nur eine Zahl eingegeben werden. 0-40 000. Das \n übernimmt 
Hterm für mich :)

Aber ich werde in der Zukunft das ganze Ausbauen, und wie du sagtest es 
Userproof machen.

von Zwie B. (zwieblum)


Lesenswert?

>> Wer sitzt am anderen Ende?
>> Ein Mensch oder ein anderes Programm?
>
> Hehe die Frage ist einfach: Ich ! :)

Nun, das ist unter Umständen keine erschöpfende Auskunft ;)

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.