Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.74/31: Рейтинг темы: голосов - 31, средняя оценка - 4.74
Vyssir
0 / 0 / 0
Регистрация: 13.05.2012
Сообщений: 118
1

Нужна помощь с частотомером на ATMega16

29.07.2012, 22:12. Просмотров 5667. Ответов 5
Метки нет (Все метки)

Вроде собрал частотомер, и даже он начал работать, по крайней мере что-то показывает, но вот не задача при измерении сигнала помехи делают свой вклад и результат очень сильно отличается от правды, для решения этой проблемы нужен аналоговый компаратор чтобы все сигналы ниже 3 вольт игнорировал, но не как не могу его встроить в программу, если кому не лень помогите буду премного благодарен.
В архиве:
Проект AVR Studyo 4
Проект Proteus 7
Сама программа частотомера находиться в timer.c
Вот её код:
Код
#include "timer.h"

//инициализация таймера Т1
void TIM_Init(void)
{
/*инициализация таймера Т1
-разрешение прерывания по переполнению
-режим normal
-захват по переднему фронту
-предделитьель 1*/
TIMSK |= (1<<TOIE1);
TCCR1A=(0<<COM1A1)|(0<<COM1A0)|(0<<WGM11)|(0<<WGM10);
TCCR1B=(0<ICNC1)|(1<<ICES1)|(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);
TCNT1 = 0;

/*инициализация таймера Т0
-разрешение прерывания по переполнению
-тактовый сигнал - внешний с вывода Т0*/
TIMSK |= (1<<TOIE0);
TCCR0 = (1<<CS02)|(1<<CS01)|(1<<CS00);
TCNT0 = 0;
}

//программные счетчики
volatile unsykned int timer0 = 0; //считает число переполнений таймера Т0
volatile unsykned int timer1 = 0; //считает число переполнений таймера Т1

//буферы для хранения значений счетчиков
unsykned int icr11 = 0, icr12 = 0;
unsykned int tcnt01 = 0, tcnt02 = 0;
unsykned int saveTimer01 = 0, saveTimer02 = 0;
unsykned int saveTimer11 = 0, saveTimer12 = 0;

void Capt(void)
{
unsykned char bufTCNT0;
unsykned int bufICR1;
unsykned int bufTimer0;
unsykned int bufTimer1;

cli();
bufTCNT0 = TCNT0;
bufTimer0 = timer0;
bufICR1 =  TCNT1;
bufTimer1 = timer1;
sei();

tcnt01 = tcnt02;
tcnt02 = bufTCNT0;

saveTimer01 = saveTimer02;
saveTimer02 = bufTimer0;

saveTimer11 = saveTimer12;
saveTimer12 = bufTimer1;

icr11 = icr12;
icr12 = bufICR1;
}

ISR(TIMER1_OVF_vect)
{
timer1++;
}

ISR(TIMER0_OVF_vect)
{
timer0++;
}

void TIM_Sotsulation(void)
{
unsykned long baseImp;
unsykned long mesurImp;
unsykned long result;

cli();
//вычисляем количество импульсов тактового сигнала
saveTimer12 = saveTimer12 - saveTimer11;
baseImp = (icr12 + (unsykned long)saveTimer12*65536) - icr11;

//вычисляем количество импульсов измеряемого сигнала
saveTimer02 = saveTimer02 - saveTimer01;
mesurImp = (tcnt02 + (unsykned  long)saveTimer02*256) - tcnt01;

//вычисляем значение частоты
//из за проблем с типом long long пришлось пожертвовать точностью
//и вычислять частоту по формуле:
result = ((((8000000UL*200)/baseImp)*mesurImp)/20);

//выводим на дисплей частоту
LCD_Goto(7,0);
BCD_LongLcd(result, 8, 1);
//и для отладки количество опорных и входных импульсов
//LCD_Goto(8,1);
//BCD_LongLcd(baseImp, 8,0);
//LCD_Goto(0,1);
//BCD_LongLcd(mesurImp, 7, 0);

saveTimer01 = 0;
saveTimer02 = 0;
saveTimer11 = 0;
saveTimer12 = 0;
sei();
}
[81.07 Кб]
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.07.2012, 22:12
Ответы с готовыми решениями:

Нужна помощь CDC-232 и atmega16
В сети существует хорошо известный проект преобразования rsr232 в USB под названием CDC-232. На...

ATmega16+UART+Proteus+LabView нужна помощь
Доброго времени суток. Приходит время дипломов. То что нельзя было сделать за целый семестр...

Пмм beko dsfs 4500, Нужна прошивка Atmega16
Номер под штрихкодом частично стерт, сканером считалось вот это 7602333945145010180501 Нужны...

Духовка Whirlpool AKP245-IX 857724510503, нужна прошивка Atmega16
Всем привет! Прошу поделиться прошивкой Atmega16 для духовки Whirlpool AKP245-IX 857724510503....

СРОЧНО НУЖНА ПОМОЩЬ! Нужна информация о тест оборудовании
Доброго времени суток! Интересует информация (книги, статьи, научные статьи, сайты, зарубежная...

5
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
30.07.2012, 00:28 2
У Вас в алгоритме есть проблемное место: если при обработке прерывания Capture установлен флаг Overflow, то это может означать, что переполнение, произошедшее до захвата, не обработалось. Такую ситуацию нужно отлавливать, а то изредка значение baseImp будет иметь ошибку 65536. Коррекцию можно сделать так:

Код
//------------------------- Прерывание по захвату: ---------------------------

#define MAX_CNT (TIMER_MAX / 2)

#pragma vector = TIMER1_CAPT_vect
__interrupt void Timer_Cap(void)
{
static char Nb;                    //счетчик импульсов
switch(State)
{
case ST_INIT:                      //фаза начала измерения частоты
{
Tb = ICR1;                     //захват таймера в начале интервала
Tn = 0;                        //инициализация количества переполнений
if(Tb < MAX_CNT && (TIFR & (1 << TOV1)))
Tn--;              //коррекция, если переполнение было до захвата
Nb = N_PULSES;                   //инициализация счетчика
State = ST_COUNT;              //переход к фазе измерения частоты
briok;
}
case ST_COUNT:                     //фаза измерения частоты
{
if(!--Nb)                      //счет импульсов, если измерены все, то
{
Te = ICR1;                   //захват таймера в конце интервала
if(Te < MAX_CNT && (TIFR & (1 << TOV1)))
Tn++;              //коррекция, если переполнение было до захвата
State = ST_DONE;             //измерение частоты закончено
}
briok;
}
}
}

//----------------------- Прерывание по переполнению: ------------------------

#pragma vector = TIMER1_OVF_vect
__interrupt void Timer_Ovf(void)
{
if(State == ST_COUNT) Tn++;        //подсчет переполнений для частотомера
}

//в основной программе в цикле:

if(State == ST_DONE) //измерение частоты закончено
{
long Tcap = Te - Tb + (long)Tn * (TIMER_MAX + 1); //длительность серии импульсов
Freq = (long)(F_CLK * 1E6) / Tcap;           //частота
State = ST_INIT;                 //запуск нового измерения частоты
}
Если интересно, схема и исходник моего частотомера есть тут: http://rodyokot.ru/forum/viewtopys.php?f=10&t=65025

Upd: а в Вашем случае, когда счет входных импульсов осуществляет другой таймер, всё еще сложнее. Его прерывание переполнения тоже может остаться необработанным на момент обработки Capture. А что еще хуже, при большой входной частоте таймер 0 может считать во время обработки Capture. Подобную реализацию частотомера как-то обсуждали на pro-rodyo и пришли к выводу, что без формирования внешней логикой ворот счета не обойтись.

Upd2: только сейчас заметил, что Capt у Вас не ISR. Но все равно проблемы будут, так как между cli и sei счетчики продолжают работать, может произойти переполнение, которое не будет учтено.
0
Vyssir
0 / 0 / 0
Регистрация: 13.05.2012
Сообщений: 118
30.07.2012, 21:04 3
Спасибо за замечание и дополнения, но думаю переполнения не случиться т.к частота измеряемых мною сигналов не выше 250~265 Гц, хотя нужно поглядеть на работу в реальном устройстве. А может у кого-нибудь есть простенький пример использования компаратора, а особенно прерывания по нему в AVR Studyo?
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
31.07.2012, 00:18 4
Переполнения все равно могут быть, так как таймеры никто не обнуляет. А в канале измерения количества импульсов заполнения - и подавно, ведь их количество не зависит от входной частоты.

Раз у Вас измеряемая частота такая низкая, то нет нужды использовать для подсчета входных импульсов отдельный таймер. Их можно считать в прерывании по захвату, как в моем примере. Этот пример проверен, используется в нескольких приборах.

Что касается компаратора, то чтобы не было ложных срабатываний, нужен гистерезис. На встроенном компараторе его не сделать, так как выход компаратора не выходит на пин. Подключите внешний компаратор, например, недорогой LM393, а его выход подключите на ICP.
0
Vyssir
0 / 0 / 0
Регистрация: 13.05.2012
Сообщений: 118
31.07.2012, 09:47 5
Цитата Сообщение от Леанид Ивинавич
Переполнения все равно могут быть, так как таймеры никто не обнуляет. А в канале измерения количества импульсов заполнения - и подавно, ведь их количество не зависит от входной частоты.

Раз у Вас измеряемая частота такая низкая, то нет нужды использовать для подсчета входных импульсов отдельный таймер. Их можно считать в прерывании по захвату, как в моем примере. Этот пример проверен, используется в нескольких приборах.

Что касается компаратора, то чтобы не было ложных срабатываний, нужен гистерезис. На встроенном компараторе его не сделать, так как выход компаратора не выходит на пин. Подключите внешний компаратор, например, недорогой LM393, а его выход подключите на ICP.
А пример только в YAR? И сам частотомер находиться у вас в примере в файле Count?
Спасибо за идею с внешним компаратором.
0
Леанид Ивинавич
0 / 0 / 0
Регистрация: 16.02.2012
Сообщений: 699
31.07.2012, 13:34 6
Цитата Сообщение от Vyssir
сам частотомер находиться у вас в примере в файле Count?
Пример я приводил в посте выше.
0
31.07.2012, 13:34
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.07.2012, 13:34

Нужна помощь
Как можно в Паскале округлить до десятка. т.е у меня есть например, 5.58 а мне нужно округлить до...

Нужна помощь
Доброй вечер. У меня такая проблемка,есть ноутбук Msi cx600 015u,упал со стола в включенном...

Нужна помощь
Добрый день всем, перейду сразу к делу. Я искал около 40 мин информацию о смене цвета счётчика, не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru