Forum: Mikrocontroller und Digitale Elektronik MPLABX - Timer-Verfahren (nach Peter Dannegger) AVR


von Karl W. (acm2014)


Lesenswert?

möchte gerne die Routine von Peter Dannegger testen.

kann mir jemand dabei helfen? bin neu in der PIC Programmierung.

habe einen pic12f1572, mplabx, einen taster mit led.

nutze den INTOSC mit 4MHZ, und die ISR mit 1ms Timer. (war Vorgabe)

kann man das so übersetzen wie ich es mache?

Hier das Programm:
1
#include <xc.h>
2
#include <stdbool.h>
3
4
//*** PIC12F1572 Configuration Bit Settings
5
// CONFIG1
6
#pragma config FOSC = INTOSC    
7
#pragma config WDTE = OFF      
8
#pragma config PWRTE = ON       
9
#pragma config MCLRE = ON     
10
#pragma config CP = OFF         
11
#pragma config BOREN = OFF      
12
#pragma config CLKOUTEN = OFF   
13
14
//*CONFIG2
15
#pragma config WRT = OFF        
16
#pragma config PLLEN = ON      
17
#pragma config STVREN = ON      
18
#pragma config BORV = LO       
19
#pragma config LPBOREN = OFF    
20
#pragma config LVP = ON         
21
22
//#include <avr/stdint.h>
23
//#include <avr/avr/io.h>
24
//#include <avr/avr/interrupt.h>
25
26
27
//#define KEY_DDR         TRISA   // DDRB
28
//#define KEY_PORT        LATA    // PORTB
29
#define KEY_PIN         PORTA   // PINB
30
#define KEY0            0
31
#define KEY1            PORTAbits.RA4   // BUTTON
32
#define KEY2            2
33
#define ALL_KEYS        (1<<KEY0 | 1<<KEY1 | 1<<KEY2)
34
35
#define REPEAT_MASK     (1<<KEY1 | 1<<KEY2)       // repeat: key1, key2
36
#define REPEAT_START    500                       // after 500ms
37
#define REPEAT_NEXT     200                       // every 200ms
38
39
#define LED_DDR         TRISA  // DDRA
40
#define LED_PORT        LATA   // PORTA
41
#define LED0            0
42
#define LED1            LATAbits.LATA2    // LED
43
#define LED2            2
44
45
#define word unsigned int
46
47
// global variables
48
volatile word key_state;             // debounced and inverted key state:
49
                                     // bit = 1: key pressed
50
volatile word key_press;             // key press detect
51
volatile word key_rpt;               // key long press and repeat
52
static word ct0,ct1,rpt;
53
word i;
54
static word w1ms = 248;              // overflow factor
55
56
57
void interrupt isr(void)
58
{
59
    TMR0 = 256 - w1ms;        // increment interrupt count (every 1000 us)
60
61
    i = key_state ^ ~KEY_PIN;            // key changed ?
62
    ct0 = ~( ct0 & i );                  // reset or count ct0
63
    ct1 = ct0 ^ (ct1 & i);               // reset or count ct1
64
    i &= ct0 & ct1;                      // count until roll over ?
65
    key_state ^= i;                      // then toggle debounced state
66
    key_press |= key_state & i;          // 0->1: key press detect
67
68
    if( (key_state & REPEAT_MASK) == 0 ) // check repeat function
69
       rpt = REPEAT_START;               // start delay
70
    if( --rpt == 0 ){
71
      rpt = REPEAT_NEXT;                 // repeat delay
72
      key_rpt |= key_state & REPEAT_MASK;  
73
    }
74
75
    INTCONbits.TMR0IF = 0;               // clear interrupt flag
76
}
77
78
///////////////////////////////////////////////////////////////////
79
//
80
// check if a key has been pressed. Each pressed key is reported
81
// only once
82
//
83
word get_key_press( word key_mask )
84
{
85
  di();                        // disable global interrupts
86
  key_mask &= key_press;                          // read key(s)
87
  key_press ^= key_mask;                          // clear key(s)
88
  ei();                        // enable global interrupts
89
  return key_mask;
90
}
91
92
///////////////////////////////////////////////////////////////////
93
//
94
// check if a key has been pressed long enough such that the
95
// key repeat functionality kicks in. After a small setup delay
96
// the key is reported being pressed in subsequent calls
97
// to this function. This simulates the user repeatedly
98
// pressing and releasing the key.
99
//
100
word get_key_rpt( word key_mask )
101
{
102
  di();                        // disable global interrupts
103
  key_mask &= key_rpt;                            // read key(s)
104
  key_rpt ^= key_mask;                            // clear key(s)
105
  ei();                        // enable global interrupts
106
  return key_mask;
107
}
108
109
///////////////////////////////////////////////////////////////////
110
//
111
// check if a key is pressed right now
112
//
113
word get_key_state( word key_mask )
114
115
{
116
  key_mask &= key_state;
117
  return key_mask;
118
}
119
120
///////////////////////////////////////////////////////////////////
121
//
122
word get_key_short( word key_mask )
123
{
124
  di();                        // disable global interrupts
125
  return get_key_press( ~key_state & key_mask );
126
}
127
128
///////////////////////////////////////////////////////////////////
129
//
130
word get_key_long( word key_mask )
131
{
132
  return get_key_press( get_key_rpt( key_mask ));
133
}
134
135
int main(void)
136
{
137
    //*** Initialisation
138
    // configure port
139
    ANSELA = 0x00;             // set PortA digital
140
    LED_PORT = 0b00000100;     // Set RA2 high  -> LED off
141
    LED_DDR = 0b00011011;   // set RA2 as output and RA4, RA5 as input
142
143
    // Configure debouncing routines
144
    //KEY_DDR &= ~ALL_KEYS;   // configure key port for input
145
    //KEY_PORT |= ALL_KEYS;   // and turn on pull up resistors
146
147
    /*
148
    TCCR0 = (1<<CS02)|(1<<CS00);         // divide by 1024
149
    TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5); 
150
    TIMSK |= 1<<TOIE0;                   // enable timer Interrupt
151
    sei();
152
    */
153
154
    // configure oscillator
155
    OSCCONbits.SCS1= 1;          // select Internal oscillator block
156
    OSCCONbits.IRCF = 0b1101;    // Set Internal Oscillator to 4MHz HF
157
                                 // -> 1 us / instruction cycle
158
159
    // configure Timer0
160
    OPTION_REGbits.TMR0CS = 0;   // select timer mode
161
    OPTION_REGbits.PSA = 0;      // assign prescaler to Timer0
162
    OPTION_REGbits.PS  = 0b001;  // prescaling = 4, 255 * 1us * 4
163
                                 // -> increment TMR0 every 1024 uss
164
165
    // enable interrupts
166
    INTCONbits.TMR0IE = 1;       // enable Timer0 interrupt
167
    ei();                        // enable global interrupts
168
169
      while(1){
170
        if( get_key_short( 1<<KEY1 ))
171
          LED_PORT ^= 1<<LED1;
172
173
        if( get_key_long( 1<<KEY1 ))
174
          LED_PORT ^= 1<<LED2;
175
176
        // single press and repeat
177
178
        if( get_key_press( 1<<KEY2 ) || get_key_rpt( 1<<KEY2 )){
179
          word i = LED_PORT;
180
181
          i = (i & 0x07) | ((i << 1) & 0xF0);
182
          if( i < 0xF0 )
183
            i |= 0x08;
184
          LED_PORT = i;
185
        }
186
      }
187
    return 0;
188
}

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.