www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Pic Zeitschleife geht nich, verstehe nicht wieso


Autor: Pascal (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

also ich habe einige Zeitschleifen geschrieben, nur passiert nichts wenn 
sie aufgerufen werden... also nie wieder.
Hab ich da irgentwie eine Endlosschleife gebaut?
Oder Funktioniert das mit dem _asm ... _endasm so nicht?
Ich verstehe nicht warum es so nicht funktioniert.

Ich benutze MPLAB mit dem C18 Compiler.

Hier die 3 Verzögerungen, vom Takt her habe ich 4MHz das erstmal fest 
gelegt, da es zur Zeit nur diesen Aufbau gibt.

void DelayUs(unsigned int x);
void DelayMs(unsigned int x);
void DelayS(unsigned int x);

void DelayUs(unsigned int x)
{
  // 4MHz -> 1 Zyklus = 1us!
  while(x>0)
  {
    x--;
    _asm NOP _endasm
  }
}
void DelayMs(unsigned int x)
{
  int i,j;
  for(i=0;i<x;i++)
  {
    for(j=0;j<4;j++)
      DelayUs(250);
  }
}
void DelayS(unsigned int x)
{
  int i,j;
  for(i=0;i<x;i++)
  {
    for(j=0;j<4;j++)
      DelayMs(250);
  }
}

Dann habe ich noch ein kleines Testprogramm, das eine LED an Port-A 
blinken lassen soll.

#include <p18f458.h>
#pragma config OSC=EC, PWRT=ON, WDT=OFF

// Hier stehen die Zeitfunktionen von oben zwischen.

void main(void)
{
  TRISA = 0;
  while(1)
  {
    PORTAbits.RA0 = 1;
    DelayS(1);
    PORTAbits.RA0 = 0;
    DelayS(1);
  }
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#pragma config OSC=EC...

Hast du auch einen externen Taktgenerator dran?

Autor: Severino R. (severino)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pascal schrieb:
> Hallo,
>
> also ich habe einige Zeitschleifen geschrieben, nur passiert nichts wenn
> sie aufgerufen werden... also nie wieder.
> Hab ich da irgentwie eine Endlosschleife gebaut?
> Oder Funktioniert das mit dem _asm ... _endasm so nicht?
> Ich verstehe nicht warum es so nicht funktioniert.

Funktioniert es in echter Hardware nicht, oder im Simulator nicht, oder 
in beiden nicht?

> void DelayUs(unsigned int x)
> {
>   // 4MHz -> 1 Zyklus = 1us!
>   while(x>0)
>   {
>     x--;
>     _asm NOP _endasm

Du führst ja nicht nur NOP aus, sondern auch x--, das braucht auch noch 
ein paar Zyklen.

Autor: Uwe Nagel (ulegan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach mal die Verzögerung kürzer, denn dein DelayUs dauert sicher 
deutlich länger als eine Mikrosekunde. Nicht nur der nop frisst Zeit, 
x-- braucht auch und das x>0 will ausgewertet werden. Dazu kommt der 
Aufruf und die Rückkehr aus dem Unterprogramm. Selbst ohne das irgendwas 
auf dem Stack gesichert wird, und das wird es ganz bestimmt, würde ein 
CALL und ein RETURN schon 4 Zyklen brauchen.
Ich schätze ein DelayUs(1) mal auf mindestens 30 Zyklen = 30 µs.
Betrachte mal den erzeugten Assemblercode.

Uwe

Autor: RoGerZ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... while (x>0) ist immer wahr,
wenn x eine unsigned int ist...

Kleine Ursache, große wirkung!

Gruß,
R.

Autor: RoGerZ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, zu schnell geantwortet:
Das geschriebene stimmt natürlich nur, wenn da stehen würde "while 
(x>=0)" ... steht da aber nicht, muß also ander Ursache haben ...

Gruß,
R.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal so:
void main(void)
{
 ADCON0=0;          //AD-Wandler aus
 ADCON1=0x0F;       //Alle Analogeingänge auf digital
 CMCON=0x07;        //Komparatoren aus

  TRISA = 0;
  while(1)
  {
    PORTAbits.RA0 = 1;
    DelayS(1);
    PORTAbits.RA0 = 0;
    DelayS(1);
  }
}

Und wie oben schon gesagt wurde, werden deine
Delays länger sein als erwartet.

>Oder Funktioniert das mit dem _asm ... _endasm so nicht?

Doch, das geht so.

Autor: Pascal (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja hab einen externen Takt angeschlossen.

Es funktioniert in der Hardware nicht, wie man simuliert hab ich noch 
nicht rausgefunden.

Ok, in Asm sieht das ganze schon etwas anders aus. Also die Us Funktion 
zumindest:

void DelayUs(unsigned int x)
  0008    CFD9     MOVFF 0xfd9, 0xfe6             // 2 Zyklen
  000A    FFE6     NOP
  000C    CFE1     MOVFF 0xfe1, 0xfd9             // 2 Zyklen
  000E    FFD9     NOP
27:                {
28:                  // 4MHz -> 1 Zyklus = 1us!
29:                  while(x>0)
  0010    50D9     MOVF 0xfd9, W, ACCESS          // 1 Zyklus
  0012    0FFD     ADDLW 0xfd                     // 1 Zyklus
  0014    6EE9     MOVWF 0xfe9, ACCESS            // 1 Zyklus
  0016    0EFF     MOVLW 0xff                     // 1 Zyklus
  0018    20DA     ADDWFC 0xfda, W, ACCESS        // 1 Zyklus
  001A    6EEA     MOVWF 0xfea, ACCESS            // 1 Zyklus
  001C    0E00     MOVLW 0                        // 1 Zyklus
  001E    80D8     BSF 0xfd8, 0, ACCESS           // 1 Zyklus
  0020    54EE     SUBFWB 0xfee, W, ACCESS
  0022    0E00     MOVLW 0                        // 1 Zyklus
  0024    54ED     SUBFWB 0xfed, W, ACCESS
  0026    E207     BC 0x36
  0034    D7ED     BRA 0x10                       // 1 Zyklus
30:                  {
31:                    x--;
  0028    0EFD     MOVLW 0xfd                     // 1 Zyklus
  002A    06DB     DECF 0xfdb, F, ACCESS          // 1-2 Zyklus
  002C    0EFE     MOVLW 0xfe                     // 1 Zyklus
  002E    E201     BC 0x32                        // 1 Zyklus
  0030    06DB     DECF 0xfdb, F, ACCESS          // 1-2 Zyklus
32:                    _asm NOP _endasm
  0032    0000     NOP                            // 1 Zyklus
33:                  }
34:                }
  0036    52E5     MOVF 0xfe5, F, ACCESS          // 1 Zyklus
  0038    CFE7     MOVFF 0xfe7, 0xfd9             // 2 Zyklus
  003A    FFD9     NOP
  003C    0012     RETURN 0                       // 2 Zyklus


so gob über den Daumen insgesamt 27 Zyklen... anstatt 1 wie gedacht.

Bei den anderen Funktionen für Ms und S, ist das dann genauso, das 
heisst es wird "etwas" länger dauern... wenn ich dann noch die for() 
Schleifen in Asm übersetzt sehe, wird mir klar warum nichts passiert, es 
dauert einfach zu lange...

Hm, ok hab jetzt versucht eine Us Funktion in Asm zu schreiben, mit dem 
Schluss das das woll nichts wird, weil der Aufruf und der Rücksprung bei 
4Mhz schon länger wie 1us dauert.

Gibts nicht irgentwo eine Art Bibiotek die fertige Zeitfunktionen hat, 
die auch ohne größere Schwierigkeiten in MPLAB zum laufen gebraucht 
werden können?

Autor: Sebastian B. (mircobolle)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat dein PIC einen freien Timer, oder eine Real Time Clock?

Warum realisierst du die Wartefunktion nicht mit einer Interrupt 
Funktion?

etwa so:

static volatile unsigned int s_v_u16_counter=0;

void wait_ms (unsigned int u16_wait_cnt)
{
   s_v_u16_counter = u16_wait_cnt;

   while (s_v_u16_counter > 0)
   {
      _asm{"nop"};
   }
}

und dann in der Timer ISR
void isr_timer_overflow (void)
{
   reset_overflow_flag(); // Makro
   if (s_v_u16_counter > 0)
   {
     s_v_u16_counter--;
   }
}

Die "Wartezeit" wird dann ueber den Timer Counter Wert bestimmt.
So bekommt man allerdings keine Genauigkeit im us Bereich hin. Aber für 
ms und s reicht es.

Gruß

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.