Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: timer0 interrupt
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
i.dmitry
исходные данные:
плата Olimex LPC-P2148
cpu: lpc2148
хочу: мигать светодиодом каждые 2 секунды по прерыванию от таймера 0
результат: вообще ничего не происходит (не мигает)

код задержки
Код
void Soft_Delay (DWORD N)
{
    volatile DWORD i;
    for (i=0; i<N; i++)
    {
       ;
    }
    return;
}



код main:
Код
//******************************************************************************
//  GLOBAL    DEFINITIONS
//******************************************************************************
#define TIMER0_INT 0x00000010  

#define LED 0x00000400          // P0.10 pin

#define PRESCALE_VAL 0x0001869F // TC increments on every 100000 PCLK

#define MATCH_VAL 0x00000078    // Match on 120 value (decimal)

#define MATCH_CONFIG 0x0003     // Interrupt on MR0; Reset on MR0



//******************************************************************************
//  FUNCTION    PROTOTYPE
//******************************************************************************
__irq void FIQ_Handler (void);



//******************************************************************************
//  CODE
//******************************************************************************
int main()
{
    //Fosc = 12 MHz
    Init_PLL(0x42, 0x00); // CCLK = 2*Fosc = 24 MHz; PCLK = CCLK / 4 = 6 MHz
                                  
    IO0DIR=LED;    // Set P0.10 as output
    IO0SET=LED;  // initially turn OFF LED    

    Init_Timer(PRESCALE_VAL, MATCH_VAL, MATCH_CONFIG);
    Enable_Timer(0x00);        // Timer 0 enable    
                                                      
    VICIntSelect = TIMER0_INT; //assign TIMER0 intterupt to FIQ category
    VICIntEnable = TIMER0_INT; //Enable TIMER0 interrupt
    
    while(1)
    {
       ;
    }
}

//interupt handler function
__irq void FIQ_Handler (void)
{
    IO0CLR=LED;            // turn ON LED
    Soft_Delay(10000000);  // delay
    IO0SET=LED;            // turn OFF LED
    T0IR = 0x00;           // Clear the interrupt flag  
}


код PLL_Init
Код
void Init_PLL (BYTE MP_Mask, BYTE PCLK_Mask)
{
    //set multiplier and divider of the PLL0
    PLL0CFG = MP_Mask;
    //enable PLL0
    PLL0CON = 0x1;
    //provide feed sequence
    PLL0FEED = 0xAA;
    PLL0FEED = 0x55;
    //wait until PLL0 is locked
    while (!(PLL0STAT & PLL0_LOCKED))
    {
       ;
    }
    //connect PLL0
    PLL0CON = 0x3;
    //provide feed sequence
    PLL0FEED = 0xAA;
    PLL0FEED = 0x55;
    //set peripheral clock
    VPBDIV  = PCLK_Mask;
    return;
}


Init_timer:
Код
void Init_Timer(DWORD Prescale_Val, DWORD Match_Val, WORD Match_Config)
{                                                
    T0PR = Prescale_Val;
    T0MR0 = Match_Val;
    T0MCR = Match_Config;    
    return;
}
void Enable_Timer(BYTE Timer_Num)
{
    if (Timer_Num==0)
    {
        T0TCR = 0x01;
    }
    else
    {
        T1TCR = 0x01;
    }
    return;
}


PCLK настроил на 6 МГц (VPBDIV=0 --> pclk=0.25*cclk),
в таймере Prescale настроил на 100000 чтобы счетчик считал с частотой 60 Герц (6MHz/100000), в MR записал 120 (120/60 = 2 сек), т.е. каждые 2 секнды должно быть прерывание по таймеру 0 и LED должен мигнуть.

но этого не происходит ... в чем проблема - понять не могу.
sKWO
i.dmitry, с lpc не работал. может причина в том что вы не разрешили прерывания в мэйне после инициализации периферии?
i.dmitry
Цитата(sKWO @ Aug 28 2008, 23:13) *
i.dmitry, с lpc не работал. может причина в том что вы не разрешили прерывания в мэйне после инициализации периферии?

вроде бы разрешил:
VICIntEnable = TIMER0_INT;
aaarrr
Ужас-ужас 07.gif
Код
//interupt handler function
__irq void FIQ_Handler (void)
{
    IO0CLR=LED;            // turn ON LED
    Soft_Delay(10000000);  // delay
    IO0SET=LED;            // turn OFF LED
    T0IR = 0x00;           // Clear the interrupt flag  
}

Soft_Delay(10000000) у Вас сколько по времени выполняется? Я уж не говорю о том, что использовать такие конструкции в прерывании вообще некорректно, но Вы просто можете получить такую картину: LED_SET->LED_CLR->Soft_Delay(очень много)->LED_SET->LED_CLR->
и ничего мигать (заметно) не будет.

Просто инвертируйте вывод диода в прерывании, без всяких задержек.
i.dmitry
Цитата(aaarrr @ Aug 28 2008, 23:39) *
Ужас-ужас 07.gif
Код
//interupt handler function
__irq void FIQ_Handler (void)
{
    IO0CLR=LED;            // turn ON LED
    Soft_Delay(10000000);  // delay
    IO0SET=LED;            // turn OFF LED
    T0IR = 0x00;           // Clear the interrupt flag  
}

Soft_Delay(10000000) у Вас сколько по времени выполняется? Я уж не говорю о том, что использовать такие конструкции в прерывании вообще некорректно, но Вы просто можете получить такую картину: LED_SET->LED_CLR->Soft_Delay(очень много)->LED_SET->LED_CLR->
и ничего мигать (заметно) не будет.

Просто инвертируйте вывод диода в прерывании, без всяких задержек.


я скопировал эту часть кода пару раз в начало программы до бесконечного цикла. светодиод мигнул пару раз примерно на 1.5 сек. так что задержка вполне нормальная.

Код
IO0CLR=LED;            // turn ON LED
    Soft_Delay(10000000);  // delay
    IO0SET=LED;            // turn OFF LED


далее я изменил функции следующим образом, чтобы как только произошло прерывание, он в нем и остался и диод горел бы:
Код
//interupt handler function
__irq void FIQ_Handler (void)
{
    IO0CLR=LED;            // turn ON LED
//    Soft_Delay(10000000);  // delay
//    IO0SET=LED;            // turn OFF LED
//    T0IR = 0x00;           // Clear the interrupt flag  
}

но он не подает признаков жизни в этом случае, значит наверное не происходит входа в функции обработчик прерывания
zltigo
Цитата(i.dmitry @ Aug 28 2008, 22:01) *
но он не подает признаков жизни в этом случае, значит наверное не происходит входа в функции обработчик прерывания

1. Вас уже спрашивали, а FIQ-то разрешили контроллеру обрабатывать - ответ был неверный.
2. Ну кто у Вас обработчик-то вызывает? startup правили?
3. Стек-то инициализировали?
4. Eсли компилятор подддерживает,то лучше _fiq.
aaarrr
Цитата(i.dmitry @ Aug 29 2008, 00:01) *
но он не подает признаков жизни в этом случае, значит наверное не происходит входа в функции обработчик прерывания

Или грохается при входе. FIQ точно разрешено? С вектором все в порядке?
Попробуйте перенести мигание в основной цикл и посмотреть, не зависает ли процессор при получении прерывания.
sKWO
Народ, подскажите а чё в ЛПС нету регистра статуса с битиком разрешения глобального прерывания.
Автору, в прерываниях большие задержки ставить глупо, лучше ивертировать состояние, тогда светодиод должен мигать раз в четыре секунды.
aaarrr
Цитата(sKWO @ Aug 29 2008, 00:13) *
Народ, подскажите а чё в ЛПС нету регистра статуса с битиком разрешения глобального прерывания.

В ARM7 вообще и в LPC в частности - целых два.
sKWO
Цитата(aaarrr @ Aug 28 2008, 23:16) *
В ARM7 вообще и в LPC в частности - целых два.

Подскажите, где автор разрешил глобально прерывание?
не глобальное а глобально, спасибо aaarrr, Вы и так поняли.
aaarrr
Цитата(sKWO @ Aug 29 2008, 00:19) *
Подскажите, где автор разрешил глобальное прерывание?

В стартапе (если разрешил, конечно).
i.dmitry
Цитата(zltigo @ Aug 29 2008, 00:11) *
1. Вас уже спрашивали, а FIQ-то разрешили контроллеру обрабатывать - ответ был неверный.


а почему неверный?
что тогда делает следующая строчка:
VICIntEnable = TIMER0_INT;
как я понял это Interrupt Enable Register.

startup я взял готовый из сборки code.bundle.lpc213x.lpc214x.uvision.zip готовых примеров.
судя по тому, что там написано, то все должно быть правильно наверное.

я со стартапом столкнулся в первый раз, если что-то не так, то скажите, пожалуйсто, где нужно прочитать об этом
Код
// Pre-defined interrupt handlers that may be directly
// overwritten by C interrupt functions
EXTERN CODE32 (Undef_Handler?A)
EXTERN CODE32 (SWI_Handler?A)
EXTERN CODE32 (PAbt_Handler?A)
EXTERN CODE32 (DAbt_Handler?A)
EXTERN CODE32 (IRQ_Handler?A)
EXTERN CODE32 (FIQ_Handler?A)

