Forum: Mikrocontroller und Digitale Elektronik PIC18F4550 oscillator Initialisieren


von Hans (Gast)



Lesenswert?

Hallo zusammen,

PIC: PIC18F45550
Treiber: C18
Tools: MPLAB IDE 8.92

Problembeschreibung:
Wie kann ich wissen was für eine internal Oscillator hat das PIC nach 
der folgende Konfiguration?

Das Pic ist wie folgenden konfiguriert:

  #pragma config PLLDIV   = 3
  #pragma config CPUDIV   = OSC1_PLL2
  #pragma config USBDIV = 2
  #pragma config FOSC     = HSPLL_HS

  Laut das Configuration Setting bedeuten diesen Einstellungen (Seh 
bitte Anhang): (Microchip MPLAB IDE_Configuration Setting_PIC18F4450)

In der Clock Diagram (in der Datenblatt: Fig 2-1)ist noch einmal alles 
geklärt.
Seh bitte Anhang ( PIC18F4550_Datenblatt_ClockDiagram)


Ich bin leider dadurch nich schlauer geworden: Mit welchen Frequnenz 
soll ich das OSCI einstellen.



Danke

von Little B. (lil-b)


Lesenswert?

Wenn ich das richtig interpretiere, taktet die CPU und die Peripherals 
mit 48MHz beim POR.

Wenn dir das so recht ist, brauchst du nichts mehr an den Registern 
ändern

von Hans (Gast)


Lesenswert?

Little Basdart schrieb:
> Wenn ich das richtig interpretiere, taktet die CPU und die Peripherals
> mit 48MHz beim POR.

eben nicht weil:

OSC2 und OSC1 (seh bitte Anhang : " PIC18F4550_Datenblatt_ClockDiagram" 
)Anschlüsse sind mit einem Osci (12MHZ) verbunden.
Diese ist wieder durch 3 dividiert (#pragma config PLLDIV   = 3 )
Ist das so richtig?

von Little B. (lil-b)


Lesenswert?

ja, das ist so weit richtig.

Das muss so sein, weil die PLL nur 4MHz als Input erlaubt. Heraus kommt 
dann 96MHz, die mit dem PLL_Postscaler durch 2 geteilt werden und auf 
die CPU und Peripherals gegeben werden.

von Toxic (Gast)


Angehängte Dateien:

Lesenswert?

Wenn ich die Konfigurationseinstellungen richtig interpretiere,muesste 
der SystemClock nach einem POR tatsaechlich bei 48MHz liegen.
siehe Anhang

von Hans (Gast)


Lesenswert?

Little Basdart schrieb:
> Das muss so sein, weil die PLL nur 4MHz als Input erlaubt. Heraus kommt
> dann 96MHz, die mit dem PLL_Postscaler durch 2 geteilt werden und auf
> die CPU und Peripherals gegeben werden.
@Danke
Toxic schrieb:
> Wenn ich die Konfigurationseinstellungen richtig
> interpretiere,muesste
> der SystemClock nach einem POR tatsaechlich bei 48MHz liegen.
> siehe Anhang
@Danke

Dazu habe ich folgenden:

Ich möchte einen Timer1 Interrupt einbauen.

Als erste habe ich den Timer1 initialisert:
1
void InitTimer1()
2
{
3
   T1CONbits.RD16 = 1;                  /*   timer1 is a 16-bit timer                                    */
4
    TMR1H = 0;                               /*   clear timer                                                     */
5
    TMR1L = 0;                               /*   clear timer                                                     */
6
  T1CONbits.TMR1ON = 0;                /*   Timer1 OFF                                               */
7
    PIE1bits.TMR1IE = 1;                     /*   enable interupt on timer1                                */
8
  PIR1bits.TMR1IF = 0;                     /*   Enable Timer1 Overflow interrupt                    */
9
  IPR1bits.TMR1IP = 1;                     /*   set Timer1 overflow interrupt to HIGH priority   */
10
  T1CONbits.TMR1CS = 0;                /*   user internal clock to increment Timer1           */
11
  //Prescaler
12
  T1CONbits.T1CKPS1 = 0;              /*    Prescaler 1:1                                  */
13
    T1CONbits.T1CKPS0 = 0;
14
    INTCONbits.GIE = 1;                /*   Enable global interrupts                        */  
15
16
}

Das heisst:
Internal Instruction Cycle = 1/[ 48MHZ/4 ] = 8.33 ns
TMR1 ist ein 16-Bit Register

Bis einen TimerOverflow gibt ist t(die nötige Zeit bist einen Overflow ) 
= 8.33 ns *  65536 = 0.0054 s.


Ist das so richtig?


dann überprüfe ich ob der Flag TMR1IF gesetzt und zwar wie folgenden:
Wenn es einen Timeroverflow springt das Prog direkt in der ISR Routine,
die so implementiert ist:
1
void ISRPriorityCode()
2
{
3
  if(PIR1bits.TMR1IF)
4
  {
5
       PIR1bits.TMR1IF = 0;          /*  clear interrupt flag       */
6
       Timer1Flag.Bit.Timeout = 1;        /*  indicate Timeout           */
7
  //Message
8
  // TODO   MessageTimerOverflow();
9
10
  }
11
}

von Little B. (lil-b)


Lesenswert?

Sieht soweit richtig aus.

Aber beachte bei den Interrupts:
- Wenn du Interrupt Priorities nutzen willst, musst du noch RCON.IPEN = 
1 setzen
- Wenn du keine Interrupt Priorities nutzen willst, musst du noch 
INTCON.PEIE = 1 setzen

sonst wird der Interrupt nicht ausgelöst

von Toxic (Gast)


Lesenswert?

Hans schrieb:
> Internal Instruction Cycle = 1/[ 48MHZ/4 ] = 8.33 ns

1/[ 48MHZ/4 ] = 83.3ns

=================================

Hans schrieb:
> Bis einen TimerOverflow gibt ist t(die nötige Zeit bist einen Overflow )
> = 8.33 ns *  65536 = 0.0054 s.

83.3ns * 65536 = 5.46ms

Irgendwie verhaust Du dich (oder ich) hier und da mit den 10er-Potenzen

von Hans (Gast)


Lesenswert?

Toxic schrieb:
> Irgendwie verhaust Du dich (oder ich) hier und da mit den 10er-Potenzen

Ja Das stimmt

:-)

