Forum: Mikrocontroller und Digitale Elektronik PIC18F67K22 Projekt


von Gschwande (Gast)


Lesenswert?

Hallo,

ich bin leider absoluter Anfänger in Mikrocontroller bzw. C 
programmieren, deshalb benötige ich jetzt Hilfe.

Ich hab mir ein Steuerkästchen gebaut, mit dem man einen Elektromotor 
per Schalter starten bzw. stoppen und mittels Poti die Drezahl regeln 
kann.

Ich will das Poti über den AD-Wandler einlesen und dann über ein PWM 
Signal an den Motor ausgeben.

Für den AD-Wandler hab ich mir schon bissl was gebastelt (siehe weiter 
unten), aber wie das mit dem PWM hinhaut hab ich leider gar keine 
Ahnung, kann mir da bitte jemand ein Code Beispiel oder so geben? Ich 
verwende den PIC 18F67K22.

Vielen Dank!

  while (1)
    {

        int i;
        int warte;
        i = 0;
        int summe;
        summe = 0;



        for (i; i<=3; i++)

        {
         // kurz warten
            warte = 200;
            while(warte--);
         // Wandeln starten
            ADCON0 |= 0b00000011;
            warte = 2500;
            while ((ADCON0bits.GODONE == 1) && (warte-- != 0));
            erg = ADRESH;
            erg <<= 8;
            erg |= ADRESL;
            summe = summe + erg;

        }

         erg = summe/3;



       CLRWDT();

}

: Verschoben durch User
von WehOhWeh (Gast)


Lesenswert?

Mit Beispielen für PIC18 kann ich leider direkt nicht dienen.

Microchip bietet aber selber Code Examples an:
https://www.microchip.com/CodeExamplesByFunc.aspx

Sonst gibts noch die MLA:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en547784

Ich bin übrigens bisher immer gut damit durchgekommen, die Datenblätter 
"apzutippen". Das relevante Kapitel bei deinem PIC wäre 20.3 oder 20.4.

von vloki (Gast)


Lesenswert?

Gschwande schrieb:
> Für den AD-Wandler hab ich mir schon bissl was gebastelt (siehe weiter
> unten), aber wie das mit dem PWM hinhaut hab ich leider gar keine
> Ahnung,

Im Prinzip steht, wie WehOhWeh schon erwähnt hat, natürlich alles im 
Datenblatt. Bei den PICs mit mehreren gleichen Modulen kann es aber 
trotzdem etwas verwirrend sein.

Also wenn du ein PWM Modul verwenden möchtest, dann hat der 67K22 wohl 7 
davon (Nr. 4..10). Da suchst du dir das aus, welches den passendsten 
Ausgangs-PIN hat. (Der am günstigsten liegt oder was auch immer)
Ich häng mal unten ein Beispiel an wo das das Modul mit der Nummer "1" 
war, die es bei dir aber nicht gibt.

Bevor du weitermachst schaust du dir die Abbildung "FIGURE 19-3 
SIMPLIFIED PWM BLOCK DIAGRAM" im Datenblatt an. (ist beispielhaft mit 
CCP4 und Timer2)

Das Modul stellst man über das zugehörige CCPxCON Register auf den 
richtigen Modus (PWM mit einem Ausgang) ein.

Die Verknüpfung mit dem gewünschten Timer wird im Register CCPTMRSx 
vorgenommen.

Bei dir wird vermutlich die Periode immer die gleiche sein und das 
Tastverhältnis soll sich ändern. Im Beispiel unten ist es umgekehrt da 
wird die Periode geändert und das Tastverhältnis ist immer ~50%.
Die Periode wird mit PRx (Periodenregister des Timers) eingestellt, das 
Tastverhältnis im Register CCPRxL.

Die Auflösung der PWM "kann" 10bit betragen. Wenn für deine Anwendung 
8bit ausreichen, dann war es das eigentlich schon. Sobald der Timer 
läuft, läuft auch die PWM.

Ach ja, der PWM-Output muss natürlich noch als solcher konfiguriert 
werden.

PS: bei 8bit -> ADC linksbündig und nur ADRESH verwenden. Was sind das 
eigentlich für Wartezeiten bei der AD Wandlung?
1
void Sound_PWM(void){   //PWM   ###TODO -> Lautstaerke !
2
    unsigned short frequency = 300;
3
//--------------------------------------------------- __init()
4
    OSCCONbits.IRCF = IRCF_4MHZ;
5
    LCD_Init();
6
    LCD_ConstTextOut(0,0,"uC-Quick");
7
    LCD_ConstTextOut(1,0," Sound ");
8
    ENC_INT_TRI = INPUT_PIN;    // encoder setup
9
    ENC_DIR_TRI = INPUT_PIN;
10
    mENC_IR_CLR();
11
    mENC_IR_EN();
12
13
//#####################################################################
14
    CCP1CONbits.CCP1M = 0b1100;                             // PWM mode
15
16
    CCP1CONbits.P1M = 0;                                    // single
17
18
    CCPTMRS0bits.C1TSEL = 0;                                // CCP1-TMR2
19
20
    PR2 = 62500 / frequency;                                // 1MHz:16
21
22
    CCPR1L = PR2 >> 1;
23
24
    SPEAKER_TRI = OUTPUT_PIN;                               // PWM output
25
26
    OpenTimer2(TIMER_INT_OFF & T2_PS_1_16 & T2_POST_1_1);
27
//    OpenTimer2(TIMER_INT_OFF & T2_PS_1_1 & T2_POST_1_1);
28
//#####################################################################
29
30
    flags.all = 0;
31
    INTCONbits.GIE = 1;
32
//----------------------------------------------- main()
33
    while(1){
34
        if(flags.encUp){
35
            if(frequency < 800) {frequency = frequency + 10;}
36
              else {frequency = frequency + 100;}
37
            if(frequency > 15600){frequency = 15600;}
38
            PR2 = (62500 / frequency) -1;             // 1MHz : 16
39
            CCPR1L = PR2 >> 1;
40
            LCD_ConstTextOut(1,0,"      ");      // delete old value
41
            LCD_ValueOut(1,1,frequency);
42
            flags.encUp = 0;
43
        }
44
        if(flags.encDown){
45
            if(frequency < 800) {frequency = frequency - 10;}
46
              else {frequency = frequency - 100;}
47
            if(frequency < 250) {frequency = 250;}
48
            PR2 = (62500 / frequency)-1;              // 1MHz : 16
49
            CCPR1L = PR2 >> 1;
50
            LCD_ConstTextOut(1,0,"      ");      // delete old value
51
            LCD_ValueOut(1,1,frequency);
52
            flags.encDown = 0;
53
        }
54
    }
55
}
56
57
void interrupt high_isr(void)
58
{
59
    if (ENC_IR){                         // encoder interrupt
60
        if(ENC_DIR == ENC_DIR_UP)
61
            flags.encUp = 1;
62
        else
63
            flags.encDown = 1;
64
        mENC_IR_CLR();
65
        return;
66
    }
67
...
68
}

von Gschwande (Gast)


Lesenswert?

Und wie mach ich es, dass das PWM Signal meinen AD Wandler Wert ausgibt?

von Volker S. (vloki)


Lesenswert?

vloki schrieb:
> Die Periode wird mit PRx (Periodenregister des Timers) eingestellt, das
> Tastverhältnis im Register CCPRxL.

Für den Anfang kannst du ja mal PRx auf 255 und
dann CCPRxL = ADRESH oder CCPRxL = 255-ADRESH

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.