Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - Zum C-Control-I-Forum - Zum C-Control-II-Forum

Re: @PeterS - AVR32 LCD-Ausgabe stört Interrupt Bearbeitung Kategorie: CC-Pro Unit & Appl.Board (von PeterS - 13.07.2014 11:08)
Als Antwort auf Re: @PeterS - AVR32 LCD-Ausgabe stört Interrupt Bearbeitung von Hannes24 - 28.06.2014 19:43

> > > Hallo,
> > >
> > > ich möchte von der Netzspannung die beiden Scheitelpunkte nach dem Nulldurchgang
> > > messen. Dabei gebe ich auf den ext.INT4 das Nullspannungssignal (im Bild gelb)
> > > und starte nach Auslösen des IRQ zwei Timer die dann 5ms und 15ms später
> > > (im Bild blau) den ADC auslesen.
> > > Das funktioniert absolut stabil, solange keine LCD-Ausgabe stattfindet.
> > > Findet eine LCD-Ausgabe statt und ein Hard- oder Software IRQ wird ausgelöst,
> > > dann zittert das ADC Signal (blau) wie verrückt und eine präzise Messung ist nicht
> > > mehr möglich.
> > >
> > > Kann man der Abarbeitung eines Hard- oder Software IRQ oberste Priorität geben ?
> > > Eine verzögerte oder unterbrochene LCD-Ausgabe spielt ja sowieso keine Rolle.
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > //--------------------------------------------------------------------------------
> > > #define PORT_LED3 117                           // PortBit 117
> > > #define PORT_LED4 119                           // PortBit 119
> > >
> > > word x;
> > >
> > >
> > > void main(void)
> > > {
> > >
> > >     Port_Attribute(10, PORT_ATTR_INPUT);        // P15 auf Eingang = Ext_Int4 (Nullsp)
> > >     Port_Attribute(PORT_LED1,PORT_ATTR_OUTPUT|PORT_ATTR_INIT_LOW);        // LED 1
> > >     Port_Attribute(PORT_LED2,PORT_ATTR_OUTPUT|PORT_ATTR_INIT_LOW);        // LED 2
> > >     Port_Attribute(PORT_LED3,PORT_ATTR_OUTPUT|PORT_ATTR_INIT_LOW);        // LED 3
> > >     Port_Attribute(PORT_LED4,PORT_ATTR_OUTPUT|PORT_ATTR_INIT_LOW);        // LED 4
> > >
> > >
> > >     Irq_SetVect(INT_100HZ, ISR_10ms);               // Interrupt alle 10ms
> > >
> > >     Irq_SetVect(INT_4, ISR_ZeroCrossing);           // Int4 setzen fĂĽr Nulldurchgang
> > >     Ext_IntEnable(4,2);                             // Int4: Mode 2 = fallende Flanke
> > >
> > >     Irq_SetVect(INT_TIMER0, ISR_Timer0);            // Timer0 IRQ, 5ms nach Nulldurchg.
> > >     Irq_SetVect(INT_TIMER1, ISR_Timer1);            // Timer1 IRQ, 15ms nach Nulldurchg.
> > >
> > >     LCD_Init();                                     // Display initialisieren
> > >     LCD_ClearLCD();
> > >     LCD_CursorOff();                                // Display Cursor ausschalten
> > >
> > >     while(1)
> > >     {
> > >         x++;
> > >     }
> > >
> > >
> > >
> > > }
> > >
> > > // -------------------------- IRQ Nulldurchgang (50Hz) ------------------------------
> > > //
> > > void ISR_ZeroCrossing(void)
> > > {
> > >     Timer_Set(0, TIM_128, 2579, TIMFLG_IRQ);    // 2579*1,939us = 5ms
> > >     Timer_Set(1, TIM_128, 7736, TIMFLG_IRQ);    // 7736*1,939us = 15ms
> > >
> > >     Irq_GetCount(INT_4);
> > > }
> > >
> > >
> > > // ----------------------- IRQ Timer0, 5ms nach Nulldurchgang ----------------------
> > > // den ADC0 auslesen (=Scheitelpunkt der 1.Halbwelle)
> > > //
> > > void ISR_Timer0(void)
> > > {
> > >     Port_WriteBit(PORT_LED2,PORT_ON);
> > >     Irq_GetCount(INT_TIMER0);
> > >     Timer_Disable(0);
> > >     Port_WriteBit(PORT_LED2,PORT_OFF);
> > > }
> > >
> > > // ----------------------- IRQ Timer1, 15ms nach Nulldurchgang ----------------------
> > > // den ADC0 auslesen (=Scheitelpunkt der 2.Halbwelle)
> > > //
> > > void ISR_Timer1(void)
> > > {
> > >     Port_WriteBit(PORT_LED2,PORT_ON);
> > >     Irq_GetCount(INT_TIMER1);
> > >     Timer_Disable(1);
> > >     Port_WriteBit(PORT_LED2,PORT_OFF);
> > > }
> > >
> > > // ---------------------------System IRQ 100Hz, alle 10ms --------------------------
> > > //
> > > void ISR_10ms(void)
> > > {
> > >
> > >
> > >     Port_WriteBit(PORT_LED1,PORT_ON);
> > >
> > >     LCD_CursorPos(0x00);                        // dauert 1.2ms
> > >     LCD_WriteWord(x, 5);
> > >
> > >     Port_WriteBit(PORT_LED1,PORT_OFF);
> > >     Irq_GetCount(INT_100HZ);
> > >
> > > }
> > >
> > >
> > >
> >
> > Hallo Hannes,
> >
> > die Priorität spielt keine Rolle, das Problem ist vielmehr, das für den Interpreter
> > Libraryfunktionen wie LCD_CursorPos oder LCD_WriteWord atomar in Assembler
> > ablaufen, und nicht unterbrochen werden können. Man könnte aber die Delays
> > minimieren, in dem Du z.B. mit LCD_WriteChar immer nur einen Buchstaben ausgibst.
> >
> > Ich sehe im Programmcode nicht, wie der ADC angesprochen wird, eine Abarbeitung im
> > "Free Running Mode" ist das beste um kontinuerlich präzise Werte zu samplen.
> >
> > Gruss Peter
>
>
>
>
> Hallo Peter,
>
> ich habe den ADC als IRQ initialisiert
>
> ADC_SetInput(0, 0, ADC_GND, ADC_SHG_1);        
> ADC_Enable(ADC_MODE_10BIT|ADC_MODE_ENAB_IRQ, 100000, ADC_ADCREF0,1, 13);
>
> die ADC-Messung funktioniert u. ist ausreichend genau. In meinem
> Testprogramm, das die Störung des Timings reproduziert schalte
> ich anstelle der ADC-Konvertierung einfach die LED2 EIN und AUS
> (blaues Signal). Gleichzeitig findet ĂĽber den System-IRQ 100Hz,
> alle 10ms eine LCD-Ausgabe statt. Da beide Vorgänge nicht
> synchronisiert sind, wird der ADC verzögert gelesen, wenn gerade
> am LCD was ausgegeben wird.
>  
> Es gibt dann wohl nur die eine Lösung, dass die LCD-Ausgabe
> zwischen den ADC-Messungen (ca. 8ms) stattfinden muss und das zu
> timen wird interessant.
>
> Wie verhält es sich, wenn gerade andere Komponenten angesprochen werden
> z.B. I2C, SPI, RS232, SD-Card, int. EEprom
>
> Danke + Gruss

Sorry diesen Post hatte ich durch meinem Urlaub ĂĽbersehen.

Alle Bibliotheksfunktionen werden durch Interrupts nicht unterbrochen. Es
wird sich gemerkt das ein Interrupt stattgefunden hat, und dann fĂĽhrt der
Interpreter bei dem nächsten Bytecode den Interrupt aus.

Gruss Peter


    Antwort schreiben


Antworten: