Отговори на тема  [ 31 мнения ]  Отиди на страница Предишна  1, 2, 3  Следваща
Странен проблем с CCP на PIC - моля за помощ 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
valioman написа:
А и колко време мислиш отнема едно set_timer1(0);


Две инструкции ASM (най-много 3 с банкирането), не бих разчитал на CCS да ми направи сметката с изваждането, особено след като много пъти съм го хващал да се дъни точно в такива ситуации


Сря Окт 04, 2006 9:49 am
Профил
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Вто Окт 25, 2005 10:54 am
Мнения: 896
Мнение 
Извинявам се че според вас информацията която давам е непълна, просто мислех че давам достатъчно инфо за проблема, ето целия код

Код:
#include <16F73.h>
#include <stdio.h>

#fuses NOWDT,XT, PUT, NOPROTECT, BROWNOUT
#use delay(clock=4000000)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

volatile unsigned int16 pulse_width;

int16 ccp2;
#locate ccp2 = 0x1B

#bit FE_RE   = 0x1D.0
#bit CREN    = 0x18.4

#int_CCP2
CCP2_isr()
{
   static unsigned int16 ccp2_start;

   FE_RE = !FE_RE;

   if ( FE_RE )
      ccp2_start = ccp2;
   else
      pulse_width = ccp2 - ccp2_start;
}

void main()
{
unsigned int ii;

   // init peripherals
   //=================
   set_tris_a( 0b00111111 );
   set_tris_b( 0b00000000 );
   set_tris_c( 0b11111001 );
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
   setup_timer_2(T2_DISABLED,0,1);
   setup_ccp2(CCP_CAPTURE_FE);
   enable_interrupts(INT_CCP2);
   enable_interrupts(GLOBAL);

   // main loop
   //==========
   while ( 1 )
     printf( "%lu\r\n", pulse_width );
}


Принципно кода работи, но нестабилно - резултатите не са постоянни, промъкват се доста грешки, с осцилоскоп на пина се вижда че импулса е достатъчно чист и е с постоянна ширина.
Кода е доста прост... аз все си мисля че проблема не е в кода... но пък след като с осц се вижда че и входния импулс е добре, просто незнам... за опитите опитах и с нулиране на таймера - все тая.


Сря Окт 04, 2006 11:23 am
Профил
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Вто Окт 25, 2005 10:54 am
Мнения: 896
Мнение 
Малко размисли:
така погледнат кода може да прави проблеми ако дойде прекъсване точно когато принтф взима стойността на променливата защото ПИКа е осем битов, т.е. точно в този момент трябва да направя някакаво мутекс подобно синхронизиране на достъпа до променливата, обаче този код дава грешки и когато променливата е сведена до осем битова, т.е. там не може да се получи горния конфликт, просто защото ЦПУто я пише наведъж, с други думи този проблем не е "проблемът" :)


Сря Окт 04, 2006 11:34 am
Профил
Ранг: Напреднал
Ранг: Напреднал

Регистриран на: Нед Авг 14, 2005 1:08 pm
Мнения: 433
Местоположение: Казанлък
Мнение 
Не виждам къде 4истиш флага на прекъсването CCP1IF PIR1<2> oswen ako ne stawa auto в самото прекъсване от компилатора


Сря Окт 04, 2006 1:22 pm
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 17, 2005 5:07 pm
Мнения: 813
Местоположение: Сливен
Мнение 
t_i_t_o написа:

#int_CCP2
CCP2_isr()
{
static unsigned int16 ccp2_start;

FE_RE = !FE_RE;

if ( FE_RE )
ccp2_start = ccp2;
else
pulse_width = ccp2 - ccp2_start;
}





Пробвай това =>
Код:
#int_CCP2
CCP2_isr()
{
   
   FE_RE = !FE_RE;

   if ( FE_RE )
      set_timer1(0);
   else
      pulse_width = ccp2;
     
     
}




Сря Окт 04, 2006 2:11 pm
Профил ICQ
Ранг: Новодошъл
Ранг: Новодошъл

Регистриран на: Вто Май 23, 2006 4:56 pm
Мнения: 113
Местоположение: Варна
Мнение 
VSU написа:
Не виждам къде 4истиш флага на прекъсването CCP1IF PIR1<2> oswen ako ne stawa auto в самото прекъсване от компилатора

Това, което казва VSU трябва да се провери, а другото което може да е проблем е ако при влизане в прекъсване компилатора не запазва текущото състояние на W и STATUS регистрите и съответно да ги възстановява след изход от прекъсването.


Сря Окт 04, 2006 2:21 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Окт 07, 2004 1:22 pm
Мнения: 1949
Местоположение: София
Мнение 
mndsl написа:
VSU написа:
Не виждам къде 4истиш флага на прекъсването CCP1IF PIR1<2> oswen ako ne stawa auto в самото прекъсване от компилатора

Това, което казва VSU трябва да се провери, а другото което може да е проблем е ако при влизане в прекъсване компилатора не запазва текущото състояние на W и STATUS регистрите и съответно да ги възстановява след изход от прекъсването.


Компилатора се грижи за темпорари регистрите, както и за чистенето на флага за прекъсване при излизане от него...аз продължавам да си мисля, че проблема е в зануляването, ама давай все така твърдоглаво и ще напишем 10 страници докато изключим всички възможни варианти, в които се получава грешка :wink:


Сря Окт 04, 2006 2:41 pm
Профил
Ранг: Напреднал
Ранг: Напреднал

Регистриран на: Нед Авг 14, 2005 1:08 pm
Мнения: 433
Местоположение: Казанлък
Мнение 
Я дай малко инфо колко е кварца на ПИКа (ако е разли4ен от 4MHz)колко е приблизително ширината на импулса който мериш в mS (или от колко до колко е)да направя едно опит4е


