CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Using 18F26K22

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

Using 18F26K22
PostPosted: Tue Mar 14, 2017 4:49 am     Reply with quote

Hi,
I am new to this device and have been studying the datasheet and looking on this forum, but I have questions:

1). I want to use the internal 16MHz oscillator with PLL to give a 64MHz clock.
In the .h file, I have:
Code:

#include <18F26K22.h>
#device ADC=10

#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES WDT                      //Watch Dog Timer
#FUSES WDT1                     //Watch Dog Timer uses 1:1 Postscale
#FUSES NOBROWNOUT               //No brownout 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)
#FUSES NOPLLEN                  //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET

#use delay(clock=64M, internal=16MHz)


I am confused by the PLLEN/NOPLLEN. Why the h/w and s/w versions and when should you use one or the other?

2). I need to drive a relay (via a mosfet) from one of the I/O pins. The relay needs to be de-energised for 30 minutes, energised for one second, de-energised for 30 minutes etc, while the PIC does other things. I presume a timer is the solution, but I can't see the wood for trees on how to implement it! Can anyone assist me please?

Thanks
Brian
temtronic



Joined: 01 Jul 2010
Posts: 9097
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Mar 14, 2017 5:30 am     Reply with quote

First step with PICs, any PIC, all PICs is to cut/compile/test the classic 1Hz LED program. It'll confirm your hardware is good as well as show th ecompiler's fine and the PIC works.
Build upon what works
Add comments to nearly every line of code
Only make a few changes per compile

re: PLL
printout the page with the clock flowchart, use a highlighter to 'follow' the path that you want. It'll show you the various registers and bits needed to be set/cleared for your project
some PICs can set the PLL under software (program ) control.Though I've never seen an application that used it(why??), it's a feature....
others will report I'm sure..

Jay
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Tue Mar 14, 2017 9:01 am     Reply with quote

does NOBODY bother to read data sheets anymore ?

if you are a serious hardware designer the answer
to this question is pretty obvious but for the rest
go to the data sheet and study the graph identified as

FIGURE 28-33: PIC18F2X/4XK22 MAXIMUM IDD: RC_RUN HF-INTOSC with PLL

it shows you can trade 4x speed for 5x current consumption......
this is CMOS circuit design 101 - illustrated


Last edited by asmboy on Tue Mar 14, 2017 9:03 am; edited 1 time in total
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Tue Mar 14, 2017 9:03 am     Reply with quote

Hi,
Thanks for the reply. I agree about the 1Hz LED and will do that. Having programmed for some 30 years (but not all that much with PICs), I know the desirability of thorough commenting!
With the pll, doing as you say is fine, but the datasheet talks about setting registers, whereas CCS doesn't do the same, which is confusing!

Brian
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Tue Mar 14, 2017 9:04 am     Reply with quote

Sometimes also things can be made unnecessarily complex.
Just use:

Code:

#include <18F26K22.h>
#device ADC=10

#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES WDT                      //Watch Dog Timer
#FUSES WDT1                     //Watch Dog Timer uses 1:1 Postscale
#FUSES NOBROWNOUT               //No brownout 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)
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET

#use delay(INTERNAL=64MHz)

Just using the keyword 'INTERNAL', the delay statement will set all the clock fuses and settings for you. The only one you need to add is the INTRC_IO one, otherwise it'll enable the clock out.
It'll in fact wake up with the PLL set to software operation, and the enable it automatically at the start of the code. Reason for this is that the default RC clock selection does not support the PLL.

Now are you sure you want a watchdog this fast?.
Generally even if you intend to use the watchdog, start your development with it off. You need to get your code working 'right' before enabling a watchdog.
Then look through your code. What things have to be happening and when?. If (for instance), the code has to do something every second, and you 'know' that you can test for this happening (in your case possibly update a counter), then have the watchdog set to trigger at just slightly over one second, and clear it if the counter updates correctly.

Why do you want to run this fast?.
Speed costs power. How much else is the PIC having to do?.

The standard way to do what you describe, would be to just have a system 'tick' interrupt at a nice 'sub interval' of one second. Have this operate a When it resets to zero, decrement a 'time' counter.
Easiest to use of of the timers that can have a programmed count. So 2,4,6.

Now if the timer is fed off Fosc/4, these give a maximum division of 16*256*16 = 65536. 16000000/65536 = 244.14 timer per second. So lets choose the slowest easy to use interval just faster than this. Say 1/250th second. Division therefore by 64000. 64000/16 (largest prescaler), gives /4000. Using the largest postscaler (/16 again), means a count of 250 needed. So:

Code:

//some configurations for the timer
enum {WAIT_30, WAIT_1} relay_state=WAIT_1;
//I start by triggering a change from the one second delay to the
//30 minute delay. This will ensure relay is switched off.
#define RELAY_PIN PIN_xx //select to suit your relay

#define ONE_SEC 1
#define THIRTY_MINUTES 1800 //counts for time intervals

#INT_TIMER4
void tick_interrupt(void) //250Hz
{
   static int8 per_sec=1; //trigger a change straight away
   static int16 counter=1; //trigger a change straight away
   if (--per_sec==0)
   {
       per_sec=250; //250 counts per second
       //here once per second
       switch(relay_state)
       {
       case WAIT_30:
          if (--counter==0)
          {
             counter=ONE_SEC;
             output_high(RELAY_PIN); //turn on relay
             relay_state=WAIT_1;
          }
          break;
      case WAIT_1:
         if (--counter==0)
         {
             counter=THIRTY_MINUTES;
             output_low(RELAY_PIN); //turn off relay
             relay_state=WAIT_30;
         }
         break;
      }
   }
} //end of interrupt code     


   //Somewhere at the start of main
   setup_timer_4(T4_DIV_BY_16,249,16); //divisor is PR2 val+1
   enable interrupts(INT_TIMER4);
   enable_interrupts(GLOBAL);


Now what happens is that timer4, will interrupt 250 times per second.

Each time it decrements a counter. If the counter gets to '0', it then decrements a 'slow' counter, which is loaded with either 1 or 1800.
If this gets to zero, it changes the state of the relay pin, and loads the other counter value.

Now I start it by having all the counters containing '1', so the first time the interrupt is called it ensures the relay is turned 'off' and starts the 30minute timer count.
The actual code in the interrupt is tiny. For 249 times it'll just decrement an 8 bit counter, and return if the value is not zero. On the 250th time, it'll decrement a larger counter and return if this is not zero. Only when both are zero, does it update the relay drive pin, and load the new counter value.

Beware if driving a relay. Be very careful to clamp the energy that is in the relay coil when it is turned off. Otherwise you can very easily damage circuitry and cause the code to run badly....
BLL



Joined: 11 Nov 2006
Posts: 181
Location: Birmingham, UK

View user's profile Send private message

PostPosted: Tue Mar 14, 2017 9:50 am     Reply with quote

Hi Ttelmah
Thank you for such a detailed and helpful reply.
As to your question on speed, the PIC will be using both h/w ports at 115200Bd, although the traffic will be small.
In addition, it will be commanding a dual H-bridge driver, operating 2 motors plus 3 relays (including the one in the post). I guess that 16MHz should be fine.

I am using IRFD110 Mosfet switches, which have protection diodes built in, but for belt and braces, I always put a 1N4007 across each coil!

Thank you very much for the timer code - I shall go and play!!

Brian
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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