printf bei Handy-SMS Code aus Artikel geht nicht?

OP #2249611
Lesenswert?

Hallo,
Ich bin gerade dabei, aus der Artikelsammlung das "mikrocontroller 
verschickt SMS an Siemens-Handy"-Projekt nachzubauen. Hab auch alles 
soweit, Handy geht, etc. jetzt schaue ich, dass ich den Code auf einen 
ATmega8 abgespeckt bekomme.

Leider geht die printf-Funktion nicht, der µC sendet dabei nix über das 
UART raus...Woran kann das liegen? Ich habe im Makefile schon 
printf-options auf "minimalistic" eingestellt. Warum geht diese 
printf-Variante nicht?

In meiner Hauptroutine steht jetzt zum Test:
1
uart_sends("hallo"); //das funktioniert
2
printf("at+cclk?\r\n"); //da kommt nix an
3
_delay_ms(2500);
4
sms_send("015781581259","Die Krümmung ist eine Größe der inneren Geometrie");
5
//da kommt auch nix an

Die wichtigsten Code-Schnipsel aus dem Artikel für die SMS-Funktionen 
lauten so:
1
void sms_init(void){
2
  // Initialisierung der seriellen Schnittstelle Asynchron
3
  uart_init();
4
  // öffnet Kanal für printf
5
  //stdout = &mystdout;
6
  fdevopen (uart_sendc, uart_receive);
7

8
  UCSRB &= ~(1 << RXCIE);    // UART Receive ISR ausstellen
9

10
  printf("ATE0\r\n");    // Echo off, reduce traffic
11
  _delay_ms(200);
12
  printf("AT+CPMS=\"ME\",\"MT\",\"MT\"\r\n");    // Speicher von gelesenen, geschriebenen und empfangenen SMS auf Telefonspeicher stellen
13
  _delay_ms(200);
14
  printf("AT+CNMI=1,1,0,0,1\r\n");        // new message indication --> "+CMTI:<mem>,<index>"
15
  _delay_ms(200);
16

17
  // Auslesen der ersten 5 Telefonnummern der SIM-Karte
18
  char telnr[SMS_TELNR_MAX_LEN+1];
19
  uint8_t i=0;
20
  int dummy;
21
  printf("AT+CPBS=\"SM\"\r\n");          // Telefonbuch auf SIM Karte umstellen
22
  _delay_ms(200);
23
  uart_clear();
24
  for (i=0;i<SMS_TELNR_LIST_MAX;i++) {
25
    uart_clear();
26
    printf("AT+CPBR=%i\r\n",i+1);
27
    gets(telnr);
28
    scanf("+CPBR: %i,\"%[^\"]",&dummy,telnr);
29
    _delay_ms(400);                // Rest der Antwort abwarten und verwerfen
30
    if (strlen(telnr)>3) {
31
      strcpy(sms_telnr_list[i].telnr,telnr);  // ausgelesene Telefonnummer in Struktur speichern  
32
    }
33
    else { strcpy(sms_telnr_list[i].telnr, "noNR");}
34
  }
35
  uart_clear();
36
  if (UART_ISR!=0) {UCSRB |= (1 << RXCIE);}    // UART Receive ISR wieder einstellen
37
}

