Forum: Mikrocontroller und Digitale Elektronik Probleme mit PIC und Interrupt


von Lena R. (eny)


Lesenswert?

Hoffe das ist das richtige Forum.
µC ist PIC18F23K22, IDE MPLAB X und Compiler XC8.

Möchte eigentlich nur, dass eine LED nach ca. 1 Sekunde an geht, dann 
wieder aus, wieder an und zu Übungszwecken mit Interrupts.
Eigentlich ja keine soo große Sache, aber es will einfach nicht und ich 
weiß nicht weiter.

Der PIC führt nach dem laden garnichts aus, als ob er irgendeinen Fehler 
hat.
Hier mal der Code, vielleicht kann mal jemand draufschauen.
1
/* 
2
 * File:   main.c
3
 * Author: Lena
4
 *
5
 * Created on 29. Juli 2013, 22:55
6
 */
7
8
9
/** I N C L U D E S *******************************************/
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <htc.h>
13
#include <pic18f23k22.h>
14
#include "Config.h"
15
16
#define LED LATAbits.LATA0
17
18
/*Globals*/
19
int led_state = 0;
20
unsigned int counter=0;                //Overflow Zähler
21
22
/*Protos*/
23
void interrupt isr_high(void);
24
void interruptcode(void);
25
void led_an(void);
26
void led_aus(void);
27
28
29
/////////////////////////////////////////////////////////////////
30
31
void interrupt isr_high(void)
32
{
33
    #asm
34
    goto _interruptcode
35
    #endasm
36
}
37
38
39
/////////////////////////////////////////////////////////////////
40
//#pragma interrupt interruptcode
41
void interruptcode(void)
42
{
43
    if(INTCONbits.TMR0IF == 1)
44
    {
45
        INTCONbits.TMR0IF = 0;
46
        if(led_state == 0)
47
        {
48
           led_an();
49
           led_state = 1;
50
        } else {
51
           led_aus();
52
           led_state = 0;
53
        }
54
    }
55
56
}
57
58
void main(void) {
59
60
61
    T0CONbits.TMR0ON = 0;
62
    
63
    //Port A
64
    LATA = 0x00;                //Pegel
65
    TRISA = 0x00;    //Alle Pins von Port A sind Ausgänge
66
    ANSELA = 0x00;    //Alle Pins von Port A sind digitale I/O's
67
    //Port B
68
    LATB = 0x00;
69
    TRISB = 0xFF;    //Alle Pins von Port B sind Eingänge    
70
    ANSELB = 0x00;    //Alle Pins von Port A sind digitale I/O's
71
    //Port C
72
    LATC = 0x00;
73
    TRISC = 0xF0;    //RC0..RC3 = Ausgänge, RC4..RC7 = Eingänge
74
    ANSELC = 0x30;    //nur RC4 und RC5 sind analoge Eingänge
75
    
76
    RCONbits.IPEN = 1;          //Interrupts können Prioritäten haben
77
    INTCONbits.GIE_GIEH = 1;     //Interrupts können hohe P. haben
78
    INTCONbits.PEIE = 1;  //Peripheral Interrupts enablen
79
80
                                //Timer0 Konfig
81
    INTCONbits.TMR0IE = 1;      //Timer0 erzeugt bei Überlauf Int....
82
    INTCON2bits.TMR0IP = 1;     //...und zwar mit hoher Prio.
83
    INTCONbits.TMR0IF = 0;  //Interruptflag zurücksetzen
84
    T0CON = 0b00000101;
85
    TMR0H = 0x00;               //16 / 4 = 5MHz / 64 = 78125 / 65536 = 1.2
86
    TMR0L = 0x00;
87
88
89
    /*T0CONbits.T08BIT = 1;       //Timer0 8-bit Modus
90
    T0CONbits.T0PS = 0;         //Prescaler benutzen
91
    T0CONbits.T0PS0 = 1;        //1:256
92
    T0CONbits.T0PS1 = 1;        //16MHz / 4 = 5MHz / 256 = 19531 / (256 - 30)
93
    T0CONbits.T0PS2 = 1;        // = 69 mal pro Sekunde ein Überlauf
94
    T0CONbits.T0CS = 0;         //interner Clock*/
95
96
    T0CONbits.TMR0ON = 1;
97
98
    while(1){ }
99
100
}
101
102
void led_an() {
103
    LED = 1;
104
}
105
106
void led_aus() {
107
    LED = 0;
108
}

