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

 
 
> Таймеры и прерывания
AiDream
сообщение Jan 24 2012, 09:16
Сообщение #1


Участник
*

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



Здравствуйте!
В программировании микроконтроллеров новичок, поэтому прошу не ругать сразу)
Встала задача:
На вход микроконтроллера постоянно поступают импульсы. Необходимо замерять временной интервал между ними, запоминать эти значения и проводить над ними простые математические операции.
Длительность импульсов - 5 мс, амплитуда - 12 В.
Пока что продумываю алгоритм.
Как я понимаю, надо настроить один из таймеров на запуск по входному нарастающему импульсу. Тут вопрос - остановится ли таймер по приходу следующего импульса, чтобы можно было считать накопленное им значение?
Заранее благодарю за помощь.

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

Расстояние между импульсами от 10 до 200 мс.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AiDream
сообщение Jan 31 2012, 06:15
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 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);
      }
}
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 31 2012, 07:04
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 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 в ноль, и начать счет дальше. Эту ситуацию (переполнение счетчиков) тоже нужно учитывать/отслеживать (нужна процедура обработки прерывания по переполнению) и учитывать при вычислении периода.
Go to the top of the page
 
+Quote Post
AiDream
сообщение Jan 31 2012, 08:41
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 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. да, про это я подумал, но думал, что мне хватает разрядности таймера. Теперь понял свою ошибку.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 31 2012, 09:10
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 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?
Вероятно. Или уменьшить частоту таймера. В любом случае нужно предусмотреть ситуацию, когда импульсы следуют через большой интервал времени - хорошая программа при этом должна отображать что-то "внятное"...
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 18:51
Рейтинг@Mail.ru


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