Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Странен проблем с CCP на PIC - моля за помощ
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=2984
Страница 1 от 3

Автор:  t_i_t_o [ Пон Окт 02, 2006 9:09 am ]
Заглавие:  Странен проблем с CCP на PIC - моля за помощ

Меря ширината на един импулс но ПИКа ми дава прекалено много грешни данни, на осцилоскоп ясно се вижда че самите импулси са чисти, остава въпроса защо се получава така? Бъг в ПИКа или аз не правя нещата както трябва?

Това е кода:

Код:
volatile unsigned int16 pulse_width;
int16 ccp2;
#locate ccp2 = 0x1B

#bit FE_RE   = 0x1D.0

#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;
}

п.с. Гарантирано е че таймера има по голям период на препълване от най широкия импулс за мерене.

Преди време за една дипломна работа пак имах същия проблем - мереше се коефициент за запълване от температурен датчик - тогава закърпих нещата, но сега наистина трябва да ги реша :)

Автор:  mndsl [ Пон Окт 02, 2006 9:15 am ]
Заглавие: 

Кой ПИК използваш?

Автор:  Predator_MF [ Пон Окт 02, 2006 12:02 pm ]
Заглавие: 

PIC-а е някаква 16-ка, компилатора като гледам е CCS (където volatile и static нямат ефект).
Проблема е много вероятно да е в следната ти сметка:
Код:
if ( FE_RE )
      ccp2_start = ccp2;
   else
      pulse_width = ccp2 - ccp2_start;

По-точно - при Front меренето приравняваш ccp2_start на регистъра ccp2, който в момента е някакво 16-битово число, при Rear измерване имаш разликата между ccp2 и това число, обаче представи си, че в първия момент (Front) имаш число близко до 65536, във втория момент когато правиш разликата ccp2 вече е превъртял през 0 и получаваш грешна сметка....в случая е много възможно да имаш повече от 50% грешки в зависимост от измерваната честота.

PS: Направи така, че при Front (стартиране) на измерването да зануляваш CCP2, а при следващия импулс просто четеш резултата от него :)

Автор:  valioman [ Пон Окт 02, 2006 1:30 pm ]
Заглавие: 

Нулираш ли таймера преди всяко измерване.

Има чудесен работещ пример май беше за измерването на реакция на реле . Потърси го в примерите на CCS-a.


:)

Автор:  t_i_t_o [ Пон Окт 02, 2006 1:34 pm ]
Заглавие: 

Единия ПИК беше 16ф628 а другия май 16ф87.

Проблема с препълването според мен го няма, просто защото дори и при препълване аритметиката си е правилна стига да е гарантирано че мерения импулс е по малак и не може да позволи таймера да препълни два пъти, пример:
първо мерене 0xFFF0, второ 0x0008, разликата 8-0xFFF0 е 0x0018 - т.е. точно колкото си е.

Друг е въпроса ако наистина статик не важи, т.е. ако стойността не се пази между две извиквания, от друга страна обаче ПИКовете нямат стек за променливи и ако всички променливи са на едно и също място винаги то стойността не би трябвало да се губи.

Според мен няма нужда таймера да се нулира, просто защото аритметиката си е вярна дори и таймера да е препълнил (еднократно).

Автор:  mndsl [ Пон Окт 02, 2006 2:15 pm ]
Заглавие: 

#locate ccp2 = 0x1B
на адрес 0x1B няма нищо - Unimplemented data memory locations, read as ‘0’.

При Capture режима резултата се записва в CCPR1L и CCPR1H регистрите, т.е. в тях се прехвърля стойноста на Таймер1 при импулс на входа. Този ccp2 регистър на адрес 0х1В, освен че не съществува, няма нищо общо с това което искаш да направиш.
Освен това с тази програма дори и да тръгне ще измериш периода на импулсите , а не ширината им ,защото CCP модула се задейства или само по преден или само по заден фронт. За да измериш ширината трябва след като получиш стойноста при предния фронт, да промениш CCP Модула да сработва на заден фронт.

Хората са направили такава хубава документация, ама кой да чете...

Автор:  t_i_t_o [ Пон Окт 02, 2006 2:35 pm ]
Заглавие: 

mndsl написа:
#locate ccp2 = 0x1B
на адрес 0x1B няма нищо - Unimplemented data memory locations, read as ‘0’.

При Capture режима резултата се записва в CCPR1L и CCPR1H регистрите, т.е. в тях се прехвърля стойноста на Таймер1 при импулс на входа. Този ccp2 регистър на адрес 0х1В, освен че не съществува, няма нищо общо с това което искаш да направиш.
Освен това с тази програма дори и да тръгне ще измериш периода на импулсите , а не ширината им ,защото CCP модула се задейства или само по преден или само по заден фронт. За да измериш ширината трябва след като получиш стойноста при предния фронт, да промениш CCP Модула да сработва на заден фронт.

Хората са направили такава хубава документация, ама кой да чете...


Съжалявам че съм те подвел с ПИКа - става дума за 16Ф73, при него точно на 0х1В си е ССР регистъра от който трябва да чета.
А сега по поста ти: пределно ми е ясно как работи ССР модула. Ако малко се загледаш ще видиш че точно втория ред в прекъснването сменя фронтовете.
Доста добре съм проче менюала.

Автор:  mndsl [ Пон Окт 02, 2006 2:54 pm ]
Заглавие: 

Цитат:
става дума за 16Ф73

Ами с това трябваше да започнеш. Като даваш грешно задание е нормално да получиш грешен отговор.

Като се задават такива въпроси трябва да се дава всичка необходима информация. Как е настроен таймер1 и делите му, как е конфигуриран ССП модула, колко е честотата на процесора. Даваш 1 функция и ние трябва да гадаем защо не работи ли?! Вече за 2-и път задавам въпрос за доизясняване и само си губим взаимно времето.

Не го приемай лично, просто казвам на всички като задават въпроси да изясняват всичко, за да се реши проблема с минимално писане и за максимално кратко време.

Автор:  Predator_MF [ Пон Окт 02, 2006 5:56 pm ]
Заглавие: 

Аз все си мисля, че няма да се затрудниш особено да проваш със зануляване на CCP2, два реда имаш да напишеш, пък и песитш едни 2 байта в RAM-а...
Код:
if (FE_RE)
   CCP2 = 0;
else
   pulse_width = CCP2;
   

И недей да разчиташ на CCS компилатора да ти направи сметката, както я написа, освен това за него две различни неща са числото 13 и (unsigned int16)13

Автор:  t_i_t_o [ Вто Окт 03, 2006 8:26 pm ]
Заглавие: 

Нарочно не искам да нулирам таймера (не ССР) защото това ще ми вкара стaтична грешка, т.е. крайния резултат трябва да го събера с времето което е минало от каптуре момента до нулирането на таймера. Разчитам на сметките защото са такива, т.е. при изваждане на голямо от малко число се получава един вид "обратно" препълване (преход от 0 към 0xFFFF) и резултата си е пак както трябва.

Автор:  perlsite [ Вто Окт 03, 2006 9:05 pm ]
Заглавие: 

Виждам, че хем не работи и хем искаш да е по твоя начин :wink:
Защо не пробваш както предлагат колегите... може и да стане :roll: :wink:

Автор:  VSU [ Сря Окт 04, 2006 12:15 am ]
Заглавие: 

Просто защото не е необходимо да го прави както му казват колегите подхода му е правилен така че давай тито

Автор:  Predator_MF [ Сря Окт 04, 2006 12:37 am ]
Заглавие: 

Ами аз съм ползвал CCP в няколко 16-ки, в 12-kа и 18-ка, никъде не съм срещал подобен проблем, мери се абсолютно точно...поне CCP е мястото където Microchip нямат errata и всичко работи както си го пише. Евентуално се опитвам да помогна на колегата t_i_t_o с прост съвет, опита ще отнеме до 5 минути, ама като е сигурен, че проблема не е там, да продължава напред...все пак кода, който е постнал съдържа само тези два реда и по пътя на логиката, като изключим проблем в инициализацията и хардуера на CCP, остава само този код :wink:

Автор:  VSU [ Сря Окт 04, 2006 1:08 am ]
Заглавие: 

Predator много добре знаеш че проблема не е до CCP модула както ти така и аз и много други тук са ползвали кепчара и той си работи .Много вероятно е да има смущаващи импулси които да генерират прекъсване и да дават грешки а най вероятно е да има проблем със софта от един фрагмен от програмата не може да се каже кое как е ами ако има и друго прекъсване а ако има и трето :) ами ако ..... ами ако ..... та нека зор имащите или да постват по обширен код или да тестват само проблема си и тогава да плачат ако са сигурни че проблема е в кода иначе само догадки :)

Автор:  valioman [ Сря Окт 04, 2006 9:01 am ]
Заглавие: 

t_i_t_o написа:
Нарочно не искам да нулирам таймера (не ССР) защото това ще ми вкара стaтична грешка, т.е. крайния резултат трябва да го събера с времето което е минало от каптуре момента до нулирането на таймера. Разчитам на сметките защото са такива, т.е. при изваждане на голямо от малко число се получава един вид "обратно" препълване (преход от 0 към 0xFFFF) и резултата си е пак както трябва.



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

Ами ако точно тук Таймера се препълва и почвва от нулата а преди това ccp2_start ти е примерно 250 а ccp2 ти е 100 ?????

За предпочитане е да истирвеш един период но да си нулираш таймера така резултата ти е сигурен.
А и колко време мислиш отнема едно set_timer1(0);

Поздрави!!!

Страница 1 от 3 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/