CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

18f24K22. Timer1 causing spurious state changes on CCP2 or 3

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

18f24K22. Timer1 causing spurious state changes on CCP2 or 3
PostPosted: Fri Sep 09, 2016 6:19 am     Reply with quote

Hi all,
Does anybody have any thoughts on this problem.

We have a product that uses the 18f24K22 PIC.
We have 2 pwm outputs generated by using the CCP2 and CCP3 modules in compare mode.
We noticed that very occasionally (on average 5 mins) there would be a big spike on the smoothed PWM output.
Eventually I've narrowed it down to the code below, this shows the problem with just CCP2 running.

For some reason I can't figure out, if timer1 is running (but not used) when I reset timer 3 in the CCP interrupt code the CCP2 output gets set or reset straight away and effectively misses a high or low pulse.
I set another output (LED_A) in the same code which I've also got on the scope.
This test code has the CCP running faster so the problem occurs every 30 seconds or so.

If I comment out the line that enables timer1 the problem does not occur.
But there should be no connection between timer1 and the CCP using Timer3 (also happens on CCP3 using timer5).

If I don't reset timer3 but instead add the period value to CCP2 the problem also doesn't occur. So I have a work around but why is it happening ?

Scope pictures are below, Blue (bottom) trace is the CCP2 output (on B3), the Yellow (top) trace is the LED_A output which is set in the interrupt code so I know the interrupt is being processed.

Compiler version 4.130
I've tried the test code on a pcb with just the processor and the problem still occurs.

Code:


#include <18f24K22.h>
#device ADC=10
#device *=16

#fuses INTRC_IO, put, WDT512, nolvp, nocpd, PROTECT, NOMCLR, WRT, BROWNOUT, NODEBUG, BORV29, NOFCMEN, NOIESO,PLLEN, NOPBADEN, CCP2B3, CCP3B5

#use delay(clock=64000000,RESTART_WDT)

#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(e)

#byte port_a = 0x0f80
#byte port_b = 0x0f81
#byte port_c = 0x0f82
#byte port_e = 0x0f84

#bit led_a = port_a.6
#bit pwm_1 = port_b.3
#bit pwm_2 = port_b.5

int1  pwm_state=0;

#int_ccp2
void compare2_interrupt_handler(void)
{
if(pwm_state==0)
   {
   led_a=0;
   set_timer3(0);
   CCP_2=4096;
   setup_ccp2(CCP_COMPARE_SET_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4);
   }
   else
   {
   led_a=1;
   set_timer3(0);
   CCP_2=4096;
   setup_ccp2(CCP_COMPARE_CLR_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4);
   }
   
pwm_state=!pwm_state;
}


void main()
{
   setup_ccp2(ccp_off);
   setup_ccp3(ccp_off);
   setup_adc (adc_off);
   setup_timer_0(T0_DIV_256 | T0_INTERNAL);
   setup_adc_ports(no_analogs);
   
   setup_timer_1 (T1_INTERNAL | T1_DIV_BY_2 ); // ****** Disable timer 1 and problem does not occur. ******
   
   setup_timer_3 (T3_INTERNAL | T3_DIV_BY_2 );
   setup_timer_5 (T5_INTERNAL | T5_DIV_BY_2 ); 
   
   port_a =   0b00000000;
   set_tris_a(0b00011111);
   
   port_b=    0b00000000;
   set_tris_b(0b10000000);
   port_b_pullups(0);

   port_c =   0b00000010;
   set_tris_c(0b10000000);
   set_tris_e(0b00001000);
   
   CCP_2=4096;
   set_timer3(0);
   setup_ccp2(CCP_COMPARE_SET_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4);
   
   enable_interrupts(int_ccp2);
   enable_interrupts(global);
     
   while(1)
   {
   restart_wdt();
   }
}



Scope pictures:

https://www.dropbox.com/s/g0f07sxr9ql10z9/scope1.jpg?dl=0

https://www.dropbox.com/s/8ak1ki6k43a73bg/scope2.jpg?dl=0

Many thanks,

Jim
newguy



Joined: 24 Jun 2004
Posts: 1903

View user's profile Send private message

PostPosted: Fri Sep 09, 2016 7:55 am     Reply with quote

Does the chip's errata say anything about PWM at all? You might have discovered a chip (silicon) problem. Might be best to open a support ticket with Microchip.

Quite some time ago I found that a documented errata of a dsPIC wasn't quite correct. Even though the errata clearly stated that the documented issue only happened under very specific conditions, it was actually occurring under a slightly broader range of conditions as well. I opened a support ticket with Microchip and they confirmed the issue within a few days' time.
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Sep 09, 2016 8:04 am     Reply with quote

newguy wrote:
Does the chip's errata say anything about PWM at all? You might have discovered a chip (silicon) problem. Might be best to open a support ticket with Microchip.

Quite some time ago I found that a documented errata of a dsPIC wasn't quite correct. Even though the errata clearly stated that the documented issue only happened under very specific conditions, it was actually occurring under a slightly broader range of conditions as well. I opened a support ticket with Microchip and they confirmed the issue within a few days' time.


Hi, yes,
I have checked the errata I could find for this chip and it didn't seem to have anything on it relating to the CCP module and the only thing relating to the timers was if they were in asynchronous mode.

http://ww1.microchip.com/downloads/en/DeviceDoc/80000512H.pdf

My feeling also is it may be a silicon problem but i'd like to be sure it's not a compiler or my code issue before I mention it to Microchip.

Many thanks,

Jim
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Sep 09, 2016 8:24 am     Reply with quote

does this happen if you leave timer1 enabled and shut off the
watchdog code?

also
this does not compile as is
SO where do you define CCP_2 ??
and what is it's purpose ?
( i HOPE as an int16 )

and c'mon here .....

Code:

#int_ccp2
void compare2_interrupt_handler(void)
{
    led_a=pwm_state;
   set_timer3(0);
   CCP_2=4096;
   setup_ccp2(CCP_COMPARE_SET_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4); //THIS LOOKS SUSPECT <<
pwm_state=!pwm_state;
}


LASTLY since all your timers are setup the same
BUT not synchronously - have you considered what happens when you start zeroing JUST timer3 later in your code?

there has to be more going on in this code than you are showing ( since it won't compile anyway) and sorry but i am more concerned with subtle programmer errata than this chip
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Sep 09, 2016 8:51 am     Reply with quote

Hi, thank you for your reply.

asmboy wrote:
does this happen if you leave timer1 enabled and shut off the
watchdog code?


Still the same problem.

Quote:

this does not compile as is
SO where do you define CCP_2 ??
and what is it's purpose ?
( i HOPE as an int16 )


It compiles fine under PCH version 4.130

CCP_2 is the actual compare register for the CCP module.
CCP_2 is declared in the 18F24K22.H CCS header file as:

#word CCP_2 = getenv("SFR:CCPR2L")


Quote:

setup_ccp2(CCP_COMPARE_SET_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4); //THIS LOOKS SUSPECT <<


This is correct as far as I can see, the second half sets which timers the CCPx module uses.
It's in the 18f24K22.h file like this:

Code:
////////////////////////////////////////////////////////////////// CCP
// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
// Constants used for SETUP_CCPx() are:
#define CCP_OFF                         0
#define CCP_CAPTURE_FE                  4
#define CCP_CAPTURE_RE                  5
#define CCP_CAPTURE_DIV_4               6
#define CCP_CAPTURE_DIV_16              7
#define CCP_COMPARE_SET_ON_MATCH        8
#define CCP_COMPARE_CLR_ON_MATCH        9
#define CCP_COMPARE_INT                 0xA
#define CCP_COMPARE_INT_AND_TOGGLE      0x2       
#define CCP_COMPARE_RESET_TIMER         0xB
#define CCP_PWM                         0xC
#define CCP_PWM_PLUS_1                  0x1c 
#define CCP_PWM_PLUS_2                  0x2c
#define CCP_PWM_PLUS_3                  0x3c
//#define CCP_USE_TIMER3                0x100  OBSOLETE, SEE TIMER-3     
#word   CCP_1       =                   getenv("SFR:CCPR1L")
#byte   CCP_1_LOW   =                   getenv("SFR:CCPR1L")
#byte   CCP_1_HIGH  =                   getenv("SFR:CCPR1H")
// The following are used to select the Timer source for the CCP/ECCP
// The first timer is the timer used when in CAPTURE or COMPARE mode
// The second timer is the timer used when in PWM mode
#define CCP_USE_TIMER1_AND_TIMER2       0x0000
#define CCP_USE_TIMER3_AND_TIMER4       0x0100
#define CCP_USE_TIMER5_AND_TIMER6       0x0200



Quote:

LASTLY since all your timers are setup the same
BUT not synchronously - have you considered what happens when you start zeroing JUST timer3 later in your code?


I have tried initialising the timers to different values, indeed, in the full project they are deliberately started at different values so the interrupts don't coincide.

Quote:

there has to be more going on in this code than you are showing ( since it won't compile anyway) and sorry but i am more concerned with subtle programmer errata than this chip


I think I have addressed all your program concerns.

Many thanks,

Jim
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 09, 2016 10:13 am     Reply with quote

Quote:
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_2 );

You have the Timer1 divisor set to /2. That could be the problem.

The PIC16(L)F1768/1769 errata lists a bug that sounds very similar
to your problem. I know it's a different PIC and the CCP mode in the
errata is different than yours. But sometimes Microchip hasn't found or
published all the silicon bugs that exist. I think they likely re-use silicon
modules across many PIC families. Or at least they use one module as
the basis to design a new one. Therefore bugs can be replicated across
PIC familes.

My suggestion is to try the Method 1 work-around below.
Quote:

3. Module: ECCP

3.1 Compare Mode
The ECCP Compare Toggle modes
(CCPxCON<3:0> bits = 0010 or 0001) work
properly as long as the Timer1 prescaler value is
configured to 1:1
. When the Timer1 prescaler
value is configured to any other value, the ECCP
Compare output yields unexpected results
.

Work-arounds -

Method 1:
Only use the Compare Toggle mode when the
Timer1 prescaler value is set to 1:1.

Method 2:
Use CCP Compare mode with pulse output
(CCPxCON<3:0> bits = 1011) to clock a CLC
configured as a J-K flip-flop in Toggle mode.
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Mon Sep 12, 2016 5:31 am     Reply with quote

Hi PCM programmer,
Thank you for your suggestion.
I have tried setting both timer1 only to 1:1 and all 3 timers to 1:1
Unfortunately it has no effect on the problem.
Interestingly slowing timer1 down to 1:8 doesn't seem to make any difference to how often the problem occurs.
So it's just having timer1 enabled that is causing the problem, not it's actual frequency.

I'll send the details to Microchip and see what they have to say.

Many thanks,

Jim
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Mon Sep 12, 2016 1:23 pm     Reply with quote

I'd suspect that during the change from sampling the rising edge to falling edge, the chip is momentarily selecting timer1 (it is the default). If this happens to meet the sampling criteria during this time, you will get a spurious trigger.
Now this is partially because this is a ECCP, which involves several registers being updated.
My suggestion would be to try the following. Read the data sheet and work out the minimum bits that need to change to just change the sampling edge.
Then once the CCP is started, to change the edge, don't use the CCS code, instead manually disable the CCP, and just change the bits that are needed, then re-enable it. If the behaviour changes, then you know you are in the right area.....
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Sep 13, 2016 1:09 am     Reply with quote

Looking at the data sheet, try:
Code:

#byte CCP2CON=getenv("SFR:CCP2CON")
#bit CLR_ON2 = CCP2CON.0

#int_ccp2
void compare2_interrupt_handler(void)
{
   if(CLR_ON2==FALSE)
   {
      led_a=0;
      set_timer3(0);
      CCP_2=4096;
      CLR_ON2=TRUE; //clear on match
   }
   else
   {
      led_a=1;
      set_timer3(0);
      CCP_2=4096;
      CLR_ON2=FALSE; //set on match
   }
}


This also gets rid of the pwm_state variable (uses the bit in the CCP register, saying which edge to work on).
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Sep 13, 2016 2:29 am     Reply with quote

Hi Ttelmah,
Thank you very much for doing that, after your previous message I was going to go through it when I got into work this morning, but you've beaten me to it.

The great news is that this does cure the problem.

I'll brush up on my PIC assembly code and try and figure out which bit of the CCS code for the setup_ccp2(CCP_COMPARE_SET_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4); statement upsets things.

Many thanks for your help,

Jim


Ttelmah wrote:
Looking at the data sheet, try:
Code:

#byte CCP2CON=getenv("SFR:CCP2CON")
#bit CLR_ON2 = CCP2CON.0

#int_ccp2
void compare2_interrupt_handler(void)
{
   if(CLR_ON2==FALSE)
   {
      led_a=0;
      set_timer3(0);
      CCP_2=4096;
      CLR_ON2=TRUE; //clear on match
   }
   else
   {
      led_a=1;
      set_timer3(0);
      CCP_2=4096;
      CLR_ON2=FALSE; //set on match
   }
}


This also gets rid of the pwm_state variable (uses the bit in the CCP register, saying which edge to work on).
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Sep 13, 2016 4:11 am     Reply with quote

Hi All,
After working out what the CCS code for the Setup_ccp2 function was doing the problem becomes apparent, it is as Ttelmah suggested, the source for CCP2 is momentarily set to Timer1 before it is reset to timer3.

Assuming I have understood the assembly correctly, the last few instructions I wasn't familiar with, I think they are new for the PIC 18 chips.



Code:
....................     setup_ccp2(CCP_COMPARE_CLR_ON_MATCH | CCP_USE_TIMER3_AND_TIMER4); 

00E6:  BSF    LATB.LATB3     // bit set LATB3
00E8:  MOVLW  09               // W reg=0x09
00EA:  MOVWF  CCP2CON     // CCP2CON = 0x09
00EC:  CLRF   PWM2CON      // PWM2CON = 0x00         
00EE:  CLRF   ECCP2AS        // ECCP2AS = 0x00
00F0:  MOVLW  01               // W reg = 0x01
00F2:  MOVWF  PSTR2CON   // PSTR2CON = 0x01
00F4:  MOVLW  E7               // W reg = 0xE7
00F6:  MOVLB  F                  // BSR (bank select register) = 0x0F
00F8:  ANDWF  x49,F           // AND W(0xE7) and F  =  AND W (0xE7 0b‭11100111‬)  with SFR 0x49 CCPTMRS0  this selects timer 1 for CCP2 !!
00FA:  MOVLW  08               // W reg = 0x08
00FC:  IORWF  x49,F            // OR W and F  =  OR W (0x08 0b00001000) with SFR 0x49 CCPTMRS0 this selects timer 3 for CCP2


Would this be classed as a compiler bug ??
It would be better to read the CCPTMRS0 register, do the AND and OR operations and then store the result back in the register.
Rather than working directly on the register.

Can somebody with the latest version of the compiler try the original code and see if this function it still compiles to the same assembly code.
Maybe they have already fixed it, the last version I have is PCWH version 4.130

Many thanks for all the help,

Jim
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Sep 13, 2016 7:12 am     Reply with quote

It's a problematical one.

The supplied function, is doing a 'complete' setup on the registers. Lots of I/O control etc., and then the alternative timer setup as the last operation. They didn't contemplate anyone using the 'toggle' trick, and also wanting to use the alternative timers. Adding code to handle just changing the required bit, then means the routine would no longer be performing the full setup. Perhaps an option to just toggle the edge, as a separate routine, would be the nicest solution.

However this is easy to code yourself, and the the bit change route I've posted is even easier. Very Happy

The actual design of the ECCP, makes it harder than it really needs to be, since there is not a single bit to disable the ECCP....
Jim Hearne



Joined: 22 Dec 2003
Posts: 109
Location: West Sussex, UK

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Sep 13, 2016 7:59 am     Reply with quote

Hi Ttelmah,
Yes, maybe I am using the function in an unexpected way.
Though, from searching the net to try and find the problem, it doesn't seem uncommon to use the compare function in this way to generate pwm outputs.

Your method of just changing the one bit works perfectly, and means quite a bit less code in the interrupt routine, always good.

Many thanks,

Jim
Ttelmah



Joined: 11 Mar 2010
Posts: 19368

View user's profile Send private message

PostPosted: Tue Sep 13, 2016 8:13 am     Reply with quote

Good. Smile

Just updated.
I've posted to CCS, suggesting that it would be rather nice to add a new option to the setup_ccp function:

setup_ccp(CCP_CHANGE_TRIGGER_EDGE);

Which should just do this. Allowing the edge to be changed without having to set the other registers.
Hopefully they will consider this a worthwhile suggestion.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group