for Schleife einsetzen

OP (Firma: Privat) #3718619
Lesenswert?

Hallo Z'men,

anhang eines AD-Wandlers von AT89C51CC03 habe das Programm unten 
geschrieben geschrieben. Aber ich weiss nicht genau, wo die For-Schleife 
einzubringen ist, wenn ich die Messwerte im Bereich 150MicroS und 
4200MicroS auch mit jedem Potis P16 und P17 einlesen moechte, denn ich 
die Werte mit beiden Potis im Bereich von 1ms - 256ms.

Lange Rede kurzer Sinn, hier das Programm:

1
/****************************************************************************************************/
2
    /*  Dieses Programm namens "recht_2.C" gibt ein zeitlich komplett parametrierbares                  */
3
    /*  Rechtecksignal am Port-Pin P1.0 aus.                                                            */
4
    /* Damit kann man waehrend des Betriebs die Breitenwerte des Signals einstellen                     */
5
    /* -->fuer die positive Impulsbreite tp wird der Trimm-Poti P1.6 im Bereich 1ms bis 256ms verwendet */
6
    /* -->fuer die negative Impulsbreite tn wird der Trimm-Poti P1.7 im Bereich 1ms bis 256ms verwendet */
7
    /* Der A/D-Wandler wird im 8-Bit-Modus betrieben                                                    */
8
    /*                                                                                                  */
9
    /****************************************************************************************************/
10

11
/*** Einbinden von Include-Dateien ***/
12
#include<stdio.h>
13
#include<at89c51cc03.h>
14

15

16

17
void main (void)     // Start des Hauptprogramms
18
{
19
    unsigned int wert_p16, wert_p17;  //Variablen zur Aufnahme des Teilergebnisses von Trimm-Poti p1.6 und p1.7
20
    unsigned int wert;              //Variable zur Aufnahme des zusammengesetzten Gesamtergebnisses
21

22
    /**************************************************************/
23
    /*  Initialisierung der seriellen Schnittstelle 0 des CC03ers */
24
    /*  Schnittstellenparameter: 9600Baud, 8 Datenbit, 1 Stopp-Bit*/
25
    /*  asynchroner Betrieb                                       */
26
    /**************************************************************/
27
    SCON=0x52;
28
    TMOD |=0x20;
29
    TH1=0xfd;
30
    TR1=1;
31
    TI=1;
32
    
33
    /* Initialisierung des A/D-Wandlers */
34
    ADCF = 0xc0;    // Port P1.6 und P1.7 als Analogeingang definieren,
35
                    // d.h., CH6 und CH7 sollen angesprochen werden
36
    ADCON = 0x20;   // Enable ADC, mit ADEN =1 und
37
                    // SCH2, SCH1, SCH2 sollen respektiv die Werte 110 und 111
38
                    // um den P1.0 steuern zu können...
39

40

41
    printf("\x1b\x48\x1b\x4a"); //löschen des Bildschirms
42
 
43
    while(1)
44
    {
45
        ADCON &= ~0x07;             // Sicher stellen, dass SCH2, SCH1, SCH0 auf null initialisiert sind
46
        ADCON |= 0x06;              // Auswahl von CH6
47
        ADCON &= ~0x40;             // Standard Mode
48
        ADCON = ADCON | 0x08;       // Start der Wandlung
49
        
50
        while ((ADCON & 0x10)==0);  //warten bis Wandlung fertig ist
51

52
        ADCON = ADCON & 0xef;       // End of Conversion Bit löschen
53
        wert_p16 = ADDH;            //Ergebnis des eingestellten Wertes von Poti P1.6 speichern
54

55
        /*Das vermeiden vom Programmabsturz */
56
        if(wert_p16==0)
57
        {
58
            wert_p16++;
59
        }
60
        _wait_ms(wert_p16);
61
        printf("tp hat den wert: %u ms\n\n", wert_p16); // Ausgabe von tp(positive Impulbreite)
62

63

64
        ADCON &= ~0x07;             // Sicher stellen, dass SCH2, SCH1, SCH0 auf null initialisiert sind
65
        ADCON |= 0x07;              // Auswahl von CH7
66
        ADCON &= ~0x40;             // Standard Mode
67
        ADCON = ADCON | 0x08;       // Start der Wandlung
68
        
69
        while ((ADCON & 0x10)==0);  //warten bis Wandlung fertig ist
70

71
        ADCON = ADCON & 0xef;       // End of Conversion Bit löschen
72
        wert_p17 = ADDH;             //Ergebnis des eingestellten Wertes von Poti P1.7 speichern
73

74
        
75
        /*Das vermeiden vom Programmabsturz */
76
        if(wert_p17==0)
77
        {
78
            wert_p17++;
79
        }
80
        _wait_ms(wert_p17);
81
        printf("tn hat den wert: %u ms\n\n", wert_p17); // Ausgabe von tn
82

83
        wert = wert_p16 + wert_p17; //tp + tn zusammenfuegen
84

85
    
86
        printf("die gesamte Impulsbreite ist: %u ms\n\n", wert);  //Ausgabe der gesamten Impulsbreite --> (tp + tn)
87
      
88

89

90
    }//end while
91
    
92
 
93

94
} //end main()
Angehängte Dateien:
Gast #3718627
Lesenswert?

Ist ja furchtbar. Fang das am Besten nochmal von vorne an.

Es ist wesentlich besser, die Speicherung des AD-Wandlungsergebnises und 
die Umstellung des Kanals in einer Interrupt-Routine zu erledigen.

Dann, wenn das funktioniert, stellst Du in (ich würde mal sagen in der 
selben Interrupt-Routine) das Timerregister für die PWM um.

Die Hauptschleife ist im wesentlichen leer (falls Du die Ausgabe nicht 
wirklich brauchst).

Eine For-Schleife kommt da überhaupt nicht vor.
Gast #3718630
Lesenswert?

Ach, und noch ein Hinweis:

Die Bits in den Steuerregistern haben Namen, die auch in at89c51cc03.h 
definiert sind. Verwende die und nicht irgendwelche Literale, die Du 
dann in Kommentaren lang und breit erklären musst.
OP (Firma: Privat) #3719641
Lesenswert?

Danke erstmal fuer die schnelle Antwort ;)

@Bitfluesterer
Heuuu, leider haben wir noch nicht den Interrupt-Kapitel behandelt. es 
gilt auch fuer die PMW...
Zur Aufgabe habe ich als Hinweise, die For-Loop zu benutzen, um den 
Zeitbereich zw 150ms und 4200ms darzustellen.

@Lothar
damit die Werte im Bereich 150microS und 4200microS auch mit dem 
Oszilloskop geprueft/dargestellt werden koennen, gaben sie mir als 
Hinweis eine For-Loop zu benutzen. ich habe folgendes z.B direkt nachdem 
wait_ms()-Funktion probiert und natuerlich als Datentyp "float" 
deklariert:
1
        for(wert_p17==0.150; wert_p17<=4.2; (wert_p17++*0.001))
2
        {
3
            printf("tn hat den wert: %3.2f ms\n\n", wert_p17);
4
        }


@Peter,
ich habe das Programm selber geschrieben ;) und es laeuft(Halleluja)
Es ist wahr, dass ich printf mit 1ms schon laeuft, aber waehrend ich an 
den Potis drehe, wird die Impulsbreite immer groesser(max 510ms). 
Hauptsache ist es, dass ich kein NULL im meiner wait_ms()funktion habe, 
um den Abstuerz des Programms zu vermeiden(deshalb die if-loop).

Danke nochmal fuer die Hilfe.
Gast #3719700
Lesenswert?

g r u s e l i g.

a) statt
1
if(wert_p17==0)
2
{
3
    wert_p17++;
4
}
5
_wait_ms(wert_p17);

