|
Таймеры, Опять они родимые=)) |
|
|
|
May 19 2008, 04:17
|

Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
May 21 2008, 05:02
|

Частый гость
 
Группа: Участник
Сообщений: 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"); } }
|
|
|
|
|
May 21 2008, 05:30
|

Гуру
     
Группа: Свой
Сообщений: 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); //Разрешить прием и передачу
|
|
|
|
|
May 21 2008, 05:37
|

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

|
Убрал. Все равно стопорится. На этой записи Код void USART_Transmit (unsigned char data) { while (!(UCSRA&(1<<UDRE))); //Пока UDRE 0, делать ->
|
|
|
|
|
May 21 2008, 22:03
|

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

|
Цитата Хорошо, что до трёх! Посмотрите на своё произведение. Таймер на прескалере 1 считает до 30 и генерит прерывание, в котором по готовности USART передаётся байт со скоростью (предположительно) 9600 бод. Посчитайте время между прерываниями таймера и время передачи одного байта по USART... Ерунда получается... Это я для симулятора так ставил, чтобы нагляднее(быстрее) было видно работу прерываний. Я тренируюсь в отладке на компиляторе.. За совет спасибо. Буду пробовать О.. Спасибо огромное.. Все прекрасно заработало=)))))) Надо будет теперь как нибудь прошить контроллер. Кстати может кто нибудь расскажет почему так получалось?
Сообщение отредактировал dvs85 - May 21 2008, 22:07
|
|
|
|
|
May 28 2008, 01:43
|

Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
May 28 2008, 14:40
|

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

|
Цитата(dvs85 @ May 28 2008, 04:43)  Сказали, только, что алгоритм неправильный, а в чем ошибка не сказали.. Программа теоритически должна считать временной интервал имульса На первый взгляд, вроде, верно... Но 1. Переменную OVF нужно обнулять (перед началом работы и после вычисления TimeClocks) 2. При вычислении TimeClocks константу нужно записать 0x10000 L3. Вычисление TimeClocks и TimeClocks_ms, ИМХО, лучше вынести из прерывания
|
|
|
|
|
May 28 2008, 23:31
|

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

|
Примерно то же мне сказали другие люди. Также они сказали, что лучше использовать компаратор и таймер. То есть срабатывает компаратор и таймер начинает считать.. Не мог ли кто нибудь подсказать алгоритм работы такой программы? То есть Код main() 1. Инициализация компаратора: - установить разряд разрешения захвата на входе компаратора - разрешить прерывания от аналогового компаратора по нарастающему фронту
2. Настройка таймера Разрешение прерывания по переплнению
3.Происходит прерывание по срабатыванию компаратора=> происходит включение таймера 4. При включении таймера производится подсчет количества переполнений и подсчет текущего значения таймера. Расчет времени Примерно так? Как расчитать значение по количеству переполнеий и текущему значению? Как произвести прерывание по завершению импульса?
Сообщение отредактировал dvs85 - May 29 2008, 00:30
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|