www.mikrocontroller.net

Forum: Compiler & IDEs Peak bei Initialisierung


Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich habe folgendes Problem:

Ich habe eine LED am PORTB PB0 welche wenn der Ausgang gesetzt ist NICHT 
leuchtet.
Bei meinem Programm wird anfangs der Watchdog gesetzt anschließend 
werden die Ports gesetzt und dann der Prozessor abgeschaltet.
int main( void )
{
  wdt_enable(WDTO_120MS);          //Watchdog akivieren
  clock_prescale_set(clock_div_2);
  DDRB  = 0b00010111;
  PORTB  = 0b11101101;

  sleep_mode();


Das Problem ist, dass beim initialisieren des Portes immer ein Peak 
entsteht, der wenn man das selbe in Assembler schreibt, bei der ASM 
Variante "ASM noPeak" nicht entsteht.

//ASM noPeak
/*
     ldi   TEMP    , 0b00010111
     ldi   _TEMP   , 0b11101101
     out   PORTB   , _TEMP
     out   DDRB    , TEMP                ; Port B initialisieren
*/

//ASM Peak
/*
         ldi       TEMP    , 0b00010111
         out       DDRB    , TEMP                ; Port B initialisieren
         ldi       _TEMP   , 0b11101101
         out       PORTB   , _TEMP
*/

Gibt es eine Möglichkeit das Port in C so zu intialisieren ,dass dieser 
Peak ebenfalls nicht entsteht?

Danke Norton

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es nur die Reihenfolge der Portzugriffe (1. PORTB setzen, 2. DDRB 
setzen statt 1. DDRB und 2. PORTB) ist, dann so:
   
     // ASM No-Peak
     // ldi   TEMP    , 0b00010111
     // ldi   _TEMP   , 0b11101101
     // out   PORTB   , _TEMP
     // out   DDRB    , TEMP
     PORTB = 0xED;
     DDRB = 0x17;

Wenn du die zwei OUT Befehle unmittelbar hintereinander brauchst, melde 
dich noch mal.

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau um die zwei OUT befehle geht es. Gibts da auch eine elegante 
Lösung die gleich hintereinander zu machen.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fällt mir ausser über Inline-Assembler nur der Umweg über eine Funktion 
ein.

#include <avr/io.h>

void doit(unsigned char t1, unsigned char t2) __attribute__ ((noinline));

void doit(unsigned char t1, unsigned char t2)
{
  PORTB = t1;
  DDRB = t2;
}

int main(void)
{
  doit(0xED, 0x17);

  while(1)
    ;

  return 0;
}


Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Norbert S. wrote:
> Gibt es eine Möglichkeit das Port in C so zu intialisieren ,dass dieser
> Peak ebenfalls nicht entsteht?

Natürlich, schreibs einfach in der richtigen Reihenfolge hin.

Der Peak entsteht dadurch, daß Du erst den Pin auf Ausgang setzt und 
später auf High.

Machs umgekehrt und der Peak ist weg.



> Ja genau um die zwei OUT befehle geht es. Gibts da auch eine elegante
> Lösung die gleich hintereinander zu machen.

Dazu gibts keinen Grund, die zusätzlichen 50ns merkt keine Sau nach den 
65000000ns Resetzeit.


Peter

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort @stefan

Die Funktion hat leider nicht den gewünschte Erfog gebracht.
Ich bin noch Anfäger und hätte da noch einige dumme Fragen:

> void doit(unsigned char t1, unsigned char t2) __attribute__
> ((noinline));

Was bewirkt diese Zeile eigentlich?


Habe mich mal mit Inline Assembler versucht und bekomme folgenden 
Fehler:
asm volatile ("ldi   r16     , 0b00010111    \n\t"
              "ldi   r17     , 0b11101101    \n\t"
              "out   PORTB   , r17           \n\t"
              "out   DDRB    , r16        \n\t"
        );
C:\DOKUME~1\NORBER~1\LOKALE~1\Temp/ccBMwlIL.s:75: Error: constant value 
required

Was ist bei der Inline Assembler Funktion falsch?

Autor: Norbert S. (norton)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke an alle!

Ich habe nun zuerst den Pin gesetzt und anschließend auf Ausgang --> der 
Peak ist weg.
(so einfach kann die Lösung sein :-) )

Aus interesse würde trotzdem gerne wissen was beim Inline Assembler 
schief gelaufen ist?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und ich frage extra noch, ob es nur um die Reihenfolge geht ;-)

Zu Inline_Assembler gibt es eine gute Doku bei 
http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

#include <avr/io.h>

void doit(unsigned char t1, unsigned char t2) __attribute__ ((noinline));

void doit(unsigned char t1, unsigned char t2)
{
  PORTB = t1;
  DDRB = t2;
}

int main(void)
{
  // doit(0xED, 0x17);

  asm volatile ("ldi   r17, %0    \n\t"
                "ldi   r16, %1    \n\t"
                "out   %2, r17    \n\t"
                "out   %3, r16    \n\t"
                // Ausgabe (leer)
                :
                // Eingabe
                : "M" (0xED), "M" (0x17),  
                  "I" (_SFR_IO_ADDR(PORTB)), "I" (_SFR_IO_ADDR(DDRB))
                // verschmutzt
                : "r17", "r16"                                           
        );


  while(1)
    ;

  return 0;
}

Diese Zeile

void doit(unsigned char t1, unsigned char t2) __attribute__ ((noinline));


verhindert, dass GCC die Pippifax-Funktion doit() inline in main() 
reinzieht. Als inline-Funktion würden die beiden OUT-Statements nicht 
unmittelbar hintereinander stehen. Der Code wäre inline identisch mit 
diesen Statements.

  PORTB = 0xED;
  DDRB = 0x17;


Möglicherweise funktioniert das bei in meinem Testfall nur wegen -Os 
Optimierung und/oder WinAVR-20071221 Version. Müsste man mehr 
experimenteren und jeweils das *.LSS File ansehen, was rauskommt.

Aber wenn deine Lösung jetzt ja funktioniert...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.