Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage - Stoppuhr mittels CCP Module


von David M (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei, eine Stoppuhr mittels des CCP Modules zu 
realisieren. Die Ausgabe der laufenden Zeit am LCD funktioniert schon. 
Jetzt würde ich das Programm aber gerne so anpassen, dass beim Drücken 
einen Tasters die Messung gestartet wird und beim Drücken eines 2 
Tasters gestoppt wird. Ich habe im Datenblatt was gelesen con CPP1_High 
aber ich habe leider keine Idee wie ich das genau implementieren soll. 
Kann mir vl bitte Jemand helfen?

PIC: 18F27J53

Hier mein derzeitiges Programm:
1
//
2
//
3
// myPIC/Bootloader-Demo  Test-Ausgabe
4
// ---------------------
5
//
6
//     Compiler:  CCS 4.3.0.357
7
//     Hardware:  myPIC mit HTL-BootLoader
8
//                Prozessor:  PIC 18F27J53  48MHz (20MHZ-Quarz mit PLL)
9
//   
10
//     Funktion:  Test-Ausgabe am LCD-Display
11
//     
12
// uC-Einstellungen --------------------------------------------------------
13
#include <18F27J53.h>
14
#device ADC=12                                // nicht verändern
15
#fuses  HSPLL,PLLEN,PLL5, NOCPUDIV, NOWDT,NOPROTECT              // nicht verändern
16
#fuses  ADC12, RTCOSC_INT, DSWDTOSC_T1                    // nicht verändern
17
#use    delay(clock=48000000)                        // nicht verändern
18
19
// Für Bootloader ------------------------------------------------
20
#build (reset=0x1000, interrupt=0x1008)  // neue Adressen          // nicht verändern
21
#org 0x0,0xfff {}            // res. Bereich            // nicht verändern
22
// ---------------------------------------------------------------
23
24
//
25
//LCD Lib
26
#include "D:\Dropbox\Abend-HTL\6ABELI\FTKLÜ\Mini-Projekt\Programm\LCD.c"
27
//
28
int hs;    // hunderstel Sekunden
29
int zs;    // zehntel Sekunden
30
int s;     // Sekunden
31
int m;     //Minuten
32
33
#Int_CCP5 // ISR für Timer1 (alle 10ms)
34
void time()
35
{
36
   hs += 1;
37
   if(hs == 10)
38
   {
39
      hs = 0;
40
      zs += 1;
41
      if(zs == 10)
42
      {
43
         zs = 0;
44
         s += 1;
45
         if(s == 60)
46
         {
47
            s = 0;
48
            m += 1;
49
         }
50
      }
51
   }
52
}
53
// Hauptprogramm
54
void main() 
55
{
56
   hs = 0;    // hunderstel Sekunden
57
   zs = 0;    // zehntel Sekunden
58
   s = 0;     // Sekunden
59
   m = 0;     //Minuten
60
61
   Setup_Timer_1(T1_Internal | T1_DIV_BY_8); // Interner Takt, 1:8
62
   Setup_CCP5(CCP_COMPARE_RESET_TIMER);
63
64
   enable_interrupts(GLOBAL);    // Globaler Interrupt wird aktiviert
65
   enable_interrupts(Int_CCP5);  // CCP1 Interrupt wird aktiviert
66
  
67
   
68
   CCP_5=15015; // alle 9999 Zyklen
69
70
   // Splash Screen
71
   lcd_init();
72
   lcd_gotoxy(1,1);
73
   lcd_putc("ARZ-GPS\n"); 
74
   lcd_putc("V 0.1");
75
   delay_ms(500);
76
   printf(lcd_putc,"\f1.Runde:");
77
   
78
     while(1)
79
   {
80
      if(m > 0)
81
      {
82
         lcd_gotoxy(9,1);
83
         printf(lcd_putc,"%02u:%02u:%u",m,s,zs);
84
      }
85
      else
86
      {
87
         lcd_gotoxy(9,1);
88
         printf(lcd_putc,"%02u:%u",s,zs);
89
      }
90
      delay_ms(100);
91
   }
92
}

Und hier das Header-File des PIC's:
1
//////// Standard Header file for the PIC18F27J53 device ////////////////
2
#device PIC18F27J53
3
#nolist
4
//////// Program memory: 65532x16  Data RAM: 3760  Stack: 31
5
//////// I/O: 22   Analog Pins: 10
6
//////// C Scratch area: 00   ID Location: 0000
7
//////// Fuses: NOWDT,WDT,PLL12,PLL10,PLL6,PLL5,PLL4,PLL3,PLL2,PLL1,PLLEN
8
//////// Fuses: NOPLLEN,NOSTVREN,STVREN,NOXINST,XINST,DEBUG,NODEBUG,CPUDIV6
9
//////// Fuses: CPUDIV3,CPUDIV2,NOCPUDIV,PROTECT,NOPROTECT,INTRC_IO,INTRC
10
//////// Fuses: INTRC_PLL_IO,INTRC_PLL,HS,HSPLL,EC,ECPLL,SOSC_LOW,SOSC_DIG
11
//////// Fuses: SOSC_HIGH,NOCLOCKOUT,CLOCKOUT,NOFCMEN,FCMEN,NOIESO,IESO,WDT1
12
//////// Fuses: WDT2,WDT4,WDT8,WDT16,WDT32,WDT64,WDT128,WDT256,WDT512
13
//////// Fuses: WDT1024,WDT2048,WDT4096,WDT8192,WDT16384,WDT32768
14
//////// Fuses: DSWDTOSC_T1,DSWDTOSC_INT,RTCOSC_INT,RTCOSC_T1,NODSBOR,DSBOR
15
//////// Fuses: NODSWDT,DSWDT,DSWDT2,DSWDT8,DSWDT32,DSWDT128,DSWDT512
16
//////// Fuses: DSWDT2048,DSWDT8192,DSWDT32768,DSWDT131072,DSWDT524288
17
//////// Fuses: DSWDT2097152,DSWDT8388608,DSWDT33554432,DSWDT134217728
18
//////// Fuses: DSWDT536870912,DSWDT2147483648,NOIOL1WAY,IOL1WAY,ADC12,ADC10
19
//////// Fuses: MSSPMSK5,MSSPMSK7,NOWPFP,WPFP,WPCFG,NOWPCFG,NOWPDIS,WPDIS
20
//////// Fuses: WPBEG,WPEND,LS24MHZ,LS48MHZ
21
//////// 
22
////////////////////////////////////////////////////////////////// I/O
23
// Discrete I/O Functions: SET_TRIS_x(), OUTPUT_x(), INPUT_x(),
24
//                         PORT_x_PULLUPS(), INPUT(),
25
//                         OUTPUT_LOW(), OUTPUT_HIGH(),
26
//                         OUTPUT_FLOAT(), OUTPUT_BIT()
27
// Constants used to identify pins in the above are:
28
29
#define PIN_A0  31744
30
#define PIN_A1  31745
31
#define PIN_A2  31746
32
#define PIN_A3  31747
33
#define PIN_A5  31749
34
#define PIN_A6  31750
35
#define PIN_A7  31751
36
37
#define PIN_B0  31752
38
#define PIN_B1  31753
39
#define PIN_B2  31754
40
#define PIN_B3  31755
41
#define PIN_B4  31756
42
#define PIN_B5  31757
43
#define PIN_B6  31758
44
#define PIN_B7  31759
45
46
#define PIN_C0  31760
47
#define PIN_C1  31761
48
#define PIN_C2  31762
49
#define PIN_C4  31764
50
#define PIN_C5  31765
51
#define PIN_C6  31766
52
#define PIN_C7  31767
53
54
////////////////////////////////////////////////////////////////// Useful defines
55
#define FALSE 0
56
#define TRUE 1
57
58
#define BYTE int8
59
#define BOOLEAN int1
60
61
#define getc getch
62
#define fgetc getch
63
#define getchar getch
64
#define putc putchar
65
#define fputc putchar
66
#define fgets gets
67
#define fputs puts
68
69
////////////////////////////////////////////////////////////////// Control
70
// Control Functions:  RESET_CPU(), SLEEP(), RESTART_CAUSE()
71
// Constants returned from RESTART_CAUSE() are:
72
#define WDT_TIMEOUT       7    
73
#define MCLR_FROM_SLEEP  11    
74
#define MCLR_FROM_RUN    15    
75
#define NORMAL_POWER_UP  12    
76
#define BROWNOUT_RESTART 14    
77
#define WDT_FROM_SLEEP    3    
78
#define RESET_INSTRUCTION 0    
79
80
#define POR_FROM_DS      0x0100
81
#define MCLR_FROM_DS     0x0400
82
#define RTC_FROM_DS      0x0800
83
#define DSWDT_FROM_DS    0x1000
84
#define ULPWU_FROM_DS    0x2000
85
#define FAULT_FROM_DS    0x8000
86
#define EXT_FROM_DS      0x0200
87
88
//Constants for calls to sleep() to enable deep sleep mode are:
89
#define DEEP_SLEEP       3
90
// Any of the following may be OR'ed in with the above using |
91
#define WAKE_FROM_RTCC   4  // Wake-up from RTCC is enabled
92
#define WAKE_FROM_ULP    8  // ULPWU module is enabled in Deep Sleep
93
94
#byte DSGPR0 = getenv("SFR:DSGPR0")
95
#byte DSGPR1 = getenv("SFR:DSGPR1")
96
97
// Constants for calls to sleep() are:
98
#define REG_LOW_POWER    2
99
#define REG_NORMAL       0  // default
100
101
// Constants for calls to sleep() are:
102
#define SLEEP_FULL       0  // Default
103
#define SLEEP_IDLE       1  // Clock and peripherals don't stop
104
105
////////////////////////////////////////////////////////////////// Timer 0
106
// Timer 0 (AKA RTCC)Functions: SETUP_COUNTERS() or SETUP_TIMER_0(),
107
//                              SET_TIMER0() or SET_RTCC(),
108
//                              GET_TIMER0() or GET_RTCC()
109
// Constants used for SETUP_TIMER_0() are:
110
#define T0_INTERNAL   0
111
#define T0_EXT_L_TO_H 32
112
#define T0_EXT_H_TO_L 48
113
114
#define T0_DIV_1      8
115
#define T0_DIV_2      0
116
#define T0_DIV_4      1
117
#define T0_DIV_8      2
118
#define T0_DIV_16     3
119
#define T0_DIV_32     4
120
#define T0_DIV_64     5
121
#define T0_DIV_128    6
122
#define T0_DIV_256    7
123
124
#define T0_OFF        0x80  
125
126
#define T0_8_BIT      0x40  
127
128
#define RTCC_INTERNAL   0      // The following are provided for compatibility
129
#define RTCC_EXT_L_TO_H 32     // with older compiler versions
130
#define RTCC_EXT_H_TO_L 48
131
#define RTCC_DIV_1      8
132
#define RTCC_DIV_2      0
133
#define RTCC_DIV_4      1
134
#define RTCC_DIV_8      2
135
#define RTCC_DIV_16     3
136
#define RTCC_DIV_32     4
137
#define RTCC_DIV_64     5
138
#define RTCC_DIV_128    6
139
#define RTCC_DIV_256    7
140
#define RTCC_OFF        0x80  
141
#define RTCC_8_BIT      0x40  
142
143
// Constants used for SETUP_COUNTERS() are the above
144
// constants for the 1st param and the following for
145
// the 2nd param:
146
147
////////////////////////////////////////////////////////////////// WDT
148
// Watch Dog Timer Functions: SETUP_WDT() or SETUP_COUNTERS() (see above)
149
//                            RESTART_WDT()
150
// WDT base is 4ms
151
//
152
#define WDT_ON        0x100
153
#define WDT_OFF       0
154
155
////////////////////////////////////////////////////////////////// Timer 1
156
// Timer 1 Functions: SETUP_TIMER_1, GET_TIMER1, SET_TIMER1
157
// Constants used for SETUP_TIMER_1() are:
158
//      (or (via |) together constants from each group)
159
#define T1_DISABLED         0
160
#define T1_INTERNAL         0x07
161
#define T1_EXTERNAL         0x87
162
#define T1_EXTERNAL_SYNC    0x83
163
#define T1_FOSC             0x47
164
165
#define T1_ENABLE_SOSC    0x08
166
167
#define T1_DIV_BY_1         0
168
#define T1_DIV_BY_2         0x10
169
#define T1_DIV_BY_4         0x20
170
#define T1_DIV_BY_8         0x30
171
172
#define T1_GATE           0x8000
173
#define T1_GATE_INVERTED  0xC000
174
#define T1_GATE_TOGGLE    0xA000
175
#define T1_GATE_SINGLE    0x9000
176
#define T1_GATE_TIMER2    0x8100
177
#define T1_GATE_COMP1     0x8200
178
#define T1_GATE_COMP2     0x8300
179
180
////////////////////////////////////////////////////////////////// Timer 2
181
// Timer 2 Functions: SETUP_TIMER_2, GET_TIMER2, SET_TIMER2
182
// Constants used for SETUP_TIMER_2() are:
183
#define T2_DISABLED         0
184
#define T2_DIV_BY_1         4
185
#define T2_DIV_BY_4         5
186
#define T2_DIV_BY_16        6
187
188
////////////////////////////////////////////////////////////////// Timer 3
189
// Timer 3 Functions: SETUP_TIMER_3, GET_TIMER3, SET_TIMER3
190
// Constants used for SETUP_TIMER_3() are:
191
//      (or (via |) together constants from each group)
192
#define T3_DISABLED         0
193
#define T3_INTERNAL         0x07
194
#define T3_EXTERNAL         0x87
195
#define T3_EXTERNAL_SYNC    0x83
196
#define T3_FOSC             0x47
197
198
#define T3_ENABLE_SOSC    0x08
199
200
#define T3_DIV_BY_1         0
201
#define T3_DIV_BY_2         0x10
202
#define T3_DIV_BY_4         0x20
203
#define T3_DIV_BY_8         0x30
204
205
#define T3_GATE           0x8000
206
#define T3_GATE_INVERTED  0xC000
207
#define T3_GATE_TOGGLE    0xA000
208
#define T3_GATE_SINGLE    0x9000
209
#define T3_GATE_TIMER4    0x8100
210
#define T3_GATE_COMP1     0x8200
211
#define T3_GATE_COMP2     0x8300
212
213
////////////////////////////////////////////////////////////////// Timer 4
214
// Timer 4 Functions: SETUP_TIMER_4, GET_TIMER4, SET_TIMER4
215
// Constants used for SETUP_TIMER_4() are:
216
#define T4_DISABLED         0
217
#define T4_DIV_BY_1         4
218
#define T4_DIV_BY_4         5
219
#define T4_DIV_BY_16        6
220
221
////////////////////////////////////////////////////////////////// Timer 5
222
// Timer 5 Functions: SETUP_TIMER_5, GET_TIMER5, SET_TIMER5
223
// Constants used for SETUP_TIMER_5() are:
224
//      (or (via |) together constants from each group)
225
#define T5_DISABLED         0
226
#define T5_INTERNAL         0x07
227
#define T5_EXTERNAL         0x87
228
#define T5_EXTERNAL_SYNC    0x83
229
#define T5_FOSC             0x47
230
231
#define T5_ENABLE_SOSC    0x08
232
233
#define T5_DIV_BY_1         0
234
#define T5_DIV_BY_2         0x10
235
#define T5_DIV_BY_4         0x20
236
#define T5_DIV_BY_8         0x30
237
238
#define T5_GATE           0x8000
239
#define T5_GATE_INVERTED  0xC000
240
#define T5_GATE_TOGGLE    0xA000
241
#define T5_GATE_SINGLE    0x9000
242
#define T5_GATE_TIMER6    0x8100
243
#define T5_GATE_COMP1     0x8200
244
#define T5_GATE_COMP2     0x8300
245
246
////////////////////////////////////////////////////////////////// Timer 6
247
// Timer 6 Functions: SETUP_TIMER_6, GET_TIMER5, SET_TIMER5
248
// Constants used for SETUP_TIMER_6() are:
249
//      (or (via |) together constants from each group)
250
#define T6_DISABLED         0
251
#define T6_DIV_BY_1         4
252
#define T6_DIV_BY_4         5
253
#define T6_DIV_BY_16        6
254
255
////////////////////////////////////////////////////////////////// Timer 8
256
// Timer 8 Functions: SETUP_TIMER_8, GET_TIMER8, SET_TIMER8
257
// Constants used for SETUP_TIMER_8() are:
258
//      (or (via |) together constants from each group)
259
#define T8_DISABLED         0
260
#define T8_DIV_BY_1         4
261
#define T8_DIV_BY_4         5
262
#define T8_DIV_BY_16        6
263
264
////////////////////////////////////////////////////////////////// RTC
265
// RTC Functions: setup_rtc(), setup_rtc_alarm(), rtc_read(),
266
//                rtc_write(), rtc_alarm_read(), rtc_alarm_write()
267
// Structure used in read and write functions (pass pointer):
268
typedef struct {
269
   int8 tm_year;
270
   int8 tm_yday;  // Not used by built in functions
271
   int8 tm_mday;
272
   int8 tm_mon;
273
   int8 tm_hour;
274
   int8 tm_wday;
275
   int8 tm_sec;
276
   int8 tm_min;
277
   int8 tm_isdst; // Not used by built in functions
278
} rtc_time_t;
279
//
280
// Constants used in setup_rtc() are:  // Second param is calibration
281
#define RTC_ENABLE           0x8000
282
#define RTC_DISABLE          0
283
#define RTC_OUTPUT_SOURCE    0x20400
284
#define RTC_OUTPUT_SECONDS   0x10400
285
#define RTC_OUTPUT_ALARM     0x00400
286
//
287
// Constants used in setup_rtc_alarm() first param are:
288
#define RTC_ALARM_ENABLE     0x80
289
#define RTC_ALARM_DISABLE    0
290
#define RTC_CHIME_ENABLE     0x40
291
#define RTC_CHIME_DISABLE    0
292
// Constants used in setup_rtc_alarm() second param are:  // Third param is repeat#
293
#define RTC_ALARM_HALFSECOND 0x00
294
#define RTC_ALARM_SECOND     0x04
295
#define RTC_ALARM_10_SECONDS 0x08
296
#define RTC_ALARM_MINUTE     0x0C
297
#define RTC_ALARM_10_MINUTES 0x10
298
#define RTC_ALARM_HOUR       0x14
299
#define RTC_ALARM_DAY        0x18
300
#define RTC_ALARM_WEEK       0x1C
301
#define RTC_ALARM_MONTH      0x20
302
#define RTC_ALARM_YEAR       0x24
303
304
////////////////////////////////////////////////////////////////// CCP
305
// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
306
// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
307
// Constants used for SETUP_CCPx() are:
308
#define CCP_OFF                         0
309
#define CCP_CAPTURE_FE                  4
310
#define CCP_CAPTURE_RE                  5
311
#define CCP_CAPTURE_DIV_4               6
312
#define CCP_CAPTURE_DIV_16              7
313
#define CCP_COMPARE_SET_ON_MATCH        8
314
#define CCP_COMPARE_CLR_ON_MATCH        9
315
#define CCP_COMPARE_INT                 0xA
316
#define CCP_COMPARE_INT_AND_TOGGLE      0x2       
317
#define CCP_COMPARE_RESET_TIMER         0xB
318
#define CCP_PWM                         0xC
319
#define CCP_PWM_PLUS_1                  0x1c  
320
#define CCP_PWM_PLUS_2                  0x2c
321
#define CCP_PWM_PLUS_3                  0x3c
322
//#define CCP_USE_TIMER3                0x100  OBSOLETE, SEE TIMER-3     
323
#word   CCP_1       =                   getenv("SFR:CCPR1L")
324
#byte   CCP_1_LOW   =                   getenv("SFR:CCPR1L")
325
#byte   CCP_1_HIGH  =                   getenv("SFR:CCPR1H")
326
// The following are used to select the Timer source for the CCP/ECCP
327
// The first timer is the timer used when in CAPTURE or COMPARE mode
328
// The second timer is the timer used when in PWM mode
329
#define CCP_USE_TIMER1_AND_TIMER2       0x0000 //used for CCP 1 2 3 4 5 6 7 8 9 10 
330
#define CCP_USE_TIMER3_AND_TIMER4       0x0100 //used for CCP 1 2 3 4
331
#define CCP_USE_TIMER3_AND_TIMER6       0x0200 //used for CCP 1 2 3 4
332
#define CCP_USE_TIMER3_AND_TIMER8       0x0300 //used for CCP 1 2 3
333
#define CCP_USE_TIMER5_AND_TIMER4       0x0100 //used for CCP 5 7
334
#define CCP_USE_TIMER5_AND_TIMER2       0x0100 //used for CCP 6
335
#define CCP_USE_TIMER5_AND_TIMER6       0x0200 //used for CCP 7
336
#define CCP_USE_TIMER5_AND_TIMER8       0x0300 //used for CCP 7
337
#define CCP_USE_TIMER1_AND_TIMER6       0x0200 //used for CCP 8 
338
#define CCP_USE_TIMER1_AND_TIMER4       0x0100 //used for CCP 8 9 
339
340
// The following should be used with the ECCP unit only (or these in)
341
#define CCP_PWM_H_H                     0x0c
342
#define CCP_PWM_H_L                     0x0d
343
#define CCP_PWM_L_H                     0x0e
344
#define CCP_PWM_L_L                     0x0f
345
346
#define CCP_PWM_FULL_BRIDGE             0x40
347
#define CCP_PWM_FULL_BRIDGE_REV         0xC0
348
#define CCP_PWM_HALF_BRIDGE             0x80
349
350
#define CCP_SHUTDOWN_ON_COMP1           0x100000
351
#define CCP_SHUTDOWN_ON_COMP2           0x200000
352
#define CCP_SHUTDOWN_ON_COMP            0x300000
353
#define CCP_SHUTDOWN_ON_INT0            0x400000
354
#define CCP_SHUTDOWN_ON_COMP1_INT0      0x500000
355
#define CCP_SHUTDOWN_ON_COMP2_INT0      0x600000
356
#define CCP_SHUTDOWN_ON_COMP_INT0       0x700000
357
358
#define CCP_SHUTDOWN_AC_L               0x000000
359
#define CCP_SHUTDOWN_AC_H               0x040000
360
#define CCP_SHUTDOWN_AC_F               0x080000
361
362
#define CCP_SHUTDOWN_BD_L               0x000000
363
#define CCP_SHUTDOWN_BD_H               0x010000
364
#define CCP_SHUTDOWN_BD_F               0x020000
365
366
#define CCP_SHUTDOWN_RESTART            0x80000000  
367
368
#define CCP_PULSE_STEERING_A            0x01000000
369
#define CCP_PULSE_STEERING_B            0x02000000
370
#define CCP_PULSE_STEERING_C            0x04000000
371
#define CCP_PULSE_STEERING_D            0x08000000
372
#define CCP_PULSE_STEERING_SYNC         0x10000000
373
#define CCP_COMPLEMENTARY_AB            0x43000000  
374
375
#word   CCP_2       =                   getenv("SFR:CCPR2L")
376
#byte   CCP_2_LOW   =                   getenv("SFR:CCPR2L")
377
#byte   CCP_2_HIGH  =                   getenv("SFR:CCPR2H")
378
#word   CCP_3       =                   getenv("SFR:CCPR3L")
379
#byte   CCP_3_LOW   =                   getenv("SFR:CCPR3L")
380
#byte   CCP_3_HIGH  =                   getenv("SFR:CCPR3H")
381
#word   CCP_4       =                   getenv("SFR:CCPR4L")
382
#byte   CCP_4_LOW   =                   getenv("SFR:CCPR4L")
383
#byte   CCP_4_HIGH  =                   getenv("SFR:CCPR4H")
384
#word   CCP_5       =                   getenv("SFR:CCPR5L")
385
#byte   CCP_5_LOW   =                   getenv("SFR:CCPR5L")
386
#byte   CCP_5_HIGH  =                   getenv("SFR:CCPR5H")
387
#word   CCP_6       =                   getenv("SFR:CCPR6L")
388
#byte   CCP_6_LOW   =                   getenv("SFR:CCPR6L")
389
#byte   CCP_6_HIGH  =                   getenv("SFR:CCPR6H")
390
#word   CCP_7       =                   getenv("SFR:CCPR7L")
391
#byte   CCP_7_LOW   =                   getenv("SFR:CCPR7L")
392
#byte   CCP_7_HIGH  =                   getenv("SFR:CCPR7H")
393
#word   CCP_8       =                   getenv("SFR:CCPR8L")
394
#byte   CCP_8_LOW   =                   getenv("SFR:CCPR8L")
395
#byte   CCP_8_HIGH  =                   getenv("SFR:CCPR8H")
396
#word   CCP_9       =                   getenv("SFR:CCPR9L")
397
#byte   CCP_9_LOW   =                   getenv("SFR:CCPR9L")
398
#byte   CCP_9_HIGH  =                   getenv("SFR:CCPR9H")
399
#word   CCP_10      =                   getenv("SFR:CCPR10L")
400
#byte   CCP_10_LOW  =                   getenv("SFR:CCPR10L")
401
#byte   CCP_10_HIGH =                   getenv("SFR:CCPR10H")
402
403
////////////////////////////////////////////////////////////////// SPI
404
// SPI Functions: SETUP_SPI, SPI_WRITE, SPI_READ, SPI_DATA_IN
405
// Constants used in SETUP_SPI() are:
406
#define SPI_DISABLED             0x00
407
#define SPI_MASTER               0x20
408
#define SPI_SLAVE                0x24
409
#define SPI_SCK_IDLE_HIGH        0x10
410
#define SPI_SCK_IDLE_LOW         0x00
411
#define SPI_CLK_DIV_4            0x00
412
#define SPI_CLK_DIV_16           0x01
413
#define SPI_CLK_DIV_64           0x02
414
#define SPI_CLK_T2               0x03
415
#define SPI_SS_DISABLED          0x01
416
417
#define SPI_XMIT_L_TO_H          0x4000
418
#define SPI_XMIT_H_TO_L          0x0000
419
420
#define SPI_SAMPLE_AT_MIDDLE     0x0000
421
#define SPI_SAMPLE_AT_END        0x8000
422
423
//The following are provided for compatibility
424
#define SPI_L_TO_H       SPI_SCK_IDLE_LOW
425
#define SPI_H_TO_L       SPI_SCK_IDLE_HIGH
426
427
////////////////////////////////////////////////////////////////// UART
428
// Constants used in setup_uart() are:
429
// FALSE - Turn UART off
430
// TRUE  - Turn UART on
431
#define UART_ADDRESS           2
432
#define UART_DATA              4
433
#define UART_AUTODETECT        8
434
#define UART_AUTODETECT_NOWAIT 9
435
#define UART_WAKEUP_ON_RDA     10
436
#define UART_SEND_BREAK        13
437
////////////////////////////////////////////////////////////////// COMP
438
// Comparator Variables: C1OUT, C2OUT, C3OUT
439
// Constants used in setup_comparator() are:
440
//
441
#define NC_NC_NC_NC   0x040404
442
#define NC_NC         0x040404
443
444
//Pick one constant for COMP1
445
#define CP1_A3_A0    0x000080
446
#define CP1_A5_A0    0x000081
447
#define CP1_A2_A0    0x000082
448
#define CP1_FVR_A0    0x000083
449
#define CP1_A3_VREF    0x000084
450
#define CP1_A5_VREF    0x000085
451
#define CP1_A2_VREF    0x000086
452
#define CP1_FVR_VREF  0x000087
453
//Optionally OR with any of the following
454
#define CP1_OUT_ON_RP  0x000040
455
#define CP1_INVERT    0x000020
456
#define CP1_INT_L2H    0x000008
457
#define CP1_INT_H2L    0x000010
458
459
//Pick one constant for COMP2
460
#define CP2_A2_A1    0x008000
461
#define CP2_B2_A1    0x008100
462
#define CP2_C2_A1    0x008200
463
#define CP2_FVR_A1    0x008300
464
#define CP2_A2_VREF    0x008400
465
#define CP2_B2_VREF    0x008500
466
#define CP2_C2_VREF    0x008600
467
#define CP2_FVR_VREF  0x008700
468
//Optionally OR with any of the following
469
#define CP2_OUT_ON_RP  0x004000
470
#define CP2_INVERT    0x002000
471
#define CP2_INT_L2H    0x000800
472
#define CP2_INT_H2L    0x001000
473
474
//Pick one constant for COMP3
475
#define CP3_A2_B3    0x800000
476
#define CP3_B1_B3    0x810000
477
#define CP3_B0_B3    0x820000
478
#define CP3_FVR_B3    0x830000
479
#define CP3_A2_VREF    0x840000
480
#define CP3_B1_VREF    0x850000
481
#define CP3_B0_VREF    0x860000
482
#define CP3_FVR_VREF  0x870000
483
//Optionally OR with any of the following
484
#define CP3_OUT_ON_RP  0x400000
485
#define CP3_INVERT    0x200000
486
#define CP3_INT_L2H    0x080000
487
#define CP3_INT_H2L    0x100000
488
489
#bit C1OUT = 0xF70.0
490
#bit C2OUT = 0xF70.1
491
#bit C3OUT = 0xF70.2
492
493
////////////////////////////////////////////////////////////////// VREF
494
// Constants used in setup_vref() are:
495
//
496
#define VREF_OFF     0
497
#define VREF_LOW     0xA0
498
#define VREF_HIGH    0x80
499
#define VREF_EXT     0x10  // Range for ref gen VREF- to VREF+
500
#define VREF_OUT_A2  0x40
501
// Or (with |) the above with a number 0-15
502
503
////////////////////////////////////////////////////////////////// VREF
504
// Constants used in setup_low_volt_detect() are:
505
//
506
#define LVD_LVDIN   0x1F
507
#define LVD_34      0x1E
508
#define LVD_31      0x1D
509
#define LVD_30      0x1C
510
#define LVD_29      0x1B
511
#define LVD_28      0x1A
512
#define LVD_26      0x19
513
#define LVD_24      0x18
514
515
#define LVD_TRIGGER_BELOW 0
516
#define LVD_TRIGGER_ABOVE 0x80
517
518
519
////////////////////////////////////////////////////////////////// INTERNAL RC
520
// Constants used in setup_oscillator() are:
521
#define OSC_31250   0x8000
522
#define OSC_PLL_ON  0x4000
523
#define OSC_PLL_OFF 0
524
#define OSC_31KHZ   0
525
#define OSC_125KHZ  0x10
526
#define OSC_250KHZ  0x20
527
#define OSC_500KHZ  0x30
528
#define OSC_1MHZ    0x40
529
#define OSC_2MHZ    0x50
530
#define OSC_4MHZ    0x60
531
#define OSC_8MHZ    0x70
532
// The following may be OR'ed in with the above using |
533
#define OSC_TIMER1  1
534
#define OSC_INTRC   3
535
#define OSC_NORMAL  0
536
// The following may be OR'ed in with the above using |
537
#define OSC_IDLE_MODE  0x80
538
// A second optional parameter may be used with this part to fine
539
// tune the speed (signed int,0-31)
540
// Result may be (ignore all other bits)
541
#define OSC_STATE_STABLE 4
542
#define OSC_STATE_EXT_RUNNING 8
543
544
545
////////////////////////////////////////////////////////////////// ADC
546
// ADC Functions: SETUP_ADC(), SETUP_ADC_PORTS() (aka SETUP_PORT_A),
547
//                SET_ADC_CHANNEL(), READ_ADC()
548
// Constants used for SETUP_ADC() are:
549
#define ADC_OFF               0           // ADC Off
550
#define ADC_CLOCK_DIV_2   0x100
551
#define ADC_CLOCK_DIV_4    0x04
552
#define ADC_CLOCK_DIV_8    0x01
553
#define ADC_CLOCK_DIV_16   0x05
554
#define ADC_CLOCK_DIV_32   0x02
555
#define ADC_CLOCK_DIV_64   0x06
556
#define ADC_CLOCK_INTERNAL 0x03           // Internal 2-6us
557
// The following may be OR'ed in with the above using |
558
#define ADC_TAD_MUL_0      0x00
559
#define ADC_TAD_MUL_2      0x08
560
#define ADC_TAD_MUL_4      0x10
561
#define ADC_TAD_MUL_6      0x18
562
#define ADC_TAD_MUL_8      0x20
563
#define ADC_TAD_MUL_12     0x28
564
#define ADC_TAD_MUL_16     0x30
565
#define ADC_TAD_MUL_20     0x38
566
567
// Constants used in SETUP_ADC_PORTS() are:
568
// First argument:
569
// OR together desired pins
570
#define sAN12            0x10     //| B0
571
#define sAN11            0x8      //| C2
572
#define sAN10            0x4      //| B1
573
#define sAN9             0x2      //| B3
574
#define sAN8             0x1      //| B2
575
#define sAN4            0x100000  //| A5
576
#define sAN3             0x80000  //| A3
577
#define sAN2             0x40000  //| A2
578
#define sAN1             0x20000  //| A1
579
#define sAN0             0x10000  //| A0
580
#define NO_ANALOGS           0x0  // None
581
#define ALL_ANALOG      0xff00ff  // A0 A1 A2 A3 A5 E0 E1 E2 B2 B3 B1 C2 B0
582
583
// Optional Second argument:
584
#define VSS_VDD              0x0000        //| Range 0-Vdd
585
#define VSS_VREF             0x4000        //| Range 0-Vref
586
#define VREF_VREF            0xc000        //| Range Vref-Vref
587
#define VREF_VDD             0x8000        //| Range Vref-Vdd
588
589
590
// Constants used in READ_ADC() are:
591
#define ADC_START_AND_READ     7   // This is the default if nothing is specified
592
#define ADC_START_ONLY         1
593
#define ADC_READ_ONLY          6
594
595
////////////////////////////////////////////////////////////////// INT
596
// Interrupt Functions: ENABLE_INTERRUPTS(), DISABLE_INTERRUPTS(),
597
//                      CLEAR_INTERRUPT(), INTERRUPT_ACTIVE(),
598
//                      EXT_INT_EDGE()
599
//
600
// Constants used in EXT_INT_EDGE() are:
601
#define L_TO_H              0x40
602
#define H_TO_L                 0
603
// Constants used in ENABLE/DISABLE_INTERRUPTS() are:
604
#define GLOBAL                    0xF2C0
605
#define PERIPH                    0xF240
606
#define INT_RTCC                  0x00F220
607
#define INT_TIMER0                0x00F220
608
#define INT_TIMER1                0x009D01
609
#define INT_TIMER2                0x009D02
610
#define INT_TIMER3                0x00A002
611
#define INT_EXT_L2H               0x5000F210
612
#define INT_EXT_H2L               0x6000F210
613
#define INT_EXT                   0x00F210
614
#define INT_EXT1_L2H              0x5001F008
615
#define INT_EXT1_H2L              0x6001F008
616
#define INT_EXT1                  0x00F008
617
#define INT_EXT2_L2H              0x5002F010
618
#define INT_EXT2_H2L              0x6002F010
619
#define INT_EXT2                  0x00F010
620
#define INT_RB                    0x01FFF208
621
#define INT_AD                    0x009D40
622
#define INT_RDA                   0x009D20
623
#define INT_TBE                   0x009D10
624
#define INT_SSP                   0x009D08
625
#define INT_CCP1                  0x009D04
626
#define INT_CCP2                  0x00A001
627
#define INT_BUSCOL                0x00A008
628
#define INT_RDA2                  0x00A320
629
#define INT_TBE2                  0x00A310
630
#define INT_TIMER4                0x00A308
631
#define INT_OSCF                  0x00A080
632
#define INT_HLVD                  0x00A004
633
#define INT_BUSCOL2               0x00A340
634
#define INT_EXT3_L2H              0x5003F020
635
#define INT_EXT3_H2L              0x6003F020
636
#define INT_EXT3                  0x00F020
637
#define INT_USB                   0x00A010
638
#define INT_SSP2                  0x00A380
639
#define INT_RTC                   0x00A301
640
#define INT_COMP                  0x00A020
641
#define INT_COMP2                 0x00A040
642
#define INT_TMR3G                 0x00A302
643
#define INT_CTMU                  0x00A308
644
#define INT_CCP3                  0x008E01
645
#define INT_CCP4                  0x008E02
646
#define INT_CCP5                  0x008E04
647
#define INT_CCP6                  0x008E08
648
#define INT_CCP7                  0x008E10
649
#define INT_CCP8                  0x008E20
650
#define INT_CCP9                  0x008E40
651
#define INT_CCP10                 0x008E80
652
#define INT_TMR1G                 0x009101
653
#define INT_TMR5G                 0x009102
654
#define INT_TIMER5                0x009104
655
#define INT_TIMER6                0x009108
656
#define INT_TIMER8                0x009110
657
#define INT_COMP3                 0x009120
658
#define INT_RB4                   0x110F208
659
#define INT_RB5                   0x120F208
660
#define INT_RB6                   0x140F208
661
#define INT_RB7                   0x180F208
662
663
#list

von Peter D. (peda)


Lesenswert?

Lesen ist wohl nicht Deine Stärke:

-----------------------------------------------------------------------
Antwort schreiben
Wichtige Regeln - erst lesen, dann posten!

    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
-----------------------------------------------------------------------

von Karl H. (kbuchegg)


Lesenswert?

Sagen wir mal so.
Das systemspezifische Header File vom PIC brauchst du nicht posten. 
Diejenigen die PIC programmieren haben das sowieso und der Rest gewinnt 
keine Information daraus.

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:

> Jetzt würde ich das Programm aber gerne so anpassen, dass beim Drücken
> einen Tasters die Messung gestartet wird und beim Drücken eines 2
> Tasters gestoppt wird.

Dann wirst du dir wohl Support für 2 Tasten einbauen müssen und in der 
ISR die Zeit nur dann weiterzählen, wenn die Stoppuhr 'eingeschaltet' 
ist.

> Ich habe im Datenblatt was gelesen con CPP1_High

Mir ist nicht klar, was ein CPP1_High da jetzt damit zu tun haben 
könnte?

> aber ich habe leider keine Idee wie ich das genau implementieren soll.

globale Variable namens clockRunning

in der ISR wird die Uhr nur dann hochgezählt, wenn diese Variable auf 
TRUE steht.
In der Hauptschleife in main() fragst du deine Taster ab. Ist der eine 
gedrückt, dann stellst du clockRunning auf TRUE. Ist der andere 
gedrückt, dann stellst du clockRunning auf FALSE. Und da clockRunning 
von der ISR ausgewertet wird und als Entscheidungsgrundlage dafür dient, 
ob die Zeit hochgezählt wird, läuft dadurch die Uhr nur dann, wenn du 
den einen Taster drückst und sie stoppt wieder, wenn du den anderen 
Taster drückst.

Wo liegt jetzt das Problem?`
Es gibt nicht für alles vorgefertigte Hardware-Komponenten. Manchmal 
muss man wahrhaftig auch programmieren.

von Karl H. (kbuchegg)


Lesenswert?

> int hs;    // hunderstel Sekunden
> int zs;    // zehntel Sekunden
> int s;     // Sekunden
> int m;     //Minuten

Darüber würde ich nochmal nachdenken, ob ich einen kleinen 8-Bit PIC 
unnötiger Weise in 16 Bit Arithmetik reinteibe, wenn keine der Variablen 
jemals größer als maximal 100 werden kann.

von David M (Gast)


Angehängte Dateien:

Lesenswert?

Also mit CCP1_High meinte ich den CCP_Pin (siehe beigefügtem Foto). Weil 
wenn ich das richtig verstanden habe, brauche ich dann keine extra ISR?

@Karl Heinz:
Du meinst also ich sollte besser int8 verwenden?

@Peter:
Sorry, mein Fehler.

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:
> Also mit CCP1_High meinte ich den CCP_Pin (siehe beigefügtem Foto). Weil
> wenn ich das richtig verstanden habe, brauche ich dann keine extra ISR?

Du brauchst für die Taster ja sowieso keine ISR.
Die Uhr hingegen ist doch erst mal gut so wie sie ist. Warum willst du 
da eingreifen?
1
volatile uint8_t  clockRunning = FALSE;
2
3
void time()
4
{
5
  if( clockRunning )
6
  {
7
    hs++;
8
    if(hs == 10)
9
    {
10
      hs = 0;
11
      zs ++;
12
      if( zs == 10 )
13
      {
14
        zs = 0;
15
        s++;
16
        if(s == 60)
17
        {
18
          s = 0;
19
          m++;
20
        }
21
      }
22
    }
23
  }
24
}
25
26
27
void main()
28
{
29
   ....
30
31
  Tastenport initialisieren
32
33
  .....
34
35
36
  while( 1 )
37
  {
38
    if( Taste 1 ist gedrückt )
39
    {
40
      if( Taste 2 ist gedrückt )
41
      {
42
        hs = zs = s = m = 0;
43
      }
44
      else
45
      {
46
        clockRunning = TRUE;
47
      }
48
    }
49
50
    else if( Taste 2 ist gedrückt )
51
      clockRunning = FALSE;
52
53
    .....
54
  }
55
}

> @Karl Heinz:
> Du meinst also ich sollte besser int8 verwenden?

Das würde ich meinen.
Allerdings: wieso int? Können deine Sekunden negativ werden, so dass du 
ein Vorzeichen brauchst?

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> David M schrieb:
>> Also mit CCP1_High meinte ich den CCP_Pin (siehe beigefügtem Foto). Weil
>> wenn ich das richtig verstanden habe, brauche ich dann keine extra ISR?
>
> Du brauchst für die Taster ja sowieso keine ISR.

Ach, jetzt hat es bei mir klick gemacht.

Deine Befürchtung ist, dass das alles ungenau wird.
Keine Sorge. Was denkst du, wie schnell dein µC die Hauptschleife einmal 
durcharbeiten kann. Da reden wir von ein  paar Zehn-millionstel 
Sekunden. Also weit weg von den hunderstel, mit denen du in der Zeit 
operierst. Und wenn du die Anzeige nur dann updatest, wenn sich die Zeit 
auch tatsächlich geändert hat, dann liegt deine Genauigkeit auf das 
ansprechen auf Tastendrücke weit über dem, was deine Taster oder dein 
Benutzer zeitlich auflösen können. Sprich: die 10 Millionstel Sekunden 
'Fehler' spielen überhaupt keine Rolle.

von David M (Gast)


Lesenswert?

Genau, mir ist es um die Genauigkeit gegangen bzw. darum, dass auch 
während der Abarbeitung des Hauptprogramms die Zeit gestoppt wird. Und 
auch aus reinen Eigeninteresse würde ich dies gern mit dem CCP-Module 
realisieren. Nur mir fehlt leider das Verständnis der 
Zuweisung/Verwendung des CCP-Pins.

LG
David

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:

> Und
> auch aus reinen Eigeninteresse würde ich dies gern mit dem CCP-Module
> realisieren. Nur mir fehlt leider das Verständnis der
> Zuweisung/Verwendung des CCP-Pins.


Der Capture hat aber eine vollkommen andere Verwendung.
Da geht es darum, dass der 'Timer' auf 'Befehl von aussen' (zb 
Tastendruck) seinen momentanen Zählerstand wegspeichert.

Selbst wenn ich mich sehr anstrenge, fällt mir nichts ein, wie man 
dieses Verhalten bei einer Stoppuhr wie deiner sinnvoll einsetzen 
könnte.

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:
> Genau, mir ist es um die Genauigkeit gegangen bzw. darum, dass auch
> während der Abarbeitung des Hauptprogramms die Zeit gestoppt wird.

Wenn deine Hauptschleife regelmässig für einen Durchlauf durch die 
Schleife länger als, sagen wir mal, eine halbe Millisekunde braucht, 
dann hast du sowieso etwas grundlegend falsch gemacht.
Die Verwendung von
1
      delay_ms(100);
ist zum Beispiel ein Paradebeispiel, wie man die Dinge nicht macht.


Du willst die Zeit nur dann am LCD updaten, wenn sich an der Anzeige 
auch tatsächlich etwas ändern muss, weil sich die Zeit auch tatsächlich 
geändert hat. Ob das so ist, das weiß die ISR. Ok, hier macht man einen 
Kompromiss, weil man Wissen in die ISR trägt, dass die Anzeige auf 
Zehntel-Sekunden sein soll und die ISR daher eine Benachrichtigung an 
die Hauptschleife gibt, dass die Anzeige zu aktualisieren ist. Aber bei 
derart kleinen Programmen ist das akzeptabel.
1
volatile uint8_t  clockRunning = FALSE;
2
volatile uint8_t  clockTick = TRUE;
3
4
void time()
5
{
6
  if( clockRunning )
7
  {
8
    hs++;
9
    if(hs == 10)
10
    {
11
      hs = 0;
12
      zs++;
13
      clockTick = TRUE;
14
15
      if( zs == 10 )
16
      {
17
        zs = 0;
18
        s++;
19
        if(s == 60)
20
        {
21
          s = 0;
22
          m++;
23
        }
24
      }
25
    }
26
  }
27
}
28
29
30
void main()
31
{
32
   ....
33
34
  Tastenport initialisieren
35
36
  .....
37
38
39
  while( 1 )
40
  {
41
    if( Taste 1 ist gedrückt )
42
    {
43
      if( Taste 2 ist gedrückt )
44
      {
45
        hs = zs = s = m = 0;
46
        clockTick = TRUE;
47
      }
48
      else
49
      {
50
        clockRunning = TRUE;
51
      }
52
    }
53
54
    else if( Taste 2 ist gedrückt )
55
      clockRunning = FALSE;
56
57
    if( clockTick )
58
    {
59
      clockTick = FALSE;
60
      lcd_gotoxy(9,1);
61
      if(m > 0)
62
      {
63
        printf(lcd_putc,"%02u:%02u:%u",m,s,zs);
64
      }
65
      else
66
      {
67
        printf(lcd_putc,"%02u:%u",s,zs);
68
      }
69
    }
70
  }
71
}

Jetzt wird die Anzeige nur dann aktualisiert, wenn sich auch tatsächlich 
an der Anzeige etwas verändert. Es ist kein delay_ms mehr notwendig und 
die Durchlaufzeit durch die Hauptschleife (und damit die Abfragefrequenz 
der Tasten) ist wieder um einige Zehnerpotenzen höher, als du überhaupt 
sinnvoll die Zeit messen kannst.

von David M (Gast)


Lesenswert?

Danke einmal, habe es jetzt einmal nach deinem Vorschlag gelöst. 
Natürlich wird dieses Programm noch umfangreicher. Später soll durch ein 
Signal die Messung gestoppt werden und am LCD ausgegeben werden. 
Währenddessen läuft aber eine neue Zählung in der 2en Zeile (Runde 2). 
Beim Beginn der 3.Runde soll dann kurz die Zeitdifferenz zwischen der 1. 
und 2.Runde angezeigt werden. Darum wollte ich eigentlich das CCP-Module 
verwenden, da dieses mehrere Timer gleichzeitig verwaltet/steuert(?). 
Leider hab ich bis jetzt kein Bsp-Programm oder dergleichen gefunden, 
welches mir die Funktion des CCP-Modules näher bringt.

LG
David

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:
> Danke einmal, habe es jetzt einmal nach deinem Vorschlag gelöst.
> Natürlich wird dieses Programm noch umfangreicher. Später soll durch ein
> Signal die Messung gestoppt werden und am LCD ausgegeben werden.
> Währenddessen läuft aber eine neue Zählung in der 2en Zeile (Runde 2).
> Beim Beginn der 3.Runde soll dann kurz die Zeitdifferenz zwischen der 1.
> und 2.Runde angezeigt werden.

Ja, macht ja nix.
Hauptschleife und ISR 'kommunizieren' über globale Variablen. Der eine 
sagt der anderen 'was zu tun ist' und der andere sagt dem einen, wenn 
sich etwas getan hat.

> Darum wollte ich eigentlich das CCP-Module
> verwenden, da dieses mehrere Timer gleichzeitig verwaltet/steuert(?).

Nochmal.
Das sind HARDWARE-Timer. Die kannst du nicht benutzen, weil die viel zu 
schnell ablaufen. Capture Einheit nimmst du dann, wenn dein Hardware 
Timer alleine ausreicht um Zeiten zu zählen, wie zb, bei einer 
Frequenzmessung bei der man eine Pulslänge ausmessen will. Für dich 
völlig ungeeignet, weil du deine Uhr nicht mit dem Timer alleine ohne 
Hilfsvariablen abwickeln kannst. Oder kannst du deine Timer so 
einstellen, dass sie ein paar Minuten lang (bei dir immerhin maximal bis 
100 Minuten) durchzählen ohne Overflow? Würde mich wundern, wenn du das 
hinkriegst.
Der Zählerstand des Hardware-Timers selbst interessiert dich ja 
überhaupt nicht. Dich interessieren die Variablen, die Timergetrieben 
ihren Wert ändern. Und auf die hat der Capture ja keinen Einfluss.


Das wars für mich. Du kannst ja noch 3 Tage den falschen Baum anbellen 
wenn du willst. Einer Lösung deines 'Problems' wirst du dadurch nicht 
näher kommen. Aber ist ok.

von Karl H. (kbuchegg)


Lesenswert?

Und bitte: keine delay_ms !
Das ist wichtig. Wenn du dich daran hältst, dann wird dir auch nicht 
viel passieren. Wenn du Verzögerungen, wie zb Anzeigeverzögerungen haben 
willst, dann geht das immer über einen Timer der regelmässig eine ISR 
aufruft (und den du schon hast)

zb so
1
volatile int8_t delayTime;
2
3
void time()
4
{
5
  if( clockRunning )
6
  {
7
    ...
8
  }
9
10
  if( delayTime > 0 )
11
    delayTime--;
12
}

was bringt dir das?
Ganz einfach. In der Hauptschleife setzt du dir bei 'Beginn der 
Wartezeit' die Variable auf einen dir genehmen Wert und die ISR sorgt 
dafür, dass diese Variable langsam runterzählt, bis sie wieder 0 
erreicht. Fragst du in deiner Hauptschleife daher bei jedem Durchlauf 
die Variable ab, dann weißt du, dass die Wartezeit abgelaufen ist, wenn 
du die Variable wieder bei 0 erwischt.
1
void main()
2
{
3
  ...
4
5
6
  while( 1 )
7
  {
8
9
     if( Taste 1 gedrückt )
10
       delayTime = 200;
11
12
     if( delayTime != 0 )
13
       lcd_print( "Verzögerung läuft" );
14
     else
15
       lcd_print( "keine Verzögerung" );
16
  }
17
}

Variationen davon sind möglich. Insbesondere muss man sich überlegen, in 
welcher Aufruffreuqenz man die ISR hat und ob wirklich bei jedem Aufruf 
runtergezählt werden soll, ob 8 Bit Variablen reichen, etc. Aber allen 
ist das Muster gemeinsam: Die Hauptschleife setzt der ISR eine Variable 
und die ISR meldet über diese (oder eine andere Variable) den Ablauf 
(bei dir) einer Zeitspanne zurück, woraufhin die Hauptschleife in ihrem 
Durchlauf etwas macht bzw. etwas anders macht.

keine Delays. Dann hast du auch keine Probleme, dass dein Programm 
mehrere Dinge scheinbar 'gleichzeitig' machen muss, ohne dass die 
Funktionalität darunter leidet.


Deine Maxime lautet:
delay_ms ist nicht die Lösung sondern das Problem!
In der Hauptschleife werden nacheinander 'Ereignisse' (in Form von 
Werten von Variablen) geprüft, ob sie eingetreten sind. Ist dies der 
Fall, dann wird dieses Ereignis behandelt und weiter gehts mit der 
Abfrage der diversen Ereignisanzeiger. Aber gewartet - gewartet wird 
grundsätzlich nicht. Alles wird so umgeformt, dass es in Form von 
'Ereignissen' auftaucht. Und sei es nur, dass eine Timer-ISR ein 
entsprechendes 'Ereignis' x Sekunden nach Triggerung in Form eines 
speziellen Variablenwertes anzeigt.

Und so gelingt es deinem µC die Runden auf 8 Spuren der Autorennbahn zu 
zählen, aktuelle Rundenzeit und vergangene Rundenzeit auf allen 8 Spuren 
zu managen und zu verwalten, Durschnittszeit und 
Durchschnittsgeschwindigkeit auszurechnen, die Zeiten zu kummulieren, 
die Zeiten mehrere Autos als Teamzeiten zu addieren, zusammenzuzählen 
und eine aktuelle Reihung zu führen, das ganze auf LCD und UART 
auszugeben und auch noch die jeweilige Siegerhymne zu spielen. Das alles 
während auf 3 Spuren noch gefahren wird.
Und nebenbei, damit ihm nicht fad wird, spielt er noch eine Partie 
Schach.

von David M (Gast)


Lesenswert?

Okay, hab es verstanden. CCP-Module ist das falsche für meine Anwendung. 
Ist es somit auch falsch, dass ich mittels CCP die ISR Int_CCP5 alle 10 
ms aufrufe?
1
#include <18F27J53.h>
2
#device ADC=12                                // nicht verändern
3
#fuses  HSPLL,PLLEN,PLL5, NOCPUDIV, NOWDT,NOPROTECT              // nicht verändern
4
#fuses  ADC12, RTCOSC_INT, DSWDTOSC_T1                    // nicht verändern
5
#use    delay(clock=48000000)                        // nicht verändern
6
7
// Für Bootloader ------------------------------------------------
8
#build (reset=0x1000, interrupt=0x1008)  // neue Adressen          // nicht verändern
9
#org 0x0,0xfff {}            // res. Bereich            // nicht verändern
10
// ---------------------------------------------------------------
11
12
//
13
//LCD Lib
14
#include "D:\Dropbox\Abend-HTL\6ABELI\FTKLÜ\Mini-Projekt\Programm\LCD.c"
15
//
16
unsigned char hs;    // hunderstel Sekunden
17
unsigned char zs;    // zehntel Sekunden
18
unsigned char s;     // Sekunden
19
unsigned char m;     //Minuten
20
volatile unsigned int clockRunning = FALSE;
21
volatile unsigned int  clockTick = TRUE;
22
23
#Int_CCP5 // ISR für Timer1 (alle 10ms)
24
void time()
25
{
26
   if(clockRunning)
27
  {
28
    hs++;
29
    if(hs == 10)
30
    {
31
      hs = 0;
32
      zs++;
33
      clockTick = TRUE;
34
35
      if( zs == 10 )
36
      {
37
        zs = 0;
38
        s++;
39
        if(s == 60)
40
        {
41
          s = 0;
42
          m++;
43
        }
44
      }
45
    }
46
  }
47
}
48
// Hauptprogramm
49
void main() 
50
{
51
   hs = 0;    // hunderstel Sekunden
52
   zs = 0;    // zehntel Sekunden
53
   s = 0;     // Sekunden
54
   m = 0;     //Minuten
55
56
   Setup_Timer_1(T1_Internal | T1_DIV_BY_8); // Interner Takt, 1:8
57
   Setup_CCP5(CCP_COMPARE_RESET_TIMER);
58
59
   enable_interrupts(GLOBAL);    // Globaler Interrupt wird aktiviert
60
   enable_interrupts(Int_CCP5);  // CCP1 Interrupt wird aktiviert
61
  
62
   
63
   CCP_5=15015; // alle 15015 Zyklen
64
65
  .
66
  .

von PittyJ (Gast)


Lesenswert?

Warum wird in der Interrupt-Routine schon so viel gerechnet?

Zähl doch einfach die hunderstel in einer long Variable. Und erst, wenn 
das Ergebnis später mal angezeigt werden muss, wird es zu Sekunden, 
Minuten etc umgerechnet. Das braucht er ja nicht 100 mal im Interrrupt 
machen.
Bei der Anzeige kann man dann auch wunderbar Division und Modulo nehmen.
Und schneller als 10tel kann ein Mensch eh nicht sehen. Ist also 
unnötig, die hunderstel während des Laufens anzuzeigen.

von Karl H. (kbuchegg)


Lesenswert?

PittyJ schrieb:
> Warum wird in der Interrupt-Routine schon so viel gerechnet?

So viel ist das auch nicht.
Das schaut nur nach viel Code aus. Sind aber nur 4 mal laden, Increment 
und wieder wegspeichern. In Assembler ist das überschaubar wenig. Das 
zieht sich nur in C durch die Schreibweise in die Länge. Sind aber alles 
nur 8 Bit Operationen und somit für den µC mundgerechte Happen. Wenn er 
einen long zum inkrementieren durchschleusen muss, ist das auch für 
einen 8-Bitter einiges an Aufwand.


> Ist also unnötig, die hunderstel während des Laufens anzuzeigen.

Das allerdings schon. Wobei auch die Zehntel schon übertrieben sind. 
Auch die kann kein Mensch mehr sinnvoll lesen. Während die Zeit läuft, 
ist man mit ganzen Sekunden mehr als ausreichend bedient.

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:
> Okay, hab es verstanden. CCP-Module ist das falsche für meine Anwendung.
> Ist es somit auch falsch, dass ich mittels CCP die ISR Int_CCP5 alle 10
> ms aufrufe?

Du verwechselst da was. Nicht alles was CCP heißt, tritt in der gleichen 
Funktion aus.
Einen regelmässigen Timerinterrupt brauchst du, damit du eine Uhr 
realisiern kannst.
Aber bei dem von dir vorhin angesprochenen 'MOdul' ging es um die 
Capture Einheit der CCP. Und die kannst du hier nicht sinnvoll 
einsetzen.

von David M (Gast)


Lesenswert?

Ich gebe ja auch während der Fahrt nur die Sekunden und Minuten aus. Den 
Rest brauch ich nur für die Berechnung. Die macht mir aber gerade 
Probleme. Konkret geht es darum, die Differenz der Rundenzeiten zu 
berechnen. Um dies zu bewerkstelligen, habe ich mir gedacht die Zeit in 
Zehntelsekunden umzurechnen, dann die zwei Zeiten zu subtrahieren und 
anschließend wieder rück zu rechnen. Aber irgendwie funktioniert das mit 
dem Type Casting nicht. Ich habe immer bei 255 einen Oberflow. Kann der 
PIC kein TypeCasting oder mach ich hier etwas falsch?
1
//
2
unsigned char hs;    // hunderstel Sekunden
3
unsigned char zs;    // zehntel Sekunden
4
unsigned char s;     // Sekunden
5
unsigned char m;     //Minuten
6
unsigned int convzs, rec_m, rec_s, rec_zs ;
7
volatile int8 clockRunning = FALSE;
8
volatile int8  clockTick = TRUE;
9
.
10
.
11
else if(input(PIN_A5))
12
{
13
  clockRunning = FALSE;
14
  rec_m = (unsigned int) m; //TypeCasting von uns. char in uns. int
15
  rec_s= (unsigned int) s; //TypeCasting von uns. char in uns. int
16
  rec_zs= (unsigned int) zs; //TypeCasting von uns. char in uns. int
17
  convzs= ((600*rec_m) + (10*rec_s) + rec_zs); //Umrechnung in zs
18
  lcd_gotoxy(1,2);
19
  printf(lcd_putc,"%u",conzs);
20
}

von Karl H. (kbuchegg)


Lesenswert?

entweder du hast nicht deinen richtigen Code gepostet oder du hast 
gerade gerlent, dass vernünftige Variablennamen kein Luxus sind bzw. das 
das Aufteilen in Funktionen Code nicht nur übersichtlicher (weil kürzer) 
macht, sondern auch Fehlern vorbeugt, die durch zu großen Codeumfang 
bzw. zu viele Variablen entstehen (es ist nicht sinnvoll ALLE Variablen 
global zu machen. Manche Variablen sind besser dort aufgehoben, wo sie 
tatsächlich gebraucht werden)

  convzs= ((600*rec_m) + (10*rec_s) + rec_zs); //Umrechnung in zs
  ######

  printf(lcd_putc, "%u", conzs );
                         #####

vergleich mal die beiden Variablennamen!

von David M (Gast)


Lesenswert?

Das war nur ein Fehler beim Posten, leider kann ich den Text als Gast 
nicht editieren. Aber im Programm ist dies richtig. Ich habe die 
Variablen derzeit nur global definiert, da ich es erst testen will ob es 
funktioniert ;)

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:
> Das war nur ein Fehler beim Posten,

Dir ist schon klar, dass man sich damit in diesem Forum ganz schnell 
sehr unbeliebt machen kann?

Poste deinen richtigen Code!
Poste, wenn möglich und nicht zu lang, den kompletten Source Text! Denn 
das Problem steckt oft genug in dem Code, den du nicht zeigst.

Längerer Source Code (ab 2 bis 3 Bildschirmseiten) hängt man als 
Attachment (Dateianhang) an. Dazu sind Attachments da.

Poste keine Codeschnipsel. Das ist
* für dich mehr Arbeit
* für uns unter Umständen nicht hilfreich, weil das Problem oft genug
  ganz woanders sitzt, als du es vermutest
* für uns mehr Arbeit
* fehleranfällig, wie du gesehen hast
* für uns mühsam, weil wir dann Fehler suchen, die in deinem 'richtigen'
  Code gar nicht vorhanden sind.

Also ... warum solltest du dir die Mühe machen und einen Codeexzerpt 
anfertigen? Häng das C-File als Attachment an und gut ists.


> nicht editieren. Aber im Programm ist dies richtig. Ich habe die
> Variablen derzeit nur global definiert, da ich es erst testen will ob es
> funktioniert ;)

Ja, ja. Immer dieses 'ich will erst mal'. Mach es gleich richtig! Das 
erpart dir viele Fehler, die du erst mal suchen musst.

von David M (Gast)


Angehängte Dateien:

Lesenswert?

Ok, tut mir leid. Wollte es halt am Anfang auf die einfachste Art 
erledigen um andere Fehler auszuschließen. Habe jetzt die C-Files 
angehängt.

von David M (Gast)


Lesenswert?

Was vielleicht auch noch von Bedeutung ist, ich verwende MPLAB v.8.89 
und den CCS-Compiler v.4.140

von David M (Gast)


Lesenswert?

Habe jetzt schon folgendes versucht:
*Von Anfang an unsigned Integer-Variablen zu verwenden --> kein Erfolg
*Die Multiplikatoren 600 und 10 als unsigned  Integer-Variablen anlegen 
--> kein Erfolg.

Egal was ich versucht habe, ab einen Sekunden-Wert von größer 25 bekomme 
ich falsche Ergebnisse.

von Karl H. (kbuchegg)


Lesenswert?

David M schrieb:
> Ok, tut mir leid. Wollte es halt am Anfang auf die einfachste Art
> erledigen um andere Fehler auszuschließen. Habe jetzt die C-Files
> angehängt.

ACh komm.
Von einem RAR-File war nicht die Rede.

Einfach die C (und H) Files als mehrere Attachments anhängen!
Mach dir doch nicht mehr Arbeit als notwendig! Und mach es nicht 
kompliziert.

Ich weiß, du meinst es gut. Aber wenn du es gut meinst, dann hängst du 
einfach deine 3 oder 4 Files (mehr werden es ja meistens eh nicht sein) 
als Attachment an. Dann kann jeder einfach auf das File klicken, dass 
ihn interessiert und kriegt im Browser eine Codeanzeige mit 
Syntax-Coloring.

Mit deinem RAR File muss ich das jetzt erst mal downloaden, entpacken, 
und im entpacketen Zustand kann ich mir dann wieder die Einzelfiles 
ansehen. Was glaubst du, wie groß meine Lust dazu ist? Ich verrate es 
dir: nahezu 0

von Karl H. (kbuchegg)


Lesenswert?

Da der printf Mechanismus auf deinem System recht offensichtlich nicht 
standard ist:

Bist du sicher, dass %u der richtige Format-Spezifier für einen unsigned 
int auf deinem System ist?

von David M. (david_m70)


Angehängte Dateien:

Lesenswert?

Also laut der Compiler-Hilfe ist %u für unsigned int (siehe Anhang).

von David M. (david_m70)


Lesenswert?

Hab den Fehler gefunden. Der CCS-Compiler nimmt bei einer Deklaration 
mit int automatisch die Bus-Breite des PIC's, also bei mir int8. Habe 
die int durch int16 ersetzt und siehe da es geht :)

von Karl H. (kbuchegg)


Lesenswert?

David M. schrieb:
> Also laut der Compiler-Hilfe ist %u für unsigned int (siehe Anhang).

Interessant.


Die Sache ist die.
Aus Standard-C Sicht, gibt es an
1
void convert_zs (unsigned int8 m, unsigned int8 s, unsigned int8 zs)
2
{
3
   unsigned int convzs, rec_m, rec_s, rec_zs;
4
   unsigned int multipmin= 600;
5
   unsigned int multipsek= 10;
6
   rec_m= (unsigned int) m;
7
   rec_s= (unsigned int) s;
8
   rec_zs= (unsigned int) zs;
9
   convzs= ((multipmin*rec_m) + (multipsek*rec_s) + rec_zs);

nichts auszusetzen. Das war auch bei deinen früheren, kompakteren 
Versionen schon so. Im Grund darf es bei einem
1
void convert_zs (unsigned int8 m, unsigned int8 s, unsigned int8 zs)
2
{
3
   unsigned int convzs = m*600 + s*10 + zs;

keinen Overflow geben, solange das Gesamtergebnis nicht größer als 65535 
wird. Ein Overflow bei 255 im Endergebnis ist (bei Standard-C) 
vollkommen ausgeschlossen.

Daher habe ich zunächst auf die Ausgabe getippt, dass die irgendwas mit 
dem unsigned int anstellt.


Jetzt ist es aber auch so, dass µC-Compiler schon mal auch vom 
C-Standard abweichen. Das hier
1
   convzs= ((multipmin*rec_m) + (multipsek*rec_s) + rec_zs);

bei dem ja nun wirklich alles und jedes ein unsigned int ist, darf auf 
gar keinen Fall nach 25 Sekunden überlaufen. Deine unsigned int sind 
doch 16 Bit - Oder? Das wäre zwar eine grobe Verletzung des C-Standards 
aber das hat µC-Compiler Hersteller meist nur selten gestört.

von Karl H. (kbuchegg)


Lesenswert?

David M. schrieb:
> Hab den Fehler gefunden. Der CCS-Compiler nimmt bei einer Deklaration
> mit int automatisch die Bus-Breite des PIC's, also bei mir int8.


Was'n das für ein Scheiss?
Kann man das mit einem Command Line Switch abdrehen?


Wenn nicht wäre das für mich ein Grund den Compiler zu wechseln.

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.