1  | #include "p18cxxx.h"
  | 
2  | #include "xc.h"
  | 
3  | #include "config.h"
  | 
4  | 
  | 
5  | #define BTN_IGNORE_FACTOR 10
  | 
6  | #define _XTAL_FREQ 1000000
  | 
7  | 
  | 
8  | volatile unsigned char ad_msb = 0, ad_lsb = 0;
  | 
9  | 
  | 
10  | void delay(int time);
  | 
11  | void SetupOscillator(void);
  | 
12  | void SetupPWM(void);
  | 
13  | void SetupADC(void);
  | 
14  | void interrupt low_priority Low_Priority_ISR(void);
  | 
15  | 
  | 
16  | void main(void) {
 | 
17  | 
  | 
18  |    unsigned char button = 0, ignorebutton = 0;
  | 
19  | 
  | 
20  |    ANSEL = 0x00;                             //Eingänge Digital
  | 
21  |    ANSELH = 0x00;
  | 
22  |    INTCONbits.GIEH = 1;             //Alle High-Priority Interrupts enabled
  | 
23  |    INTCONbits.GIEL = 1;             //Alle Low-Priority Interrupts enabled
  | 
24  |    RCONbits.IPEN = 1;               //Enable Priority levels on Interrupts
  | 
25  | 
  | 
26  |    SetupOscillator();                          //Frequenz 1MHz
  | 
27  |    SetupADC();    //Analogsignal RA0 einlesen, Digital RB0 einlesen(Taster)
  | 
28  |    SetupPWM();  
  | 
29  |    while (1) {
 | 
30  |        ADCON0bits.GO_DONE = 1;                    //A/D-Wandlung starten
  | 
31  |        while(ADCON0bits.GO_DONE != 0);         //auf A/D-Wandlung warten
  | 
32  |        ad_msb = ADRESH;                         //A/D-Ergebnis Bit 2 bis 10
  | 
33  |        ad_lsb = ADRESL;                          //A/D-Ergebnis Bit 0 und 1
  | 
34  |        if (PORTBbits.RB0 == 0 && ignorebutton == 0) { //Taster gedrückt? (=0, 1= not pressed)
 | 
35  |             button = button ^ 1;       //Modus toggeln -> PWM/Laufschrift
  | 
36  |             ignorebutton = BTN_IGNORE_FACTOR; //Taster für bestimmte Zeit ignorieren
  | 
37  |         }
  | 
38  |         if (ignorebutton > 0) ignorebutton--;    //Ignorierzeit verringern
  | 
39  |         if (button == 0) {                //Modus checken
 | 
40  |              PIE1bits.ADIE = 0;           //ADC-Interrupt disabled
  | 
41  |              CCPR2L = ad_msb;
  | 
42  |              CCPR1L = ad_msb;
  | 
43  |              CCP2CONbits.DC2B = ad_lsb;    //Steigerung Duty Cycle auf 0,1%
  | 
44  |              CCP1CONbits.DC1B = ad_lsb;
  | 
45  |              //PIE1bits.ADIE = 1;          //ADC-Inerrupt enabled
  | 
46  |              LATD = ad_msb;
  | 
47  |         }  else{
 | 
48  |             CCPR1L = CCPR1L - 1;           //PWM Duty Cycle an CCP1/RC2 verringern -> abklingen
  | 
49  |             delay(25);                     //25ms warten
  | 
50  |             if(CCPR1L == 0){
 | 
51  |                 button = 0;
  | 
52  |             }
  | 
53  |             
  | 
54  |         }
  | 
55  | 
  | 
56  |     }
  | 
57  | }
  | 
58  | 
  | 
59  | void delay(int time) {
 | 
60  |    int counter = 0;
  | 
61  |    for (counter = 0; counter<time; counter++)
  | 
62  |         __delay_ms(1);
  | 
63  | }
  | 
64  | 
  | 
