Forum: Mikrocontroller und Digitale Elektronik Problem mit Timer0 und PIC18F13K22


von Hendrik M. (nicksput)


Lesenswert?

Hallo verehrte Gemeinde!

Seit einigen Tagen beschäftige ich mich mit dem Thema 
PIC-Programmierung, da ich kleinere Anwendungen hierüber sehr gut für 
Testumgebungen in unserer Entwicklungsumgebung einsetzen kann. Ich habe 
hier auf der Seite und im Forum schon etliche hilfreiche Tipps gefunden. 
Jetzt habe ich mich trotz hunderter Tutorials und anderer Anleitungen 
mit meinen Miniversuchen festgefahren und hoffe auf Eure Expertenhilfe.

Wie im Betreff bereits angedeutet arbeite ich mit einem PIC18F13K22 und 
habe das Gefühl das 400-seitige Datenblatt häufiger gelesen zu haben als 
so mancher Priester die Bibel. Ich habe mir eine Testplatine gebastelt 
und konnte auch schon diverse kleine Versuchsprojekte umsetzen.
Ich habe eine LED am Pin RA0 und setze über die Standardschnittstelle 
ein PICKit3 zur Programmierung und zum Debuggen über MPLAB v8.90 ein.

Ich bekomme die LED zum Leuchten, einen ADC Input von einem Poti 
ausgewertet und schaffe es auch über die delay-Funktion einen Ausgang 
blinken zu lassen. Hardwaremäßig scheint soweit also alles mal zu 
passen.

Wenn ich jetzt allerdings versuche den Timer0 einzusetzen bekomme ich 
das Ganze nicht mehr zum Laufen. Bitte helft mir den Fehler zu finden.

Zunächst bin ich mir nicht sicher ob meine Configurationbits alle 
korrekt sind, daher hier mein config.h - file:

//Konfigurationsbits für PIC18F13K22

__CONFIG(1, OSC_INT_RC & PLLEN_OSCILLATOR_USED_DIRECTLY & 
PCLKEN_PRIMARY_CLOCK_ENABLED & FCMEN_DISABLED & IESO_ENABLED);
__CONFIG(2, nPWRTEN_ENABLED & BOREN_ENABLED_IN_HARDWARE__SBOREN_DISABLED 
& BORV_1_9V & WDTEN_DISABLED_CONTROLLED_BY_SWDTEN_BIT & WDTPS_1_32768);
__CONFIG(3, 
HFOFST_THE_SYSTEM_CLOCK_IS_HELD_OFF_UNTIL_THE_HFINTOSC_IS_STABLE & 
MCLRE_MCLR_ENABLED_RA3_DISABLED);
__CONFIG(4, STVREN_ENABLED & LVP_DISABLED & BBSIZ_1_KW_BOOT_BLOCK_SIZE & 
XINST_DISABLED & BACKBUG_ENABLED);
__CONFIG(5, CPB_DISABLED & CPD_DISABLED & CP_1_DISABLED & 
CP_0_DISABLED);
__CONFIG(6, WRT_0_DISABLED & WRT_1_DISABLED & WRTC_DISABLED & 
WRTB_DISABLED & WRTD_DISABLED);
__CONFIG(7, EBTR_0_DISABLED & EBTR_1_DISABLED & EBTRB_DISABLED);


Des weiteren ist hier mein C-Code:

/** I N C L U D E S *******************************************/

#include <htc.h>
#include <pic18f13k22.h>
#include "config.h"

/** C O N F I G U R A T I O N *********************************/

//Die Configurationsbits wurden mit der config.h eingebunden
//Die Definitionen der Bits finden sich in der pic18f13k22.h

/** D E F I N E S *********************************************/

#define LED1  LATAbits.LATA0  //LED liegt an Port A RA0
#define Taster1 LATCbits.LATC0  //Taster liegt an Port C RC0

/** G L O B A L E ** V A R I A B L E N ************************/

int zeit=0;
int wartezeit=10;
char status=0;

/** P R O T O T Y P E S ***************************************/

void interrupt ISRTimer(void);
void initTimer0(void);
void restartTimer0(void);
void stopTimer0(void);
void wait(int sec);
void delay( int ms );

/** I N T E R R U P T S ***************************************/
void interrupt ISRTimer(void) {

  INTCONbits.TMR0IF = 0;    //Interruptflag des Timers zurücksetzen

  zeit++;            //Zeit inkrementieren bis Wartezeit
  if(zeit >= wartezeit){        //erreicht ist
    zeit = 0;
    stopTimer0();
    INTCONbits.INT0IF = 0;  //Interruptflag zurücksetzen
    INTCONbits.INT0IE = 1;  //Tasterinterrupt freischalten
    if(LED1==0){
      LED1=1;
    }else{
      LED1=0;
    }
  }else{
    restartTimer0();
  }
  return;

}

/** H A U P T P R O G R A M M *********************************/

void main(void)
{

  OSCCON=0x76;        // Takt auf 16MHz setzen


  //Port A
  LATA = 0x00;
  TRISA = 0x00;        // Alle Pins von Port A sind Ausgänge

  //Port B
  LATB = 0x00;
  TRISB = 0x10;        // RB4 ist ein Eingang, alle anderen Pins von 
Port B sind Ausgänge

  //Port C
  LATC = 0x00;
  TRISC = 0x01;        // Alle Pins von Port C sind Ausgänge nur C0 ist 
ein Eingang

  ANSEL = 0x00;        // RA0-RA4 und RC0-RC3 sind digitale I/Os
  ANSELH = 0x04;        // RB4 ist ein analoger Eingang RB5, RC6 und RC7 
sind digitale I/Os


INTCONbits.PEIE = 1;      // Peripheral Interrupts aktivieren
INTCONbits.INT0IF = 0;      // Interruptflag zurücksetzen
INTCONbits.INT0IE = 1;      // externen Interrupt aktivieren
INTCONbits.GIE = 1;        // Globale Interrupts aktivieren
initTimer0();
restartTimer0();


  while(1) {          //Hauptschleife
                //tue nichts
  }

}

/** F U N K T I O N E N *********************************/

// Timer 0 wird initialisiert
void initTimer0(void){
  T0CON = 0b00000111;      // 16-Bit-Timer, Prescaler = 256
  TMR0H = 0x00;        // Highbyte ist 0 --> die ersten beiden Stellen 
0xHHLL (HH)
  TMR0L = 0x00;        // Lowbyte ist 0 --> die letzten beiden Stellen 
0xHHLL (LL)
  INTCONbits.TMR0IF = 0;    // Interruptflag zurücksetzen
  INTCONbits.TMR0IE = 1;    // Timerinterrupt aktivieren
  return;
}

// Timer 0 wird zurückgesetzt
void restartTimer0(void){
int TimerValue=0;
  T0CON = 0b00000111;      // 16-Bit-Timer, Prescaler = 256, Timer0 
deaktiviert
  TMR0H = 0xC2;        // Timer-Wert für 1 sec: 65535-15625=49910 = 
0xC2F6
  TMR0L = 0XF6;        // Highbyte und Lowbyte s. "initTimer0"
  INTCONbits.TMR0IE = 1;    // Timer0-Interrupt aktivieren
  INTCONbits.TMR0IF = 0;    // Interruptflag zurücksetzen
  T0CONbits.TMR0ON = 1;    // Timer0 aktivieren
  return;
}

// Timer anhalten
void stopTimer0(void){
  T0CON = 0b00000111;
  TMR0H = 0x00;
  TMR0L = 0x00;
  INTCONbits.TMR0IF = 0;    // Interruptflag zurücksetzen
  INTCONbits.TMR0IE = 0;    // Timer0-Interrupt deaktivieren
  return;
}

// Pausensequenz -> nur für Testzwecke
void delay( int ms ) {
  int i=0;
  //1 ms = 4000 Befehlstakte (16 MHz Quarz / 4)
  for( i=0; i<ms; i++ ) {
    _delay(4000);
  }
}



Ich würde mich sehr freuen, wenn mir jemand helfen könnte.

Viele Grüße aus dem Schwarzwald

von Stefan (Gast)


Lesenswert?

Irgendwie ist alles doppelt
und dreifach bei dir gemacht worden
mit dem Timer0.
Hier eine Routine für 10MHz Quartz.
Alle 50ms wird ein Interrupt ausgelöst.

//Timer0
//Prescaler 1:2; TMR0 Preload = 3034; Actual Interrupt Time : 50 ms

//Place/Copy this part in declaration section
void InitTimer0(){
  T0CON   = 0x80;
  TMR0H   = 0x0B;
  TMR0L   = 0xDA;
  GIE_bit   = 1;
  TMR0IE_bit   = 1;
}

void Interrupt(){
  if (TMR0IF_bit){
    TMR0IF_bit = 0;
    TMR0H   = 0x0B;
    TMR0L   = 0xDA;
    //Enter your code here
  }
}

von Hendrik M. (nicksput)


Lesenswert?

Hallo Stefan,

vielen Dank für die schnelle Antwort!

Das schien mir auch etwas viel doppelt gemoppelt, aber ich hatte einiges 
davon aus Beispielen bzw. aus dem FRANZIS-Werk "PIC-Mikrocontroller"

Ich habe jetzt das mal soweit es mir sinnvoll schien verschlankt, es 
funktioniert!!!

Der Vollständigkeit halber hier der Code der funktioniert:
1
/** I N C L U D E S *******************************************/
2
3
#include <htc.h>
4
#include <pic18f13k22.h>
5
#include "config.h"
6
7
/** C O N F I G U R A T I O N *********************************/
8
9
//Die Configurationsbits wurden mit der config.h eingebunden
10
//Die Definitionen der Bits finden sich in der pic18f13k22.h
11
12
/** D E F I N E S *********************************************/
13
14
#define LED1  LATAbits.LATA0  //LED liegt an Port A RA0
15
#define Taster1 LATCbits.LATC0  //Taster liegt an Port C RC0
16
17
/** G L O B A L E ** V A R I A B L E N ************************/
18
19
int zeit=0;
20
int wartezeit=10;
21
22
/** P R O T O T Y P E S ***************************************/
23
24
void interrupt ISRTimer(void);
25
void initTimer0(void);
26
void restartTimer0(void);
27
void delay( int ms );
28
29
/** I N T E R R U P T S ***************************************/
30
void interrupt ISRTimer(void) {
31
32
  INTCONbits.TMR0IF = 0;    //Interruptflag des Timers zurücksetzen
33
  
34
  zeit++;            //Zeit inkrementieren bis Wartezeit  
35
  if(zeit >= wartezeit){    //erreicht ist
36
    zeit = 0;
37
    INT0IF = 0;  //Interruptflag zurücksetzen
38
    if(LED1==0){
39
      LED1=1;
40
    }else{
41
      LED1=0;
42
    }
43
    restartTimer0();  
44
  }else{  
45
    restartTimer0();
46
  }
47
  return;
48
49
}
50
51
/** H A U P T P R O G R A M M *********************************/
52
53
void main(void)
54
{
55
56
  OSCCON=0x76;        // Takt auf 16MHz setzen
57
58
59
  //Port A
60
  LATA = 0x00;    
61
  TRISA = 0x00;        // Alle Pins von Port A sind Ausgänge
62
63
  //Port B
64
  LATB = 0x00;
65
  TRISB = 0x10;        // RB4 ist ein Eingang, alle anderen Pins von Port B sind Ausgänge    
66
67
  //Port C
68
  LATC = 0x00;
69
  TRISC = 0x01;        // Alle Pins von Port C sind Ausgänge nur C0 ist ein Eingang
70
71
  ANSEL = 0x00;        // RA0-RA4 und RC0-RC3 sind digitale I/Os
72
  ANSELH = 0x04;        // RB4 ist ein analoger Eingang RB5, RC6 und RC7 sind digitale I/Os
73
74
75
GIE = 1;            // Globale Interrupts aktivieren
76
initTimer0();
77
restartTimer0();
78
79
80
  while(1) {          //Hauptschleife
81
                //tue nichts    
82
  }    
83
84
}
85
86
/** F U N K T I O N E N *********************************/
87
88
// Timer 0 wird initialisiert 
89
void initTimer0(void){
90
  T0CON = 0b00000111;      // 16-Bit-Timer, Prescaler = 256
91
  TMR0H = 0xC2;        // Highbyte ist 0 --> die ersten beiden Stellen 0xHHLL (HH)
92
  TMR0L = 0xF6;        // Lowbyte ist 0 --> die letzten beiden Stellen 0xHHLL (LL)
93
                // Timer-Wert für 1 sec: 65535-15625=49910 = 0xC2F6
94
  TMR0IF = 0;          // Interruptflag zurücksetzen
95
  TMR0IE = 1;          // Timerinterrupt aktivieren
96
  return;
97
}
98
99
// Timer 0 wird zurückgesetzt
100
void restartTimer0(void){
101
int TimerValue=0;
102
  T0CON = 0b00000111;      // 16-Bit-Timer, Prescaler = 256, Timer0 deaktiviert
103
  TMR0IF = 0;          // Interruptflag zurücksetzen
104
  TMR0ON = 1;          // Timer0 aktivieren
105
  return;
106
}

Danke, danke, danke!

Ich hoffe ich kann hier auch irgendwann mal jemandem sinnvolle Tipps 
geben.

Viele Grüße

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.