|
|
View previous topic :: View next topic |
Author |
Message |
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
CCS C + PIC18F26K22 + Timer |
Posted: Sat Aug 20, 2011 9:18 am |
|
|
Hi Guys,
I am having issues trying to get a 1ms timer to work with CCS C, seems to be the higher I wait for, for example 5000ms (5 seconds) it clocks quicker, if I set it to 1000ms(1 second) it seems to delay for 1 second.
I used this:
Code: |
#byte timer0low = 0xfd6
#int_RTCC
void RTCC_isr(void) {
timer0low = timer0low + 6;
one_millisecond = TRUE;
}
|
and also this:
Code: |
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256);
|
64MHZ (16MHZ + 4XPLL).
I also tried Timer 1 instead, but that doesn't seem to work correctly either!
Am I missing something simple? I have read the datasheet, but cant seem to find any timer calcs.
Wilksey |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Aug 20, 2011 2:18 pm |
|
|
Quote: |
64MHZ (16MHZ + 4XPLL).
RTCC_INTERNAL|RTCC_8_BIT|RTCC_DIV_256);
|
You have Timer0 set as an 8-bit counter. That won't work to get a 1 ms
Timer0 period with a 64 MHz oscillator. Remove that parameter and try
again. Also be aware that Timer0 will clock at 1/4 of the Fosc, which will
be 16 MHz in your case. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sat Aug 20, 2011 3:11 pm |
|
|
I think the divisions would be OK with 8bit mode, except for the calculations being 'out' by the factor of 4. He is using the /256 prescaler, and adding six in the interrupt handler, to give division by 256*250*4 = 256000, so the interrupt frequency would ideally be 4mSec.
However there are a series of 'caveats':
1) The timing will never be accurate. When you write a timer register, it clears the prescaler, so the timer is going to run significantly slow. Section 9.3 in the data sheet. The effect of this will get larger, the faster you try to run the interrupt.
2) Why fiddle?. Use Timer2. Set it to /16 prescaler, 99 count (/100), and /10 postscaler. 1mSec interrupt without having to fiddle with writing values.
Best Wishes |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Sat Aug 20, 2011 4:25 pm |
|
|
Thank you PCM and Ttelmah
I can get a 1ms timer, but when I try to count 5000ms it seems to be more like 500ms if that makes sense.
I dont think that register is correct for the PIC i'm using as when I removed that code it didn't make any difference, so I dont think it was writing that 6 to any register.
I got something hashed together with Timer0 (RTCC), it's not ideal though.
So can I only set up Timer2 as my 1ms timer? I understand the FOSC/4.
Would this be correct for Timer2:
setup_timer_2(T2_DIV_BY_16,99,10);
I want a reliable timer for counting and interrupting at 1ms intervals.
Could the same thing not be acheived with timer0,1,3,4,5 etc?
The only issue is that when I count to 1000ms it works as 1 second, but as I said before 5000ms (5 seconds) only counts half a second, is this a 8/16 bit thing? |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Sat Aug 20, 2011 4:54 pm |
|
|
Ttelmah,
I just tried your Timer2 settings and it is way to fast, seems less than 1/2 a second!
main.c
Code: |
#include <main.h>
#int_TIMER2
void rtcc_timer2(void)
{
milliseconds++;
}
void main()
{
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
//setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit); //1.0 ms overflow
setup_timer_2(T2_DIV_BY_16,99,10);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
delay_ms(50);
while(1)
{
if(milliseconds == 1000)
{
printf("Output...\r\n");
milliseconds = 0;
}
}
}
|
main.h
Code: |
#include <18F26K22.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES PLLEN //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES IESO //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES MCLR //Master Clear pin used for I/O
#FUSES NOSTVREN //Stack full/underflow will not cause reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(clock=64MHz)
#use rs232(baud=38400,parity=N, UART1, bits=8)
int8 milliseconds = 0;
|
Wilksey |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Sat Aug 20, 2011 4:59 pm |
|
|
PCM, just tried your suggestion of removing the RTCC_8_BIT flag, and the timer interrupt doesn't fire at all without this! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Aug 20, 2011 6:01 pm |
|
|
Quote: | int8 milliseconds = 0;
if(milliseconds == 1000) |
What's wrong here ? Data types, data types, data types.
Download the CCS manual:
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Look on page 43 (page 57 in the Acrobat reader). Look at this section:
Quote: | Basic and Special types
|
Note the range of each data type. |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Sat Aug 20, 2011 6:40 pm |
|
|
Hmmm...I see what you're saying...i'm an idiot!!
So, I changed it to int16, and it still isn't giving me quite what I need.
The timer2 code still doesn't work, in fact it doesn't appear to fire at all!
If I remove the RTCC_8_BIT from timer0 code, I have to set RTCC_DIV_1 to get a 4/5 ms delay, but can't seem to acheive 1ms still.
Wilksey |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Aug 21, 2011 2:27 am |
|
|
One thing I notice, you have the comment 'Master Clear pin used for I/O', but have the fuse 'MCLR' which means the master clear pin is enabled, and you must have a pull-up on the master clear pin.
I'd add:
setup_oscillator(OSC_64MHz);
as the first line of the main code. Some compiler versions don't turn the software PLL on, without this.
Don't enable the interrupts, until you have set them up. Won't matter really (just risks an extra trigger), but 'bad practice'.
One thing I notice, is you don't have the NOPBADEN fuse, which means port B will wake up as analog by default.
I rewrote the code to generate a 5 second time using a 1mSec tick on Timer2, as:
Code: |
#include <18F25K22.h>
#FUSES NOWDT, WDT128, INTRC_IO, NOFCMEN, NOIESO, BORV42, WDT_NOSLEEP, NOPBADEN, NOLPT1OSC, NOHFOFST, NOMCLR, NOLVP, NOXINST
#use delay(clock=64000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1,errors)
int16 milliseconds=5000;
#int_timer2
void tick(void) {
if (milliseconds) --milliseconds;
}
void main()
{
setup_oscillator(OSC_64MHZ);
setup_timer_4(T4_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_timer_2(T2_DIV_BY_16,99,10);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
do {
if (milliseconds==0) {
milliseconds=5000;
printf("5 seconds\n\r");
}
} while(TRUE);
}
|
and it merrily displays '5 seconds' on the serial, every 5 seconds exactly.
Using the 'countdown', makes it impossible for the value to be missed if the main loop takes too long (doesn't apply here).
Best Wishes |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Sun Aug 21, 2011 5:07 pm |
|
|
Hi Ttelmah,
Thank you for your reply, I will check your code and see what it does on my board.
Can the code count up instead of down?
I tried adding the setup_oscillator to 64MHZ, but doesn't make any difference, both UARTS i have tried work fine, so im guessing the crystal setting is ok as if it wasn't i'd get garbage.
MCLR is pulled to +5V with a 10k pull up.
I dont think portb pullups are an issue, but I will add that fuse setting in for good practice!
Although, doesn't this override it?
Code: |
setup_adc(ADC_OFF | NO_ANALOGS);
|
Wilksey |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Sun Aug 21, 2011 6:08 pm |
|
|
Hi,
Just tried your code, changed the header to the 26K22, had to remove one of the fuses, cause it didn't exist on my chip, it just sits there and does nothing, I have tested the UART and it works ok, but your code just sits and does nothing?
Wilksey |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Aug 22, 2011 1:47 am |
|
|
What compiler version have you got?.
The fuses should be right. The 25K, and the 26K are identical, except the 26K has more memory. The code ran exactly as it is on a 25K, and compiles with no changes at all to run on a 26K. I wonder if you have an early compiler for the 26K, which has problems setting the chip up....
Best Wishes |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Mon Aug 22, 2011 10:08 am |
|
|
It was this fuse that caused errors:
NOLPT1OSC
I use 4.120
Thanks
Wilksey |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 22, 2011 1:47 pm |
|
|
I was able to make Ttelmah's code work with vs. 4.120 with the following
changes (in various places below). This is the program output:
Quote: |
Start:
5 seconds
5 seconds
5 seconds
5 seconds
|
Here is the test program:
Code: |
#include <18F45K22.h>
#FUSES INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN, NOHFOFST
#use delay(clock=64M)
#use rs232(baud=9600, UART1, ERRORS)
#byte OSCCON2 = getenv("SFR:OSCCON2")
#bit PLLRDY = OSCCON2.7
int16 milliseconds=5000;
#int_timer2
void tick(void)
{
if(milliseconds)
--milliseconds;
}
//=========================
void main()
{
while(!PLLRDY); // Wait until 64 MHz osc is running OK
printf("\n\rStart: \n\r");
setup_timer_2(T2_DIV_BY_16,99,10);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
do{
if(milliseconds==0)
{
milliseconds=5000;
printf("5 seconds\n\r");
}
}while(TRUE);
}
|
Note that testing the PLLRDY bit at the start of main() was the only way
I could get the program to display "Start" correctly at the beginning
of the program. I tried other methods and they didn't work. |
|
|
Wilksey
Joined: 14 Aug 2011 Posts: 36 Location: Somerset, UK
|
|
Posted: Mon Aug 22, 2011 4:00 pm |
|
|
Thanks PCM
I will try that code on my board tomorrow!
Thanks to both of you for all of your patience and help so far!!
Wilksey |
|
|
|
|
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
|