|
Таймеры и прерывания |
|
|
|
Jan 24 2012, 09:16
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 8-09-11
Пользователь №: 67 064

|
Здравствуйте! В программировании микроконтроллеров новичок, поэтому прошу не ругать сразу) Встала задача: На вход микроконтроллера постоянно поступают импульсы. Необходимо замерять временной интервал между ними, запоминать эти значения и проводить над ними простые математические операции. Длительность импульсов - 5 мс, амплитуда - 12 В. Пока что продумываю алгоритм. Как я понимаю, надо настроить один из таймеров на запуск по входному нарастающему импульсу. Тут вопрос - остановится ли таймер по приходу следующего импульса, чтобы можно было считать накопленное им значение? Заранее благодарю за помощь. Цитата(AiDream @ Jan 24 2012, 11:47)  Здравствуйте! В программировании микроконтроллеров новичок, поэтому прошу не ругать сразу) Встала задача: На вход микроконтроллера постоянно поступают импульсы. Необходимо замерять временной интервал между ними, запоминать эти значения и проводить над ними простые математические операции. Длительность импульсов - 5 мс, амплитуда - 12 В. Пока что продумываю алгоритм. Как я понимаю, надо настроить один из таймеров на запуск по входному нарастающему импульсу. Тут вопрос - остановится ли таймер по приходу следующего импульса, чтобы можно было считать накопленное им значение? Заранее благодарю за помощь. Расстояние между импульсами от 10 до 200 мс.
|
|
|
|
|
 |
Ответов
|
Jan 31 2012, 06:15
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 8-09-11
Пользователь №: 67 064

|
Программу переработал, снова пытаюсь в протеусе посмотреть. На экране lcd появляется какой то значок, только не то, что мне надо. Вот думаю в чем проблема. Может переменные надо переводить где то из одной системы исчисления в другую. Или Fuse выставлять. Кстати, почему то в протеусовской модели Atmega88 нельзя поставить тактовую частоту 16 МГц. Добавлю код, посмотрите пожалуйста, кому не трудно. Код #include <mega88.h> // Подключение библиотеки LCD модуля #include <alcd.h>
//Объявление переменных unsigned int EdgeR, EdgeF;//время первого и второго импульса unsigned long PulseClocks;//количество тактовых импульсов внутри импульса на входе ICP
// Прерывание таймера 1 по событию захват на входе PB0 interrupt [TIM1_CAPT] void timer1_capt_isr(void) { static unsigned char a;//локальная статическая переменная if(!a) //если чётный вход в обработчик по нарастающему фронту (новое измерение периода) { EdgeR = ICR1L; //запоминаем значение счётчика a = 1; //изменяем переменную для завершения текущего измерения } else //если нечётный вход в обработчик по нарастающему фронту (завершение текущего измерения) { EdgeF = ICR1L; //запоминаем значение счётчика a = 0; //изменяем переменную для нового измерения периода PulseClocks = ((unsigned long)EdgeF - (unsigned long)EdgeR);//вычисляем период }
}
void main(void) { // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif
// Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=P State6=P State5=P State4=P State3=P State2=P State1=P State0=P PORTB=0xFF; DDRB=0x00;
// Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTC=0x00; DDRC=0x00;
// Port D initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x00;
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Input Capture on Rising Edge // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: On TCCR1A=0x00; TCCR1B=0x43; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 1 Interrupt(s) initialization TIMSK1=0x20;
lcd_init(16);
// Global enable interrupts #asm("sei")
while (1) { // выводим значение переменной на экран lcd_gotoxy(0,0); lcd_putchar(PulseClocks); } }
|
|
|
|
|
Jan 31 2012, 07:04
|

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

|
Цитата(AiDream @ Jan 31 2012, 10:15)  На экране lcd появляется какой то значок, только не то, что мне надо. Вы выдаёте на LCD байт со значением периода в "тиках" таймера следования импульсов, а не последовательность символов, соответствующему этому периоду (естественно, требуется преобразование - самое простое, но не эффективное: использовать процедуру sprintf). Цитата(AiDream @ Jan 31 2012, 10:15)  посмотрите пожалуйста, кому не трудно. 1. Читаете, почему-то, только младший байт регистра Код EdgeR = ICR1L; //запоминаем значение счётчика ..... EdgeF = ICR1L; //запоминаем значение счётчика Нужно, примерно так: Код EdgeR = ICR1; //запоминаем значение счётчика ..... EdgeF = ICR1; //запоминаем значение счётчика 2. Таймер считает с частотой 250кГц, а период следования импульсов 0.2 с. Т.е. за максимальный период у Вас получается 50 000 "тиков" таймера... В переменную можно поместить такое число? Нет... 3. Между импульсами таймер может досчитать до максимального значения и сбросить свои счетчики TCNT в ноль, и начать счет дальше. Эту ситуацию (переполнение счетчиков) тоже нужно учитывать/отслеживать (нужна процедура обработки прерывания по переполнению) и учитывать при вычислении периода.
|
|
|
|
|
Jan 31 2012, 08:41
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 8-09-11
Пользователь №: 67 064

|
Цитата(Палыч @ Jan 31 2012, 10:04)  Вы выдаёте на LCD байт со значением периода в "тиках" таймера следования импульсов, а не последовательность символов, соответствующему этому периоду (естественно, требуется преобразование - самое простое, но не эффективное: использовать процедуру sprintf). 1. Читаете, почему-то, только младший байт регистра Код EdgeR = ICR1L; //запоминаем значение счётчика ..... EdgeF = ICR1L; //запоминаем значение счётчика Нужно, примерно так: Код EdgeR = ICR1; //запоминаем значение счётчика ..... EdgeF = ICR1; //запоминаем значение счётчика 2. Таймер считает с частотой 250кГц, а период следования импульсов 0.2 с. Т.е. за максимальный период у Вас получается 50 000 "тиков" таймера... В переменную можно поместить такое число? Нет... 3. Между импульсами таймер может досчитать до максимального значения и сбросить свои счетчики TCNT в ноль, и начать счет дальше. Эту ситуацию (переполнение счетчиков) тоже нужно учитывать/отслеживать (нужна процедура обработки прерывания по переполнению) и учитывать при вычислении периода. Спасибо. Но мне то как раз нужно, чтобы на дисплей выводилось значение переменной в тиках таймера 250 кГц) 1. Когда я выставляю ICR1, CodeVision ругается на эту строку undefined symbol. 2. Значит надо использовать переменную long? 3. да, про это я подумал, но думал, что мне хватает разрядности таймера. Теперь понял свою ошибку.
|
|
|
|
|
Jan 31 2012, 09:10
|

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

|
Цитата(AiDream @ Jan 31 2012, 12:41)  Но мне то как раз нужно, чтобы на дисплей выводилось значение переменной в тиках таймера 250 кГц) Пусть, например, период в тиках таймера получился 85. Если Вы выдадите байт с этим значением как символ(байт) на LCD, то на экране увидите символ "U" (если я не ошибаюсь). Вам же надо вывести (в данном примере) два символа "8" и "5". Такое преобразование из числа в последовательность символов производит функция sprintf (бывают и другие функции для такого преобразования). Цитата(AiDream @ Jan 31 2012, 12:41)  Когда я выставляю ICR1, CodeVision ругается на эту строку undefined symbol. В некоторых трансляторах двухбайтный регистр ICR1 определён. В Вашем случае можно сделать так: Код EdgeR = ICR1L; EdgeR= EdgeR | (ICR1H << 8); Цитата(AiDream @ Jan 31 2012, 12:41)  Значит надо использовать переменную long? Вероятно. Или уменьшить частоту таймера. В любом случае нужно предусмотреть ситуацию, когда импульсы следуют через большой интервал времени - хорошая программа при этом должна отображать что-то "внятное"...
|
|
|
|
Сообщений в этой теме
AiDream Таймеры и прерывания Jan 24 2012, 09:16 Палыч Вы не указали тип МК, который предполагается испол... Jan 24 2012, 09:24 AiDream Цитата(Палыч @ Jan 24 2012, 12:24) Вы не ... Jan 24 2012, 09:32  Палыч Цитата(AiDream @ Jan 24 2012, 13:32) То е... Jan 24 2012, 09:49   AiDream Цитата(Палыч @ Jan 24 2012, 12:49) Да, дл... Jan 24 2012, 10:02 birden Могу посоветовать "средство" - Winavr, и... Jan 25 2012, 03:49 AiDream Цитата(birden @ Jan 25 2012, 06:49) Могу ... Jan 25 2012, 06:42
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|