Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
29.07.2010, 01:27
|
|
Частый гость
Регистрация: 17.11.2009
Адрес: Владивосток
Сообщений: 18
Сказал спасибо: 2
Сказали Спасибо 1 раз в 1 сообщении
|
Помогите пожалуйста разобраться с частотным дискриминатором
Суть в чем: Нужно устройство которое про подаче на вход частоты больше 133 Гц зажигает светодиод.
Пытаюсь реализовать на ATTiny13
Логика следующая:
так как счетчик/таймер один то:
каждый такт плюсуем i++ (long int)
Прерывание на модуле совпадения таймера при совпадении на 0x85 (133)
в прерывании сравниваем i c тактовой частотой.
Если i больше тактовой, значит частота меньше 133
обнуляем i, TCNT0
PORTB.0=1
Иначе
обнуляем i, TCNT0
PORTB.0=0
Схема - проще некуда PortB.0 - выход, светодиод, PortB.2 - вход, счетчик/таймер
И ведь не рабатает. =(
Код:
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
if (i›9600000)
{
PORTB.0=1;
i=0;
TCNT0=0x00;
}
else
{
PORTB.0=0;
i=0;
TCNT0=0x00;
};
}
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTB=0x01;
DDRB=0x01;
TCCR0A=0x00;
TCCR0B=0x07;
TCNT0=0x00;
OCR0A=0x85;
OCR0B=0x00;
GIMSK=0x00;
MCUCR=0x00;
TIMSK0=0x0C;
ACSR=0x80;
ADCSRB=0x00;
#asm("sei")
while (1)
{
#asm("cli")
i++;
#asm("sei")
};
}
Последний раз редактировалось GRTH32; 29.07.2010 в 02:23.
Причина: Обновил код
|
|
|
|
29.07.2010, 01:45
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: Помогите пожалуйста разобраться с компаратором.
Сообщение от GRTH32
|
каждый такт плюсуем i++ (long int)
|
Вы действительно думаете что увеличение 4-х байтной переменной можно сделать за 1 такт? Запустите в симуляторе, ну хоть в той же студии и посмотрите как на самом деле. Повезет если за 4 такта идет увеличение. Ну и повторить - это переход еще 2 такта. И все равно Ваш метод плохо применим - на время увеличения переменной надо запрещать прерывания.
И смените название темы - компаратор и модуль совпадения таймера совсем разные устройства.
|
|
|
|
29.07.2010, 02:23
|
|
Частый гость
Регистрация: 17.11.2009
Адрес: Владивосток
Сообщений: 18
Сказал спасибо: 2
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Помогите пожалуйста разобраться с компаратором.
Спасибо. Просто я новичек в деле освоения микроконтроллеров.
Да и в программировании тоже.
МОжет у Вас будет вариант более оптимально кода?
Как можно узнать, за сколько тактов происходит инкриминация?
--- Наверное можно попробовать загнать в AVR Studio и прогнать по шагам...
Да в железе пока и не собирал. Гоняю в протеусе.
Добавил запрет прерывания.
Посчитав количество тактов можно будет подобрать нужное значение i.
Просто инетерсно сделать именно на это микросхеме. На тини25 конечно проще.
Последний раз редактировалось GRTH32; 29.07.2010 в 02:26.
|
|
|
|
29.07.2010, 02:50
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: Помогите пожалуйста разобраться с компаратором.
Сообщение от GRTH32
|
МОжет у Вас будет вариант более оптимально кода?
|
А Вы задачу распишите подробно. Не забудьте указать диапазон частоты, которая может быть подана на вход. Ну и приемлемую ошибку определения порога срабатывания - типа +-1Гц или +-5Гц.
Сообщение от GRTH32
|
Наверное можно попробовать загнать в AVR Studio и прогнать по шагам...
|
Конечно, это сразу расставит точки над е.
|
|
|
|
29.07.2010, 03:01
|
|
Частый гость
Регистрация: 17.11.2009
Адрес: Владивосток
Сообщений: 18
Сказал спасибо: 2
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Помогите пожалуйста разобраться с компаратором.
Задача в следующем - в целях освоения микроконтроллеров я хочу сделать схему, которая будет зажигать светодиод при оборотах коленвала в районе 8000 об.м
Соответственно минимальные обороты 1000об.м (16Гц), срабатывание 8000об.м (133Гц), максимальные 12000 (200Гц).
Приемлимая ошибка... примерно +-200 об.мин, те 3Гц
Схема и обвязка пока меня не интересуют. Хочу отладить логику и программу.
Инкриминация происходит за 39тактов. Те моё i надо делить как минимум на 39 (блин, еще же переход на прерывание, обработка и выход... пойду дальше мучать студию...). и еще:
Не смотря на то, что в проекте CodeVisionAVR выставлена частота 9.МГц, AVR Studio указал 4МГц. Где искать ошибку?
Последний раз редактировалось GRTH32; 29.07.2010 в 03:03.
|
|
|
|
29.07.2010, 03:58
|
|
Вид на жительство
Регистрация: 14.10.2009
Сообщений: 338
Сказал спасибо: 35
Сказали Спасибо 92 раз(а) в 73 сообщении(ях)
|
Re: Помогите пожалуйста разобраться с компаратором.
GRTH32,
Ну, начнем с простого - зачем компаратор?
Построй логику так. У нас есть наша частота теоретическая вращения коленвала.
К примеру это 10000 оборотов
У нас есть таймер. Таймер выставляем на частоту обороты * 2 или лучше *3
Тоесть частота повторов должна быть к примеру 30000 прерываний в секунду. так как прерывание само по себе отбирает порядка 20 тактов, то нужно частоту микроконтроллера выбрать с запасом это
30000*20 + 1мгц= 1.6Мгц Этого будет достаточно для нормальной удобной и экономичной работы. Если нет на 1.6 то можно поставить 2 или 4 мгц. Нам важно просто иметь запас.
Так вот в каждом прерывании по таймеру мы плюсуем i
PORTB.1 мы устанавливаем как ПРЕРЫВАНИЕ (задействуем функцию INT0)
На эту ногу подключаем датчик с вала.
Теперь что делаем в программе...
Мы смотрим по прерыванию от датчика сколько у нас i если меньше трех то загораем светодиод.
PHP код:
|
#include ‹tiny13.h›
unsigned int i=0;
//Прерывание от данных пришедших с вала двигателя interrupt [EXT_INT0] void ext_int0_isr(void) {
if (i ‹ 3) //если i не успевает приплюсоваться до трех значит частота на валу Больше чем ограничение. PORTB.0=1; else PORTB.0=0; i=0; //наплюсовали - надо снулить нашу i дабы снова она начала плюсоваться
}
// Прерывание по таймеру 25 килогерц проц 1.60 мегагерц interrupt [TIM0_OVF] void timer0_ovf_isr(void) { TCNT0=0x01; i++; if (i ›= 65535) i=0; }
void main(void) { // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=0x80; CLKPR=0x00; #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif
PORTB=0x00; DDRB=0b01; //PORTB.0 у нас будет выходом на светодиод
// Организуем таймер на: 25,000 kHz TCCR0A=0x00; TCCR0B=0x03; TCNT0=0x01; OCR0A=0x00; OCR0B=0x00;
// Зададим выпадание в прерывание если идет падающий сигнал от датчика на валу GIMSK=0x40; MCUCR=0x02; GIFR=0x40;
Прочее TIMSK0=0x02; ACSR=0x80; ADCSRB=0x00;
#asm("sei")
while (1) { //Траляля три рубля =))) Нифига тут нам не надо }; }
|
__________________
Найди путь или проложи сам!
Последний раз редактировалось MasterMushi; 29.07.2010 в 04:00.
|
|
|
|
29.07.2010, 04:34
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.12.2004
Сообщений: 3,172
Сказал спасибо: 11
Сказали Спасибо 692 раз(а) в 504 сообщении(ях)
|
Re: Помогите пожалуйста разобраться с компаратором.
Сообщение от GRTH32
|
Соответственно минимальные обороты 1000об.м (16Гц), срабатывание 8000об.м (133Гц), максимальные 12000 (200Гц).
|
Это мотоцикл?
Измеряйте период, а не частоту. Дальше скользящее среднее по 4-8 отсчетам, сравнение и индикация превышения если нужно.
|
|
|
|
29.07.2010, 07:06
|
|
Частый гость
Регистрация: 17.11.2009
Адрес: Владивосток
Сообщений: 18
Сказал спасибо: 2
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Помогите пожалуйста разобраться с компаратором.
Сообщение от MasterMushi
|
GRTH32,
Ну, начнем с простого - зачем компаратор?
Построй логику так. У нас есть наша частота теоретическая вращения коленвала.
К примеру это 10000 оборотов
У нас есть таймер. Таймер выставляем на частоту обороты * 2 или лучше *3
Тоесть частота повторов должна быть к примеру 30000 прерываний в секунду. так как прерывание само по себе отбирает порядка 20 тактов, то нужно частоту микроконтроллера выбрать с запасом это
30000*20 + 1мгц= 1.6Мгц Этого будет достаточно для нормальной удобной и экономичной работы. Если нет на 1.6 то можно поставить 2 или 4 мгц. Нам важно просто иметь запас.
Так вот в каждом прерывании по таймеру мы плюсуем i
PORTB.1 мы устанавливаем как ПРЕРЫВАНИЕ (задействуем функцию INT0)
На эту ногу подключаем датчик с вала.
Теперь что делаем в программе...
Мы смотрим по прерыванию от датчика сколько у нас i если меньше трех то загораем светодиод.
PHP код:
|
#include ‹tiny13.h›
unsigned int i=0;
//Прерывание от данных пришедших с вала двигателя
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (i ‹ 3) //если i не успевает приплюсоваться до трех значит частота на валу Больше чем ограничение.
PORTB.0=1;
else PORTB.0=0;
i=0; //наплюсовали - надо снулить нашу i дабы снова она начала плюсоваться
}
// Прерывание по таймеру 25 килогерц проц 1.60 мегагерц
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x01;
i++;
if (i ›= 65535) i=0; - [COLOR="#ff0000"]это, как я понимаю, на случай очень низкой частоты?[/COLOR]
}
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTB=0x00;
DDRB=0b01; //PORTB.0 у нас будет выходом на светодиод
// Организуем таймер на: 25,000 kHz
TCCR0A=0x00;
TCCR0B=0x03;
TCNT0=0x01; [COLOR="Red"]- это компенсация какого-то такта?[/COLOR]
OCR0A=0x00;
OCR0B=0x00;
// Зададим выпадание в прерывание если идет падающий сигнал от датчика на валу
GIMSK=0x40;
MCUCR=0x02;
GIFR=0x40;
Прочее
TIMSK0=0x02;
ACSR=0x80;
ADCSRB=0x00;
#asm("sei")
while (1)
{
//Траляля три рубля =))) Нифига тут нам не надо
};
}
|
|
Построй логику так. У нас есть наша частота теоретическая вращения коленвала.
К примеру это 10000 оборотов - немного не верно - 10000об = 10000/60 = 166.(6)Гц
У нас есть таймер. Таймер выставляем на частоту обороты * 2 или лучше *3
Тоесть частота повторов должна быть к примеру 30000 прерываний в секунду. Те тут несколько перебор с прерываниями... так как прерывание само по себе отбирает порядка 20 тактов, то нужно частоту микроконтроллера выбрать с запасом это
// Прерывание по таймеру 25 килогерц проц 1.60 мегагерц
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x01;
i++;
if (i ›= 65535) i=0; - это, как я понимаю, на случай очень низкой частоты?
}
// Организуем таймер на: 25,000 kHz
TCCR0A=0x00;
TCCR0B=0x03;
TCNT0=0x01; - это компенсация какого-то такта?
OCR0A=0x00;
OCR0B=0x00;
//Прерывание от данных пришедших с вала двигателя
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (i ‹ 3) //если i не успевает приплюсоваться до трех значит частота на валу Больше чем ограничение.
PORTB.0=1; - PORTB.0 и есть INT0 -ошибся, PORTB.1!!!
else PORTB.0=0;
i=0; //наплюсовали - надо снулить нашу i дабы снова она начала плюсоваться
}
И ещё вопрос - как тактуется Tiny13? выхода и входа XTAL у нее нет. Как я понял с даташита - есть внутренний осцилятор на 128кГц, 4.8МГц и 9.6МГц... И какое-то внешнее тактование.
Сейчас попробую адаптировать Ваш код под себя.
Блин. Как просто и красиво. =)
Последний раз редактировалось GRTH32; 29.07.2010 в 08:13.
|
|
|
|
29.07.2010, 07:11
|
|
Частый гость
Регистрация: 17.11.2009
Адрес: Владивосток
Сообщений: 18
Сказал спасибо: 2
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Помогите пожалуйста разобраться с компаратором.
Сообщение от kison
|
Это мотоцикл?
Измеряйте период, а не частоту. Дальше скользящее среднее по 4-8 отсчетам, сравнение и индикация превышения если нужно.
|
Да, мотоцикл.
Скользящее среднее, я так понимаю, для большей стабильности показаний?
Городить расчеты в прерывании, наверное, не хорошо, а делать это в теле цикла основной программы - я пока не смогу посчитать поправки на такты. =(
Сначала попробую более простой вариант, затем буду уже усложнять.
Спасибо.
|
|
|
|
29.07.2010, 08:33
|
|
Частый гость
Регистрация: 17.11.2009
Адрес: Владивосток
Сообщений: 18
Сказал спасибо: 2
Сказали Спасибо 1 раз в 1 сообщении
|
Re: Помогите пожалуйста разобраться с компаратором.
В общем, код приобрел следующий вид:
PHP код:
|
#include ‹tiny13.h›
unsigned int i=0;
//Прерывание от данных пришедших с вала двигателя
interrupt [EXT_INT0] void ext_int0_isr(void)
{
if (i ‹ 70) //если i не успевает приплюсоваться до 70 значит частота на валу Больше чем ограничение.
PORTB.3=0;
else PORTB.3=1;
i=0; //наплюсовали - надо снулить нашу i дабы снова она начала плюсоваться
}
// Прерывание по таймеру 9375 Герц проц 9.60 МегаГерц
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0=0x01;
i++;
if (i ›= 65535) i=0;
}
void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
PORTB=0b001000; // Ставим бит в PORTB.3, так как диод на VCC.
DDRB=0b001000; //PORTB.3 у нас будет выходом на светодиод
// Организуем таймер на: 9375 Hz
TCCR0A=0x00;
TCCR0B=0x05; //делим 9600000 на 1024 = 9375 Гц
TCNT0=0x01; /// Зачем?
OCR0A=0x00;
OCR0B=0x00;
// Зададим выпадание в прерывание если идет падающий сигнал от датчика на валу
GIMSK=0x40; // Прерывание по INT0
MCUCR=0x03; // Прерывание на INT0 нарастающему фронту
GIFR=0x40;
//Прочее
TIMSK0=0x02;
ACSR=0x80;
ADCSRB=0x00;
#asm("sei")
while (1)
{
//Траляля три рубля =))) Нифига тут нам не надо
};
}
|
Соответственно не работает. =)
Прерывание по INT0 обрабатывается.
Что вызывает внимание:
1) AVR Studio всё время указывает частоту 4МГц, как сменить на 9.6Мгц?
P.S. Наверное, хорошим тоном до прерывания по INT0 отправлять контроллер в спячку?
Последний раз редактировалось GRTH32; 29.07.2010 в 09:09.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 04:38.
|
|