|
|
View previous topic :: View next topic |
Author |
Message |
Nathan Guest
|
PIC 16F818 Timer 2 Issue |
Posted: Mon Oct 16, 2006 10:46 am |
|
|
Code: |
/**
*** $Revision: 1.7 $
*** $Date: 2006/06/15 11:45:13 $
*** $Author: nathani $
**/
/*****************************************************************************/
/** Includes and Device Configuration **/
/*****************************************************************************/
#include <16F818.h>
#device adc=10
#use delay(clock=8000000)
#fuses NOWDT,INTRC_IO, NOPUT, NOMCLR, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT
#use fast_io(A)
#use fast_io(B)
//#use standard_io(A)
//#use standard_io(B)
/*****************************************************************************/
/** Replacements and Macros **/
/*****************************************************************************/
#define PIR1 0x0C
#define DIGIT_1 PIN_A6
#define DIGIT_2 PIN_A7
#define DIGIT_3 PIN_A2
#define DIGIT_4 PIN_A4
#define SEGMENT_A PIN_B4
#define SEGMENT_B PIN_B6
#define SEGMENT_C PIN_B0
#define SEGMENT_D PIN_B2
#define SEGMENT_E PIN_B3
#define SEGMENT_F PIN_B5
#define SEGMENT_G PIN_B7
#define SEGMENT_DOT PIN_B1
/*****************************************************************************/
/** Global Variables **/
/*****************************************************************************/
int i;
/*****************************************************************************/
/* Interrupt Service Routines */
/*****************************************************************************/
/**************************************************************************/
/* Timer 0 Overflow, Read analog inputs */
#int_TIMER2
void control_timer_isr()
{
bit_clear(*PIR1,1);
}
/*****************************************************************************/
/* Main routine. Called at power up and reset */
/*****************************************************************************/
#zero_ram
void main()
{
//restart_wdt();
setup_adc_ports(RA0_RA1_ANALOG_RA3_REF);
setup_adc(ADC_CLOCK_INTERNAL);
setup_spi(FALSE);
setup_counters(RTCC_INTERNAL,WDT_576MS);
setup_oscillator(OSC_8MHZ);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_4,0,1); //1,953Hz timer or 500us timer
enable_interrupts(INT_TIMER2);
enable_interrupts(global);
SET_TRIS_A(00101011);
SET_TRIS_B(00000000);
output_low(DIGIT_1);
output_low(DIGIT_2);
output_low(DIGIT_3);
output_low(DIGIT_4);
output_high(SEGMENT_A);
output_high(SEGMENT_B);
output_high(SEGMENT_C);
output_high(SEGMENT_D);
output_high(SEGMENT_E);
output_high(SEGMENT_F);
output_high(SEGMENT_G);
output_high(SEGMENT_DOT);
bit_clear(*PIR1,1);
do //Main program loop
{
i++;
switch(i)
{
case 1:
output_high(DIGIT_2);
output_low(SEGMENT_A);
output_high(SEGMENT_DOT);
break;
case 2:
output_high(DIGIT_2);
output_low(SEGMENT_B);
output_high(SEGMENT_A);
break;
case 3:
output_high(DIGIT_2);
output_low(SEGMENT_C);
output_high(SEGMENT_B);
break;
case 4:
output_high(DIGIT_2);
output_low(SEGMENT_D);
output_high(SEGMENT_C);
break;
case 5:
output_high(DIGIT_2);
output_low(SEGMENT_E);
output_high(SEGMENT_D);
break;
case 6:
output_high(DIGIT_2);
output_low(SEGMENT_F);
output_high(SEGMENT_E);
break;
case 7:
output_high(DIGIT_2);
output_low(SEGMENT_G);
output_high(SEGMENT_F);
break;
case 8:
output_high(DIGIT_2);
output_low(SEGMENT_DOT);
output_high(SEGMENT_G);
break;
case 9:
i = 0;
break;
}
delay_ms(250);
} while (TRUE);
} // main()
|
Above is my code. I have been working with 18F's for a little while now, but I’ve been asked to build and analog reader that displays on a 7 seg display, so I thought an 18F would be overkill (stupid me, should spend the extra 1$ and work with what I know) and chose a 16F818. I'm in early development and I can't seem to get it to work. I can get the main loop to run but only if I disable timer2. The weird thing is that I can't get the ICD to program it once I disable timer2 unless I drop the system voltage down to about 3V. The code above does not display anything on the 7 seg but will program with the ICD normally. I'm at my whit's end with this thing and any help would be much appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 16, 2006 12:15 pm |
|
|
I don't have a 16F818 to test. I do have a 16F88, which is a similar PIC.
I stripped down your code, to make the short test program shown below.
It works. On Pin B0, I see a 15.2 KHz square wave on the oscilloscope.
I suggest that you take this code, change only the #include statement
to a 16F818.H and see if it works.
Code: |
#include <16F88.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay (clock=8000000)
#int_timer2
void control_timer_isr()
{
output_toggle(PIN_B0);
}
//==============================
void main()
{
setup_timer_2(T2_DIV_BY_4, 0, 1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while(1);
} |
|
|
|
Nathan Guest
|
|
Posted: Mon Oct 16, 2006 1:38 pm |
|
|
Sorry guys I forgot to mention that I am using the internal clock on the 16F818. I have been reviewing the data sheet and Timer2 doesn't appear to be selectable in this mode (must be drive from external clock). I'm going to try timer0 and get back to you. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 16, 2006 1:51 pm |
|
|
Quote: |
Sorry guys I forgot to mention that I am using the internal clock on the
16F818. I have been reviewing the data sheet and Timer2 doesn't
appear to be selectable in this mode (must be drive from external
clock). I'm going to try timer0 and get back to you. |
Where do you see this in the data sheet ?
In section 8.0 TIMER2 MODULE, the data sheet says this,
in the 2nd paragraph:
Quote: |
The input clock (FOSC/4) has a prescale
option of 1:1, 1:4 or 1:16, selected by
control bits, T2CKPS1:T2CKPS0 (T2CON<1:0>). |
It's driven by Fosc/4, which is completely normal for PICs.
It doesn't say anything about only using an external clock.
Quote: |
The weird thing is that I can't get the ICD to program it once I disable
timer2 unless I drop the system voltage down to about 3V.
|
This shouldn't be happening. My feeling is that there is something
wrong with your external circuits. The MCLR circuit may not be
correct. Some external circuit may be supplying power to the PIC
through an i/o pin, unintentionally. (Via the upper protection diode).
My suggestion is, strip away most of the external circuits, except for
a pullup resistor on MCLR (10K for ICD2, or 47K for CCS ICD), and
also a 100 nF capacitor (0.1 uF) on the Vdd pin, and then run the
program I posted above.
If you can't get it to work after doing that, then post your compiler
version. |
|
|
Natahn Guest
|
|
Posted: Mon Oct 16, 2006 3:32 pm |
|
|
Code: |
#include <16F818.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay (clock=8000000)
#define DIGIT_1 PIN_A6
#define DIGIT_2 PIN_A7
#define DIGIT_3 PIN_A2
#define DIGIT_4 PIN_A4
#define SEGMENT_A PIN_B4
#define SEGMENT_B PIN_B6
#define SEGMENT_C PIN_B0
#define SEGMENT_D PIN_B2
#define SEGMENT_E PIN_B3
#define SEGMENT_F PIN_B5
#define SEGMENT_G PIN_B7
#define SEGMENT_DOT PIN_B1
#int_timer2
void control_timer_isr()
{
output_toggle(PIN_B0);
}
//==============================
void main()
{
output_low(DIGIT_1);
output_low(DIGIT_2);
output_low(DIGIT_3);
output_low(DIGIT_4);
output_high(SEGMENT_A);
output_high(SEGMENT_B);
output_high(SEGMENT_C);
output_high(SEGMENT_D);
output_high(SEGMENT_E);
output_high(SEGMENT_F);
output_high(SEGMENT_G);
output_high(SEGMENT_DOT);
setup_timer_2(T2_DIV_BY_4, 0, 1);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
while(1);
}
|
Ok so this appears to be operating fine. All my pins are as they should be and the BO pin is oscillating (I didn't check it with a scope (don't have one here), but my meter reads a non zero AC voltage and about 2.5 VDC.
This is with my existing circuitry (didn't strip it down). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 16, 2006 4:41 pm |
|
|
My advice is to slowly add the important parts of your program back
into the working program.
There are some things in your code that could be improved:
1. You don't need to use #fast_io, at least not initially. Because you're
using CCS pin i/o functions, the compiler will automatically set the
correct TRIS for you. You therefore don't need the set_tris()
statements.
2. In your original code, you had the #use delay() statement above
the #fuses statement. Notice that in my test program, it's placed
below the #fuses line. That way, the compiler will automatically
put in code to setup the oscillator for the correct speed. You don't
need the setup_oscillator() statement.
3. You don't need to manually turn off the Timer2 interrupt flag inside
the isr. The compiler automatically inserts code to do this.
4. Inside your main() code, you are clearing the Timer2 interrupt flag.
CCS has a function to do this: clear_interrupt(INT_TIMER2);
5. You don't need to turn off the spi module in main(). It's 'off' by
default, upon power-on reset.
6. Normally a little variable like 'i' would be local to main(). It wouldn't
be declared globally. |
|
|
Nathan Guest
|
|
Posted: Mon Oct 16, 2006 4:43 pm |
|
|
Ok so I went out and found myself a scope. I indeed have a square wave. Period is about 62.6 us. About 16KHz. |
|
|
Nathan Guest
|
|
Posted: Mon Oct 16, 2006 5:03 pm |
|
|
Okk... I'm trying to tune the timer2 to be more the frequency i'm looking for. I would like about 500us. I've tried
setup_timer_2(T2_DIV_BY_1, 0, 1);
setup_timer_2(T2_DIV_BY_4, 0, 1);
setup_timer_2(T2_DIV_BY_16, 0, 1);
and RBO comes out with the same frequency every time. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 16, 2006 5:25 pm |
|
|
You need to change the PR2 value to be something other than 0.
This is the middle parameter in the setup_timer_2() function.
Set it to 128 initially, and then you can experiment by changing
it to higher or lower values later. With a PR2 value of 128, you
can change the prescaler and notice the change in frequency. |
|
|
Nathan Guest
|
|
Posted: Mon Oct 16, 2006 5:34 pm |
|
|
Ok, that makes sense. Thanks |
|
|
|
|
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
|