// Exception Vectors
// Mapped to Address 0.
// Absolute addressing mode must be used.

Vectors:        LDR     PC,Reset_Addr        
                LDR     PC,Undef_Addr
                LDR     PC,SWI_Addr
                LDR     PC,PAbt_Addr
                LDR     PC,DAbt_Addr
                NOP                            /* Reserved Vector */
;               LDR     PC,IRQ_Addr
                LDR     PC,[PC, #-0x0FF0]      /* Vector from VicVectAddr */
                LDR     PC,FIQ_Addr

Reset_Addr:     DD      Reset_Handler
Undef_Addr:     DD      Undef_Handler?A
SWI_Addr:       DD      SWI_Handler?A
PAbt_Addr:      DD      PAbt_Handler?A
DAbt_Addr:      DD      DAbt_Handler?A
                DD      0                      /* Reserved Address */
IRQ_Addr:       DD      IRQ_Handler?A
FIQ_Addr:       DD      FIQ_Handler?A


насколько я понял это, то что мне надо...
LDR PC,FIQ_Addr
FIQ_Addr: DD FIQ_Handler?A
zltigo
Цитата(i.dmitry @ Aug 28 2008, 22:25) *
а почему неверный?

Потому, что не о том. Перечитайте неcколько предыдущих постов.
aaarrr
Цитата(i.dmitry @ Aug 29 2008, 00:25) *
а почему неверный?
что тогда делает следующая строчка:
VICIntEnable = TIMER0_INT;
как я понял это Interrupt Enable Register.

Да, VIC'а. А есть еще разрешение прерываний у ядра.
zltigo
Цитата(i.dmitry @ Aug 28 2008, 22:25) *
насколько я понял это, то что мне надо...

Сгодится...
aaarrr
Цитата(i.dmitry @ Aug 29 2008, 00:25) *
startup я взял готовый из сборки code.bundle.lpc213x.lpc214x.uvision.zip готовых примеров.
судя по тому, что там написано, то все должно быть правильно наверное.

Посмотрел. Там все разрешено.
i.dmitry
Цитата(aaarrr @ Aug 29 2008, 00:21) *
В стартапе (если разрешил, конечно).

стартап я не менял, значит не разрешил скорее всего, потолму чот не знаю как.
подскажите плиз где это нужно сделать в стартапе?
i.dmitry
Цитата(aaarrr @ Aug 29 2008, 00:13) *
Попробуйте перенести мигание в основной цикл и посмотреть, не зависает ли процессор при получении прерывания.


сделал, как вы советовали. нет, не зависает. нормально мигает.

Цитата
Автору, в прерываниях большие задержки ставить глупо, лучше ивертировать состояние, тогда светодиод должен мигать раз в четыре секунды.

это как?
вместо
Код
    IO0CLR = LED;       //turn on LED            
    Soft_Delay(DELAY);  //delay
            
    IO0SET = LED;       //turn off LED  
    Soft_Delay(DELAY);  //delay

сделать так:
Код
static DWORD tmp = LED;
- объявить глобально
а в обраб. прерывания:
Код
__irq void IRQ_Handler(void)
{
    //Blink();     // LED Blink ~0.5 sec
    tmp = ~tmp;
    IO0CLR = tmp;
    IO0SET = ~tmp;
    T0IR = 0x00; // Clear the interrupt flag
}



Цитата
Код
а почему неверный?
что тогда делает следующая строчка:
VICIntEnable = TIMER0_INT;
как я понял это Interrupt Enable Register.


Да, VIC'а. А есть еще разрешение прерываний у ядра.

это нужно разрешать в стартапе как я понял из предыдущих постов.

может кто-нибудь ткнуть пальцем в мой стартап где это сделано? я постараюсь разобраться.

я ошибся в предыдущем посте.

в стартапе было написано
Код
FIQ_Addr    DCD     FIQ_Handler


а у меня в коде IRQ_Handler.

это изменил. далее в бесконечный цикл поставил мигание диода.
запустил. диод начал мигать. дальше перестал.

2) я закоментировал прототип обработчика и саму функцию обработчика. результат - тот же. мигал, потом перестал.

пото м я закоментировал еще и это
Код
    VICIntSelect = TIMER0_INT; //assign TIMER0 intterupt to FIQ category
    VICIntEnable = TIMER0_INT; //Enable TIMER0 interrupt


и он начал мигать без сбоев.

что-от происходит при входе в прерыванеи навернео
zltigo
Полное непонимание того, что пишите и железа. Этот код, конечно, можно залатать, дабы мигал, но дерьмом он так и останется. Начните с еще более простых вещей, и ... ну и с "C".... Залатанные файлы в приложении.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.