реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Таймеры, Опять они родимые=))
dvs85
сообщение May 19 2008, 04:17
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Всем здрасте!
Продолжаю разбираться с таймерами..
Сейчас делаю такое простейшее задание - секундомер.
То бишь через каждую секунду наступает прерывание и светодиод на STK500 моргает.
Написал такую программу
Код
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//----------------------------------
ISR (TIMER1_COMPA_vect)
{
        PORTA = 0x00;
        _delay_ms(500);
        PORTA = 0xff;
}

//----------------------------------
int main (void)
{
    DDRA = 0xff;
    TIMSK  = (1<<OCIE1A);
    TCCR1B = (1<<CS12)|(1<<WGM13);
    OCR1A   = 15624;
    sei();
     for(;;)
      {
      asm("nop");
      asm("nop");
      }
}


Но она работает не так как я хотел)). Наступает одно прерывание и все.. Дальше никаких действий не происходит..
МК - Атмега16, пишу в АВР Студио.
Подскажите, что не так?



Сори, нашел ошибку.. Прошу прощения

Сообщение отредактировал dvs85 - May 19 2008, 04:17
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 21 2008, 05:02
Сообщение #2


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Решил дописать программу помоднее=))
Чтобы контроллер через терминал выводил секунды на комп.
Пока не имею программатора, поэтому балуюсь в отладчике. Так вот...Новая ошибка..
Он почему то считает до 2 и зависает.. Может кто подскажет ошибку?


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

unsigned int i;
//===============================================
//Настройка процессора
void cpu_inet(void)
{
  
  DDRC = 0xFF;
  PORTC = 0b10100101;
  
//установки ком порта 9600 8 N 1
  
  UBRRH=0x00;                                 //Установка BUAD скорости.
  UBRRL=25;  
  
  UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);        //Разрешить прием и передачу
  UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);    // 9600 8 N 1
}
//==============================================
//Программа для передачи через СОМ порт
void USART_Transmit (unsigned char data)  
{
    while (!(UCSRA&(1<<UDRE)));                //Пока UDRE 0, делать ->
    asm("nop");
    UDR=data;
    }
//----------------------------------
ISR (TIMER1_COMPA_vect)
{
        
    i=i+1;
    USART_Transmit (i);    

}

//----------------------------------
int main (void)
{
    i=0;
    DDRA = 0xff;
    TIMSK  = (1<<OCIE1A);
    TCCR1B = (1<<CS10)|(1<<WGM12);
    OCR1A   = 30;
    sei();
     for(;;)
      {
      PORTA = 0xff;
      asm("nop");
      asm("nop");
      }
}
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 21 2008, 05:30
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(dvs85 @ May 21 2008, 08:02) *
Может кто подскажет ошибку?
Код
  UCSRB=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);        //Разрешить прием и передачу
Вы не только разрешили прием и передачу, но также разрешили прерывание по окончанию передачи, а соответствующего обработчика - нет (он Вам, собственно, не нужет, т.к. передача - по готовности). Следует убрать установку RXCIE:

Код
  UCSRB=(1<<RXEN)|(1<<TXEN);        //Разрешить прием и передачу
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 21 2008, 05:37
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Убрал. Все равно стопорится.
На этой записи
Код
void USART_Transmit (unsigned char data)  
{
    while (!(UCSRA&(1<<UDRE)));                //Пока UDRE 0, делать ->
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 21 2008, 05:54
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(dvs85 @ May 21 2008, 08:37) *
Убрал. Все равно стопорится.
Может быть, потому, что в main нет вызова cpu_inet()
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 21 2008, 05:56
Сообщение #6


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Действительно.. Ха. Теперь он до трех считает))

Сообщение отредактировал dvs85 - May 21 2008, 05:58
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 21 2008, 06:55
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(dvs85 @ May 21 2008, 08:56) *
Ха. Теперь он до трех считает))
Хорошо, что до трёх! Посмотрите на своё произведение. Таймер на прескалере 1 считает до 30 и генерит прерывание, в котором по готовности USART передаётся байт со скоростью (предположительно) 9600 бод. Посчитайте время между прерываниями таймера и время передачи одного байта по USART... Ерунда получается... Из прерывания выводить по готовности - очень плохо. Как вариант: в прерываниях от таймера взводится некий флаг - требования вывода байта по USART; в основной программе (main) в бесконечном цикле этот флаг анализируется и при его установленном значении - сбрасывается и производится соответствующий вывод байта по USART. Ну, или что-то в этом роде...
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 21 2008, 22:03
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Цитата
Хорошо, что до трёх! Посмотрите на своё произведение. Таймер на прескалере 1 считает до 30 и генерит прерывание, в котором по готовности USART передаётся байт со скоростью (предположительно) 9600 бод. Посчитайте время между прерываниями таймера и время передачи одного байта по USART... Ерунда получается...

Это я для симулятора так ставил, чтобы нагляднее(быстрее) было видно работу прерываний. Я тренируюсь в отладке на компиляторе..
За совет спасибо. Буду пробовать