Danke

von Hans (Gast)


Lesenswert?

Eine Frage habe ich noch:


Wenn es einen Timeroverflow geschieht, springt das Prog direkt in der 
ISR Methode.

und von dort an muss ich die HandlingsRoutine aufrufen die irgendwas 
macht.
zB:
1
void YourHighPriorityISRCode()
2
{
3
  if(PIR1bits.TMR1IF)
4
  {
5
      PIR1bits.TMR1IF = 0;                  /*  clear interrupt flag         */
6
      Timer1Flag.Bit.Timeout = 1;         /*  indicate Timeout           */
7
      //Message
8
         //MessageTimerOverflow();     
9
  
10
  }
11
}
Ist mein Vorgehen richtig?

von Volker S. (vloki)


Lesenswert?

Hans schrieb:
> Eine Frage habe ich noch:
> Wenn es einen Timeroverflow geschieht, springt das Prog direkt in der
> ISR Methode.
Ja


> und von dort an muss ich die HandlingsRoutine aufrufen die irgendwas
> macht.
> zB:
>
>
1
> void YourHighPriorityISRCode()
2
> {
3
>   ...
4
>
Ja


> Ist mein Vorgehen richtig?
Das was du gepostet hast ist zumindest nicht falsch.
Es fehlt aber noch einiges das du aber vielleicht einfach nur nicht 
gepostet hast ;-)