Danke :)

von Sebastian H. (technik_freak)


Lesenswert?

Hallo,

Wie ist deine Controller-Konfiguration(Quarz, ...)?
Es kann sein, dass z.B die falsche Taktquelle angegeben ist und dadurch 
nichts passiert(die Config.h ist keine PräPro-Headerdatei =>Stammt diese 
Datei von Dir/aus einer Vorlage? Ist in dieser Datei das 
Konfigurationswort, dann wäre es sinnvoll, diese Datei auch hochzuladen)

von Lena R. (eny)


Lesenswert?

Externer Quarz 16MHz.

Problem ist, ich habe Beispiele für Interrupts, die ohne weiteres 
funktionieren und im Grunde genauso sind von der Syntax.
Hatte das ja so übernommen mehr oder weniger.

Trotzdem nochmal die config.h Datei aus einer Vorlage/Beispiel Programm 
zu Interrupts:
1
//Konfigurationsbits für PIC18F23K22
2
3
__CONFIG(1, FOSC_HSHP & PLLCFG_OFF & PRICLKEN_ON & FCMEN_OFF & IESO_OFF);
4
__CONFIG(2, PWRTEN_ON & BOREN_SBORDIS & BORV_190 & WDTEN_SWON & WDTPS_512);
5
__CONFIG(3, CCP2MX_PORTB3 & CCP3MX_PORTB5 & HFOFST_OFF & T3CMX_PORTB5 & P2BMX_PORTC0 & MCLRE_EXTMCLR);
6
__CONFIG(4, STVREN_ON & LVP_OFF & XINST_OFF & DEBUG_OFF);
7
__CONFIG(5, CP0_OFF & CP1_OFF & CPB_OFF & CPD_OFF);
8
__CONFIG(6, WRT0_OFF & WRT1_OFF & WRTC_OFF & WRTB_OFF & WRTD_OFF);
9
__CONFIG(7, EBTR0_OFF & EBTR1_OFF & EBTRB_OFF);

von Sebastian H. (technik_freak)


Lesenswert?

Wenn ich es richtig sehe, ist der Watchdog eingeschaltet. Dieser wird 
aber nicht zurückgesetzt, wodurch es einen Reset gibt. Schalte diesen 
lieber aus und versuche einmal, entweder via Debugger zu Prüfen, ob der 
PIC festhängt/stoppt oder lasse eine weitere LED innerhalb der While(1) 
blinken(zum Test mit Delays)

von Lena R. (eny)


Lesenswert?

Ok, vielleicht einen Schritt weiter :)

Wenn ich mit delay eine LED blinken lassen will und T0CONbits.TMR0ON = 1 
setze, blinkt sie einmal, dann nicht mehr.

Setze ich T0CONbits.TMR0ON = 0 dann blinkt die LED ordnungsmäßig ;)


Größeres Problem aber, ich muss die Funktion void interrupt 
isr_high(void) auskommentieren, sonst passiert rein garnichts.

Hab auch keinen Programmer, sondern lade alles über einen Bootloader.
Daran sehe ich immer ob ein Programm auf dem PIC läuft oder nicht.
Wenn die obengenannte Funktion auskommentiert ist, läuft das Programm, 
sonst nicht.

von Sebastian H. (technik_freak)


Lesenswert?

http://www.sprut.de/electronic/pic/c/pic_c/pic_c90_pic_spezifisches.html 
=>Interrupts

