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

 
 
> Реализация частотомера обратного счёта на PIC24H, Нужна помощь
shkal
сообщение Jul 12 2011, 12:13
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 281
Регистрация: 29-04-08
Из: Москва
Пользователь №: 37 149



Добрый день всем. Я попал в некоторый затык и не могу выбраться из него без посторонней помощи.
Итак, пишется реализация частотомера по алгоритму, приведённому здесь
Входные импульсы считаются таймером Т2, опорные - Т3. Входы IC1 IC2 T2CK - физически один пин, мэппинг с помощью PPS. IC1 захватывает Т2, IC2 захватывает T3.
Функция F_init() инициализирует переферию.
Функция F_start() запускает цикл измерения частоты.
По первому прерывнию от IC1 сохраняются пары значений F_osc_start, F_in_start и счётчики переполнения таймеров over2_start, over3_start.
Далее модули IC1 IC2 выключаются и запускается на время gate_time таймер Т5. По его прерыванию модули IC1 IC2 опять включаются, и после очередного фронта входного сигнала в прерывании IC1
сохраняются пары значений F_osc_end, F_in_end и счётчиков переполнения таймеров over2_end, over3_end. Устанавливается флаг new_data.
В main'е крутиться простейшая state machine, после установки флага new_data значение частот вычисляется функцией F_calc() и отображается на ЛСД.

CODE
main() {

F_init();
while(1)
{


switch (main_state)
{
case 0:

F_start(200);
main_state=1;
break;

case 1:

if (new_data)
{
Freq=F_calc();
LCDWriteCmd(0x01); // clear display
delay_ms(2);
if (Freq == 0)
{
LCDputstr ("NO SIGNAL");
}
else
{
sprintf(F_display, "%15f", Freq);
LCDputstr(F_display);

}
new_data=0;
main_state=0;
}

break;

}
}



CODE
void F_init(void)
{
// init timer2 for external clock

T2CONbits.TON = 0; // Disable Timer
T2CONbits.TCS = 1; // Select external clock
T2CONbits.TGATE = 0; // Disable Gated Timer mode
T2CONbits.TCKPS = 0b00; // 1:1 prescaler
T2CONbits.T32 = 0; // 16bit mode
TMR2 = 0x00; // Clear timer register
PR2=0xffff;
IPC1bits.T2IP = 6; // INT priority=6
IFS0bits.T2IF = 0; // Clear Timer1 Interrupt Flag
IEC0bits.T2IE = 1; // Enable Timer1 interrupt


// init timer 3

T3CONbits.TON = 0; // Disable Timer
T3CONbits.TCS = 0; // Select internal clock
T3CONbits.TCKPS = 0b00; // 1:1 prescaler
T3CONbits.TGATE = 0; // Disable Gated Timer mode
TMR3 = 0x00; // Clear timer register
PR3=0xffff;
IPC2bits.T3IP = 6; //INT priorty=6
IFS0bits.T3IF = 0; // Clear Timer1 Interrupt Flag
IEC0bits.T3IE = 1; // Enable Timer1 interrupt


// init timer 5 for 0.2c

T5CONbits.TON = 0; // Disable Timer
T5CONbits.TCS = 0; // Select internal clock
T5CONbits.TCKPS = 0b11; // 1:256 prescaler
T5CONbits.TGATE = 0; // Disable Gated Timer mode
TMR5 = 0x00; // Clear timer register
PR5=2879;
IPC7bits.T5IP = 4; //INT priorty=4
IFS1bits.T5IF = 0; // Clear Timer1 Interrupt Flag
IEC1bits.T5IE = 1; // Enable Timer1 interrupt


// init input capture 1 on Timer 2

IC1CONbits.ICM= 0b000; // Disable Input Capture 1 module
IC1CONbits.ICTMR= 1; // Select Timer2 as the IC2 Time base
IC1CONbits.ICI= 0b00; // Interrupt on every capture event
IPC0bits.IC1IP = 6; // Setup IC1 interrupt priority level
IFS0bits.IC1IF = 0; // Clear IC1 Interrupt Status Flag
IEC0bits.IC1IE = 1; // Enable IC1 interrupt


// init input capture 1 on Timer 3

IC2CONbits.ICM= 0b000; // Disable Input Capture 2 module
IC2CONbits.ICTMR= 0; // Select Timer3 as the IC2 Time base
IC2CONbits.ICI= 0b00; // Interrupt on every capture event - INT from IC2 DISABLED!!!
// IPC0bits.IC1IP = 6; // Setup IC1 interrupt priority level
// IFS0bits.IC1IF = 0; // Clear IC1 Interrupt Status Flag
// IEC0bits.IC1IE = 1; // Enable IC1 interrupt

gate_flag=0;




}


void F_start (unsigned int gate_time)

{
unsigned int scale;



T5CONbits.TON = 0;
scale = gate_time*(3125/(TOSC*8)) ;
TMR5 = 0x00; // Clear timer register
PR5=scale;
new_data=0;
T2_over=0; //Clear TMR2 overflow
T3_over=0; //Clear TMR3 overflow
TMR2 = 0x00; //Clear timer 2
TMR3 = 0x00; //Clear timer 3
T2CONbits.TON = 1; //Start Timer 2
T3CONbits.TON = 1; //Start Timer 3
IC1CONbits.ICM= 0b011; // Enable IC1, every rising edge
IC2CONbits.ICM= 0b011; // Enable IC2, every rising edge

}

void __attribute__((__interrupt__)) _T2Interrupt( void )
{
T2_over++ ;
IFS0bits.T2IF = 0; /* reset timer interrupt flag */
}


void __attribute__((__interrupt__)) _T3Interrupt( void )
{
T3_over++ ;
IFS0bits.T3IF = 0; /* reset timer interrupt flag */
}


void __attribute__((__interrupt__)) _T5Interrupt( void )
{

T5CONbits.TON = 0;
IC1CONbits.ICM= 0b011; //Enable IC1 , on every rising edge
IC2CONbits.ICM= 0b011; //Enable IC2 , on every rising edge
IFS1bits.T5IF = 0; /* reset timer interrupt flag */
}

// Capture Interrupt Service Routine

void __attribute__((__interrupt__)) _IC1Interrupt(void)
{
unsigned int tmp;




if (!gate_flag)
{
F_osc_start=IC2BUF;
IC2CONbits.ICM= 0b000; //Turn OFF IC2
F_in_start=IC1BUF;
IC1CONbits.ICM= 0b000; //Turn OFF IC1 module
over2_start=T2_over;
over3_start=T3_over;
while (IC1CONbits.ICBNE)
{
tmp=IC1BUF;
}
while (IC2CONbits.ICBNE)
{
tmp=IC2BUF;
}
gate_flag=1;
T5CONbits.TON = 1; //start timer5
}
else
{
F_osc_end=IC2BUF;
IC2CONbits.ICM= 0b000; //Turn OFF IC2
F_in_end=IC1BUF;
IC1CONbits.ICM= 0b000; //Turn OFF IC1 module
over2_end=T2_over;
over3_end=T3_over;
T2CONbits.TON = 0; //Stop Timer 2
T3CONbits.TON = 0; //Stop Timer 3
while (IC1CONbits.ICBNE)
{
tmp=IC1BUF;
}
while (IC2CONbits.ICBNE)
{
tmp=IC2BUF;
}
gate_flag=0;
new_data=1;
}

IFS0bits.IC1IF=0; //reset interrupt flag
}

float F_calc(void)

{
float F;
float M; //input pulse count
float N; //clock pulse count
unsigned long A1,A2 ;




A1=((unsigned long)(over2_end-over2_start))<<16;
A2=((unsigned long)(over3_end-over3_start))<<16;
M=A1+(F_in_end-F_in_start);
N=A2+(F_osc_end-F_osc_start);
if (M == 0) F=0;
else F=(OSCIL*M)/N;
return F;
}



Проблема заключается в том, что данный код примерно в 80% циклов выдаёт правильное значение частоты, а в 20% - таймер Т2 пропускает 1 входной импульс, причем это происходит совершенно хаотично, никакой закономерности я уловить не смог.
Уже довольно долго бьюсь с отладкой, но всё мимо. Будут ли какие-нибудь идеи о причинах такого поведения?
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- shkal   Реализация частотомера обратного счёта на PIC24H   Jul 12 2011, 12:13
- - ar__systems   Цитата(shkal @ Jul 12 2011, 08:13) Добрый...   Jul 12 2011, 21:43
|- - shkal   Цитата(ar__systems @ Jul 13 2011, 00:43) ...   Jul 13 2011, 06:48
- - rx3apf   А при каких порядках входной частоты наблюдается п...   Jul 13 2011, 08:21
- - shkal   При любых. Даже очень низких, хоть 1 Гц. Тут, похо...   Jul 13 2011, 08:37
|- - rx3apf   Цитата(shkal @ Jul 13 2011, 12:37) При лю...   Jul 13 2011, 10:09
- - shkal   Написал простейшую тестовую программу (инициализац...   Jul 13 2011, 14:10
- - rx3apf   Вдумчиво изучать работу схемы синхронизации. Мутор...   Jul 13 2011, 15:16
- - shkal   Так изучай-не изучай, повлиять на работу ея я всё ...   Jul 13 2011, 21:23
- - rx3apf   Я бы: 1) разобрался с синхронизацией IC (в том чис...   Jul 13 2011, 22:15
- - shkal   Нашёл я ответ в документации на pic24f Note1 про...   Jul 14 2011, 11:43
- - rx3apf   Ну, может быть, не все так страшно, если сделать в...   Jul 14 2011, 12:59
- - shkal   Отказался в итоге от захвата таймера, считающего в...   Jul 15 2011, 13:00
- - Марк_Я   Совершенно странное решение, прямо следующее из ле...   Jul 18 2011, 04:04
- - shkal   Уважаемый, читайте внимательно алгоритм по ссылке ...   Jul 20 2011, 11:30
- - Марк_Я   Да нет, любезный автор... Это Вы меряете в качест...   Jul 20 2011, 14:13
- - shkal   Интервал счета формируется от фронтов входного сиг...   Jul 20 2011, 16:01
- - Марк_Я   Да ужжж. Тогда виноват - не понял источника на ссы...   Jul 20 2011, 17:30
- - shkal   Если я правильно понял, у вас захват двух последов...   Jul 22 2011, 20:04
- - Марк_Я   С переполнениями таймера захвата можно решить воп...   Jul 23 2011, 14:15


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

 


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


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