Ist der Interrupthandler als solcher markiert ?
(#pragma interrupt YourHighPriorytyISRCode)

Sind Sprünge an den Vektoren angelegt ?
1
/** I N T E R R U P T  V E C T O R S ******************************************/
2
#pragma code high_vector=0x08
3
void interrupt_at_high_vector(void)
4
{
5
    _asm goto YourHighPriorytyISRCode _endasm
6
}
7
8
#pragma code low_vector=0x18
9
void interrupt_at_low_vector(void)
10
{
11
    _asm goto low_isr _endasm
12
}
13
#pragma code

Wenn generelle Anfänger-Probleme bestehen, dann kannst du auch mal in 
dieses Skript
*uC_quick-X.pdf* -> 5.1 Timer_0 Interrupt (Blink Variante 3)
hier an der rechten Seite schauen -> http://www.hs-ulm.de/schilling

: Bearbeitet durch User
von Little B. (lil-b)


Lesenswert?

wenn du den xc8-compiler verwendest, reicht das "interrupt" keyword:
1
void interrupt YourHighPriorityISRCode() {
2
   ...
3
}
4
5
void interrupt low_priority interrupt_at_low_vector(void) {
6
   ...
7
}

Aber Achtung!
Aus der ISR sollte nicht via return herausgesprungen werden. Ältere 
compiler haben damit probleme, da diese dann [asm]ret[/asm] verwenden 
anstatt [asm]retfie[/asm]

(siehe dazu instruction set summary deines Datenblatts)

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Little Basdart schrieb:
> wenn du den xc8-compiler verwendest, reicht das "interrupt" keyword:

Äh, ja sorry. Vieleicht war meine Annahme C18 Compiler gar nicht richtig 
...
(aus original Post -> Treiber: C18)

Für neuere Projekte die mit C18 und XC8 verwendbar sein sollen verwende 
ich folgenden Code (den man leider nicht mehr versteht)
1
/** I N T E R R U P T  V E C T O R S ************* C18 compiler only **********/
2
3
#ifndef __XC8        // not XC8 compiler -->> C18 compiler
4
5
    #pragma interrupt high_isr
6
    #define interrupt                           // remove keyword
7
    #pragma code high_vector=0x08
8
9
    #ifdef USE_IR_PRIORITIES
10
        void interrupt_at_high_vector(void)
11
        {
12
          _asm goto high_isr _endasm
13
        }
14
        #define low_priority                    // remove keyword
15
        #pragma interruptlow low_isr
16
        #pragma code low_vector=0x18
17
        void interrupt_at_low_vector(void)
18
        {
19
          _asm goto low_isr _endasm
20
        }
21
        #pragma code
22
    #endif
23
#endif
24
25
/** D E C L A R A T I O N S ***************************************************/
26
//##############################################################################
27
// Function:        void high_isr(void)
28
// PreCondition:    None
29
// Input:
30
// Output:
31
// Side Effects:
32
// Overview:
33
//##############################################################################
34
void interrupt high_isr(void)
35
{
36
    if (IRGENDEIN_IR){
37
        ...
38
        return;
39
    }
40
    if (IRGENDEINANDERER_IR){
41
        ...
42
        return;
43
    }
44
    while(1){;}                         // (detect unexpected IR sources)
45
}
46
47
//##############################################################################
48
// Function:        void low_isr(void)
49
// PreCondition:    None
50
// Input:
51
// Output:
52
// Side Effects:
53
// Overview:
54
//##############################################################################
55
#ifdef USE_IR_PRIORITIES
56
    void interrupt low_priority low_isr(void)
57
    {
58
        ...
59
        while(1){;}                         // (detect unexpected IR sources)
60
    }
61
#endif

von Volker S. (vloki)


Lesenswert?

Little Basdart schrieb:
> Aber Achtung!
> Aus der ISR sollte nicht via return herausgesprungen werden. Ältere
> compiler haben damit probleme, da diese dann [asm]ret[/asm] verwenden
> anstatt [asm]retfie[/asm]

Ups, mache ich eigentlich schon immer (sehr lange) so
und mit C18 ist noch nie ein Problem aufgetreten.

von Little B. (lil-b)


Lesenswert?

Volker SchK schrieb:
> Little Basdart schrieb:
>> Aber Achtung!
>> Aus der ISR sollte nicht via return herausgesprungen werden. Ältere
>> compiler haben damit probleme, da diese dann [asm]ret[/asm] verwenden
>> anstatt [asm]retfie[/asm]
>
> Ups, mache ich eigentlich schon immer (sehr lange) so
> und mit C18 ist noch nie ein Problem aufgetreten.

Das hat mir mein Mikrocontrollertechnik-Prof erklärt, der ist Fachmann 
für Microchip. Offenbar hat er da schon schlechte Erfahrungen gemacht. 
Gut möglich, dass die Compiler mittlerweile damit umgehen können, aber 
ich hab mir (vor allem für die kleinen Controller) angewöhnt, kein 
return zu verwenden.

von Volker S. (vloki)


Lesenswert?

Little Basdart schrieb:
> Das hat mir mein Mikrocontrollertechnik-Prof erklärt,

Ach so. Ich würde einfach mal nachschauen was der Compiler macht ;-)

