PDA

View Full Version : CCP1CON and CCP2CON strange behaviour - need some advice



Scampy
- 4th March 2013, 18:49
Need some help here,

I have an 18F4520 which has the ability for multiple PWM outputs via CCP1 and CCP2 pins. The code I'm using originally came from a friend who had this working on an 18F2550, but for some reason when ported to an 18F4520 the output on PORTC.2 pulses at around twice per second whilst the output is set. The PWM is working as the pulses start very dim and increase in brightness as the value in the variable is increased and decreases as the variable value is reduced, rather than the LED remaining lit through out the settings. The output on PORTC.1 works fine, in that the LED starts off dim, fades up to full brightness and then fades down to zero.

I've looked at the data sheet (which could be written in Klingon for all I care), and think everything is set right as the LED does increase and decrease in brightness. But I'm at a loss as to what is causing the LED to flash. Here is the bulk of the cod, and would welcome some pointers.

Firstly the includes




'************************************************* ***************
' Include files and configure timers

DEFINE WRITE_INT 1
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _MyTimer, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
endasm

T1CON = %00000001 ; free-running, 1:1 prescaler
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts

ENABLE DEBUG

'************************************************* ***************


and now the configs



'************************************************* ***************
'Port settings

CCP1CON = %00001100 '
CCP2CON = %00001100 '
TRISA = %00000111 'set PORTA as all output apart from 0,1,2
TRISB = %00000011 'set PORTB as all output apart from 0&1
TRISC = %01011111 '

SCLpin var PORTC.3 ' RTC pin - clk
SDApin var PORTC.4 ' RTC pin - data
'************************************************* ***************


and now the main part of the code



'************************************************* ***************
;Initialization

init:
LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD
option=1
Blue_Day_Cycle = NIGHT
White_Day_Cycle = NIGHT
b_cnt = 0
w_cnt = 0

gosub read_eeprom 'Read in the data needed for the lighting periods
gosub Calc_Fade

'************************************************* ***************
;************ Main Program Loop *************
'************************************************* ***************

Main:

If SetButton=0 then ; jump to programming
goto mainmenu
endif

timeH=(RTCHour>>4) 'convert the BCD format of the hours register and store in variable timeH
timeH=(timeH &$03)*10
timeH=timeH+(RTCHour&$0F)

timeM=(RTCMin>>4)
timeM=(timeM &$07)*10
timeM=timeM+(RTCMin&$0F) 'convert the BCD format of the mins register and store in variable timeM


'if B_On_Time_H = timeH and B_On_Time_M = timeM then Blue_Day_Cycle = DAWN
'if W_On_Time_H = timeH and W_On_Time_M = timeM then White_Day_Cycle = DAWN
'if B_Off_Time_H = timeH and B_Off_Time_M = timeM then Blue_Day_Cycle = DUSK
'if W_Off_Time_H = timeH and W_Off_Time_M = timeM then Blue_Day_Cycle = DUSK

'if B_On_Time_H = timeH and B_On_Time_M = timeM then Blue_Day_Cycle = DAWN

gosub calc_fade


'*** Do BLUE daily cycle
select case Blue_Day_Cycle
case DAWN
lcdout $FE,$94,"BL: DAWN "
if b_cnt = B_Fadein_time and B_PWM < B_Max then
B_PWM = B_PWM + 1
b_cnt = 0
endif
if B_PWM = b_max then
Blue_Day_Cycle = DAY
endif
case DAY
lcdout $FE,$94,"BL: DAY "
if timeH = B_Off_Time_H and timeM = B_Off_Time_M then
Blue_Day_Cycle = DUSK
b_cnt = 0
endif
CASE DUSK
lcdout $FE,$94,"BL: DUSK "
if b_cnt >= B_Fadeout_time and B_PWM > B_Min then
B_PWM = B_PWM - 1
b_cnt = 0
endif
if B_PWM = b_min then
Blue_Day_Cycle = NIGHT
endif
case NIGHT
lcdout $FE,$94,"BL: NIGHT"
if timeH = B_On_Time_H and timeM = B_On_Time_M then
Blue_Day_Cycle = DAWN
b_cnt = 0
endif
end select

'*** Do WHITE daily cycle
select case White_Day_Cycle
case DAWN
lcdout $FE,$94+11,"WT: DAWN "
if w_cnt = w_Fadein_time and W_PWM < w_max then
W_PWM = W_PWM + 1
w_cnt = 0
endif
if W_PWM = W_max then White_Day_Cycle = DAY
case DAY
lcdout $FE,$94+11,"WT: DAY "
if timeH = W_Off_Time_H and timeM = W_Off_Time_M then
White_Day_Cycle = DUSK
w_cnt = 0
endif
CASE DUSK
lcdout $FE,$94+11,"WT: DUSK "
if w_cnt >= w_Fadeout_time and W_PWM > w_min then
W_PWM = W_PWM - 1
w_cnt = 0
endif
if W_PWM = W_min then White_Day_Cycle = NIGHT
case NIGHT
lcdout $FE,$94+11,"WT: NIGHT"
if timeH = W_On_Time_H and timeM = W_On_Time_M then
White_Day_Cycle = DAWN
w_cnt = 0
endif
end select
hpwm 1,W_PWM,1500
hpwm 2,B_PWM,1500


lcdout $FE,$80,"BLUES ",dec3 (B_PWM *100)/255,"%"
lcdout $FE,$C0,"WHITES ",dec3 (W_PWM *100)/255,"%"

OWOUT DQ, 1, [$CC, $44] ' Start temperature conversion
OWOUT DQ, 1, [$CC, $BE] ' Read the temperature
OWIN DQ, 0, [temperature.LOWBYTE, temperature.HIGHBYTE]
temperature = temperature */ 1600
lcdout $FE,$D4+11,"TEMP ",DEC(temperature / 100)," C"


I2CRead SDApin,SCLpin,$D0,$00,[RTCSec,RTCMin,RTCHour,RTCWDay,RTCDay,RTCMonth,RTCY ear,RTCCtrl] ; read DS1307 chip
If RTCHour.6=1 then

CounterA=(RTCHour>>4)&$01 ' Work-Out 12 or 24 hour Display for Hours
else
CounterA=(RTCHour>>4)&$03
endif
CounterA=CounterA*10+(RTCHour&$0F) ' Display Hours appropriately for 12 or 24 hour Mode
If RTCHour.6=1 then
LCDOut $FE,$D4,#CounterA
else
LCDOut $FE,$D4,#CounterA Dig 1,#CounterA Dig 0
endif
LCDOut ":",#(RTCMin>>4)&$0F,#RTCMin&$0F


GOTO Main

'************************************************* ***************
;************ Main Program Loop END *************
'************************************************* ***************
' Timer used to scale the PWM pulse
MyTimer:
Tick_Tmr = Tick_Tmr + 1
if Tick_Tmr >149 then ;179
Tick_Tmr = 0
b_cnt = b_cnt + 1
W_cnt = W_cnt + 1
endif
@ INT_RETURN
'************************************************* ***************

Scampy
- 6th March 2013, 20:22
I've been trying to resolve this for days... would welcome some pointers as to what is happening here

Scampy
- 6th March 2013, 22:54
OK...

Looked at the original code for the 2550 and the config settings are



asm
__CONFIG _CONFIG1L, _PLLDIV_1_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
__CONFIG _CONFIG1H, _FOSC_XTPLL_XT_1H & _FCMEM_OFF_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_ON_2L & _BORV_2_2L & _VREGEN_ON_2L
__CONFIG _CONFIG2H, _WDT_OFF_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H & _CCP2MX_ON_3H
__CONFIG _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm


Note the CCP2MX fuse setting. So I added this to the fuse settings for the 4520



ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H & _CCP2MX_ON_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM


But get "symbol not previously defined (CCP2MX_ON_3H)"

So I checked the INC file to see that everything was commented out, and it was



;************************************************* ***************
;* 18F4520.INC *
;* *
;* By : Leonard Zerman, Jeff Schmoyer *
;* Notice : Copyright (c) 2008 microEngineering Labs, Inc. *
;* All Rights Reserved *
;* Date : 09/15/08 *
;* Version : 2.60 *
;* Notes : *
;************************************************* ***************
NOLIST
ifdef PM_USED
LIST
"Error: PM does not support this device. Use MPASM."
NOLIST
else
LIST
LIST p = 18F4520, r = dec, w = -311, w = -230, f = inhx32
INCLUDE "P18F4520.INC" ; MPASM Header
;__CONFIG _CONFIG1H, _OSC_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
;__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
;__CONFIG _CONFIG3H, _CCP2MX_PORTC_3H & _PBADEN_OFF_3H & _LPT1OSC_OFF_3H & _MCLRE_ON_3H
;__CONFIG _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L
NOLIST
endif
LIST
EEPROM_START EQU 0F00000h
BLOCK_SIZE EQU 64


But noticed the way the fuse was worded so copied that to the PBP code thus



ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H & _CCP2MX_PORTC_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM


It compiled fine, but the LED on PORTC.2 (CCP1CON) still flashes whilst the LED fades up and down and the case statement is anything other than NIGHT (off) It's as if something is taking the pin low at regular interval

I would really appreciate some help here guys

Scampy
- 6th March 2013, 23:20
LOL - it does the same thing if I comment out the settings



'************************************************* ***************
'Port settings

'CCP1CON = %00001100 '
'CCP2CON = %00001100 '
TRISA = %00000111 'set PORTA as all output apart from 0,1,2
TRISB = %00000011 'set PORTB as all output apart from 0&1
TRISC = %01000000 '
T2CON = %00000100 ' Timer2 ON + 1:1 prescale

SCLpin var PORTC.3 ' RTC pin - clk
SDApin var PORTC.4 ' RTC pin - data
'************************************************* ***************


so it appears to be ignoring the code altogether

Scampy
- 8th March 2013, 10:41
100 views and not one comment or suggestion... surely someone has some idea as to what's happening ????

HenrikOlsson
- 8th March 2013, 11:17
Hi,
I think you need to try and recreate the issue with as little code as possible. Start from scratch, can you get a steady duty cycle out of both modules without the aditional on/off toggling or does the toggling happen as soon as you try to get PWM out on PortC.2?

/Henrik.

Charlie
- 8th March 2013, 12:08
This is actually a somewhat tricky problem. Without spending a couple hours going through this for you, I'm going to take a shot in the dark. Your description of the problem suggests the value of CCP1 is getting changed at an inopportune time, or the output is being switched to C2 temporarily or there's a bad TRISC or ADCON statement. The most likely cause is that you have a lot of code in your interrupt routine, and you go to it often. It's possible that CCP1 getting set / reset occasionally at unfortunate times because you are off servicing the interrupt. I'd recommend that the interrupt routine set a flag only, or simply increment Tick_Tmr and do the value comparisons (IF..THEN) as part of your main loop.
Just a guess, and maybe a new direction for you to poke.

Scampy
- 8th March 2013, 12:13
Henrik, thanks for the reply and suggestion.

The pulsing only occurs when the conditions are matched for the start of the lighting phase. For example, if the lighting period is set for an hour between 10:00 and 11:00, with a 5 minuet fade up and fade down times, this pulsing happens on C.2 when the time is => 10:00 and <=11:00. But the intensity of the LED fades up correctly between 10:00 and 10:05 and down correctly between 10:55 and 11:00. The thing that really perplexes me is that C.1 works as it should with the LED increasing in brightness, stays lit at full brightness and then fades down until turning off at the set times

Scampy
- 8th March 2013, 13:51
I seriously believe it's something to do with the port config as Charles has mentioned. It's as if the code is ignoring the configuration of this register.

I did think that the problem may be due to the fact that the RTC uses C.3 and C.4 for SLC and SDA lines but if I have read the datasheet correctly, If bits 3-0 are set to 1100 and bits 6 & 7 are set to 00 then P1B, P1C and P1D are set to port pins, but then these appear to point to pins D5, D6 and D7 rather than Port C pins - so that would rule that out

Given the fact that I can comment out the settings for the register and the code behaves exactly the same way does confuse me (easily done) and the fact that channel 2 works ok and it's channel 1 that is screwing up

HenrikOlsson
- 8th March 2013, 15:08
If it IS something with the configuration of the port then you should be able to recreate that with less code than you have now.
I don't think I have any 4520's to test and even if I did there's no way I (or I believe anyone else) could recreate your full setup without goig thru a lot of effort.

Have you tried not using the HPWM command and instead setting the dutycycle registers manually?

I haven't yet been able to tell exactly how things are configured on the 4520 but it looks to me as if there's one CCP module and one ECCP module on the 40-pin devices. If that's the case then there might be some differences between them. However, if both modules are of the ECCP module on the 40-pin devices then of course there should be no difference. Obviously only one of them has the bridge drive mode etc (which you don't use anyway).

/Henrik.

Scampy
- 8th March 2013, 16:13
Thanks again for the input.

I found an example bit of code on the net



ASM
__CONFIG _CONFIG1H, _OSC_HSPLL_1H
__CONFIG _CONFIG2L, _PWRT_ON_2L
__CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
__CONFIG _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H
__CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
ENDASM

DEFINE OSC 48 ; config settings 18F4520, 20mhz crystal
ADCON1 = $0F
clear
duty VAR WORD ' Duty cycle value (CCPR1L:CCP1CON<5:4>)

TRISC.2 = 0 ' Set PORTC.2 (CCP1) to output
CCP1CON = %00001100 ' Set CCP1 to PWM
T2CON = %00000101 ' Turn on Timer2, Prescale=4
PR2 = 249
duty = 200

mainloop:
CCP1CON.4 = duty.0
CCP1CON.5 = duty.1
CCPR1L = DUTY >> 2
duty = duty + 10
Pause 17

IF (duty < 800) Then mainloop
duty = 200
GoTo mainloop


The LED on CCP1CON (pin C.2) still flashes at the same rate as my original code whilst it runs through the loop to fade the LED :(

So it must be hardware related. I have a port splitter to allow two connections to the header pins on the EasyPIC5 board, with the RTC module attached to one set of pins on the splitter, and the breadboard connector to the other. As this example code didn't need the RTC I removed that and plugged the breadboard directly to the header pins on the EasyPIC5 board - No more pulsing of the LED, it ramped up over and over again...

So this issue is either hardware related, or the fact the RTC is connected to same port is interfering with the CCP1CON settings...

I therefore breadboarded the RTC chip and connected the breadboard direct to PORTC - It works.... so that's one addon board that will be confined to the bin !! I can't believe that it was a simple bit of hardware that could cause the issue...

Feel like a prat now... thanks Henrik for your assistance - I can now get on with the rest of the project !

HenrikOlsson
- 8th March 2013, 17:50
Hi,
Glad you've narrowed it down.
What's actually on that splitter board? Is it just passive or are there some buffers or the like on it?
I don't know if RMW can have an impact on the normal I/O-pins or maby if the normal I/O pins can have an impact on the PWM-outputs. Since getting rid of the splitter seems to solve the issue it does sound like a possible RMW issue or capacitive coupling, reflection or whatever.

/Henrik.

Scampy
- 8th March 2013, 18:24
Hi,

It's just a passive board, with a single female header on one side and two mail headers on top

6887

I think I've discovered what was happening. Looking at the schematic for the RTC2 add-on board there is an SQW pin which outputs a square wave that can be used as an interrupt... when this is plugged into the header on the EasyPIC5 board this SQW pin on the header connects to PORTC.2, hence the regular pulsing.

I didn't twig that this issue only rose it's head when I chose to use external LEDs to see what was happening as the status display LEDs for C1 and C2 on the EasyPIC5 board are covered by the 4 x 20 LCD. So much wasted time, and my apologies for wasting your time trying to troubleshoot a non-code related issue

sayzer
- 9th March 2013, 08:11
Hi,
.....So much wasted time, and my apologies for wasting your time trying to troubleshoot a non-code related issue

Nevertheless, problem solved, right? What does it matter anyway.