kannst du doch auch einfach schreiben:
1
if(wert_p17>0) {
2
  _wait_ms(wert_p17);
3
}


b) wie soll "for(wert_p17==0.150; wert_p17<=4.2; (wert_p17++*0.001))" 
denn compilieren?

"wert_p17==0.150" ist ein Vergleich.
Vermutlich wolltest du "wert_p17=0.150" hier schreiben.

Was soll "(wert_p17++*0.001)" machen?
Ich nehme mal an, es soll "(wert_p17+=0.001)" heissen?

Und was genau soll diese Schleife jetzt hilfreiches machen, ausser dass 
sie dir 4050 Float-Werte zwischen 0.15 und 4.2 auf den Schirm 
printet????


Mit viel Phantasie und einigen runden Glasgegenständen lese ich heraus, 
dass es dir eigentlich darum geht, deine Potiwerte von 0-255 in 
Delay-Werte zwischen 150us und 4200us umrechnen möchtest.

Für das eigentliche Delay nützt dir dann allerdings die Funktion 
"_wait_ms()" wenig.

Weiter sagt mir die Glaskugel, dass du statt "_wait_ms()" eine 
For-Schleife verwenden willst, um Delays im us-Bereich zu bekommen.

Ich sehe in deinem Programm allerdings auch keine Anweisungen, die einen 
Output-Port toggeln würden, damit du deine PWM mit einem Oszilloskop 
sichtbar machen könntest.

Offenbar reicht dir bisher die printf Ausgabe auf deinem Schirm, dass 
die Delay-Werte überhaupt berechnet wurden?

Rätsel,....
OP (Firma: Privat) #3724263
Lesenswert?

Soooli...

Oh je!!

Ihr habt mir eine richtige Lektion erteilt (Nie Wieder schreiben oder 
denken, dass "if" eine Schleife ist, auch wenn man es nicht so gemeint 
hat ;) )
Auf jeden Fall bin ich ein Stueck weiser geworden. Danke!!!

Weiser bin ich auch in sofern geworden, da ich anhang die guten Hinweise 
von Easylife das Programm verbessert habe (um ehrlich zu sein, habe 
ich eigentlich die mir gestellte Aufgabe besser verstanden).

Anbei, wie versprochen, das bearbeitete Programm. Ich muss zugeben, dass 
ich mir noch etwa schwer tue, was die for-Schleife (am Ende des 
Programms) anbelangt.

Also mit der For-Schleife soll es moeglich sein, die werte zw. 
150microSekunden und 4200microSekunden darzustellen. Hiermit danke ich 
euch im Voraus fuer die Inputs...
1
    /**********************************************************************************************************/
2
    /*  Dieses Programm namens "recht_3.C" gibt ein zeitlich komplett parametrierbares                         */
3
    /*  Rechtecksignal am Port-Pin P1.0 aus.                                                                   */
4
    /* Damit kann man waehrend des Betriebs die Breitenwerte des Signals einstellen                            */
5
    /* -->fuer die positive Impulsbreite tp wird der Trimm-Poti P1.6 im Bereich 1micros bis 10micros verwendet */
6
    /* -->fuer die negative Impulsbreite tn wird der Trimm-Poti P1.7 im Bereich 1micros bis 10micros verwendet */
7
    /* Der A/D-Wandler wird im 8-Bit-Modus betrieben                                                           */
8
    /*                                                                                                         */
9
    /***********************************************************************************************************/
10

11
/*** Einbinden von Include-Dateien ***/
12
#include<stdio.h>
13
#include<at89c51cc03.h>
14

15
unsigned char bit dIn_out @ 0x90;   // Port-Pin P1.0 bekommt den Variablen-Namen 
16
                                    //zugeordnet
17

18