und
1
void sms_send(char* zielnr, char* nachricht)
2
{
3
  uint8_t cnt_shiftzero=0;
4
  uint8_t cnt_nr=0;          // Zähler für Zielnummer, nach Umwandlung = Länge der Zielnummer
5
  uint8_t cnt_txt=0;          // Zähler für Nachricht, nach Umwandlung = Länge der Nachricht
6
  uint8_t shift=0;
7
  uint8_t i=0;
8
  char nachricht_neu[SMS_MESSAGE_MAX_LEN+1]={"\0"};
9
  char zielnr_neu[SMS_TELNR_MAX_LEN+1]={" "};
10

11
  UCSRB &= ~(1 << RXCIE);    // UART Receive ISR ausstellen
12

13
  // Nachricht umwandeln in PDU-Format
14
  while (nachricht[cnt_txt]!=0)
15
  {
16
    if (shift==7) {
17
      shift=0;
18
      cnt_txt++;
19
      cnt_shiftzero++;
20
    }
21
    else {                
22
      nachricht_neu[cnt_txt-cnt_shiftzero] = (((nachricht[cnt_txt]&0x7F)>>shift) | ((nachricht[cnt_txt+1])<<(7-shift)));
23
      shift++;
24
      cnt_txt++;
25
    }
26
  }
27
  nachricht_neu[cnt_txt-cnt_shiftzero]=nachricht[cnt_txt];  // '0' anfügen , Endestring
28
  
29
  // Zielnummer neu zusammensetzen
30
  // Bsp. 01 62 64 94 30 0 --> 10 26 46 49 03 F0
31
  // wenn 2 Bytes nicht voll ausgenutzt werden, 'F' einfügen
32
  while (zielnr[cnt_nr]!=0) {
33
    if (zielnr[cnt_nr+1]==0) {
34
      zielnr_neu[cnt_nr]='F';  
35
      zielnr_neu[cnt_nr+1]=zielnr[cnt_nr];
36
      cnt_nr++;
37
      cnt_nr++;
38
      zielnr_neu[cnt_nr]=zielnr[cnt_nr-1];  // '0' anfügen , Endestring
39
      break;
40
    }
41
    else {
42
      zielnr_neu[cnt_nr]=zielnr[cnt_nr+1];
43
      zielnr_neu[cnt_nr+1]=zielnr[cnt_nr];
44
      cnt_nr=cnt_nr+2;
45
    }
46
  }
47

48
  //Anzahl der Zeichen im PDU-String/2-->Hex Paare -2 (ersten 2 Hex Zeichen weglassen)
49
  //-->'Anzahl der Nachrichtenzeichen' + 'Anzahl der Nummern /2' (/2 da nur Hex Paare gezählt werden) + '7' (zusätzliche Header)
50
  if (zielnr_neu[cnt_nr-2]=='F') {
51
    printf("AT+CMGS=%i\r\n",cnt_txt-cnt_shiftzero+(cnt_nr/2)+7);
52
    cnt_nr--;    //Länge der Zielnummer -1, da 'F' angefügt
53
  }
54
  else {
55
    printf("AT+CMGS=%i\r\n",cnt_txt-cnt_shiftzero+(cnt_nr/2)+7);
56
  }
57

58
  //while(uart_receive()!=' ');    // auf antwort von Handy warten '> '
59
  _delay_ms(1000);
60
  printf("000100%02X81",cnt_nr);
61
  printf(zielnr_neu);
62
  printf("0000%02X",cnt_txt);
63
  for (i = 0;i<(cnt_txt-cnt_shiftzero);i++){
64
    printf("%02X", nachricht_neu[i]);
65
  };
66
  printf("%c",26);
67
  if (UART_ISR!=0) {UCSRB |= (1 << RXCIE);}    // UART Receive ISR wieder einstellen)
68
}

Danke!
Gast #2249640
Lesenswert?

M. G. schrieb:
> In meiner Hauptroutine steht jetzt zum Test:
> uart_sends("hallo"); //das funktioniert
> printf("at+cclk?\r\n"); //da kommt nix an
> _delay_ms(2500);
> sms_send("015781581259","Die Krümmung ist eine Größe der inneren Geometrie");
> //da kommt auch nix an

Kann ´ja auch nicht ohne vorher sms_init aufzurufen.
OP #2249654
Lesenswert?

Na, sms_init ist natürlich aufgerufen, und Platz ist auch genug auf dem 
µC (siehe unten), ich habe halt in der sms.c alle Funktionen 
rausgenommen ausser sms_send und sms_init. Ich will auch nur diese zwei 
Sachen erstmal machen!
Also die ganze Hauptroutine in main.c sieht halt so aus:
1
#include "main.h"
2
#include "uart.c"
3
#include "sms.c"
4

5
volatile uint8_t timer_flag;
6

7
int main(void) {
8

9
DDRD = (1<<PD1) | ( 1 << PD2 );
10
DDRB=0xFF;
11
PORTB=0;
12

13
  sei();
14
  sms_init();
15
  uart_clear();
16

17
uart_sends("hallo"); //geht
18
printf("at+cclk?\r\n"); //geht nicht
19

20

21
  
22
  
23
  
24
while(1) //Ende
25
{
26
PORTB = ( 1 << PB0 );
27
_delay_ms(250);
28
PORTB = ( 0 << PB0 );
29
_delay_ms(250);
30
}
31
}

Ach ja, und der AVR ist halt bis zum Rand gefüllt:
1
Program:    5112 bytes (62.4% Full)
2
(.text + .data + .bootloader)
3

4
Data:       1009 bytes (98.5% Full)
5
(.data + .bss + .noinit)
Gast #2249657
Lesenswert?

M. G. schrieb:
> #include "uart.c"
> #include "sms.c"

Das sollte eher *.h heißen.
Am original Code brauchst du sicher keine Fehler suchen, der 
funktioniert so wie er ist. Wurde schon dutzende Male erfolgreich 
verwendet. Wahrscheinlicher ist, dass du etwas auskommentiert hast, was 
du nicht hättest auskommentieren sollen (wie z.B. die header -Dateien)
OP #2249742
Lesenswert?

Ah,
das klingt nach der Lösung...
Also du meinst, man definiert für die AT-Commandostrings 
Flash-Variablen?
etwa so:
1
char StringImFlash[] PROGMEM = "at+cclk?\r\n"; // im "Flash"
2

3
printf_P(StringImFlash);

oder etwa sowas wie
1
const char Ichbinimflash[] PROGMEM = "%s";
2

3
printf_P(Ichbinimflash); 
4
??????


(Kennt jemand eigentlich mal so eine Art Dokumentation zu diesen 
merkwürdigen printf-Funktionen? Ich weiß eigentlich gar nicht genau, was 
die machen...?!)
#2249767
Lesenswert?

M. G. schrieb:
> Also du meinst, man definiert für die AT-Commandostrings
> Flash-Variablen?
> etwa so:
1
char StringImFlash[] PROGMEM = "at+cclk?\r\n"; // im "Flash"
2

3
printf_P(StringImFlash);
>
> oder etwa sowas wie
1
const char Ichbinimflash[] PROGMEM = "%s";
2

3
printf_P(Ichbinimflash);
4
??????

Oder einfach so:
1
printf_P(PSTR("at+cclk?\r\n"));


> (Kennt jemand eigentlich mal so eine Art Dokumentation zu diesen
> merkwürdigen printf-Funktionen? Ich weiß eigentlich gar nicht genau, was
> die machen...?!)
http://www.nongnu.org/avr-libc/user-manual/
Gast #2249947
Lesenswert?

Läubi .. schrieb:
> Was ich mich frage ist: Wozu benötigt man hier überhaupt printf? Nur für
> die Formatierte Ausgabe von ein paar Zahlen? Da könnte man durch eine
> eigene Routine sicherlich auch noch etwas Platz sparen.

Zitat aus Artikel:
"Die einzelnen Algorithmen sind dabei sehr einfach gehalten. Das 
bedeutet, dass es sicherlich sehr viel kürzere Varianten gibt, um z. B. 
einen Text in das PDU Format zu transformieren. Ich habe mich aber 
lieber auf mehr und damit für andere auch verständlicheren Code 
beschränkt. Das verbraucht zwar mehr Speicher, trägt aber meines 
Erachtens zum Verständnis bei."

Platz sparen war hier nicht der Ansporn, sondern vielmehr das 
Verständniß und printf kennt nun mal jeder. Der Anfänger muss siche eben 
nicht mit dem UART rumschlagen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren