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

 
 
 
Reply to this topicStart new topic
> Измерение частоты
A R T
сообщение Feb 14 2007, 10:50
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-06-06
Из: Сарапула
Пользователь №: 18 275



Доброго времени суток ВСЕМЪ!!!

Измеряю частоту синусоидального сигнала в диапазоне от 20 до 50Гц. Периодически (примерно один раз на пять замеров) происходит ошибка измерения (отклонение от реальной в 2…3 раза в обе стороны!!!).
Инициализация, обработка препывания и расчет частоты приведены ниже:

void timera_init()
//Clock source=ACLK
//Divider=1
//TIMACLK=32,768KHz
//Frequency=258,0Hz ( 3,88mS)
{
TACTL=0x00; //stop timer
//channel0
TACCTL0=0x00;
TACCR0=0x7F;
//channel1
TACCTL1=0x64;//TAOM1.1,TAOM1.0,TAOUT1
TACCR1=0x7F;
//channel2
TACCTL2=0x4110;//TASCS2,TACAP2,TACCIE2
TACCR2=0x00;

TAR=0x0000;//clear timer counter
TACTL=0x116;//TASSEL.0,TAMC.0,1,TAIE
}

#pragma vector=TIMERA1_VECTOR
__interrupt void ta_interrupt_routine(void)
{
if(TACTL&TAIFG)//Если таймер досчитал до 125
{
fTimeCounter++;//инкрементируем счетчик таймера.
TACTL&=~TAIFG;//Чистим флаг!
}

if(TACCTL2&CCIFG)//Если фронт сигнала,
{
fTime=fTimeCounter;//снимаем количество переполнений ТА.
fTime0=fTime1;//состояние ТА на начало процесса.
fTime1=TACCR2;//состояние ТА на конец процесса.
fTimeCounter=0;//обнуляем счетчик переполнений ТА.
TACCTL2&=~CCIFG;//Чистим флаг!
}
}

void main(void)
{

//Определяем частоту:
float fFreq=1/(2*(fTime*3.90625e-3+(fTime1-fTime0)*30.517578125e-6));

}

Также имеются прерывания ADC (неповторяющаяся последовательность каналов, в прерывании перезапуск).

Реализую на MSP430F1122. Тактируюсь от часового кварца (32768Гц). Частота тактирования стабильная.

Пожалуйста посоветуйте, что можно предпринят.

Зарание спасибо всем ответившим!!!


--------------------
Сделал трэш - разбудил Ктулху!!!
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Feb 14 2007, 12:37
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(A R T @ Feb 14 2007, 09:50) *
#pragma vector=TIMERA1_VECTOR
__interrupt void ta_interrupt_routine(void)
{
if(TACTL&TAIFG)//Если таймер досчитал до 125
{
fTimeCounter++;//инкрементируем счетчик таймера.
TACTL&=~TAIFG;//Чистим флаг!
}

if(TACCTL2&CCIFG)//Если фронт сигнала,
{
fTime=fTimeCounter;//снимаем количество переполнений ТА.
fTime0=fTime1;//состояние ТА на начало процесса.
fTime1=TACCR2;//состояние ТА на конец процесса.
fTimeCounter=0;//обнуляем счетчик переполнений ТА.
TACCTL2&=~CCIFG;//Чистим флаг!
}
}
Первое, что бросилось в глаза: не нужно принудительно чистить чистить флаги, но обязательно нужно читать TAIV:
Код
__interrupt void ta_interrupt_routine(void)
{
    unsigned TAIVcopy=TAIV;
    switch(TAIVcopy)
    {
        case 2:    /* CCP1 */
            ............................
        break;
        case 4:    /* CCP2 */
            ............................
        break;
    }
}
И второе - вы запрещаете прерывания на момент вычисления float fFreq=1/(2*(fTime*3.90625e-3+(fTime1-fTime0)*30.517578125e-6));?
Вот, посмотрите, аналогичный случай рассматривался: http://electronix.ru/forum/index.php?s=&am...st&p=199921


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
A R T
сообщение Feb 15 2007, 07:26
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 22-06-06
Из: Сарапула
Пользователь №: 18 275



Здравствуйте, Сергей!
Спасибо за участие и дельные советы!!!

Зарелизил обработку прерывания ТА1, как Вы предложили. Теперь выглядит так:
Код
#pragma vector=TIMERA1_VECTOR
__interrupt void ta_interrupt_routine(void)
{
  unsigned uTAIVcopy=TAIV;
  switch(uTAIVcopy)
  {
  case 0x04:
    fTime=fTimeCounter;
    fTimeCounter=0;//обнуляем счетчик таймера.
    fTime0=fTime1;
    fTime1=TACCR2;
    cFreqFalse++;//Задержка для выравнивания fTime,fTime0,fTime1.
    break;
  case 0x0a:
    fTimeCounter++;//инкрементируем счетчик таймера.
  default:
    _NOP();
  }
}


Расчет частоты сделал так:
Код
void main(void)
{

  //Определяем частоту:
  if(cFreqFalse>3) //Задержка для выравнивания fTime,fTime0,fTime1.
  {
    _DINT();
    fFreq=1/(2*(fTime*3.90625e-3+(fTime1-fTime0)*30.517578125e-6));
    cFreqFalse=0;
    _EINT();
  }

}


Ошики стали появляться реже…

Поставил точку останова после расчета частоты и при 50Гц их вообще не обнаружил, однако в реальном времени ошибки периодически случаются (всмысле при 50Гц). На частоте 20Гц ошибки появляются ~2...3 через 5…7 отсчетов. Т.е. при снижении частоты ошибки появляются чаще…

Что еще можно сделать???

Сообщение отредактировал A R T - Feb 15 2007, 07:27


--------------------
Сделал трэш - разбудил Ктулху!!!
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 25th July 2025 - 09:05
Рейтинг@Mail.ru


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