Forum: Mikrocontroller und Digitale Elektronik Character string


von Bernhard K. (looxer)


Lesenswert?

Hallo,


ich versuche gerade meine erste UART anwendung in C zu erstellen und 
habe da ein kleines problem. wenn ich den empfangsbuffer am M16C auslese 
bekomme ich diesen string:

'Hallo Welt/n'

das ganze würde ich gerne am angeschlossenen LCD ausgeben. wenn ich es 
nun mit sprintf in einen buffer kopiere und ausgebe bekomme ich nur ein 
"H" am LCD.

Wie kann ich den gesamten string ausgeben?

mir ist zwar klar das 'Hallo Welt/n' und "Hallo Welt/n" nicht das selbe 
ist. welches von beiden ist aber jetzt ein character string?


lg,
looxer

von string (Gast)


Lesenswert?

char * string = "Ich bin ein String"

char a = 'a'; // ich bin ein character

von Bernhard K. (looxer)


Lesenswert?

ok, soweit is mir das schon klar gewesen. aber ein character der aus 
mehreren zeichen besteht, ist das immer noch nur ein character? und vor 
allem  wie mache ich daraus einen string?

von Gast (Gast)


Lesenswert?

es gibt keinen character des aus mehreren Zeichen besteht :)
mitdemzaunpfahlwink
Aber gut, ich denke das ist dir klar.
Ein String ist ja im Grunde genommen nichts andere als eine 
An-Einanderreihung mehrerer Character (Stichwort Arrays).


Du könntest z.B. versuchen deinen Satz aus eben so einem Array Stück für 
Stück an das Display auszugeben.

Beispiel wäre:
1
int i;
2
char der_text[10];         //Character Array mit 10 Stellen
3
der_text = "Hallo Welt";    // zufälligerweise genau 10 Stellen ;)
4
5
for (i=0;i<=9;i++) {
6
   sprintf("%c",der_text[i]);
7
   }


obs jetzt funktionieren wird kann ich nicht mit 100%iger Sicherheit 
sagen - aber probiers einfach mal!

von Timmo H. (masterfx)


Lesenswert?

>"der_text = "Hallo Welt";    // zufälligerweise genau 10 Stellen ;)
Das sind aber 11 Zeichen (\0)

>der_text = "Hallo Welt";
Das geht nicht. Wenn dann
1
char der_text[] = "Hallo Welt";
oder eben mit strcpy.

>sprintf("%c",der_text[i]);
sprintf dient zum "drucken" einer Zeichenkette in ein String. ( int 
sprintf ( char * str, const char * format, ... ); )
printf wäre da besser.
Und wegen der Null-Terminierung kann man auch schreiben
1
i=0;
2
while(der_text[i])
3
  putchar(der_text[i++]);

Fürs senden eines Strings oder Char würden für einen AVR die Funktionen 
z.B. so aussehen:
1
void uart_putc(char c){
2
  while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
3
4
  UDR = c;                      /* sende Zeichen */
5
}
6
 
7
void uart_puts (char *s)
8
{
9
  while (*s){  
10
    uart_putc(*s);
11
    s++;
12
  }
13
}

von Bernhard K. (looxer)


Lesenswert?

erstmal vielen dank für eure antworten! ich habe beide ansätze probiert, 
leider funktionieren sie aber nicht.

wenn ich den string "Hallo Welt/n" verwende dann klappt ja alles. mit 
'Hallo Welt/n' bekomme ich wieder mein H am LCD und dannach irgendwelche 
wirren zeichen. Ich schätze mal das hier einfach über die array grenze 
hinaus gelesen wird.

von Sven P. (Gast)


Lesenswert?

'.' macht eine Zeichenkonstante. Mit der kannste rechnen, wie mit jeder 
anderen Zahl auch. 'a' ist z.B. gleich 97.

"...." ergibt einen Zeiger auf das erste Zeichen (i.S.v. 
Zeichenkonstante, s.o.) zurück, dem alle weiteren Zeichen zwischen den 
Gänsefüßchen folgen, mal einfach ausgedrückt.

von ich (Gast)


Lesenswert?

"wenn ich den string "Hallo Welt/n" verwende dann klappt ja alles"

Wenn alles klappt, wo ist jetzt das Problem?

"mit'Hallo Welt/n' bekomme ich wieder mein H am LCD"

Ist ja klar, ' ' benutzt man ja auch für einzelne Zeichen = Character 
und nicht für Zeichenketten = String.

von Bernhard K. (looxer)


Lesenswert?

schon klar, aber ich bekomme genau das 'Hallo Welt/n' aus meinem UART 
empfangsregister raus.

