View previous topic :: View next topic |
Author |
Message |
Guest
|
Porting Timer0 code from 16f877 to 18f8620 |
Posted: Sat Jan 17, 2004 9:23 am |
|
|
Hello everyone!
I wrote a bit of code based on the CCS example for using the Timer0 interrupt as a 1 second counter. I used it on a 16f877 running at 20Mhz and it works beautifully. Here it is, you've seen it before...
Code: |
#define INTS_PER_SECOND 76
int8 int_count=0;
#int_rtcc
clock_isr()
{
//this block maintains timer variables with a resolution of a ~ 1 s
if(--int_count==0)
{
int_count=INTS_PER_SECOND; //reset
//...flip a LED or something
}
}
////stuff in main
int_count=INTS_PER_SECOND;
set_timer0(0);
setup_timer_0
setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
|
Ok that being said
When I port this code as is to an 18f8620 running at the same speed, the resolution of my "1 second action" becomes something like 4 minutes. I thought I understood the formulas to compute the INTS_PER_SECOND and what not but its obviously not correct. (Yet I have verified that the interrupts are working)
SO... I understand that the 18xxxx series has a 16bit value for their timer0 but I don't see why have to change anything. (... that is... I don't see yet why)
Can someone out there help me a bit with this |
|
|
Birdasaur
Joined: 07 Oct 2003 Posts: 29
|
Use Timer2 instead of Timer0 |
Posted: Sat Jan 17, 2004 9:48 am |
|
|
I suppose you could use Timer2 instead of Timer0, then the code would work fine.
Timer0 became a 16bit counter on the 18xxxx series, which screws up the math, although I don't know how actually.
Timer2 never changed, remaining an 8bit counter just like Timer0 on the 16xxxx series.
So... cop out and just use #int_timer2 instead!
I hope somebody can explain a timer0 solution though. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Jan 18, 2004 8:37 pm |
|
|
I don't have any datasheets with me right now, but if memory serves right, timer0 defaults to 16 bits but you can set it to operate in 8 bit mode. I believe CCS supports this in the setup timer function. |
|
|
Birdasaur
Joined: 07 Oct 2003 Posts: 29
|
Anyone have an example... |
Posted: Mon Jan 19, 2004 7:38 am |
|
|
I see that mentioned in the help files but I don't quite get it. (The 8bit options for timer0 on the 18xxxx series...)
Does anyone out there happen to use the timer0 in this manner? (setting it in 8bit mode instead of the default 16bit?) |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Jan 19, 2004 7:53 am |
|
|
Timer0 can be 8 bits and yes I used this when porting code up to the PIC18F from the 16F. |
|
|
Birdasaur
Joined: 07 Oct 2003 Posts: 29
|
Code example... |
Posted: Mon Jan 19, 2004 8:45 am |
|
|
Could you or anyone else out there lay down a quick code example for us on forcing timer0 into 8bit mode? |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Jan 19, 2004 9:04 am |
|
|
Here is CCS's function:
Code: |
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16 | RTCC_8_BIT);
|
or you can just set the T08BIT bit in the T0CON register. |
|
|
Birdasaur
Joined: 07 Oct 2003 Posts: 29
|
Full example that works |
Posted: Tue Jan 20, 2004 7:25 am |
|
|
Ok so I went and tried it and this works, thanks to Mark for pointing out the way.
Code: |
#define INTS_PER_SECOND 76 //Processor and clock specific
#define LED0 PIN_J0
int8 int_count=0;
int8 data = 0;
//////////////////////////////////////////////////
#int_rtcc
clock_isr()
{
//this block maintains timer variables with a resolution of a ~ 1 s
if(--int_count==0)
{
int_count=INTS_PER_SECOND; //reset
if(data == 0)
{
output_low(LED0);
data = 1;
}
else
{
output_high(LED0);
data = 0;
}
}
}
void main(void)
{
int_count=INTS_PER_SECOND;
setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while(1) { }
}
|
So um... the LED turns on and off at about a 1 second rate. I haven't had the time or desire to time it. Good luck everyone. |
|
|
AZAPPS2 Guest
|
Problem using example |
Posted: Mon Feb 02, 2009 12:12 pm |
|
|
I am using a PIC18f4520.
I ran the example that Birdasaur posted, and I couldn't get it to work. My LED never flashes. I scoped it to make sure it wasn't flashing too quickly for me to see it, and it just never flashes.
The strange thing is, when I use my rs232 interface to xmit some test outputs to my computer screen, I get junk (from bad rs232 timing). I have already verified that my rs232 interface works correctly. This makes me think that there is a issue with the way my clock is programmed. I've programmed my clock the exact same way several times before, and it always works perfectly. In this case, since I'm running at 32 MHz, I should see the LED flash approximately 6x per second.
Can you please include your entire c file, including the #fuses and the # delay statments?
Here is my file:
Code: | #include <18F4520.h>
#device PASS_STRINGS = IN_RAM
#device HIGH_INTS=TRUE
#include <stdio.h>
#include <string.h>
#use delay(INTERNAL=8M, clock=32M)
#fuses INTRC//, DEBUG
struct portb_pin_map {
unsigned short led0; // Unused
unsigned short led1; // Unused
unsigned short led2; // Unused
unsigned short DTR; // output ready for connection
unsigned short RTS; // output ready to receive
unsigned short CTS; // input clear to send
unsigned short bit6; // Unused
unsigned short bit7; // Unused
} portb;
#locate portb = getenv("sfr:PORTB")
#use rs232(BAUD=9600, XMIT=PIN_C1, RCV=PIN_C0, BITS=8, PARITY=N)
void my_transmit_a(char *tx, int cr) {
int a=0;
while(tx[a]) {
putc(tx[a]);
a++;
}
if(cr) putc(13);
putc(10);
}
#define INTS_PER_SECOND 76 //Processor and clock specific
int8 int_count=0;
int8 data = 0;
#int_rtcc
clock_isr()
{
//this block maintains timer variables with a resolution of a ~ 1 s
putc('x');
if(--int_count==0)
{
int_count=INTS_PER_SECOND; //reset
if(data == 0)
{
portb.led1=0;
data = 1;
}
else
{
portb.led1=1;
data = 0;
}
}
}
void main(void)
{
int_count=INTS_PER_SECOND;
setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while(1) { }
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 02, 2009 12:35 pm |
|
|
Quote: | I ran the example that Birdasaur posted |
The Birdasaur code uses output_low() and output_high() which set the
correct TRIS. You are not using that code. You have substituted code
that writes directly to the PortB register. The TRISB is set to all inputs
upon power-on reset of the PIC. You need to set TRISB with a
set_tris_b() statement near the start of main(). |
|
|
AZAPPS2 Guest
|
Problem with Example (cont.) |
Posted: Mon Feb 02, 2009 1:28 pm |
|
|
PCM Programmer,
Thank you for your response. However, I did set the trisb to output in my main function in my actual program. I just didn't include that line of code in my post on the forum. That was my mistake. However, I ran his EXACT example & it didn't work. Then I modified it a little to the code that I posted, and it failed in the exact same way.
I just found out that the board I'm using has some mechanical damage that I wasn't aware of. Apparently it had been dropped and isn't working, even though it doesn't look damaged. I switched out the board and the code now works.
Thank you for your time. |
|
|
|