Es scheint, als ob der Compiler nicht weiß, wo dieser High oder 
Low-Vector ist. Versuche einmal, die Adresse mit anzugeben also #pragma 
code _HIGH_INTERRUPT_VECTOR = 0x000008

von Lena R. (eny)


Lesenswert?

Leider keine Änderung, hatte ich gestern aber auch schon versucht.

Was mich noch wundert, wenn ich den Simulator starte, sagt er:
Single breakpoint: @0x1F98

Nur habe ich keine Ahnung wo das Programm in dem Moment ist, da er mir 
den Program Counter nicht anzeigt, sprich keinen grünen Pfeil...
Was aber im Grunde ja das gleich Verhalten ist, als wenn der PIC das 
Programm ausführt, nämlich nix ;)

von Sebastian H. (technik_freak)


Lesenswert?

Versteht XC8 #asm?

Ich kenne es, wie im Beispiel von Sprut und funktioniert bei C18
1
_asm
2
      goto interruptcode
3
_endasm

von holger (Gast)


Lesenswert?

>Hab auch keinen Programmer, sondern lade alles über einen Bootloader.

Und wo im Flash liegt dieser Bootloader?
Aus meinen alten Tagen mit PIC18 und Bootloader weiss ich
noch das das zu ladende Programm speziell angepasst werden musste.
Der Resetvektor und die Interruptvektoren mussten hinter den Bootloader
gelegt werden.

extern void _startup (void);        // See c018i.c in your C18 compiler 
dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
    _asm goto _startup _endasm
}
#pragma code

void main(void)
{
....
}

#pragma code high_vector=0x0808
void interrupt_at_high_vector(void)
{
    _asm goto high_isr _endasm
}
#pragma code

Und dann musste auch noch das Linkeer Script an den Bootloader
angepasst werden.

CODEPAGE   NAME=boot       START=0x0            END=0x7FF 
PROTECTED
CODEPAGE   NAME=vectors    START=0x800          END=0x0x829 
PROTECTED
CODEPAGE   NAME=page       START=0x82A          END=0x7FFF

Ob das bei den PIC18 heute auch noch so ist weiss ich nicht.
Es war jedenfalls immer ne Menge Arbeit ein Programm zu schreiben
das man über einen Bootloader laden kann.

von Lena R. (eny)


Lesenswert?

Wie gesagt, ich hab so ein Beispielprogramm aus einem Lernpaket, welches 
mit Interrupts arbeitet, welches auch tadellos funktioniert.

_asm versteht xc8 nicht, #asm ist für den Compiler richtig.

Aber da sind wir auch schon beim nächsten Problem, hab mir mal den 
Output beim compilen genauer angeschaut:

newmain.c:32 warning: unknown pragma "code"
newmain.c:39 warning: unknown pragma "code"
newmain.c:42 warning: unknown pragma "interrupt"
newmain.c:59 warning: unknown pragma "code"

Habe jetzt auch mal den PICC18 Compiler probiert und auch den C18.
C18 kommt irgendwie mit den Headerdateien nicht zurecht, muss mich da 
erstmal einlesen.
XC8 und PICC18 liefern die oben genannten Warnings.

von Lena R. (eny)


Lesenswert?

Also alles rumprobieren nützt irgendwie nichts.

Sobald eine Funktion als void interrupt deklariert ist, geht nix mehr.
Außer in dem Beispiel Programm, wo ich nicht weiß, ob ich das hier 
einfach so posten darf.

von Gusti (Gast)


Lesenswert?

Das Problem ist, dass der Code von Sprut.de mit dem C18 Compiler 
funktioniert. Der XC8 Compiler ist der neue. Es wurde vieles geändert. 
Ich habe versuchsweise auch mal den XC8 verwendet. Da verglichen mit dem 
C18 zu viel anders ist wie z.B. auch die Interruptroutine (hatte die 
selben Probleme mit der ISR) habe ich den XC8 Compiler wieder 
deinstaliert und verwende nach wie vor den C18.
Den kannst du auch mit MPLAB X verwenden.

