Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: tiny13 не выходит из idle по прерыванию
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Arvenen
Tiny13 не выходит из idle режима по прерыванию от компаратора таймера, хотя в документации сказано, что он должен выходитьиз него по любому внутреннему или внешнему прерыванию. Подобная проблема у меня была с mega16, но там она как-то сама собой решилась... Компилятор WinAVR... Да, я пишу на Си... Знаю, для микроконтроллеров со столь малым размером памяти программы это не очень хорошо, но ассемблер я не знаю вовсе, так что буду оптимизировать программу, пока она не поместится в память. Вот программа:

Код
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

#define ADC_VREF_TYPE 0x00

// Вектор прерывания компаратора таймера:
ISR(TIM0_COMPA_vect)
{
    TCNT0 = 0x0;
    
    // Мигание лампочки:
    PORTB ^= 0b00001000;
}

int main(void)
{
    // Начальная инициализация, сгенерирована CodeVisionAVR
    
    // Input/Output Ports initialization
    // Port B initialization
    // Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In
    // State5=T State4=T State3=0 State2=T State1=T State0=T
    PORTB=0x00;
    DDRB=0x08;

    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: 150,000 kHz
    // Mode: Normal top=FFh
    // OC0A output: Disconnected
    // OC0B output: Disconnected
    TCCR0A=0x00;
    TCCR0B=0x03;
    TCNT0=0x00;
    OCR0A=0x99;
    OCR0B=0x00;

    // External Interrupt(s) initialization
    // INT0: Off
    // Interrupt on any change on pins PCINT0-5: Off
    GIMSK=0x00;
    MCUCR=0x00;

    // Timer/Counter 0 Interrupt(s) initialization
    TIMSK0=0x04;

    // Analog Comparator initialization
    // Analog Comparator: Off
    ACSR=0x80;
    ADCSRB=0x00;

    // ADC initialization
    // ADC Clock frequency: 75,000 kHz
    // ADC Bandgap Voltage Reference: Off
    // ADC Auto Trigger Source: None
    // Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
    DIDR0&=0x03;
    DIDR0|=0x00;
    ADMUX=ADC_VREF_TYPE & 0xff;
    ADCSRA=0x8F;

    sei();

    while (1)
    {
        //строки, переводящие контроллер в idle режим
        
        //set_sleep_mode(SLEEP_MODE_IDLE);
        //sleep_mode();    
        
    }
    
    return 0;
}


Так все нормально, лампочка на PB3 начинает подавать признаки жизни, но если раскомментировать строки, переводящие контроллер в idle, то лампочка не загорается... Скажите, пожалуйста, что я делаю не так?

На всякий случай:
Код
Fuses:
  OSCCAL = 5D, 5C
  EESAVE = 1
  WDTON = 1
  CKDIV = 1
  SUT = 2
  CKSEL = 2
  SELFPRGEN = 1
  DWEN = 1
  BODLEVEL = 3
  RSTDISBL = 1
defunct
поменять
MCUCR = 0;
на
MCUCR = (1 << SE);

вместо (sleep_mode / set_sleep_mode) в основном цикле пишем

asm("sleep");
Arvenen
Цитата
MCUCR = (1 << SE);

Да, упустила этот битик...

Все подправила, как вы сказали - не помогло, в обработчик прерывания компаратора программа не попадает... Причем на эмуляторе-отладчике все нормально, даже время учитывая другую частоту тактового генератора в пределах допустимого, но стоит записать на чип - и что-то явно не так...
aesok
Цитата(Arvenen @ Jun 2 2008, 20:11) *
Да, упустила этот битик...


Нет не упустили, sleep_mode() устанавливает SE бит, выполняет команду sleep, а потом сбрасывает его.

Анатолий.
smac
2 Arvenen
Если проблема еще не решена, помогу разобраться. От вас - дизасемблированная прога, на худой случай хекс. К сожалению не пишу на С, поэтому воспринимаю только асмовые команды. Надеюсь в этом случае прога не будет очень длинной, поэтому есть шанс разобраться.
Arvenen
2 smac
Нет, к сожалению, проблема так и не решена... Более того, она не сдвинулась ни в каком направлении... И я не знаю, как можно дизассемблировать hex файл... Вот его содержимое:

Код
:1000000009C022C021C020C01FC01EC01EC01CC00D
:100010001BC01AC011241FBECFE9CDBF10E0A0E65F
:10002000B0E0EEEBF0E003C0C89531960D92A0363B
:10003000B107D1F710E0A0E6B0E001C01D92A036F4
:10004000B107E1F715D03AC0DBCF1F920F920FB680
:100050000F9211248F939F9312BE88B398E0892743
:1000600088BB9F918F910F900FBE0F901F90189596
:1000700018BA88E087BB1FBC83E083BF12BE89E942
:1000800086BF19BC1BBE15BE84E089BF80E888B955
:1000900013B884B3837084BB84B384BB17B88FE870
:1000A00086B9789485B7877E886085BF85B780627A
:0E00B00085BF889585B78F7D85BFF4CFFFCFC4
:00000001FF
smac
Цитата(Arvenen @ Jun 5 2008, 17:09) *
2 smac
Нет, к сожалению, проблема так и не решена... Более того, она не сдвинулась ни в каком направлении... И я не знаю, как можно дизассемблировать hex файл... Вот его содержимое:


Хорошо, попробую помочь. Скажите только, это хекс именно того кода, что приведен в начале темы? Если нет, то приведите исходник на С именно того кода, с которого получен хекс, так наверное будет проще разобраться где именно собака порылась.
Arvenen
Цитата
Скажите только, это хекс именно того кода, что приведен в начале темы?

Вот этого обещать не могу... Я там столько раз уже пробовала все поменять... Постаралась вернуть все назад, на всякий случай, вот код на си и соответствующий ему hex:

Код
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/delay.h>

#define ADC_VREF_TYPE 0x00

ISR(TIM0_COMPA_vect)
{
    TCNT0 = 0x0;
    
    PORTB ^= 0b00001000;
}

int main(void)
{
    // Input/Output Ports initialization
    // Port B initialization
    // Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In
    // State5=T State4=T State3=0 State2=T State1=T State0=T
    PORTB=0x00;
    DDRB=0x08;

    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: 150,000 kHz
    // Mode: Normal top=FFh
    // OC0A output: Disconnected
    // OC0B output: Disconnected
    TCCR0A=0x00;
    TCCR0B=0x03;
    TCNT0=0x00;
    OCR0A=0x99;
    OCR0B=0x00;

    // External Interrupt(s) initialization
    // INT0: Off
    // Interrupt on any change on pins PCINT0-5: Off
    GIMSK=0x00;
    MCUCR=0x00;

    // Timer/Counter 0 Interrupt(s) initialization
    TIMSK0=0x04;

    // Analog Comparator initialization
    // Analog Comparator: Off
    ACSR=0x80;
    ADCSRB=0x00;

    // ADC initialization
    // ADC Clock frequency: 75,000 kHz
    // ADC Bandgap Voltage Reference: Off
    // ADC Auto Trigger Source: None
    // Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
    DIDR0&=0x03;
    DIDR0|=0x00;
    ADMUX=ADC_VREF_TYPE & 0xff;
    ADCSRA=0x8F;

    sei();

    while (1)
    {
        set_sleep_mode(SLEEP_MODE_IDLE);
        sleep_mode();    
    }
    
    return 0;
}