von spess53 (Gast)


Lesenswert?

Hi

>schon klar, aber ich bekomme genau das 'Hallo Welt/n' aus meinem UART
>empfangsregister raus.

Gar nicht. Das UART-Empfangsregister kann nur ein Zeichen enthalten. Das 
heisst du musst die einzelnen Zeichen nach Eintreffen aus UDR auslesen 
und deinen String basteln. Einzelheiten stehen im Datenblatt. Sogar in 
C.

MfG Spess

von Kobaltchlorid (Gast)


Lesenswert?

Ich kenne zwar den "M16C" nicht und weiss auch nicht,wie dein Code 
aussieht (den du hier ja nicht mitgeliefert hast), aber ein 
UART-Empfangsregister in einem Mikrocontroller kann immer nur EIN Byte 
aufnehmen.

Du musst dich normalerweise in deinem Code selber darum kümmern, dass du 
einen FIFO*-Buffer anlegst und diesen auch korrekt füllst und ausliest. 
Wenn du bloss das Empfangsregister ausliest, bekommst du logischerweise 
immer nur ein einziges Zeichen angezeigt.

*: FIFO: First In, First Out. Das zuerst geschriebene Byte wird auch als 
erstes aus dem Buffer ausgelesen.

Normalerweise sieht das so aus, dass du in der  RX-Interrupt-Funktion 
des UART (=ein einzelnes Zeichen wurde empfangen) das empfangene Zeichen 
in deinen (von dir per Code angelegten und per Code verwalteten) FIFO 
schreibst und dabei eine globale Variable (z.B. genannt "rx_count") 
hochzählst, die dir die Anzahl der empfangenen Zeichen anzeigt.

Mit einer ausserhalb des Interrupt verwendeten Funktion "getchar" (die 
ebenfalls von dir selber angelegt werden muss) holst du dir dann bei 
Bedarf ein Zeichen nach dem anderen aus deinem FIFO, wobei bei jedem 
Auslesen eines Zeichens rx_count um eins vermindert wird.

Entsprechende funktionsfähige Beispiele gibt es zu hunderten im Netz und 
normalerweise sind auch entsprechende Funktionen in den Libs des 
C-Kompilers zu finden. Ob diese Funktionen bei dir schon vorhanden sind 
(oder ob du sie erst selber schreiben musst) sollte aber in der 
Dokumentation deines Compilers stehen.

Ich würde dir auch empfehlen, erst ein mal Tutorials oder Bücher über 
C-Programmierung zu lesen. Leider fehlt's bei dir schon an ganz 
grundlegenden Kenntnissen wie z.B. dem Unterschied zwischen char und 
string.

von ich (Gast)


Lesenswert?

Oder ließt du das hier aus "'Hallo Welt/n'"?

von Bernhard K. (looxer)


Lesenswert?

ok, ich weis von output eines port sniffers das am uart ein string in 
dieser form kommt:

Hallo Welt\n

wenn ich nun den interrupt nur dazu verwende ein flag zu setzen mit dem 
ich dann an andere stelle das auslesen des uart buffers zu triggern, 
dann füllt sich der buffer mit lauter "H" auf.

hier noch der source:
ich stell an den übrigens nicht die anforderung perfekt programmiert zu 
sein, sondern einfach nur mal mehr als nur das erste zeichen vom uart 
auszugeben. ich habe ihn vom restlichen programm bereinigt. hoffentlich 
hab ich nicht zu viel gelöscht.


#include "skp_bsp.h"       // include SKP board support package
#include "stdio.h"

#define BAUD_RATE_UART  19200  // Baudrate for UART

/* Prototype declarations */
void mcu_init(void);       // MCU initialization included in mcu_init.c
void uart_init(void);      // UART initialization
void periph_init(void);      // Timers and IRQ's initialization


/* global variable declarations */
char U0_in;             // declare UART0 receive variable

/* Interrupt function declarations */
#pragma INTERRUPT U0rec_ISR     // vector modified in 
sect30_28skp_uart.inc
void U0rec_ISR (void);       // Interrupt routine for UART0 Receive


// DEBUG declarations
unsigned char buffer[35];
unsigned char temp[3];
int x;


/*********************************************************************** 
*******
Name       : main
Parameters : none
Returns    : nothing
Description: Main procedure
************************************************************************ 
******/
void main(void)
{
  periph_init();          // Initialize timers, ADC and IRQ's

  while (1){


    while (U0_in)
    {  while (x <= 35)
      {  buffer[x] = (char)u0rb;
        x++;
      }
      U0_in = 0;
      DisplayString(LCD_LINE2, buffer);
      x=0;
    }
  }
}

/*********************************************************************** 
******
Name:       UART0 Receive Interrupt Routine
Parameters:  none
Returns:     none
Description: Interrupt routine for UART0 receive
       Reads character received from keyboard and stores U0_in variable
************************************************************************ 
*****/
void U0rec_ISR(void){

  while(ri_u0c1 == 0);      // make sure receive is complete
  U0_in = 1;    // read in received data
}



/*********************************************************************** 
******
Name:      periph_init
Parameters:  none
Returns:     none
Description: initualizes all peripherialy for this uC
************************************************************************ 
*****/
void periph_init(void)
{
  mcu_init();        // Initialize MCU
  InitDisplay();      // Initialize LCD
  uart_init();      // Initialize UART
}

/*********************************************************************** 
******
Name:    uart_init
Parameters:  None
Returns:  None
Description: Uart0 initialization - 19200 baud, 8 data bits, 1 stop bit, 
no parity.
************************************************************************ 
*****/
void uart_init(void) {

  u0brg = (unsigned char)(((f1_CLK_SPEED/16)/BAUD_RATE_UART)-1);  // set 
UART0 bit rate generator
     /*
        bit rate can be calculated by:
        bit rate = ((BRG count source / 16)/baud rate) - 1

      in this example: BRG count source = f1 (10MHz)
               baud rate = 19200
               bit rate = ((10MHz/16)/19200) - 1 = 31

        ** one has to remember that the value of BCLK does not affect 
BRG count source */

    ucon = 0x00;     // UART transmit/receive control register 2
     /*
      00000000;   // transmit irq not used
      ||||||||______UART0 transmit irq cause select bit, U0IRS
        |||||||_______UART1 transmit irq cause select bit, U1IRS
        ||||||________UART0 continuous receive mode enable bit, U0RRM - 
set to 0 in UART mode
        |||||_________UART1 continuous receive mode enable bit, U1RRM  - 
set to 0 in UART mode
        ||||__________CLK/CLKS select bit 0, CLKMD0 - set to 0 in UART 
mode
        |||___________CLK/CLKS select bit 1, CLKMD1 - set to 0 in UART 
mode
        ||____________Separate CTS/RTS bit, RCSP
        |_____________Reserved, set to 0 */

    u0c0 = 0x10;     // UART0 transmit/receive control register 1
     /*
      00010000;    // f1 count source, CTS/RTS disabled, CMOS output
      ||||||||______BRG count source select bit, CLK0
        |||||||_______BRG count source select bit, CLK1
        ||||||________CTS/RTS function select bit, CRS
        |||||_________Transmit register empty flag, TXEPT
        ||||__________CTS/RTS disable bit, CRD
        |||___________Data output select bit, NCH
        ||____________CLK polarity select bit, CKPOL     - set to 0 in 
UART mode
        |_____________Transfer format select bit, UFORM   - set to 0 in 
UART mode */

    u0c1 = 0x00;     // UART0 transmit/receive control register 1
     /*
      00000000;    // disable transmit and receive
      ||||||||______Transmit enable bit, TE
        |||||||_______Transmit buffer empty flag, TI
        ||||||________Receive enable bit, RE
        |||||_________Receive complete flag, RI
        ||||__________Reserved, set to 0 */

    u0mr = 0x05;    // UART0 transmit/receive mode register
     /*
      00000101;    // 8-bit data, internal clock, 1 stop bit, no parity
      ||||||||______Serial I/O Mode select bit, SMD0
        |||||||_______Serial I/O Mode select bit, SMD1
        ||||||________Serial I/O Mode select bit, SMD2
        |||||_________Internal/External clock select bit, CKDIR
        ||||__________Stop bit length select bit, STPS
        |||___________Odd/even parity select bit, PRY
        ||____________Parity enable bit, PRYE
        |_____________Reserved, set to 0 */

    u0tb = u0rb;    // clear UART0 receive buffer by reading
    u0tb = 0;      // clear UART0 transmit buffer

    DISABLE_IRQ;    // disable irqs before setting irq registers
  s0ric = 0x04;    // Enable UART0 receive interrupt, priority level 4
  ENABLE_IRQ;      // Enable all interrupts

    u0c1 = 0x05;     // UART0 transmit/receive control register 1
     /*
      00000101;    // enable transmit and receive
      ||||||||______Transmit enable bit, TE
        |||||||_______Transmit buffer empty flag, TI
        ||||||________Receive enable bit, RE
        |||||_________Receive complete flag, RI
        ||||__________Reserved, set to 0 */
}

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.