von Michael S. (rbs_phoenix)


Lesenswert?

Gusti schrieb:
> Da verglichen mit dem
> C18 zu viel anders ist wie z.B. auch die Interruptroutine (hatte die
> selben Probleme mit der ISR) habe ich den XC8 Compiler wieder
> deinstaliert und verwende nach wie vor den C18.

Das hab ich mir auch zuerst gedacht. Dann aber hab ich mir vorgenommen 
eben genau diese Unterschiede zu erkennen und zu lernen, da der XC8 eben 
der aktuellste und demnach auch der Comiler ist, der am ehesten gewartet 
wird.

Ich hab mich bei einem USB-Projekt auch ein bisschen mit den 
Unterschieden beschäftigen müssen, so kennt der XC8 z.B. den Bezeichner 
"ROM" nicht mehr. Eine Konstante wird automatsich in den ROM gelegt, 
daher auch kein extra Bezeichner mehr.. Interrupts sehen dann z.B. so 
aus:
1
void interrupt high_priority HighPriorityISRCode(){
2
    //Check which interrupt flag caused the interrupt.
3
    //Service the interrupt
4
    //Clear the interrupt flag
5
    //Etc.
6
    USBDeviceTasks();
7
}
8
9
void interrupt low_priority LowPriorityISRCode(){
10
    if(TMR3IF == 1){
11
        TMR3IF = 0;
12
        TMR3H = 0x3C;  // Startwert für 100ms Interrupt
13
        TMR3L = 0xB0;
14
        // ....
15
    }
16
}

Da diese ISR so kurz sind, habe ich auch glatt das goto ... Weggelassen.

In deinem Fall wäre halt in der high_priority isr den Code, den du 
willst. Ich hab allerdings auch keinen Bootloader, weshalb ich auch 
keine neuen Vector-Adressen festlegen muss.

von Gusti (Gast)


Lesenswert?

Hast du irgendwelche Quellen, wo ich die Unterschiede nachlesen kann?

von Chris B. (dekatz)


Lesenswert?

Michael Skropski schrieb:
> habe ich auch glatt das goto ... Weggelassen.

Ja, ist auch unnötig.
Beim XC8 (aktuell ist 1.20) gibt es diese Krücke mit Inlineassembler und 
dem GOTO xxxxx nicht mehr.
Siehe auch MPLAB XC8 Compiler Guide 5.9 Interrupts.

von Lena R. (eny)


Lesenswert?

Wenn ich einfach die Funktion aus dem XC PDF ins Programm mache, 
passiert der gleiche Fehler.
1
void interrupt tc_int(void)
2
{
3
if (TMR0IE && TMR0IF) {
4
    TMR0IF=0;
5
    ++tick_count;
6
    return;
7
    }
8
// process other interrupt sources here, if required
9
}

Glaube auch langsam, dass das mit dem Bootloader zusammenhängt.

Nur das Beispielsprogramm funktioniert ja, aber da wird ein high 
interrupt mit einem Taster ausgelöst und ein low interrupt mit dem 
Timer.
Könnte es damit zusammenhängen?

von Michael S. (rbs_phoenix)


Lesenswert?

du kannst ja mal den Code vom Beispiel posten. Dann kann man gucken ob 
und wie der Vector verschoben wurde.

von Lena R. (eny)


Lesenswert?