von Hans (Gast)


Lesenswert?

Volker SchK schrieb:
> Ist der Interrupthandler als solcher markiert ?
> (#pragma interrupt YourHighPriorytyISRCode)
>
> Sind Sprünge an den Vektoren angelegt ?

Ja das habe ich auch so gemacht

von Volker S. (vloki)


Lesenswert?

Und funktioniert es so wie du dir das gedacht hast ?

von Hans (Gast)


Lesenswert?

Volker SchK schrieb:
> Und funktioniert es so wie du dir das gedacht hast ?

nicht ganz
Ich beschreibe kurz meine Anwendung:

Mit dem Pic versuche ich 3 Signale, die ich von einen Subsystem bekomme 
zu steueren.
Dieses 3 Signale müssen bestimmte Voraussetzungen erfüllen.
Diese Auswertung der Signale ist mit einer Pollingsverfahren realisiert 
(was es nicht unbedingt ideal aber so ist halt der IstStand)
Wenn die Signale nicht da sind oder aus irgendwie einen Grund nicht da 
sind dann schlägt das Watchdog und schaltet das Board aus.

Das Borad ist mit dem PC mittels USB verbunden.
Es wurde auch einen GUI oberfläsche (C++) entwickelt um das Borad zu 
steuern ("HID").
Die Kommunikation lauft über einen genauen vordefinierten USB protokol.

Das ist ganz Grob was die Anwendung der Pic betrifft.


Die jetzigen Überlegung ist das WDT auszuschalten und stattdessen einen 
Meldung auszugeben, wenn einen Timer1overflow gibt.


Wie gesagt Timeroverflow wird in der ISR Methode abgfragt
1
 if(PIR1bits.TMR1IF )
.
Ist der "TMR1IF" ==1 dann muss einen Message in der GUI geben, die 
besagt z.B Signal1, Signal2 oder Signal 3 nicht da ist.


--> Mir ist nur nicht ganz klar wie ich dieses Meldung zu den GUI 
weiterleite

Wie gesagt die Kommunikation mit der Board ist über einen USB 
schnittstelle.
Die Befehle werden über einen Protokoll gesendet und von der pic 
abgearbeitet.

Ich hoffe, dass ich gut geklärt habe

von Volker S. (vloki)


Lesenswert?

Hans schrieb:
> Das Borad ist mit dem PC mittels USB verbunden.
> Es wurde auch einen GUI oberfläsche (C++) entwickelt um das Borad zu
> steuern ("HID").
> Die Kommunikation lauft über einen genauen vordefinierten USB protokol.

Hans schrieb:
> --> Mir ist nur nicht ganz klar wie ich dieses Meldung zu den GUI
> weiterleite

Im "genau vordefinierten Protokoll", wird da irgendwas vom PIC zum PC 
geschickt, oder immer nur vom PC zum PIC ?

Wenn was zurückgeschickt wird, dann geht das für die neue Meldung 
genauso ...

von Hans (Gast)


Lesenswert?

Volker SchK schrieb:
> Im "genau vordefinierten Protokoll", wird da irgendwas vom PIC zum PC
> geschickt, oder immer nur vom PC zum PIC ?
@ auch von PIC zu PC

von Hans (Gast)


Lesenswert?

Hallo,

könnte mir niemenden einen Tipps geben?

Danke

von Volker S. (vloki)


Lesenswert?

Was genau ist dein Problem ?
Woher stammt dein vorgegebenes Protokoll ?

Es wird doch schon was zurückgeschickt,
warum machst du es nicht genau so ?

Vermutlich gibt es da eine ID als erstes Byte in der Nachricht oder so 
...

von Hans (Gast)


Lesenswert?

Volker S. schrieb:
> Was genau ist dein Problem ?
Mein Problem ist:
1) Wie kann ich den Timmer1Overflow (Eintritt von Interrupt) zu der GUI 
(Visual Studio) weiterleiten?
Ich habe es folgenden gemacht:
      1) Timer1 initialisiert
    2) in der ISR Routine der Flag abgefragt :
1
 if(PIR1bits.TMR1IF)
Der Timeroverflow tritt bei einen Zeitüberschreitung von 43.69 ms.
Dieses Wert wurde auch gemessen und es stimmt auch.

> Woher stammt dein vorgegebenes Protokoll ?
Das Protokoll wurde vor meine Zeit erstellt.
Es handelt sich eigentlich um Befehle bzw. Kommunikationsprotokoll.
z.B: Messung wird mit dem Befehl Nr: 26 und dieses wird in einen switch 
case ( MPLAB IDE, C18) ja nachdem was für einen Befehl ist ausgeführt.
Alle Kommunikation mit dem Board funktionieren nach dieses Muster.
Befehl schicken und auf eine Antwort warten

> Es wird doch schon was zurückgeschickt,
> warum machst du es nicht genau so ?
Das mache ich auch genau so, aber einen Interrupt abzufangen ist halt 
anders.
Man schickt keinen Timeroverflow sondern prüft, ob es geschehen ist.
Das Geschehen wird sowiso in der ISR Routine abgefangen, aber wie leite 
ich das weiter zu den GUI?

von Volker S. (vloki)


Lesenswert?

Hans schrieb:
> Alle Kommunikation mit dem Board funktionieren nach dieses Muster.
> Befehl schicken und auf eine Antwort warten

Stell dir doch für den Anfang einfach mal vor,
du schickst eine Antwort obwohl du keinen Befehl bekommen hast ...

In deinem PC Programm bekommst du dann (k)eine Antwort auf keinen 
Befehl.
Die schon bestehenden Antworten werden doch auch irgendwie ausgewertet.
(anhand einer ID oder so) Jetzt kommt einfach eine neue dazu.

von Little B. (lil-b)


Lesenswert?

Wenn du vieleicht dein Konzept überdenken willst, ich hätte da einen 
Vorschlag.

Leider Postest du ja nicht eine Zeile deines Codes, also alles was ich 
hier schreibe sind nur Annahmen, die ich mit meinen Ideen erweitere.

Da du einen timeout abfangen willst, hast du vermutlich sowas:
1
while (warte_auf_signal == 0) {
2
   // weiter warten, nichts tun
3
}

Du weißt zwar durch deinen Timer Interrupt, dass ein Timeout entstanden 
ist, jedoch muss ja auch dein Programm darauf reagieren:
1
while ( (warte_auf_signal == 0) && (Timer1Flag.Bit.Timeout == 0) ){
2
   // weiter warten, nichts tun
3
}
4
if (Timer1Flag.Bit.Timeout == 1) {
5
   MessageTimerOverflow();
6
   return;
7
}

Aber warum den Umweg über die ISR gehn? Du kannst ja auch direkt das 
Hardwareflag auswerten
1
while ( (warte_auf_signal == 0) && (PIR1bits.TMR1IF == 0) ){
2
   // weiter warten, nichts tun
3
}
4
if (PIR1bits.TMR1IF == 1) {
5
   MessageTimerOverflow();
6
   return;
7
}


Was genau in MessageTimerOverflow() gemacht wird, kann dir leider immer 
noch niemand sagen. Mach doch mal eine Arschbombe in die Protokoll-Doku 
und suche dir eine Möglichkeit, Fehlermeldungen auszugeben. Wenn es 
diese Möglichkeit nicht gibt (grober Designfehler!), dann musst du das 
Protokoll eben erweitern.

von Hans (Gast)


Lesenswert?

Folgende habe ich gemacht:
  1) einen Funktion, die mir den Timer1 initialisiert.
  Die sieht folgende aus:
1
  void InitTimer1(void)
2
  {
3
    Timer1Flag.Byte = 0;
4
    T1CONbits.RD16 = 1;                /*   timer1 is a 16-bit timer                         */
5
    TMR1H = 0;                         /*   clear timer                                      */
6
    TMR1L = 0;                         /*   clear timer                                      */
7
    T1CONbits.TMR1ON = 0;              /*   Timer1 OFF                                       */
8
    PIE1bits.TMR1IE = 1;               /*   enable interupt on timer1                        */
9
    PIR1bits.TMR1IF = 0;               /*   Enable Timer1 Overflow interrupt                 */
10
    RCONbits.IPEN  = 1;                /*   Interrupt priority is enabled                    */
11
    IPR1bits.TMR1IP = 1;               /*   set Timer1 overflow interrupt to HIGH priority   */
12
    T1CONbits.TMR1CS = 0;              /*   user internal clock to increment Timer1          */
13
    //Prescaler
14
    T1CONbits.T1CKPS1 = 1;             /*    Prescaler 1:8                                   */
15
    T1CONbits.T1CKPS0 = 1;
16
    INTCONbits.GIE = 1;                 /*   Enable global interrupts                         */   
17
                            /*   timerOverflow = ((1/[1.5MHZ])* 65536) = 43.69ms  */   
18
}

2) in der ISR Routine folgende abfrage:
1
  #pragma interrupt HighPriorityISRCode
2
  void HighPriorityISRCode()
3
  {
4
    .....
5
    if(PIR1bits.TMR1IF)                    /*  check for TMR1 overflow    */
6
    {
7
      PIR1bits.TMR1IF = 0;               /*  clear interrupt flag       */
8
      Timer1Flag.Bit.Timeout = 1;        /*  indicate Timeout           */
9
      //Message
10
      //MessageTimerOverflow();
11
    }
12
    
13
  }

Little B. schrieb:
> Aber warum den Umweg über die ISR gehn?

Wenn es einen TimerOverflow eintritt springt das Prog nicht direkt in 
die ISR Routine oder liege ich falsch?

von Little B. (lil-b)


Lesenswert?

Hans schrieb:
> Little B. schrieb:
>> Aber warum den Umweg über die ISR gehn?
>
> Wenn es einen TimerOverflow eintritt springt das Prog nicht direkt in
> die ISR Routine oder liege ich falsch?

Die ISR wird nur aufgerufen, wenn du
1
PIE1bits.TMR1IE = 1;
setzt (so wie du es gerade tust).

Wenn du das aber auf 0 lässt, wird die ISR nicht angesprungen, aber das 
Flag trotzdem gesetzt, wenn ein Overflow auftritt.

Aber das ist nur nebensächlich. Dein Hauptproblem ist gerade das 
USB-HID-Protokoll, über das du die Fehlermeldung ausgeben willst. Und 
das solltest du tunlichst nicht in der ISR machen!

von Hans (Gast)


Lesenswert?

Little B. schrieb:
> Aber das ist nur nebensächlich. Dein Hauptproblem ist gerade das
> USB-HID-Protokoll, über das du die Fehlermeldung ausgeben willst. Und
> das solltest du tunlichst nicht in der ISR machen!

Das habe ich nicht ganz verstanden was du genau meinst?

Little B. schrieb:
> Du weißt zwar durch deinen Timer Interrupt, dass ein Timeout entstanden
> ist, jedoch muss ja auch dein Programm darauf reagieren:while (
> (warte_auf_signal == 0) && (Timer1Flag.Bit.Timeout == 0) ){
>    // weiter warten, nichts tun
> }
> if (Timer1Flag.Bit.Timeout == 1) {
>    MessageTimerOverflow();
>    return;
> }
>
> Aber warum den Umweg über die ISR gehn? Du kannst ja auch direkt das
> Hardwareflag auswerten while ( (warte_auf_signal == 0) &&
> (PIR1bits.TMR1IF == 0) ){
>    // weiter warten, nichts tun
> }
> if (PIR1bits.TMR1IF == 1) {
>    MessageTimerOverflow();
>    return;
> }

Das tue ich:
1
while ( (warte_auf_signal == 0) && 
2
> (PIR1bits.TMR1IF == 0) ){
3
>    // weiter warten, nichts tun
4
> }
Das heisst die Abfrage, ob einen Timeroverflow da ist muss ich nur in 
ISR Routine überprüfen und von dort einen MessageOverflow geben richtig?

von Little B. (lil-b)


Lesenswert?

Hans schrieb:
> Das heisst die Abfrage, ob einen Timeroverflow da ist muss ich nur in
> ISR Routine überprüfen und von dort einen MessageOverflow geben richtig?

Du kannst das gerne probieren, aber ich empfehle dir, in der ISR keine 
USB-Zugriffe durchzuführen. Denn das hat das potential, sehr lange zu 
dauern oder sogar selbst einen Interrupt zu verursachen.

Du musst aber auch einen Schritt weiter denken. Was passiert, nachdem 
die Meldung rausgeschickt wurde? Was macht dein Programm? Soll es weiter 
in der Endlosschleife hängen bleiben? "Fehlerbehandlung" ist das 
Schlagwort.

Und ich sage es gern nochmals: Solang du deine Informationen nicht 
postest, kann man dir hier schlecht helfen.
Und damit meine ich nicht deine init-routine und deinen ISR-Ansatz, 
sondern das komplette projekt mit dem USB-Protokoll.
(Bevor du das postest, solltest du aber zunächst abklären, ob du diese 
Daten veröffentlichen darfst)

von Hans (Gast)


Lesenswert?

Little B. schrieb:
> Und ich sage es gern nochmals: Solang du deine Informationen nicht
> postest, kann man dir hier schlecht helfen.
> Und damit meine ich nicht deine init-routine und deinen ISR-Ansatz,
> sondern das komplette projekt mit dem USB-Protokoll.
> (Bevor du das postest, solltest du aber zunächst abklären, ob du diese
> Daten veröffentlichen darfst)

Veröffentlich das darf ich sowiso nicht.

Ich habe nachgedacht und du hast vollkommen recht.
Aus dem Grund ändere ich folgende in der Funktion InitTimer():
1
PIE1bits.TMR1IE = 0;               /*   desable interupt on timer1         */

und versuche ich was du vorgeschlagen hast zu setzen.

Aber mir ist immer noch nit ganz klar wie ich die MessageTimeroverflow 
zu der GUI weiterreiche

von Volker S. (vloki)


Lesenswert?

Hans schrieb:
> Aber mir ist immer noch nit ganz klar wie ich die MessageTimeroverflow
> zu der GUI weiterreiche

Von wo jetzt genau ?
Der ganze Weg von der Generierung der Message bis zur GUI ?

Wir können dir da nicht helfen, ohne den Code zu sehen ...
((( Wie werden die "Antworten" weitergeleitet ? )))

Kennst du das Demoprojekt aus den MLA (Microchip Libraries of 
Applications)
Läuft das bei deinem Projekt ähnlich ?

Die Verarbeitung eines Kommandos sieht etwa so aus:
1
        switch(ReceivedDataBuffer[0])        //Look at the data the host sent, to see what kind of application specific command it sent.
2
        {
3
            case COMMAND_TOGGLE_LED:  //Toggle LEDs command
4
                LED_Toggle(LED_USB_DEVICE_HID_CUSTOM);
5
                break;
6
            case COMMAND_GET_BUTTON_STATUS:  //Get push button state
7
                //Check to make sure the endpoint/buffer is free before we modify the contents
8
                if(!HIDTxHandleBusy(USBInHandle))
9
                {
10
                    ToSendDataBuffer[0] = 0x81;        //Echo back to the host PC the command we are fulfilling in the first uint8_t.  In this case, the Get Pushbutton State command.
11
                    if(BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_CUSTOM) == false)  //pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high
12
                    {
13
                            ToSendDataBuffer[1] = 0x01;
14
                    }
15
                    else                  //sw3 must be == 0, pushbutton is pressed and overpowering the pull up resistor
16
                    {
17
                            ToSendDataBuffer[1] = 0x00;
18
                    }
19
                    //Prepare the USB module to send the data packet to the host
20
                    USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0],64);
21
                }
22
                break;
Das Kommando steht im ReceivedDataBuffer[0]
Die Antwort wird in den ToSendDataBuffer geschrieben.
Wobei [0] wieder die ID der Antwort und die weiteren Bytes der Inhalt 
der Antwort sind.

Mit
USBInHandle=HIDTxPacket(CUSTOM_DEVICE_HID_EP,uint8_t*)&ToSendDataBuffer[ 
0],64);
wird der Buffer dann zum Abholen für den Host freigegeben.

von Hans (Gast)


Lesenswert?

Volker S. schrieb:
> Von wo jetzt genau ?
> Der ganze Weg von der Generierung der Message bis zur GUI ?
Ja

Volker S. schrieb:
> Läuft das bei deinem Projekt ähnlich ?
Ja
--> mein Projekt läuft sehr ähnlich.
z.B: Ich habe folgende:
1
        switch(ReceivedDataBuffer[0])        //Look at the data the host sent, to see what kind of application specific command it sent.
2
        {
3
            case COMMAND_TOGGLE_LED:  //Toggle LEDs command
4
                LED_Toggle(LED_USB_DEVICE_HID_CUSTOM);
5
                break;
6
            case COMMAND_GET_BUTTON_STATUS:  //Get push button state
7
                //Check to make sure the endpoint/buffer is free before we modify the contents
8
                if(!HIDTxHandleBusy(USBInHandle))
9
                {
10
                    ToSendDataBuffer[0] = 0x81;        //Echo back to the host PC the command we are fulfilling in the first uint8_t.  In this case, the Get Pushbutton State command.
11
                    if(BUTTON_IsPressed(BUTTON_USB_DEVICE_HID_CUSTOM) == false)  //pushbutton not pressed, pull up resistor on circuit board is pulling the PORT pin high
12
                    {
13
                            ToSendDataBuffer[1] = 0x01;
14
                    }
15
                    else                  //sw3 must be == 0, pushbutton is pressed and overpowering the pull up resistor
16
                    {
17
                            ToSendDataBuffer[1] = 0x00;
18
                    }
19
                    //Prepare the USB module to send the data packet to the host
20
                    USBInHandle = HIDTxPacket(CUSTOM_DEVICE_HID_EP, (uint8_t*)&ToSendDataBuffer[0],64);
21
                }
22
                break;
23
      case SignalMeasure:
24
      {
25
        measureSignal(ReceivedDataBuffer[2],ReceivedDataBuffer[5]........);
26
        // hier muss geprüft werden, ob es einen Timer1Overflow gegeben hat
27
      }
28
      break;
29
    }
30
    ....
31
    
32
  unsigned measureSignal(unsigned char nNumber, unsigned nOrder, unsigned char nWait....... )
33
  {
34
    ...
35
    while (!(PORTAbits.RA3) && !(PIR1bits.TMR1IF)); // Wenn es alles Okay
36
    if(PIR1bits.TMR1IF)
37
     {
38
      MessageTimer1Overflow();
39
      return;
40
     }
41
     while ((PORTAbits.RA3) && !(PIR1bits.TMR1IF)); // Wenn es alles Okay
42
    if(PIR1bits.TMR1IF)
43
     {
44
      MessageTimer1Overflow();
45
      return;
46
     }
47
  ........
48
  }

Meine Frage ist : Wie leite ich die Message der MessageTimer1Overflow() 
weiter ?

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.