Код
:1000000009C022C021C020C01FC01EC01EC01CC00D
:100010001BC01AC011241FBECFE9CDBF10E0A0E65F
:10002000B0E0EEEBF0E003C0C89531960D92A0363B
:10003000B107D1F710E0A0E6B0E001C01D92A036F4
:10004000B107E1F715D03AC0DBCF1F920F920FB680
:100050000F9211248F939F9312BE88B398E0892743
:1000600088BB9F918F910F900FBE0F901F90189596
:1000700018BA88E087BB1FBC83E083BF12BE89E942
:1000800086BF19BC1BBE15BE84E089BF80E888B955
:1000900013B884B3837084BB84B384BB17B88FE870
:1000A00086B9789485B7877E886085BF85B780627A
:0E00B00085BF889585B78F7D85BFF4CFFFCFC4
:00000001FF


И... спасибо вам огромнейшее! Это моя вторая поделка с микроконтроллером... Я правда не знаю, с какого боку можно подойти к решению возникшей проблемы...
smac
Цитата(Arvenen @ Jun 5 2008, 22:26) *
Вот этого обещать не могу... Я там столько раз уже пробовала все поменять... Постаралась вернуть все назад, на всякий случай, вот код на си и соответствующий ему hex: ...

И... спасибо вам огромнейшее! Это моя вторая поделка с микроконтроллером... Я правда не знаю, с какого боку можно подойти к решению возникшей проблемы...


Как мне кажется, проблема в прерываниях от АЦП. Согласно хекса ацп установлен в режим непрерывного преобразования, прерывания от ацп разрешены, а программа их обработки в конечном счете совершает переход на адрес 0х000. как я понял, явно обработка прерываний в данном исходнике на С не описана, хотя я могу ошибаться (С я не знаю), тем не менее она происходит. Вполне возможно, что прерывания от АЦП приходят раньше чем от таймера, поэтому таймер просто не успевает вывести МК из режима Слип. Т. Е. из режима слип МК выводят прерывания АЦП, затем таймер переинициализуруется и цикл повторяется.
Как вариант выяснения так ли это, нужно попробовать временно исключить из исходника действия с АЦП и посмотреть выводит ли таймер из режима СЛИП.
Как вариант нужно в исходнике на С изменить строку ADCSRA=0x8F; на ADCSRA=0x83; что запретит прерывания от АЦП, но позволит отслеживать флаг прерываний полингом. В общем я не знаю как описать это на С, но попробуйте предложенный вариант.
Кстати, как я понимаю симптомы того, что МК не выходит из СЛИПА проявляются в отсутствии мигания светодиода, который мигает с малой частотой.
Если это так то проблема скорее всего именна та, что я описал.
Вообще если программа не сложная легче ее на АСМЕ написать, могу взяться если опишете алгоритмы подробно.

З. Ы. Частота мигания светодиода (лампочки) 500 Гц?
Arvenen
Код
Как мне кажется, проблема в прерываниях от АЦП. Согласно хекса ацп установлен в режим непрерывного преобразования, прерывания от ацп разрешены, а программа их обработки в конечном счете совершает переход на адрес 0х000. как я понял, явно обработка прерываний в данном исходнике на С не описана, хотя я могу ошибаться (С я не знаю), тем не менее она происходит.

Как глупо blush.gif да, ацп был включен в непрерывном режиме, и прерывания от него... Но самое глупое, что я пересохраняя каждый раз файл с исходником на новое имя, не меняла его в проекте и при компиляции использовала один и тот же самый первый файл без изменений... По сути даже выложенные мной выше код на си и hex получаются далеко не одинаковыми... Эх, голова садовая... smac, большое вам спасибо!

Код
Вообще если программа не сложная легче ее на АСМЕ написать, могу взяться если опишете алгоритмы подробно.

Нет, что вы, мне и так жутко неудобно... Тем более, что программа на самом деле планируется довольно большая, я даже сомневаюсь, что она поместится в 1 килобайт памяти tiny13...
smac
Цитата(Arvenen @ Jun 6 2008, 18:54) *
[smac, большое вам спасибо!...

Всегда пожалуйста! На самом деле мне интересна тема программирования МК АВР на С, может литератруку посоветуете толковую, для непрограммеров, желательно с примерами простенькими.
Да простят меня модеры за офтоп.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.