|
|
View previous topic :: View next topic |
Author |
Message |
RickMarsen
Joined: 31 Oct 2008 Posts: 17
|
Issue with PIC18F4580 CCP Operation on Power-Up |
Posted: Fri Oct 31, 2008 6:36 pm |
|
|
I am trying to drive an analog tachometer 0-250RPM that normally interfaces with an inductive sensor using a PIC18F4580 running at 20MHz. I am generating the square wave on Pin RC2 using the CCP1 module in Capture mode. The CCP_1 value is set based on a long value from a look-up table (array rpm[n]). I realize the look-up table is not a very elegant way of doing it, but the analog gauge I am driving isn’t very linear so I basically had to “tweak” the CCP_1 value for each tick on the gauge. The RPM value 0-255 comes from a DIP-switch array connected to Port D.
Anyways, it all works quite well and responds almost immediately to DIP-switch changes…EXCEPT that on power-up the output doesn’t start up (sometimes) for several seconds. Other times, the CCP_1 value that was loaded before power-down is still in effect for a few seconds before the newly programmed value takes effect and the square wave frequency changes. The same happens whether I power down, or just ICD-reprogram without powering down. It’s almost as though CCP_1 is not erased by power removal or reprogramming.
Does anyone know what could be causing the issue – I thoroughly looked through the 18F4580 datasheet and could find nothing, although I remember seeing something about Timer1 keeping its value even after a system reset, in another device’s datasheet? Ultimately, I would like to force the output pin low on every power up (as I try to do in the micro_init() function, and have it “start” only when commanded – and with the correct CCP_1 value at that. Any ideas?
Below are the pertinent parts of the code.
Thanks,
RM
Code: | #include <18F4580.h>
#fuses HS,NOPROTECT,NOLVP,NOWDT
#use delay(clock=20000000)
const long rpm[256]={43000,41000,40064,26709,20032,16026,13355,11447,10016,8903,7350,6995,6640,6285, etc};
#int_CCP1
CCP1_isr()
{
if(++count == period)
{
output_toggle(GAUGE_PULSE); //Pin RC2
count = 0;
}
set_timer1(0);
}
void micro_init()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_timer_2(T2_DIV_BY_1,4,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_ccp1(CCP_COMPARE_INT);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
output_low(YELLOW_LED);
output_low(RED_LED);
output_low(GAUGE_PULSE);
}
void main()
{
micro_init();
CCP_1=392;
set_timer1(7000);
read_d=input_d();
period=3;
while(TRUE)
{
if(!(read_d==input_d()))
{
CCP_1=rpm[input_d()];
read_d=input_d();
}
delay_cycles(2);
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 31, 2008 7:10 pm |
|
|
1. Ideally, you should post a minimal program that fails, and that will also
compile. Your code doesn't show any variable declarations. It also has
setup code for many PIC peripherals that are not needed to show the
problem (ADC, other timers, vref, wdt, etc.).
2. Post your compiler version.
3. Add the BROWNOUT fuse.
4. Post a description of your crystal circuit.
5. Post your PIC's Vdd voltage. |
|
|
RickMarsen
Joined: 31 Oct 2008 Posts: 17
|
|
Posted: Fri Oct 31, 2008 7:55 pm |
|
|
Thanks for the reply PCM. Here are the responses
2. PCWH vesrion 3.234
3. Done - problem persists
4. I am not using a crystal, but a an external 20MHz oscillator
5. Vdd = 5V
1. Functional Code:
Code: | #include <18F4580.h>
#fuses HS,NOPROTECT,NOLVP,NOWDT,BROWNOUT
#use delay(clock=20000000)
// Pin Defines
#define YELLOW_LED PIN_B4
#define RED_LED PIN_A5
#define GAUGE_PULSE PIN_C2
// Misc Defines
#define YES 1
#define NO 0
// Not used yet
#use rs232(baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, stream=PC_COMM)
const long rpm[256]={43000,41000,40064,26709,20032,16026,13355,11447,10016,8903,7350,6995,6640,6285,
5930,5575,5220,4865,4510,4155,3800,3675,3550,3425,3300,3175,3050,2925,2800,2675,
2550,2480,2410,2340,2270,2200,2130,2060,1990,1920,1850,1819,1788,1757,1726,1695,
1664,1633,1602,1571,1535,1509,1483,1457,1431,1405,1379,1353,1327,1301,1270,1256,
1242,1228,1214,1200,1186,1172,1158,1144,1125,1111,1097,1083,1069,1055,1041,1027,
1013,999,985,975,965,955,945,935,925,915,905,895,880,871,862,853,844,835,826,817,
808,799,790,782,774,766,758,750,742,734,726,718,712,707,702,697,692,687,682,677,
672,667,657,651,645,639,633,627,621,615,609,603,600,596,592,588,584,580,576,572,
568,564,561,558,555,552,549,546,543,540,537,534,527,524,521,518,515,512,509,506,
503,500,492,489,486,483,480,477,474,471,468,465,462,460,458,456,454,452,450,448,
446,444,437,435,433,431,429,427,425,423,421,419,415,413,411,409,407,405,403,401,
399,397,392,391,390,389,388,387,386,385,384,383,382,380,378,376,374,373,371,369,
368,366,364,363,361,359,358,356,355,353,351,350,348,347,345,344,342,341,340,338,
337,335,334,332,331,330,328,327,326,324,323,322,321,319,318,317,315,314};
int16 period;
int16 count;
// Counter Variables
int i=0;
int k=0;
int16 n=0; // general long counter
int read_d=0; // Stores value of Port D DIP-Switches
// FUNCTION PROTOTYPES
void micro_init();
//INTERRUPTS
#int_TIMER2
TIMER2_isr()
{
delay_cycles(1); // Not used yet
}
#int_CCP1
CCP1_isr()
{
if(++count == period)
{
output_toggle(PIN_C2);
count = 0;
}
set_timer1(0);
}
// MAIN
void main()
{
micro_init();
CCP_1=392;
set_timer1(7000);
read_d=input_d();
period=3;
while(TRUE)
{
if(!(read_d==input_d()))
{
CCP_1=rpm[input_d()];
read_d=input_d();
}
delay_cycles(2);
}
}
void micro_init()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_timer_2(T2_DIV_BY_1,4,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_ccp1(CCP_COMPARE_INT);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
setup_low_volt_detect(FALSE);
setup_oscillator(False);
output_low(YELLOW_LED);
output_low(RED_LED);
output_low(GAUGE_PULSE);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 31, 2008 8:37 pm |
|
|
I didn't look at your code in detail, but one of your complaints is that the
CCP appears come up in some random value. Why not initialize the CCP
before you enable interrupts ? Just move that line above micro_init(),
as shown below in bold:
Quote: |
void main()
{
CCP_1=392;
micro_init();
set_timer1(7000);
read_d=input_d();
period=3; |
|
|
|
RickMarsen
Joined: 31 Oct 2008 Posts: 17
|
|
Posted: Fri Oct 31, 2008 8:50 pm |
|
|
PCM,
That's exactly what the problem was. I've been staring at this code for three days before deciding to post a question.
Almost embarrassed about the solution...
Thanks for all your help. |
|
|
|
|
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
|