Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Микроконтроллеры (MCU) и микропроцессоры (MPU) > [avr] мигание светодиодом прерываниями и таймером


Автор: KindEvil 16.11.2010, 20:03
Привет всем, я пока что полный ноль в ассеблере и программировании каких бы то ни было микропроцессоров и avr в частности , но хочется разобраться с этой задачей)

Используя систему прерываний и таймер  реализовать следующую последовательность включения светодиода (atmega8): 

1сек - ON
1сек - OFF
2сек - ON
1сек - OFF
1сек - ON
2сек - OFF

1сек - ON
1сек - OFF
2сек - ON
1сек - OFF
1сек - ON
2сек - OFF
.
.
.
Светодиод подключен к выходу  параллельного порта PB1 и к земле, через токоограничивающий резистор 200 Ом. Основной цикл программы должен быть пустым.

Приветствуется код с комментариями, иначе утону. Спасибо.

Автор: UniBomb 17.11.2010, 10:56
KindEvil, рассказывай что делал, что не получилось.

Автор: KindEvil 17.11.2010, 11:14
Цитата(UniBomb @ 17.11.2010,  10:56)
KindEvil, рассказывай что делал, что не получилось.

По-чесноку, я читал о механизмах прерываний от таймеров и до сих пор не понял, как оформить и по какому признаку (в смысле по совпадению, переполнению или захвату).  Вообщем каша, нет понимая реализации прерывания.
Алгоритм представляю следующий: 
на PB1 подать сигнал с задердкой на 1сек;
потом вот это самое прерывание от таймера;
затем опять сигнал на PB1 с задержкой на 2 сек.; и аналогичные действия для 1off, 1on, 2off

и все это в цикле.

предполагаю, что возможно упростить цикл через инкремент и декремент. 

стек необходим здесь? без него никуда, как я понял)

и еще вопрос, что дает информация о сопротвлении резистора для кода?

Автор: UniBomb 17.11.2010, 11:40
Цитата(KindEvil @  17.11.2010,  11:14 Найти цитируемый пост)
в смысле по совпадению, переполнению или захвату

По захвату отпадает, т.к. (если я правильно понял) для этого нужен внешний источник. Остаётся переполнение или совпадение. Выбор зависит от того, какой способ даст более точный квант времени.


Цитата(KindEvil @  17.11.2010,  11:14 Найти цитируемый пост)
Алгоритм представляю следующий:

Итак, смотрим задачу и видим, что весь цикл моргания у нас занимает 8 секунд. Значит всё это можно было бы оформить в следующем виде:

Код

switch(time)
{
    case 1: setLed; break;
    case 2: clrLed; break;
    case 4: setLed; break;
    case 5: clrLed; break;
    case 6: setLed; break;
    case 8: clrLed; time = 0; break;
}


Цитата(KindEvil @  17.11.2010,  11:14 Найти цитируемый пост)
и все это в цикле.

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

Нужно кстати ещё знать частоту, на которой работает мк. Ну а в общем виде программа могла бы выгядеть следущим образом:

Код

#include <avr/io.h>
#include <avr/interrupt.h>

#define clrLed PORTB &= ~(1 << 1)
#define setLed PORTB |= 1 << 1

uint8_t time = 0;

int main(void)
{
    //настраиваем порт B как нам надо
    //настраиваем счётчик

    while(1) ; //наш главный пустой цикл
}

ISR(SIG_OUTPUT_COMPARE1A)  //прерывание таймера по совпадению
{
    switch(time)
    {
        case 1: setLed; break;
        case 2: clrLed; break;
        case 4: setLed; break;
        case 5: clrLed; break;
        case 6: setLed; break;
        case 8: clrLed; time = 0; break;
    }
    time++;
}


Но есть одно но - само задание ущербно. В обработчике прерывания нужно выполнять минимальное количество действий. В лучшем случае в прерывании надо установить какой-нибудь программный флаг, а в главном цикле программы его проверять и по выставлению уже производить какие-либо действия.


Цитата(KindEvil @  17.11.2010,  11:14 Найти цитируемый пост)
стек необходим здесь?

Как видишь нет.


Цитата(KindEvil @  17.11.2010,  11:14 Найти цитируемый пост)
что дает информация о сопротвлении резистора для кода? 

Абсолютно ничего. Резистор нужен для того, что бы не сгорел светодиод. Да и к тому же маловат он в этой схеме. Сейчас через диод течёт 25 мА, а надо где-то 10-15.

Автор: Mazzi 17.11.2010, 14:51
Я бы несколько дополнил программу, чтобы она работала в реальном времени
Код

#include <avr/io.h>
#include <avr/interrupt.h>

#define clrLed PORTB &= ~(1 << 1)
#define setLed PORTB |= 1 << 1

uint8_t time = 0;

// это значение нужно подобрать под конкретную схему
#define TIME_1_SEK 1000
uint16  pre_div =0;

int main(void)
{
    //настраиваем порт B как нам надо
    //настраиваем счётчик

    while(1) ; //наш главный пустой цикл
}

ISR(SIG_OUTPUT_COMPARE1A)  //прерывание таймера по совпадению
{
    if (pre_div) pre_div--;
    else {
       pre_div = TIME_1_SEK;
       switch(time)
       {
           case 1: setLed; break;
           case 2: clrLed; break;
           case 4: setLed; break;
           case 5: clrLed; break;
           case 6: setLed; break;
           case 8: clrLed; time = 0; break;
       }
       time++;
   }
}

Автор: UniBomb 17.11.2010, 15:55
Mazzi, тут я немного не согласен  smile Зачем вводить лишние переменные, когда с одной можно справится. Ну например мы настроили таймер, что бы период срабатывания был 0,1 секунды. Тогда в свитче было бы не 1, 2, 3 и т.д. а 10, 20, 30 и т.д. В любом случае временные интервалы бы выдерживались  smile 

Автор: KindEvil 17.11.2010, 19:29
Mazzi, 
UniBomb,  спасибо вам! Но, как бы этот код выглядел в ассемблере для atmega8? 

Автор: UniBomb 18.11.2010, 09:30
KindEvil, а вот теперь давай немного сам  smile Только так ты из нуля вырастешь, хоть на экзаменах будет легче (это ведь лабораторная работа же?). Структура программы у тебя есть, ассемблерная версия не сильно будет отличаться. Ну а что не получится - мы поможем  smile 

А для ленивых студентов, которые сами не хотят ничего делать существует http://forum.vingrad.ru/forum/Vingrad-help-center.html. Но ты ведь не такой  smile 

Автор: KindEvil 18.11.2010, 21:24
UniBomb,  спасибо. Будем разбираться)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)