Перейти к содержанию
    

Захват в ATMega64

Помогите, пожалуйста, начинающему чайнику. Задача - сделать измеритель/индикатор скорости вращения двигателя постоянного тока (до 12 тысяч оборотов в минуту).

Для начала написал программу, которая анализирует наличие сигнала на ножке захвата ICP1 (PD4 контроллера ATMega 64L) и при его поступлении выводит на вывод PE2 импульс, который можно наблюдать на осциллографе симулятора VMLAB (это для изучения и отладки), инкрементирует текущее (произвольное) число и выводит это число на LCD cимулятора.

Что же получилось? После запуска программы около 2 секунд инициируется LCD (это нормально), на его экран выводится число 25. Затем в симуляторе подаётся импульс на PD4. По идее подпрограмма прерывания по захвату должна выработать импульс "отрицательной" полярности длительностью 5 мс, инкрементировать число 25 и вывести на экран LCD число 26. Однако происходит следующее:

после первой подачи импульса захвата на выводе PE2 генерируется импульс с задержкой около 2 сек, число 26 тоже появляется с такой же задержкой;

начиная со второго импульса захвата число 26 уже не инкрементируется, а выходные импульсы на PE2 продолжают генерироваться с такой же задержкой.

Вопросы: откуда такая задержка при подаче импульсов захвата? Почему число инкрементируется только один раз?

 

#include <mega64.h>

// Alphanumeric LCD Module functions

#asm

.equ __lcd_port=0x1B ;PORTA

#endasm

#include <lcd.h>

#include<stdio.h>

#include<delay.h>

 

// LCD display buffer

char lcd_buffer[33];

unsigned int x = 0x00;

 

void __vivod_LCD(void) { //Функция вывода на ЖКИ

sprintf(lcd_buffer,"%i",x); //Запись в буфер ЖКИ

lcd_clear(); //Очистка экрана ЖКИ

lcd_puts(lcd_buffer); //Вывод на ЖКИ

}

 

// Timer 1 input capture interrupt service routine

interrupt [TIM1_CAPT] void timer1_capt_isr(void)

{

PORTE.2=0;

delay_ms(5);

PORTE.2=1;

x++;

__vivod_LCD ();

}

void main(void)

{

// Input/Output Ports initialization

PORTA=0x00;

DDRA=0x00;

PORTD=0xFF;

DDRD=0x00;

PORTE=0xFF;

DDRE=0x0FF;

// Timer/Counter 1 initialization

// Clock source: T1 pin Falling Edge

TCCR1A=0x00;

TCCR1B=0x81;

TCNT1H=0x00;

TCNT1L=0x00;

ICR1H=0x00;

ICR1L=0x00;

OCR1AH=0x00;

OCR1AL=0x00;

OCR1BH=0x00;

OCR1BL=0x00;

OCR1CH=0x00;

OCR1CL=0x00;

 

// Timer(s)/Counter(s) Interrupt(s) initialization

TIMSK=0x24;

ETIMSK=0x00;

// LCD module initialization

lcd_init(16);

x=25;

__vivod_LCD ();

 

#asm("sei")

while (1)

{

}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чёто не понял вообще вашего алгоритма. И непонятно откуда у вас сигнал поступает.

 

Но одно совершенно ясно. 12000 об/мин - это 5мс на оборот. LCD - медленное устройство, ещё медленнее - глаз человека, поэтому нет смысла выводить на дисплей значения часто. К томуже дисплей может просто банально неуспевать обновлять картинку.

 

Алгоритм зависит от того, что вы планируете мерить. Можно считать обороты или мерить период. Во 2 случае у вас всегда будет мгновенное значение скорости высчитанное с точностью в зависимости от Fclk проца. В первом - прямое значение.

 

Для первого случая алгоритм примерно такой.

1) Задаём интервал отображения информации (прерывание от таймера 2 к примеру). Например 10 секунд. В этом прерывании выводим значение X*6 (значение числа импульсов за 10 сек *6 = число за 60 сек. Где Х - значение с таймера захвата. Обнуляем по прочтению

2) Инициализируем таймер захвата на счёт импульсов.

 

Можно сделать в прерывании только признак вывода инфы, а выводить в голове, по анализу признака.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопросы: откуда такая задержка при подаче импульсов захвата? Почему число инкрементируется только один раз?
1. Каким инструментом VMLAB Вы измеряли задержки?

2. VMLAB и должен помочь Вам ответить на этот вопрос. Поставьте остановы. Проследите за переменной.

И ещё. Ставить задержки и вывод на дисплей в процедере обработки прерывания - очень плохая идея.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. Каким инструментом VMLAB Вы измеряли задержки?

Не измерял. Просто внизу поля VMLAB бегут цифры (время в миллисекундах) - вот и получилось, что задержка от подачи сигнала на вход ICP1 микроконтроллера до появления на выходе PE2 импульса примерно равна 2 секундам. Хотя если то же самое делать не от прерывания по захвату, а от, к примеру, INT1, то никаких задержек практически нет.

Ставить задержки и вывод на дисплей в процедере обработки прерывания - очень плохая идея.

Согласен. Так это я сделал только лишь временно, для учебно-отладочных целей, чтобы убедиться в том, что микроконтроллер воспринял сигнал захвата и стал обрабатывать прерывание.

2. VMLAB и должен помочь Вам ответить на этот вопрос. Поставьте остановы. Проследите за переменной.

Я же самый-самый начинающий, до остановов ещё не дошёл.

Так что вопросы пока остаются.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1. В Вашей программе захват настроен на спадающий фронт сигнала. Вы от какого фронта измеряете задержку?

2. Кроме прерывания по захвату Вы разрешили прерывание по переполнению. Обработчик прерывания по переполнению в программе присутствует?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Достаточно измерить период вращения(N раз и произвести вероятностный анализ).

Пустить таймер в "свободное плавание" и фиксировать его значения по сигналу захвата, не забывая

контролировать сигнал переполнения счетчика, а дальше - ариХметика.

А выводить на индикатор раз в одну или две секунды, как вам угодно.

В симуляторе главное сформировать входной сигнал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пустить таймер в "свободное плавание" и фиксировать его значения по сигналу захвата...

Именно так я и хотел сделать. А так как это моя первая в жизни программа (я не программист), то, естественно, сразу ничего не получилось, потому решил делать по частям, а именно:

- убедиться, что захват при поступлении на вход ICP1 спадающего фронта импульса происходит. Для этого в подпрограмме прерывания по захвату сделал вывод на РЕ2 "отрицательного" импульса. Убедился, что эта часть работает. В симуляторе спадающий фронт формирую, замыкая на землю вход PD4 кнопкой К0 и контролируя это на осциллографе симулятора;

- вывести на ЖКИ любое сообщение, или константу, или инкрементируемое число. Здесь не имеет значения частота поступления на вход будущего устройства импульсов от датчика скорости вращения шпинделя; просто хотел убедиться, что вывод на экран ЖКИ происходит после очередного нажатия кнопки К0 симулятора, то есть после наступления события захвата. Ан нет, не получилось: кроме естественной 2-х секундной задержки при запуске программы, вызыванной инициализацией ЖКИ, откуда-то берётся примерно такая же задержка (точное её значение в рассматриваемом случае не имеет никакого значения) при каждом нажатии кнопки К0 симулятора (то есть при каждом захвате).

Где в тексте программы ошибка?

-----

Насчёт прерывания по переполнению... Это не специально, это из-за неправильной настройки генератора начального кода CVAVR. Однако существенно ли это для заданных вопросов?

Короче, забудем начальную задачу (тахометр, и не просто, а следящий за непрерывно меняющейся скоростью вращения). Вернёмся к программе в начале темы: где в ней ошибки? Откуда задержка вывода импульсов при наступлении событий захвата? Почему после первого инкрементирования и вывода на ЖКИ числа в дальнейшем выводимое на ЖКИ число не меняется, хотя импульсы на выходе РЕ2 генерируются?

Напомню, что до этой задачи, в порядке изучения микроконтроллеров AVR, я делал вывод на ЖКИ инрементируемого числа при подаче (тоже симулятором) импульса на вход INTn - и всй работало! То есть после первой и единственной примерно 2-х секундной задержки при запуске программы дальше числа на ЖКИ выводились практически без всяких задержек (визуально).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насчёт прерывания по переполнению... Это не специально, это из-за неправильной настройки генератора начального кода CVAVR. Однако существенно ли это для заданных вопросов?
Существенно! Прерывание по переполнению (раз оно разрещено) будет периодически происходить, и контроллер будет переходить на соответствующий вектор, но, посколько, обработчика прерывания - нет, то, обычно, транслятор заполняет такие вектора командами перехода, которые приводят контроллер на адрес 0 ("мягкий" рестарт), и контроллер начнет всё заново! Правда, я считаю, что проявления такой бяки будут несколько отличаться от того, что Вы описали в своём вопросе. Лишнее разрешённое прерывание в любом случае необходимо обязательно убрать!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Существенно! Прерывание по переполнению... будет периодически происходить, и контроллер будет переходить на ... "мягкий" рестарт...

Так вот где собака зарыта!

Сделал по-вашему и... заработало! Так, пожалуй, с вашей помощью на старости лет программистом заделаюсь :08: . Спасибо!

Однако пойду дальше...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хотелось бы Вас предупредить: не увлекайтесь симуляторами! В симуляторах удобно проверить кусок программы (исключительно логику работы или правильность вычислений), или, например, определить время выполнения участка программы. Но! На правильность симулирования периферии контроллера возлагать надежды не стоит. Несколько лет назад напрочь отказался от использования VMLAB из-за обнаруженных в нём глюков с симулированием периферии контроллера (таймеры, USART). Наверное, ошибки симулирования разработчиками устраняются, но, при этом скорее всего появляются новые. Настоятельно рекомендую обзавестись JTAG'ом, и, проверять всё с помощью JTAG + макетка + AVRStudio. Тут уж глюков симулятора, естественно, нет ни каких!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хотелось бы Вас предупредить: не увлекайтесь симуляторами!

Спасибо за предупреждение. Естественно, виртуальный секс - хорошо, а реальный - лучше :biggrin: .

В качестве макетки собираюсь использовать плату с ATMega64L от сторонней фирмы, ЖКИ со встроенным контроллером - есть, в качестве датчика скорости вращения шпинделя буду использовать самодельный генератор прямоугольных импульсов с регулируемой частотой.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...