1
//**************************************************************
2
// Beschreibung:   Das Programm merkt sich wieviel Zeit zwischen
3
//            zwei Tastendrücken vergangen ist und schaltet
4
//            in diesem Interval eine LED (Scheibenwischer)
5
//            ein und aus.
6
//            Nach einem Tastendruck wird ein Interrupt mit
7
//            hoher Priorität generiert. Der parallel
8
//            laufende Timer erzeugt Interrupts mit
9
//            niedriger Priorität.
10
//
11
//  Anmerkung:    Beim Debuggen mit einem Debugger (z.B. ICD2/3)
12
//            muss der Codeoffset auf 0 gestellt sein, da
13
//            sonst die Interruptroutinen nicht an der
14
//            richtigen Stelle stehen.
15
//
16
//**************************************************************
17
//
18
//    Dateiname:        Scheibenwischer.c
19
//    Datum:            01.05.2011
20
//    Version:          V1.0
21
//
22
//    Autor:            Michael Hofmann
23
//    Internet:         www.edmh.de
24
//    e-mail:           info@edmh.de
25
//
26
//**************************************************************
27
28
29
/** I N C L U D E S *******************************************/
30
#include <htc.h>
31
#include <p18f23k22.h>
32
#include "Config.h"      //Konfigurationsbits
33
34
/** D E F I N E S *********************************************/
35
#define TASTER   PORTBbits.RB0  //Taster liegt an Port B RB0
36
#define LED      LATAbits.LATA4  //LED liegt an Port A RA4
37
38
#define WISCHEN  LATAbits.LATA0  //Scheibenwischer
39
#define MAX_TIME  100        //maximales Interval
40
                      //10s = 100*100ms
