| Автор |
Съобщение |
|
Predator_MF
Ранг: Форумен бог
Регистриран на: Чет Окт 07, 2004 1:22 pm Мнения: 1949 Местоположение: София
|
Две инструкции ASM (най-много 3 с банкирането), не бих разчитал на CCS да ми направи сметката с изваждането, особено след като много пъти съм го хващал да се дъни точно в такива ситуации
|
| Сря Окт 04, 2006 9:49 am |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 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 |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
Малко размисли:
така погледнат кода може да прави проблеми ако дойде прекъсване точно когато принтф взима стойността на променливата защото ПИКа е осем битов, т.е. точно в този момент трябва да направя някакаво мутекс подобно синхронизиране на достъпа до променливата, обаче този код дава грешки и когато променливата е сведена до осем битова, т.е. там не може да се получи горния конфликт, просто защото ЦПУто я пише наведъж, с други думи този проблем не е "проблемът" 
|
| Сря Окт 04, 2006 11:34 am |
|
 |
|
VSU
Ранг: Напреднал
Регистриран на: Нед Авг 14, 2005 1:08 pm Мнения: 433 Местоположение: Казанлък
|
Не виждам къде 4истиш флага на прекъсването CCP1IF PIR1<2> oswen ako ne stawa auto в самото прекъсване от компилатора
|
| Сря Окт 04, 2006 1:22 pm |
|
 |
|
valioman
Ранг: Почетен член
Регистриран на: Съб Сеп 17, 2005 5:07 pm Мнения: 813 Местоположение: Сливен
|
|
| Сря Окт 04, 2006 2:11 pm |
|
 |
|
mndsl
Ранг: Новодошъл
Регистриран на: Вто Май 23, 2006 4:56 pm Мнения: 113 Местоположение: Варна
|
Това, което казва VSU трябва да се провери, а другото което може да е проблем е ако при влизане в прекъсване компилатора не запазва текущото състояние на W и STATUS регистрите и съответно да ги възстановява след изход от прекъсването.
|
| Сря Окт 04, 2006 2:21 pm |
|
 |
|
Predator_MF
Ранг: Форумен бог
Регистриран на: Чет Окт 07, 2004 1:22 pm Мнения: 1949 Местоположение: София
|
Компилатора се грижи за темпорари регистрите, както и за чистенето на флага за прекъсване при излизане от него...аз продължавам да си мисля, че проблема е в зануляването, ама давай все така твърдоглаво и ще напишем 10 страници докато изключим всички възможни варианти, в които се получава грешка 
|
| Сря Окт 04, 2006 2:41 pm |
|
 |
|
VSU
Ранг: Напреднал
Регистриран на: Нед Авг 14, 2005 1:08 pm Мнения: 433 Местоположение: Казанлък
|
Я дай малко инфо колко е кварца на ПИКа (ако е разли4ен от 4MHz)колко е приблизително ширината на импулса който мериш в mS (или от колко до колко е)да направя едно опит4е
|
| Сря Окт 04, 2006 5:50 pm |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
Кварца е точно 4MHz, меря импулс за товаряне на дюза който е от 1 до 15 ms.
|
| Чет Окт 05, 2006 8:45 am |
|
 |
|
valioman
Ранг: Почетен член
Регистриран на: Съб Сеп 17, 2005 5:07 pm Мнения: 813 Местоположение: Сливен
|
Пробва ли това което ти писах по горе???
|
| Чет Окт 05, 2006 8:52 am |
|
 |
|
mndsl
Ранг: Новодошъл
Регистриран на: Вто Май 23, 2006 4:56 pm Мнения: 113 Местоположение: Варна
|
Дойде ми прозрението  Проблема е в това - 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 |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
@мндсл
вероятно си прав но това че първия отчет грешен не е толкова критично, стига всички останали да са ОК. сменянето на условието (или промяната на сетването на фронта на друго място) просто сменя кое да се мери - ниското или високото ниво на импулса
В събота ще се отдам изцяло на тестове - и тогава се надявам да стане ясно какъв е точно проблема, определно ще пробвам всички варианти.
|
| Чет Окт 05, 2006 10:39 am |
|
 |
|
VSU
Ранг: Напреднал
Регистриран на: Нед Авг 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 <<  | CCPR1L;
else {ccp_value_new = (CCPR1H <<  | CCPR1L;
ccp_value = ccp_value_new - ccp_value_old;
new_ccp_ready = 1;
}
CCP1M0 ^= 1 ;
CCP1IF = 0;
}
}
|
| Чет Окт 05, 2006 11:37 am |
|
 |
|
t_i_t_o
Ранг: Почетен член
Регистриран на: Вто Окт 25, 2005 10:54 am Мнения: 896
|
VSU, мерси за това с забраняването на интеррупта - това наистина може да е проблема... въпреки че аз сменям този флаг в самото прекъсване и не съм много наясно дали е възможно веднага след като изляза от него да ми дойде фалшивото прекъсване т.е. дали пика пъмни прекъсването и го облужва ведната след като завърши тялото на текущото прекъсване.
За принтф - това ми дава грешка и при 8бит променлива и %d така че със сигурност не е от това, освен това при този компилатор лонга е 16 бита, затова съм сложил lu, d май ще принти само интове които тук са 8 битови.
|
| Чет Окт 05, 2006 1:52 pm |
|
 |
|
VSU
Ранг: Напреднал
Регистриран на: Нед Авг 14, 2005 1:08 pm Мнения: 433 Местоположение: Казанлък
|
бе що не смениш компилатора в момента в който нулираш флага и има преход от смущение или от нещо друго флага се дига ако компилатора ти го прави ауто нулиране на флага в на4алото то е възможно да го дига по време на сметките ти и след това пак да влиза и да дава грешка
|
| Чет Окт 05, 2006 8:43 pm |
|
|