Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[STM32] problem z prostym przerwaniem

07 Gru 2009 13:27 1721 5
  • Poziom 15  
    Witam

    Mam dziwny problem. Do STM32F103RBT6 podłączyłem sobie RTC PCF8563. RTC generuje mi sygnał o częstotliwości 1Hz który wyzwala przerwanie w ARMie. I tutaj pojawia się problem. Niektóre zbocza są jakby pomijane i nie generują przerwania. Taką samą sytuację miałem kiedy wykorzystywałem przerwanie wewnętrzne RTC_IT_SEC. Przerwanie nie zawsze było generowane co sekundę. Problem się powtarza więc pewnie coś robię źle tylko co to może być. Dodam, że w funkcji main znajduję się nieskończona pętla która wykonuje określony kod. Jeżeli z tej nieskończonej pętli wyrzucam cały kod to przerwania wydają się funkcjonować poprawnie czyli zapalają i gaszą diodę co 1s. Nie bardzo rozumiem dlaczego ta pętla ma jakikolwiek wpływ na przerwania skoro w niej dokonywane są głównie operacje na tablicach i ustawiane są stany na pinach. Zresztą co by nie było w funkcji main co nie jest w żaden sposób związane z ustawieniami dla przerwań to nie powinno przecież mieć to wpływu na przerwania. Może niepotrzebnie wspominam i mieszam wspominając o tej pętli nieskończonej w funkcji main ale na tak funkcjonujące przerwania nie są dla mnie czymś normalnym.

    Jeżeli ktoś ma jakiś pomysł to będę bardzo wdzięczny za sugestie.

    Pozdrawiam
    Mirek
  • Poziom 15  
    Konfiguracja przerwania od RTC:
    Code:
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

        GPIO_InitTypeDef GPIO_InitStructure;
        /* TIM4 channel 2 pin (PB.07) configuration */
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        NVIC_InitTypeDef NVIC_InitStructure;
        /* Enable the TIM4 global Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        TIM_ICInitTypeDef  TIM_ICInitStructure;
        TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
        TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
        TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
        TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
        TIM_ICInitStructure.TIM_ICFilter = 0x0;

        TIM_ICInit(TIM4, &TIM_ICInitStructure);
     
        /* TIM enable counter */
        TIM_Cmd(TIM4, ENABLE);

        /* Enable the CC2 Interrupt Request */
        TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);

    Obsługa przerwania:
    Code:
    void TIM4_IRQHandler(void)
    
    {
        TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
        sekundy++;
        if(sekundy == 60)
        {
            sekundy = 0;
            minuty++;
            if(minuty == 60)
            {
                minuty = 0;
                godziny++;
                if(godziny == 24)
                {
                    godziny = 0;
                    dni++;
                    if((dni == 32 && (miesiace == 1 || miesiace == 3 || miesiace == 5 || miesiace == 7 || miesiace == 8 || miesiace == 10 || miesiace == 12)) || (dni >= 31 && (miesiace == 4 || miesiace == 6 || miesiace == 9 || miesiace == 11)))
                    {
                        dni = 1;
                        miesiace++;
                        if(miesiace == 13)
                        {
                            miesiace = 1;
                            rok++;
                        }
                    }
                    else if(miesiace == 2 && dni >= 29 && (((rok % 4 != 0) || (rok % 100 == 0)) && (rok % 400 != 0)))
                    {
                        dni = 1;
                        miesiace++;
                    }
                    else if(miesiace == 2 && dni >= 30 && (((rok % 4 == 0) && (rok % 100 != 0)) || (rok % 400 == 0)))
                    {
                        dni = 1;
                        miesiace++;
                    }
                }
            }
        }
        if(sekundy%2 == 0)
            zapal_diode();
        else
            zgas_diode();
    }

    Nieskończona pętla w funkcji main:
    Code:
    while(1)                           // wysterowanie rejestrów przesuwnych i kluczy zatrzaskowych
    
       {   
            zegar++; 
            if((zegar % 2) == 1)
                SH_CP_CLEAR;
            else
                SH_CP_SET;
            if((zegar % 2) == 1)               // reakcja na zbocze opadające zega
          {
             if(zegar == 1)                   // blokada wystawiania bitów wprowadzanych do rejestrów przesuwnych
                    ST_CP_CLEAR;
             if(kolumna % 8 == 0)            
                kolumna = kolumna - 16;
             if((WT[kolumna] & (1 << wiersz)) == 0)// stany wprowadzane do rejestrów przesuwnych odpowiedzialnych za wysterowanie kolumn
                DS_P0_CLEAR;
             else   
                DS_P0_SET;
             kolumna++;
             if(zegar == 139)
                kolumna--;
             else if(zegar == 141)         
             {
                ST_CP_SET;                       // wystawienie bitów wprowadzonych do rejestrów przesuwnych
                kolumna = 128;
                zapal_wiersz(wiersz);
                    wiersz++;                  // przejście do kolejnego wiersza
                if(wiersz > 7)              // po wyświetleniu 8 wiersza powrót do 1 wiersza
                   wiersz = 0;
             }
          }   
          if(zegar == 240)
                wygas_wiersze();
          else if(zegar == 242)               // zakończenie całego cyklu wprowadzania danych sterujących układami
            {
                zegar = 0;                  // powrót do początku cyklu wprowadzania danych   sterujących układami
                if(kolejna_klatka == 1 && wiersz == 0)
                {
                    rodzaj_sekwencji--;
                    if(rodzaj_sekwencji == 0)
                        wczytaj_dane();
                    odmierz_czas();
                    kolejna_klatka = 0;
                }
            }
       }


    Wkleiłem najważniejsze fragmenty kodu.
  • Poziom 15  
    Moze nastepuje reset µkontrolera od watchdog-a?
  • Poziom 15  
    Wykluczone. W pętli while wysterowywane są rejestry przesuwne sterujące pracą diod LED i wszystko jest ok.
  • Poziom 15  
    Problem związany był z wykorzystywaniem funkcji:
    Code:
    SET_BIT(SH_CP_GPIO->ODR,SH_CP_pin);
    
    CLEAR_BIT(SH_CP_GPIO->ODR,SH_CP_pin);

    które wykorzystywałem do ustawiania stanów na pinach. Zastąpiłem je funkcjami:
    Code:
    GPIO_WriteBit(SH_CP_GPIO, SH_CP_pin, 1);
    
    GPIO_WriteBit(SH_CP_GPIO, SH_CP_pin, 0);

    i wszystko zaczęło cykać.

    Temat zamykam.