Сря Окт 04, 2006 5:50 pm
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Вто Окт 25, 2005 10:54 am
Мнения: 896
Мнение 
Кварца е точно 4MHz, меря импулс за товаряне на дюза който е от 1 до 15 ms.


Чет Окт 05, 2006 8:45 am
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Съб Сеп 17, 2005 5:07 pm
Мнения: 813
Местоположение: Сливен
Мнение 
t_i_t_o написа:
Кварца е точно 4MHz, меря импулс за товаряне на дюза който е от 1 до 15 ms.


Пробва ли това което ти писах по горе???


Чет Окт 05, 2006 8:52 am
Профил ICQ
Ранг: Новодошъл
Ранг: Новодошъл

Регистриран на: Вто Май 23, 2006 4:56 pm
Мнения: 113
Местоположение: Варна
Мнение 
t_i_t_o написа:

#int_CCP2
CCP2_isr()
{
static unsigned int16 ccp2_start;

FE_RE = !FE_RE;

if ( FE_RE )
ccp2_start = ccp2;
else
pulse_width = ccp2 - ccp2_start;
}



Дойде ми прозрението :) Проблема е в това - FE_RE = !FE_RE;
По точно мястото му не е там.
Виж какво се получава. При инициализирането установяваш CCP модула да зацепва на преден фронт. При първото прекъсването FE_RE=1. С посочения ред го променяш в 0, след което го проверяваш с If..., но тъй като той вече е 0, се изпълнява второто условие. Дефакто се получава да смяташ ширината без да имаш начална стойност. За да оправиш проблема промени кода така:

#int_CCP2
CCP2_isr()
{
static unsigned int16 ccp2_start;

if ( FE_RE )
ccp2_start = ccp2;
else
pulse_width = ccp2 - ccp2_start;

FE_RE = !FE_RE;

}


Чет Окт 05, 2006 9:40 am
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Вто Окт 25, 2005 10:54 am
Мнения: 896
Мнение 
@мндсл
вероятно си прав но това че първия отчет грешен не е толкова критично, стига всички останали да са ОК. сменянето на условието (или промяната на сетването на фронта на друго място) просто сменя кое да се мери - ниското или високото ниво на импулса

В събота ще се отдам изцяло на тестове - и тогава се надявам да стане ясно какъв е точно проблема, определно ще пробвам всички варианти.


Чет Окт 05, 2006 10:39 am
Профил
Ранг: Напреднал
Ранг: Напреднал

Регистриран на: Нед Авг 14, 2005 1:08 pm
Мнения: 433
Местоположение: Казанлък
Мнение 
TITO защо не ползваш метода който препоръчват

When the Capture mode is changed, a false capture
interrupt may be generated. The user should keep bit
CCP1IE (PIE1<2>) clear to avoid false interrupts and
should clear the flag bit CCP1IF following any such
change in operating mode.

та значи
4етеш си там регистъра при влизане в интеръпт
правиш си сметките

забраняваш CCP1IE
сменяш фронта
разрешаваш прекъсванетo


4истиш флага CCP1IF

излизаш в почивка до следващото


и тито във printf ф-та си сложил lu демек лонг a променливата ти e int провери и това да не е проблема

printf( "%X \r \n", ccp_value ); или printf( "%u \r \n", ccp_value );


ето ти нещо което при мен работи като тест е с друг компилатор съм но :)


bit new_ccp_ready;
unsigned int ccp_value_old,ccp_value_new;
unsigned int ccp_value;
void main()
{
T1CON = 0b00000001; //Start timer 1 preskaler 1:1
CCP1CON = 0b00000101; //0101 = Capture mode, every rising edge
PORTC = 0; TRISC = 0b00000100 ;
CCP1IE = 1; //TMR1IE = 1;
PEIE = 1;GIE = 1;

while(1)
{
if(new_ccp_ready)
{
di();
printf( "%X \r \n", ccp_value );
new_ccp_ready = 0;
ei();
}
}

}


void interrupt isr(void)
{
if(CCP1IF)
{
if(CCP1M0) ccp_value_old = (CCPR1H << 8) | CCPR1L;
else {ccp_value_new = (CCPR1H << 8) | CCPR1L;
ccp_value = ccp_value_new - ccp_value_old;
new_ccp_ready = 1;
}
CCP1M0 ^= 1 ;
CCP1IF = 0;
}

}


Чет Окт 05, 2006 11:37 am
Профил ICQ
Ранг: Почетен член
Ранг: Почетен член

Регистриран на: Вто Окт 25, 2005 10:54 am
Мнения: 896
Мнение 
VSU, мерси за това с забраняването на интеррупта - това наистина може да е проблема... въпреки че аз сменям този флаг в самото прекъсване и не съм много наясно дали е възможно веднага след като изляза от него да ми дойде фалшивото прекъсване т.е. дали пика пъмни прекъсването и го облужва ведната след като завърши тялото на текущото прекъсване.

За принтф - това ми дава грешка и при 8бит променлива и %d така че със сигурност не е от това, освен това при този компилатор лонга е 16 бита, затова съм сложил lu, d май ще принти само интове които тук са 8 битови.


Чет Окт 05, 2006 1:52 pm
Профил
Ранг: Напреднал
Ранг: Напреднал

Регистриран на: Нед Авг 14, 2005 1:08 pm
Мнения: 433
Местоположение: Казанлък
Мнение 
бе що не смениш компилатора в момента в който нулираш флага и има преход от смущение или от нещо друго флага се дига ако компилатора ти го прави ауто нулиране на флага в на4алото то е възможно да го дига по време на сметките ти и след това пак да влиза и да дава грешка


Чет Окт 05, 2006 8:43 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 31 мнения ]  Отиди на страница Предишна  1, 2, 3  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни