|
Тахометр на 16меге, не могу разобраться |
|
|
|
May 25 2007, 04:17
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Господа разработчики, подскажите пожалуйста, что я не так делаю? Задача следующая необходимо построить тахометр. На вход МК подается последовательность импульсов с частотой до 100 Гц. Нужно подсчитать количество импульсов за секунду и вывести на индикатор. Я использую 6мегу , кварц 8.0МГц. Завожу сигнал на вход T0 счетчика и снимаю с него параметры каждую секунду. Проблема в том что полученные результаты не постоянны. Т.е. значение на индикаторе скачет в пределах +-4 единицы. Думал, что не стабильно получаю секунду, так проверил на осциллографе… вроде нормально.. Всю голову сломал… У кого какие будут мысли? (пишу в AVR Studio) Прилагаю код … Код #define QZ 8000000L #define TIME_OCR1A ((QZ / 1024)-1)
int Speed_p; void Timer1_init(void) {
OCR1A = TIME_OCR1A; /* прерывание раз в секунду */ TCCR1A = 0x00; TCCR1B = (1 << 3) | 0x05; TIMSK |= 1 << 4; /* разрешить прерывание OCIE1A */ }
SIGNAL (TIMER1_COMPA_vect) { Speed_p=TCNT0; TCNT0=0; }
int main() { unsigned int g=0; char str[10];
Timer1_init();
// Таймер0 считает входные импульсы // Timer/Counter 0 initialization TCCR0=0x07; TCNT0=0x00; OCR0=0x00;
// Port B initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=0 State6=0 State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0xC8;
sei(); while(1) { ..........
.// Формируем строку для вывода g=(float)(Speed_p)*(float)1.66; str_out[8]=g%10;g/=10; str_out[7]=g%10;g/=10; str_out[6]=g%10; // выводим строку reload();// динамическая индикация
}
|
|
|
|
|
May 25 2007, 10:18
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(aesok @ May 25 2007, 12:57)  В reoload() запрещаются прерывания? Есть другие обработчики прерываний в проекте?
Анатолий. нет... прерывания нигде не запрещаются, и больше никаких прерываний не использую...
|
|
|
|
|
May 25 2007, 12:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008

|
Для подсчета частоты импульсов есть специальный режим работы таймера - режим захвата, может воспользоваться им? Цитата g=(float)(Speed_p)*(float)1.66; зачем вы в переменную типа int засовываете выражение типа float, при преобразовании типов тут вполне может быть и несомненно есть потеря точности, может по-этому и прыгают цифры? Здесь надо или как то считать все в int или сделать переменную g типом float и выводить на экран float с необходимой точностью. В присоединенном файле функция преобразования float в массив char. Функция не моя и может глючить, но для проверки подойдет, как альтернатива объемному printf-у с поддержкой float
Прикрепленные файлы
bcdfp.rar ( 1.85 килобайт )
Кол-во скачиваний: 226
--------------------
|
|
|
|
|
May 27 2007, 10:09
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(defunct @ May 26 2007, 23:19)  1* 2 = 2, что тут удивительного то? Берите среднее по последний трем результатам. Так я не могу понять, почему вообще значение прыгает? Поставил кварц 7,3728МГц. Получаю точную секунду. Входная частота стабильная, с генератора. Да и величина ее не более 100Гц. По-моему вообще значения должны быть стабильными. И раз прыгает только единица, то скорее всего это в каком-то определенном месте... Как же исправить ситуацию?... Иначе погрешность вычисления уж очень большая...
|
|
|
|
|
May 27 2007, 19:01
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(DAndy_boy @ May 27 2007, 13:09)  Так я не могу понять, почему вообще значение прыгает? Целое число имеет точность +-1, если его домножить на 2, то получите точность +-2... Что ж непонятного? Цитата Как же исправить ситуацию? Усреднить рез-тат.
|
|
|
|
|
May 28 2007, 07:13
|
Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 25-09-05
Из: Москва
Пользователь №: 8 922

|
Цитата(muravei @ May 28 2007, 11:02)  А может лучше мерить период вх сигнала , а не частоту? А после на "скользящее среднее" Тоже мысль..... вечером попробую.... Т.е. надо завести входной сигнал на внешнее прерывание и по фронту запускать счетчик... а по другому его останавливать... и затем секунду делим на получившееся время... Так?
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|