Forum: Compiler & IDEs Flash + String + Uart senden


von Josef K. (josefk)


Lesenswert?

Hallo zusammen,

hab ein kleines Problem mit meiner Sendefunktion. Die Funktion sollte 
einen im Flash abgelegten String senden.
1
const char spi_start[] PROGMEM = "Aktiviere SPI...";
2
const char sdparser_start[] PROGMEM = "SD Karten Zugriff...";
3
4
void uart0_init(void)
5
{
6
  // Baudrate 9600
7
  UBRR0L = 103;
8
9
  // Baudrate 115200
10
  //UBRR0L = 3;
11
12
  // Datenbyte 8
13
  UCSR0C |= (1 << UCSZ00);
14
  UCSR0C |= (1 << UCSZ01);
15
  // Parity keine
16
  UCSR0C &= ~(1 << UPM00);
17
  UCSR0C &= ~(1 << UPM01);
18
  // Stoppbit 1
19
  UCSR0C &= ~(1 << USBS0); 
20
  // Asynchronous Operation
21
  UCSR0C &= ~(1 << UMSEL0);
22
  UCSR0C &= ~(1 << UCPOL0);  
23
24
  UCSR0B |= (1 << RXCIE); // Interrupt enabel für RXC flag
25
  UCSR0B |= (1 << RXEN0);  // Receive Enable
26
  UCSR0B |= (1 << TXEN0);  // Transmitter Enable
27
28
}
29
30
void rs232_puts_P(PGM_P s)
31
{
32
   unsigned char c;
33
   while (*s != '\0')
34
   {
35
      while ( !(UCSR0A & (1<<UDRE0)));         //Warten bis UDR leer ist für Senden
36
      c = pgm_read_byte (s);
37
      UDR0 = c;
38
      s++;                                    //Adresse erhöhen
39
   }    
40
   while ( !(UCSR0A & (1<<UDRE0)));  
41
   UDR0 = '\n';   
42
   while ( !(UCSR0A & (1<<UDRE0))); 
43
   c = pgm_read_byte (s); 
44
   UDR0=c;
45
   while ( !(UCSR0A & (1<<TXC0)));              //Warten bis Senden abgeschlossen
46
}
47
48
49
main
50
{
51
//UART0 aktivieren (Logger)
52
  uart0_init();
53
  uip_ipaddr_t IpAddr;
54
//SPI Schnitstelle aktivieren
55
  rs232_puts_P(spi_start);
56
  SpiInit();
57
//erstellt obj_dir_app leer oder mit SD-Inhalt
58
  app_object_parser();
59
  rs232_puts_P(sdparser_start);
60
//...
61
while(1);
62
}

Was dann im Terminal raus kommt:
1
<\0><\0><\n>
2
ASD Karten Z<\n>
3
uAk<\n>
4
t<\0><\n>
5
A

Ich finds komisch. Irgendwo mach ich was falsch, nur wo?

von Hermann-Josef (Gast)


Lesenswert?

Hallo Josef,
1
while (*s != '\0')

prüft nicht im Flash sondern im RAM.

Ich würde das so schreiben:
1
   unsigned char c;
2
   while ( (c = pgm_read_byte(s)) != '\0')
3
   {
4
      while ( !(UCSR0A & (1<<UDRE0)));         //Warten bis UDR leer ist für Senden
5
      UDR0 = c;
6
      s++;                                    //Adresse erhöhen
7
   }

oder noch etwas 'optimiert':
1
   while ( (c = pgm_read_byte(s++)) != '\0')
und dann das Erhöhen der ADresse weiter unten weglassen.

Ciao
Hermann-Josef

von Josef K. (josefk)


Lesenswert?

Ahhh Danke. Das bringt mich schon weiter. Scheint immer noch nicht ganz 
zu funktionieren, aber der 
Beitrag "Re: Problem mit pgm_read_byte_far" zeigt auch ein 
mögliches Problem.

von Simon K. (simon) Benutzerseite


Lesenswert?

Hermann-Josef wrote:
> oder noch etwas 'optimiert':
>
1
>    while ( (c = pgm_read_byte(s++)) != '\0')
2
>

Die Bedingung wird aber auch zu Anfang der Schleife durchlaufen. Dann 
würde ja immer das erste Zeichen fehlen...

von Karl H. (kbuchegg)


Lesenswert?

Simon K. wrote:
> Hermann-Josef wrote:
>> oder noch etwas 'optimiert':
>>
1
>>    while ( (c = pgm_read_byte(s++)) != '\0')
2
>>
>
> Die Bedingung wird aber auch zu Anfang der Schleife durchlaufen. Dann
> würde ja immer das erste Zeichen fehlen...

Äh, nein, warum sollte es?
In pgm_read_byte geht ja der Wert von s vor der Erhöhung hinein.

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.