О.. Спасибо огромное.. Все прекрасно заработало=)))))) Надо будет теперь как нибудь прошить контроллер.
Кстати может кто нибудь расскажет почему так получалось?

Сообщение отредактировал dvs85 - May 21 2008, 22:07
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 22 2008, 06:11
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(dvs85 @ May 22 2008, 01:03) *
Кстати может кто нибудь расскажет почему так получалось?
Я плохо знаю WinAVR... Может Вы подскажите почему процедура прерывания оформлена ISR(TIMER1_COMPA_vect), а не SIGNAL(TIMER1_COMPA_vect) ? В последнем случае прерывания - закрыты, а в первом?
Go to the top of the page
 
+Quote Post
mdmitry
сообщение May 22 2008, 08:48
Сообщение #10


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



В документации по avr-libc все подробно сказано про ISR и SIGNAL.
Deprecated:
Do not use SIGNAL() in new code. Use ISR() instead.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 23 2008, 02:49
Сообщение #11


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



А я даже и не знаю. Изначально в примерах так было написано, я и использую. 07.gif
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 28 2008, 01:43
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Подскажите, в чем ошибка алгоритма этой программы?

Сказали, только, что алгоритм неправильный, а в чем ошибка не сказали..
Код
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

unsigned char OVF;                            //Счетчик переполнения
unsigned int FrontR, FrontF;                        //Для сохранения времени появления нарастающего и
                                                    //спадающего фронта импульса
unsigned long TimeClocks;
unsigned long TimeClocks_ms;
//========================================
//Прерывание по переполнению таймера

ISR(TIMER1_OVF_vect)                  //Если возникает прерывание по переполнению таймера,
{
    OVF++;                    //то увеличить значение счетчика переполнений
}

//=========================================
//Прерывание по захвату

ISR(TIMER1_CAPT_vect)                //При возникновении прерывания по захвату таймера,
{
               
    if ((PIND & 0x40)!=0)            //Если PD6 = высокому уровню
     {
      FrontR = ICR1;            //Запись времени возникновения захвата в EdgedR
      TCCR1B = TCCR1B & 0xBF;        //Установить захват по спадающему фронту
     }
    else                     //Если PD6 = низкий уровень
     {
      FrontF = ICR1;                //сохранить значение в EdgedF
      TCCR1B =TCCR1B| (1<<ICES1);
      //Вычислить временной интервал
      TimeClocks = (unsigned long)FrontF -     (unsigned long)FrontR + (unsigned long)OVF* 0x10000;
      //Подсчитать значение  в милисек
              TimeClocks_ms = TimeClocks/500;
     }    
}
int main (void)
{
    DDRC = 0XFF;
    TIMSK |= (1 << TOIE1)|(1<<TICIE1);    //разрешение прерывания по захвату и по переполнению
      TCCR1B|=(1<< ICES1)|(1 << CS10);    //установка коэф.деления = 8 и захват по нарастающему фронту
    sei();                    //Общее разрешение прерываний
    while(1);
    {
    }                    //Зацикливание пока не начнется прерывание
}

Программа теоритически должна считать временной интервал имульса

Сообщение отредактировал dvs85 - May 28 2008, 01:43
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 28 2008, 14:40
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(dvs85 @ May 28 2008, 04:43) *
Сказали, только, что алгоритм неправильный, а в чем ошибка не сказали..
Программа теоритически должна считать временной интервал имульса
На первый взгляд, вроде, верно... Но

1. Переменную OVF нужно обнулять (перед началом работы и после вычисления TimeClocks)

2. При вычислении TimeClocks константу нужно записать 0x10000L

3. Вычисление TimeClocks и TimeClocks_ms, ИМХО, лучше вынести из прерывания
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 28 2008, 23:31
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



Примерно то же мне сказали другие люди. Также они сказали, что лучше использовать компаратор и таймер. То есть срабатывает компаратор и таймер начинает считать..
Не мог ли кто нибудь подсказать алгоритм работы такой программы?
То есть
Код
main()
1. Инициализация компаратора:
- установить разряд разрешения захвата на входе компаратора
- разрешить прерывания от аналогового компаратора по нарастающему фронту

2. Настройка таймера
Разрешение прерывания по переплнению

3.Происходит прерывание по срабатыванию компаратора=> происходит включение таймера
4. При включении таймера производится подсчет количества переполнений и подсчет текущего значения таймера. Расчет времени


Примерно так?
Как расчитать значение по количеству переполнеий и текущему значению?
Как произвести прерывание по завершению импульса?

Сообщение отредактировал dvs85 - May 29 2008, 00:30
Go to the top of the page
 
+Quote Post
dvs85
сообщение May 29 2008, 00:48
Сообщение #15


Частый гость
**

Группа: Участник
Сообщений: 86
Регистрация: 24-03-08
Из: Владивосток
Пользователь №: 36 170



И еще вопрос.. Какую функцию выполняет бит АСО? Когда меняется значение выхода компаратора, устанавливается этот бит?

Сообщение отредактировал dvs85 - May 29 2008, 00:54
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 29th July 2025 - 15:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.0151 секунд с 7
ELECTRONIX ©2004-2016