19
void main (void)     // Start des Hauptprogramms
20
{
21
   float wert_p16, wert_p17;  //Variablen zur Aufnahme des Teilergebnisses von Trimm-Poti p1.6 und p1.7
22
   float wert;              //Variable zur Aufnahme des zusammengesetzten Gesamtergebnisses
23

24
    /**************************************************************/
25
    /*  Initialisierung der seriellen Schnittstelle 0 des CC03ers */
26
    /*  Schnittstellenparameter: 9600Baud, 8 Datenbit, 1 Stopp-Bit*/
27
    /*  asynchroner Betrieb                                       */
28
    /**************************************************************/
29
    SCON=0x52;
30
    TMOD |=0x20;
31
    TH1=0xfd;
32
    TR1=1;
33
    TI=1;
34
    
35
    /* Initialisierung des A/D-Wandlers */
36
    ADCF = 0xc0;    // Port P1.6 und P1.7 als Analogeingang definieren,
37
                    // d.h., CH6 und CH7 sollen angesprochen werden
38
    ADCON = 0x20;   // Enable ADC, mit ADEN =1 und
39
                    // SCH2, SCH1, SCH2 sollen respektiv die Werte 0, 0, 0
40
                    // um den P1.0 steuern zu können...
41

42

43
    printf("\x1b\x48\x1b\x4a"); //löschen des Bildschirms
44
 
45

46
    /*Endlosschleife*/
47
    while(1)
48
    {
49
        ADCON &= ~0x07;             // Sicher stellen, dass SCH2, SCH1, SCH0 auf null initialisiert sind
50
        ADCON |= 0x06;              // Auswahl von CH6
51
        ADCON &= ~0x40;             // Standard Mode
52
        ADCON = ADCON | 0x08;       // Start der Wandlung
53
        
54
        while ((ADCON & 0x10)==0);  //warten bis Wandlung fertig ist
55

56
        ADCON = ADCON & 0xef;       // End of Conversion Bit löschen
57
        wert_p16 = ADDH;            //Ergebnis des eingestellten Wertes von Poti P1.6 speichern
58

59
        wert_p16=((wert_p16*10.0)/255.0)+0.04; //Umwandlung in microSekunde mit Skala von 0.040 microSekunden
60
       
61
        dIn_out=0; //High Pegel am Port-Pin P1.0
62
        printf("tp hat den Wert: %3.3f microSekunde\n\n", wert_p16);
63

64

65

66
        ADCON &= ~0x07;             // Sicher stellen, dass SCH2, SCH1, SCH0 auf null initialisiert sind
67
        ADCON |= 0x07;              // Auswahl von CH7
68
        ADCON &= ~0x40;             // Standard Mode
69
        ADCON = ADCON | 0x08;       // Start der Wandlung
70
        
71
        while ((ADCON & 0x10)==0);  //warten bis Wandlung fertig ist
72

73
        ADCON = ADCON & 0xef;       // End of Conversion Bit löschen
74
        wert_p17 = ADDH;             //Ergebnis des eingestellten Wertes von Poti P1.7 speichern
75
        
76
        wert_p17=((wert_p17*10.0)/255.0)+0.04; //Umwandlung in microSekunden mit Skala von 0.040 microSekunden
77

78
        dIn_out=1; // Low Pegel am Port-Pin P1.0
79
        printf("tn hat den Wert: %3.3f microSekundes\n\n", wert_p17);
80

81

82
        wert = wert_p16 + wert_p17; //gesamte Impulsbreite tp + tn 
83

84
        for(wert=0.15; wert<=4.2; wert+=0.04)
85
        {
86
            printf("die gesamte Impulsbreite ist: %3.3f microSekundes\n\n", wert);  //Ausgabe der Impulsbreite
87
        }
88
      
89

90

91
    }//end while
92
    
93
 
94

95
} //end main()
Gast #3730624
Lesenswert?

Leider hast du die Aufgabe eben gar nicht verstanden.

Deine printf() Aufrufe musst du rausnehmen. Die brauchen viel zu viel 
Zeit.

Ich versuche dir mal die Aufgabe zu erklären:

Du sollst ein Programm schreiben, das auf einem I/O Pin eine PWM macht, 
die du mit einem Oszilloskop messen kannst.

D.h. du hast dann sowas wie
1
while(1)
2
{
3
  dIn_out=1;    // output pin auf high setzen
4
  wait(t_on);   // eine gewisse Zeit warten
5
  dIn_out=0;    // output pin auf low setzen
6
  wait(t_off);  // wieder eine gewisse Zeit warten
7
}

Da deine Wartezeiten im Bereich von 150us bis 4200us (=4.2ms) sein 
sollen, kannst du für "wait()" nicht die Funktion "_wait_ms()" nehmen.

Stattdessen wurde dir empfohlen das Delay über eine For-Schleife zu 
machen, und das sieht dann so aus:
1
void wait(unsigned t)
2
{
3
  unsigned i;
4
  for (i=0; i<t; i++)
5
    ;
6
}

D.h. du benutzt einfach eine leere for-schleife, die nichts anderes tut 
als i von 0 bis t zählen zu lassen.
Dafür braucht der Microcontroller eine gewisse Zeit, dadurch entsteht 
ein Delay.
Wie viel Zeit in Abhängigkeit von t vergeht, musst du mit dem 
Oszilloskop messen, und dann t mit einem entsprechenden Faktor 
multiplizieren um auf eine genau definierte Zeit zu kommen.

Es kann auch sein, dass die Schleife so schnell durchläuft, dass du 
damit keine 4200us mehr hinbekommst, in dem Fall musst wait() 
entsprechend mehrmals aufrufen, bzw. 2 Schleifen ineinander schachteln.

Am besten testest du erstmal mal folgendes aus:
1
  unsigned i;
2
  unsigned t = 10000;
3

4
  while(1)
5
  {
6
    dIn_out=1;    // output pin auf high setzen
7

8
    for (i=0; i<t; i++)
9
      ;
10

11
    dIn_out=0;    // output pin auf low setzen
12

13
    for (i=0; i<t; i++)
14
      ;
15
  }

und misst mal die Frequenz auf dem Output pin.
Dann kann man dir weiterhelfen einen entsprechenden Faktor zu berechnen.


Am Ende musst du auch noch berücksichtigen, dass ja dein Potentiometer 
abgefragt werden soll, daher wäre es auch wichtig zu prüfen, ob eine A/D 
Wandlung innerhalb der 150us überhaupt zu machen ist.
OP (Firma: Privat) #3731737
Lesenswert?

Hoi Zämen,

Vielen Vielen Dank Easylife!

Ich bin nur überrascht, wie du mein Anliegen besser als mich kennst.
Obwohl ich es zigmal gelesen habe, bin ich auf diese Lösung nie 
gekommen.

Aber so gut erklaert und ganz besonders sehr gut detailliert.
Phenomenal und sensationell, wenn man sich sehr gut auskennt ;-)

Danke fuer die investierte Zeit(!), denn es ist nicht immer 
selbsverstaendlich.

Deine Hinweise werde ich im Programm einsetzen und natuerlich sofort 
Posten!!!!

VG
Gast #5769525
Lesenswert?

Moin,

ich möchte dieses Beispiel gern aufgreifen, da ich selber gerade damit 
beschäftigt bin und mir sich dieses Beispiel eines Delay in Form einer 
For-Schleife zwar in der Theorie erschließt, praktisch aber nicht 
funktioniert.
Bei dem von Easylife genannten Wert für t=10000, ergibt sich an Portpin 
1.0 eine Frequenz von 3,55 Hz, was einer Periodendauer T = 282 ms 
entspricht. Bei einem symmetrischen Rechtecksignal wäre tp und tn somit 
T/2 bzw. 141ms.
Um nun die Impulsbreite (tp) und die Impulspause (tn) mit beiden Poti´s 
von 0,150 ms bis 4,2 ms einstellen zu können ist genau welcher Faktor zu 
verwenden?

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