41
42
//Zustände für die Statemachine
43
#define STOP      0
44
#define WIPE      1
45
#define RECORD_START  2
46
#define RECORD_END  3
47
48
/** P R O T O T Y P E S ***************************************/
49
void interrupt isr_high(void);
50
void interrupt low_priority isr_low(void);
51
void delay( int ms );
52
void delayInt( int ms100 );
53
void initTimer0( void );
54
void restartTimer0( void );
55
void stopTimer0( void );
56
57
/** V A R I A B L E N *****************************************/
58
char state=STOP;
59
int timeInterval=0;
60
61
/** I N T E R R U P T S ***************************************/
62
void interrupt isr_high(void) {
63
64
  INTCONbits.INT0IF = 0;  //Interruptflag zurücksetzen
65
  INTCONbits.INT0IE = 0;  //Interrupt vorrübergehend disablen
66
                  //damit das Prellen des Tasters keine
67
                  //neuen Interrupts ausführt
68
  switch( state ) {
69
  case STOP:
70
    state = RECORD_START;  //Nächster Zustand RECORD_START
71
    break;
72
  case WIPE:
73
    state = RECORD_START;  //Nächster Zustand RECORD_START
74
    break;
75
  case RECORD_START:
76
    state = RECORD_END;  //Nächster Zustand ist RECORD_END
77
    break;
78
  case RECORD_END:
79
    state = WIPE;      //Nächster Zustand ist WIPE
80
    break;
81
  default:
82
    break;  
83
  }
84
  return;
85
}
86
87
void interrupt low_priority isr_low(void) {
88
  
89
  INTCONbits.TMR0IF = 0;  //Interruptflag zurücksetzen
90
  timeInterval++;
91
  if( timeInterval >= MAX_TIME ) {
92
    //Maximales Interval wurde überschritten, es soll nicht
93
    //mehr gewischt werden
94
    timeInterval = 0;
95
    state = STOP;
96
    stopTimer0();
97
    INTCONbits.INT0IF = 0;  //Interruptflag zurücksetzen
98
    INTCONbits.INT0IE = 1;  //Taster-Interrupt freischalten
99
  } else {
100
    LATAbits.LATA1 = 1;    //Für Debugzwecke. Ausgang ist
101
                    //High, wenn der Timer läuft
102
    restartTimer0();
103
  }
104
  return;
105
}
106
107
/** H A U P T P R O G R A M M *********************************/
108
void main(void)
109
{
110
  char wiped=0;
111
  
112
  //Port A
113
  LATA = 0x00;
114
  TRISA = 0x00;    //Alle Pins von Port A sind Ausgänge
115
  ANSELA = 0x00;    //Alle Pins von Port A sind digitale I/O's
116
  //Port B
117
  LATB = 0x00;
118
  TRISB = 0xFF;    //Alle Pins von Port B sind Eingänge    
119
  ANSELB = 0x00;    //Alle Pins von Port A sind digitale I/O's
120
  //Port C
121
  LATC = 0x00;
122
  TRISC = 0xF0;    //RC0..RC3 = Ausgänge, RC4..RC7 = Eingänge
123
  ANSELC = 0x30;    //nur RC4 und RC5 sind analoge Eingänge
124
  
125
  //Es soll ein Interrupt ausgelöst werden, wenn der Taster
126
  //gedrückt wurde.
127
  INTCON2bits.INTEDG0 = 0;//Interrupt bei der fallenden Flanke
128
  INTCONbits.INT0IF = 0;  //Interruptflag zurücksetzen
129
  INTCONbits.INT0IE = 1;  //externen Interrupt enablen
130
  INTCONbits.GIE = 1;    //globale Interrupts enablen
131
  
132
  initTimer0();
133
  state = STOP;
134
  timeInterval = 0;  //Interval auf den Startzustand setzen
135
  
136
  while(1) {          //Hauptschleife
137
    switch( state ) {
138
    case STOP:
139
      LATCbits.LATC0 = 1;  //Für Debugzwecke, damit man
140
      LATCbits.LATC1 = 0;  //erkennt in welchem Zustand sich
141
      LATCbits.LATC2 = 0;  //das Programm befindet
142
      wiped = 0;
143
      WISCHEN = 0;
144
      break;
145
    case WIPE:
146
      LATCbits.LATC0 = 0;  //Für Debugzwecke, damit man
147
      LATCbits.LATC1 = 1;  //erkennt in welchem Zustand sich
148
      LATCbits.LATC2 = 0;  //das Programm befindet
149
      wiped = 0;
150
      stopTimer0();
151
      WISCHEN = 1;
152
      delay( 500 );        //Wischer für 0,5 s an
153
      WISCHEN = 0;
154
      INTCONbits.INT0IF = 0;  //Interruptflag zurücksetzen
155
      INTCONbits.INT0IE = 1;  //Taster-Interrupt freischalten
156
      delayInt( timeInterval );  //Interval zwischen zwei
157
                        //Wischzyklen
158
      break;
159
    case RECORD_START:
160
      LATCbits.LATC0 = 0;  //Für Debugzwecke, damit man
161
      LATCbits.LATC1 = 0;  //erkennt in welchem Zustand sich
162
      LATCbits.LATC2 = 1;  //das Programm befindet
163
      delay( 100 );          //Tasterentprellung
164
      while( TASTER == 0 );    //Warten, bis der Taster
165
                        //wieder losgelassen wurde
166
      //Nur Einmal wischen
167
      if( wiped == 0 ) {
168
        WISCHEN = 1;
169
        delay( 500 );        //Wischer für 0,5 s an
170
        WISCHEN = 0;
171
        wiped = 1;
172
        timeInterval = 0;  //Interval auf Startzustand setzen
173
        restartTimer0();
174
      } else {
175
        delay( 100 );
176
      }
177
      INTCONbits.INT0IF = 0;  //Interruptflag zurücksetzen
178
      INTCONbits.INT0IE = 1;  //Taster-Interrupt freischalten
179
      break;
180
    case RECORD_END:
181
      LATCbits.LATC0 = 1;  //Für Debugzwecke, damit man
182
      LATCbits.LATC1 = 1;  //erkennt in welchem Zustand sich
183
      LATCbits.LATC2 = 1;  //das Programm befindet
184
      stopTimer0();
185
      delay( 100 );          //Tasterentprellung
186
      while( TASTER == 0 );    //Warten, bis der Taster
187
                        //wieder losgelassen wurde
188
      state = WIPE;
189
      break;
190
    default:
191
      break;  
192
    }
193
  }
194
}
195
196
void delay( int ms ) {
197
  int i=0;
198
  //1 ms = 4000 Befehlstakte (16 MHz Quarz / 4)
199
  for( i=0; i<ms; i++ ) {
200
    _delay(4000);          //Verzögerung von 1ms
201
  }
202
}
203
204
void delayInt( int ms100 ) {
205
  int i=0, j=0;
206
  //1 ms = 4000 Befehlstakte (16 MHz Quarz / 4)
207
  for( i=0; i<ms100; i++ ) {
208
    for( j=0; j<100; j++ ) {  //Schleife dauert 100ms
209
      _delay(4000);        //Verzögerung von 1ms
210
    }
211
    if( state == RECORD_START ) {
212
      //Die Verzögerung soll abgebrochen werden, wenn ein
213
      //neuer Zyklus generiert wird.
214
      return;
215
    }
216
  }
217
}
218
219
//Initialisiert den Timer 0 für einen 100ms-Takt
220
void initTimer0( void ) {
221
  //Timer 0 ist ein 16-bit-Timer
222
  //Prescaler = 1:128
223
  T0CON = 0b00000110;
224
  TMR0H = 0x00;
225
  TMR0L = 0x00;
226
  INTCONbits.TMR0IF = 0;  //Interruptflag zurücksetzen
227
  INTCON2bits.TMR0IP = 0;  //niedrige Priorität
228
  INTCONbits.TMR0IE = 1;  //Interrupt für Timer 0 enablen
229
  RCONbits.IPEN = 1;
230
  INTCONbits.PEIE = 1;    //Peripheral Interrupts enablen
231
  return;  
232
}
233
234
//Startet den Timer neu
235
void restartTimer0( void ) {
236
  //mit einem Prescaler von 1:128 ensteht nach 100ms
237
  //ein Überlauf (4 MHz / 128 = 31250 Hz)
238
  T0CON = 0b00000110;
239
  INTCONbits.TMR0IF = 0;  //Interruptflag zurücksetzen
240
  INTCON2bits.TMR0IP = 0;  //niedrige Priorität
241
  //Timer Wert für 100ms = 65535 - 3125 = 62410 = 0xF3CA
242
  TMR0H = 0xF3;        //Das Highbyte muss zuerst
243
                  //geschrieben werden.
244
  TMR0L = 0xCA;        //Wenn das Lowbyte geschrieben wird,
245
                  //wird das Highbyte aktuallisiert.
246
                  //Dadurch wird es ermöglicht alle
247
                  //16 bit auf einmal zu beschreiben
248
                  //TMR0 = 0xF3CA; funktioniert an
249
                  //Stelle nicht, da zuerst das
250
                  //Lowbyte und dann das Highbyte
251
                  //geschrieben wird.
252
  INTCONbits.TMR0IE = 1;  //Interrupt für Timer 0 enablen
253
  RCONbits.IPEN = 1;    //Interrupts mit niedriger Priorität
254
  INTCONbits.PEIE = 1;    //Peripheral Interrupts enablen
255
256
  T0CONbits.TMR0ON = 1;  //Timer starten
257
  return;
258
}
259
260
//Stoppt den Timer
261
void stopTimer0( void ) {
262
  LATAbits.LATA1 = 0;
263
  T0CON = 0b00000110;    //Timer ausschalten
264
  TMR0H = 0x00;
265
  TMR0L = 0x00;
266
  INTCONbits.TMR0IF = 0;  //Interruptflag zurücksetzen
267
  INTCONbits.TMR0IE = 0;  //Interrupt für Timer 0 disablen
268
  return;
269
}

Die config.h hab ich von dem Beispiel übernommen.

von Jürgen S. (Firma: privat) (jschmied)


Lesenswert?

Du musst dem Compiler sicher sagen, wohin er die isr packen soll.

Der Bootloader muss die Standardaufrufe für isr_low und isr_high an eine 
bestimmte Adresse weiterleiten. An der Stelle der Orginal-ISR im 
Bootloader ist daher ein goto-Befehl.

Du musst nun herausbekommen, an welche Adresse diese goto gehen. Genau 
dort hin packst Du dann deine ISR. Wenn z.B. der USB-Loader von 
Microchip genutzt wird, 0x408 / 0x418. Mit dem C18 Compiler mache ichs 
wie folgt:

#ifdef BOOTLOADER
  // See AN1310 Example 3
  #pragma romdata BootloaderProgramMemorySpace = 0x6
  const rom char bootloaderProgramMemorySpace[0x400 - 0x6];
  extern void _startup(void);

  #pragma code AppVector = 0x400
  void AppVector(void){ _asm GOTO _startup _endasm }

  #pragma code AppHighIntVector = 0x408
  void AppHighIntVector(void) { _asm GOTO high_isr _endasm }

  #pragma code AppLowIntVector = 0x418
  void low_vector(void) { _asm GOTO low_isr _endasm }
#else
  #pragma code high_vector=0x08
  void interrupt_at_high_vector(void) { _asm GOTO high_isr _endasm }

  #pragma code low_vector=0x18
  void interrupt_at_low_vector(void) { _asm GOTO low_isr _endasm }
#endif

vg

Jürgen

von Erich (Gast)


Lesenswert?


von Lena R. (eny)


Lesenswert?

Danke für die ausführliche Antwort, werde mal versuchen das umzusetzen.

Nur muss ich für den C18 Compiler die config.h umschreiben, __config(..) 
versteht der nicht. Also erstmal wieder einlesen. Aber man lernt ja 
dabei ;)

Trotzdem frag ich mich, warum das Beispiel Programm funktioniert, sollte 
es wirklich am Bootloader liegen!?

@Erich: Die Links sind schon alle lila, das heisst die habe ich schon 
alle durch, trotzdem Danke :)

von Michael S. (rbs_phoenix)


Lesenswert?

Hm. Und der Code funktioniert? Mit Bootloader? Dann dürfte es ja nicht 
an der Adresse liegen (was ich geschätzt hätte, dass der Platz vom 
Bootloader genutzt wird)..

von Chris B. (dekatz)


Lesenswert?

Wenn dieses funkteonierende! Beispiel ohne bootloaderspezifische 
Anpassungen auskommt, dann liegt die "Lösung" wahrscheinlich in einem 
angepassten Linkerskript.
Dazu müsste man aber wissen was in dem Ordern mit dem funkteonierenden 
Beispiel noch für Dateien liegen bzw. welche Dateien bei der 
Projekteinstellung alles angegeben sind - sonst wird das noch 'n großes 
Ratespiel.

von Lena R. (eny)


Lesenswert?

Chris, ich glaub wir kommen langsam der Sache auf die Spur :)

Ich hab jetzt ein neues Projekt angelegt und einfach den Inhalt der 
beispiel.c eingefügt als neue Datei und die config.h mit eingebunden.

Siehe da, der PIC macht nix.

Also ist tatsächlich irgendwas bei dem beispiel.hex noch anders.
Ich mach mich mal auf die Suche.
Danke :)

von Jürgen S. (Firma: privat) (jschmied)


Lesenswert?

Schau Dir mal AN1310 an. Seite 10-14.

http://ww1.microchip.com/downloads/en/AppNotes/01310a.pdf

von Jürgen S. (Firma: privat) (jschmied)


Lesenswert?


von Lena R. (eny)


Lesenswert?

Es geht...
Code Offset auf 400 und fertig.
Kann man ja nicht glauben :D

Man war das ne schwere Geburt!

Nur die LED blinkt viel zu schnell, aber da guck ich mal, wird irgendwo 
im Programm was sein. Das ist jetzt das kleinere Problem ^^

Danke an alle fürs Helfen, ich hab richtig viel gelernt dabei, auch 
wenns teilweise ganz schön frustrierend war, häng da schon länger 
dran...

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.