Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: проблема с прерыванием TIMER2_COMP
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
tolik_zp
Есть такой код в функции main:

if (UCSRA & (1<<RXC))
{
__disable_interrupt();
rtc_day = UDR;
while (!(UCSRA & (1<<RXC)));
rtc_hour = UDR;
while (!(UCSRA & (1<<RXC)));
rtc_min = UDR;
while (!(UCSRA & (1<<RXC)));
rtc_sec = UDR;
__enable_interrupt();

Beep_Short();
}

if (!(PIND & (1<<PD7)))
{
Beep_Low();

USART_Transmit(rtc_sec);
USART_Transmit(rtc_min);
USART_Transmit(rtc_hour);
USART_Transmit(rtc_day);
while (!(PIND & (1<<PD7)));
}


Также имеем следующий обработчик прерывания:

#pragma vector = TIMER2_COMP_vect
__interrupt void rtc_interrupt (void)
{
rtc_0125_sec++;
if (rtc_0125_sec == 8)
{
rtc_0125_sec = 0;
rtc_sec++;
}
if (rtc_sec == 60)
{
rtc_sec = 0;
rtc_min++;
}
if (rtc_min == 60)
{
rtc_min = 0;
rtc_hour++;
}
if (rtc_hour == 24)
{
rtc_hour = 0;
rtc_day++;
}
if (rtc_day == 8)
rtc_day = 1;
}

Прерывание работает нормально, проверено. Проблема в том, что иногда, после получения из UART'а данных, программа виснет, но прерывание по-прежнему работает. Такое впечатление, что PC улетает в неведомые дали. StartUp-код стандартный IAR'овский, проц мега8. Подскажите, всезнающий all, в чем может быть проблема?
andrvisht
Цитата(tolik_zp @ Jan 24 2007, 10:51) *
Есть такой код в функции main:

Код
А этот код должен исполниться только 1 раз ?
или он должен гоняться в цикле ?
если 2-е то добавьте
__task void main(void)
{
    while (1)
   {
   Ваш код
   }
}

поставте больший уровень оптимизации или расширьте CSTACK.
это в опциях проекта в General Options/System
tolik_zp
[/quote]
поставте больший уровень оптимизации или расширьте CSTACK.
это в опциях проекта в General Options/System
[/quote]

большое спасибо, помогло. только не cstack, а rstack, вернее cross-call optimization. у меня там было число 2. поставил unlimited - все заработало. вот только что могло съесть 16 уровней стека - не понятно.

PS/ сорри, если задаю глупые вопросы. только что начал писать на с

рано обрадовался... не помогло
Сергей Борщ
Цитата(tolik_zp @ Jan 24 2007, 10:12) *
рано обрадовался... не помогло
Откуда известно, что прерывание работает? Дерганья ногой в нем не замечаю. Зато вижу, что при приходе любого числа байт, не кратного четырем код будет крутиться в одном из циклов
Код
while (!(UCSRA & (1<<RXC)));
rtc_hour = UDR;
while (!(UCSRA & (1<<RXC)));
rtc_min = UDR;
while (!(UCSRA & (1<<RXC)));

с запрещенными прерываниями. Почему бы не сделать так:
Код
typedef struct {
    uint8_t day;
    uint8_t hour;
    uint8_t min;
    uint8_t sec;
    uint8_t sec_div8;
} rtc_t;

rtc_t rtc;

if (UCSRA & (1<<RXC))
{
    rtc_t Received;
    Received.day = UDR;
    while (!(UCSRA & (1<<RXC)));
    Received.hour = UDR;
    while (!(UCSRA & (1<<RXC)));
    Received.min = UDR;
    while (!(UCSRA & (1<<RXC)));
    Received.sec = UDR;
    Received.sec_div8 = 0;
    __disable_interrupt();
    rtc = Received;
    __enable_interrupt();
    Beep_Short();
}

#pragma vector = TIMER2_COMP_vect
__interrupt void rtc_interrupt (void)
{
    rtc.sec_div8++;
    if (rtc.sec_div8 == 8)
    {
        rtc.sec_div8 = 0;
        rtc.sec++;
        if (rtc.sec == 60)
        {
            rtc.sec = 0;
            rtc.min++;
            if (rtc.min == 60)
            {
                rtc.min = 0;
                rtc.hour++;
                if (rtc_hour == 24)
                {
                    rtc.hour = 0;
                    rtc.day++;
                    if (rtc.day == 8)
                        rtc.day = 1;
                }
            }
        }
    }
}
Здесь прерывания запрещены на короткое время копирования из временной структуры в основную.

Кстати, определить куда именно улетела программа можно вставив дерганье ногой в ключевые места.
andrvisht
Цитата(tolik_zp @ Jan 24 2007, 12:12) *
вот только что могло съесть 16 уровней стека - не понятно.
рано обрадовался... не помогло


Ну прерывание и сьело. Это обсуждалось не один раз, поищите поиском.
причина в том что функция должна быть описана в том же модуле, или в теле прерывания, как у вас.
кроме того иногда компилятору нужно указать чтобы он её встроил
Код
#pragma vector = TIMER1_COMPB_vect
#pragma inline = forced
__interrupt void COMPB(void)
{

}


Но и этого иногда мало, чтобы он начал инлайнить ему нужно выставить оптимизацию.

иначе он будет сохранять все рабочие регистры, а их немало.
попробуйте отладить в S-CPY, или в AVR-Studio (выходной файл ubrof8)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.