65  | void SetupOscillator(){
 | 
66  |     OSCCONbits.SCS = 0x3;       //Interner Oscillator
  | 
67  |     OSCCONbits.OSTS = 0;        //Interner Oscillator
  | 
68  |     OSCCONbits.IRCF0 = 1;
  | 
69  |     OSCCONbits.IRCF1 = 1;
  | 
70  |     OSCCONbits.IRCF2 = 0;       //Oscillatorfrequenz 1MHz
  | 
71  |     OSCCONbits.IDLEN = 0;       //Sleep-Mode bei sleep
  | 
72  | }
  | 
73  | 
  | 
74  | void SetupPWM(){
 | 
75  |    TRISCbits.RC1 = 1;           //Port RC1/CCP2 PWM als Ausgang sperren
  | 
76  |    TRISCbits.RC2 = 1;           //Port RC2/CCP1 PWM als Ausgang sperren
  | 
77  |    T2CONbits.T2CKPS = 0x00;     //Timer 2 Eingang: Fosc 1MHz/4 = 250kHz
  | 
78  |    PR2 = 249;                 //PWM-Periode: PR+1 * 1/250kHz = 1ms, f=1kHz
  | 
79  |    CCP2CONbits.CCP2M = 0x0F;    //CCP2 auf PWM
  | 
80  |    CCP1CONbits.CCP1M = 0x0C;    //CCP1 auf PWM
  | 
81  |    CCP1CONbits.P1M = 0x00;      //CCP1 Single Mode
  | 
82  |    PSTRCONbits.STRA = 1;        //P1A als Ausgang für CCP1
  | 
83  |    TRISCbits.RC1 = 0;           //Port RC1/CCP2 PWM als Ausgang
  | 
84  |    TRISCbits.RC2 = 0;           //Port RC2/CCP1 PWM als Ausgang
  | 
85  |    T2CONbits.TMR2ON = 1;        //Timer 2 an
  | 
86  | }
  | 
87  | 
  | 
88  | void SetupADC(){
 | 
89  |    TRISAbits.RA0 = 1;            //Port RA0 Poti auf Eingang setzen
  | 
90  |    TRISBbits.RB0 = 1;            //Port RB0 Taster auf Eingang setzen
  | 
91  | 
  | 
92  |    ANSELbits.ANS0 = 1;     //RA0 auf Analogeingang setzen (=1, 0 = digital)
  | 
93  |    ADCON0bits.ADON = 1;          //A/D-Wandler aktivieren
  | 
94  |    ADCON0bits.CHS = 0x00;        //AN0/RA0 als A/D-Converter Eingang
  | 
95  |    ADCON1bits.VCFG1 = 0;  //Negative Voltage Reference (=Vss , 0 = AN2,RA2)
  | 
96  |    ADCON1bits.VCFG0 = 0;  //Positive Voltage Reference (=Vdd , 0 = AN3,RA3)
  | 
97  |    ADCON2bits.ADFM = 0;   //A/D-Wandler Conversion Result Format: Links beginnend
  | 
98  | 
  | 
99  |    //PIE1bits.ADIE = 1;            //ADC-Interrupt enabled
  | 
100  |    IPR1bits.ADIP = 0;            //ADC-Interrupt Low-Priority
  | 
101  |    PIR1bits.ADIF = 0;            //Interruptflag zurücksetzen
  | 
102  |    ADCON0bits.GO_DONE = 1;       //A/D-Wandler starten
  | 
103  | }
  | 
104  | void low_priority interrupt Low_Priority_ISR(){
 | 
105  |     if(PIR1bits.ADIF == 1 && ADCON0bits.GO_DONE == 0){
 | 
106  |         ad_msb = ADRESH;
  | 
107  |         ad_lsb = ADRESL;
  | 
108  |         PIR1bits.ADIF = 0;
  | 
109  |         ADCON0bits.GO_DONE = 1;
  | 
110  |     }
  | 
111  |     return;
  | 
112  | }
  |