View previous topic :: View next topic |
Author |
Message |
buchtsucht
Joined: 14 May 2010 Posts: 20
|
18LF46K22 with #fuses WDT sleeps for ever - solved |
Posted: Fri Dec 02, 2011 8:02 am |
|
|
I had many problems with the 18LF46K22:
The CTMU sometimes did not work while a PIN is set by PWM - the only solution was to check the PWM-timer if it will roll over and may wait with CTMU.
(Parasitic capacitances inside the chip?).
I am not able to activate PIN D4 for PWM. Datasheet says it is a alternative PWM PIN, but don´t tell me how to do = which register must be written.
CCS v.4.120 cant´t do anything too.
Now I am stupid (not many experience with sleep) or there is a bug too:
After sleep the CPU can only be waked up by a reset on MCLR.
I can do what I want or wait 10 Minutes:
After reset MCLR I see only one single peak=delay_cycles(10) on my scope.
Code: |
#include <18LF46K22.h>
#fuses WDT
//#fuses WDT_SW
#fuses WDT1
#fuses MCLR
#fuses INTRC
#FUSES IESO
void Main()
{ //SETUP_TIMER_1(T1_INTERNAL|T1_DIV_BY_1);
//enable_interrupts(INT_TIMER1);
//enable_interrupts(GLOBAL);
//setup_wdt(wdt_on);
//set_Tris_D(0);output_d(0);
while(1)
{ output_high(PIN_D5);delay_cycles(10);
output_low (PIN_D5);
sleep();
output_high(PIN_D5);delay_cycles(200);
output_low (PIN_D5);}
} |
MPLAB v8.76 / CCS v.4.120
Last edited by buchtsucht on Sat Dec 03, 2011 4:55 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Dec 02, 2011 10:07 am |
|
|
The ECCP module, can produce a PWM output on this pin, but not by involving re-routing. It is the standard pin for it's second output, and you can connect a single pwm output to this with:
setup_CCP1(CCP_PWM_H_H | CCP_PULSE_STEERING_B);
Which selects it's 'B' output to be used.
You should check that CCS updates the TRIS when you do this. Generally they have a habit of forgetting to change the TRIS settings when alternative pins are selected....
Now, onto sleep. Your code as posted, has nothing setup to wake the chip from sleep, so 'of course' it stays asleep until you reset.
Any _asynchronous_ interrupt, can be set to wake the chip. So:
Code: |
#include <18LF46K22.h>
#fuses WDT
#fuses WDT1
#fuses MCLR
#fuses INTRC
//#FUSES IESO //unless you have a second oscillator, don't use
void Main(void) {
portb_pullups(0b00000001); enable pullup on pin B0
while(1) {
output_high(PIN_D5);
delay_cycles(10);
output_low (PIN_D5);
//Do not enable global interrupts, unless you have an interrupt handler
//for int_ext
disable_interrupts(GLOBAL);
enable_interrupts(INT_EXT_H2L); //enable EXT interrupt on falling edge
clear_interrupt(INT_EXT); //ensure interrupt is clear
sleep();
delay_cycles(1); //This instruction is prefetched when you sleep
//Use a NOP here - delay_cycles(1) gives this.
disable_interrupts(INT_EXT); //Disable here before you enable any
//other interrupts.
output_high(PIN_D5);
delay_cycles(200);
output_low (PIN_D5);
}
}
|
Now, the chip will sleep, and it's clock will stop. This is why the interrupt source must be one that doesn't depend on a processor clock (asynchronous). If you pull down pin B0, the chip will start.
Basically, it'll wake, if any 'enabled' interrupt, gets it's interrupt flag set. Because the 'global' flag is _not_ set, it won't call a 'handler', but just wake up.
Best Wishes |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Fri Dec 02, 2011 3:53 pm |
|
|
On why the WDT doesn't wake it - you have stopped the WDT oscillator....
Look at section 2.7 in the data sheet.
You must set the oscillator to stay running in sleep if you want to use the WDT to wake - look at OSC_IDLE_MODE in the setup oscillator instruction.
Best Wishes |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Fri Dec 02, 2011 11:41 pm |
|
|
Thanks, I forgot to say, I want to wake up the PIC by WDT. And I tried several settings for Interrupts / Timer1 / LFINTOSC - no success.
I read 2.2 / 2.7 / 3.3 in Datasheet, but maybe I understand something wrong.
Datsheet S 51: ......If the WDT is selected, the LFINTOSC source will continue to operate.....When a wake event occurs in Sleep mode (by interrupt, Reset or WDT time-out), the device will not be clocked
until the clock source selected by the SCS<1:0> bits becomes ready (see Figure 3-5), or it will be clocked from the internal oscillator block if either the Two-Speed Start-up or the Fail-Safe Clock Monitor are enabled.....
Following work at my other PICs but not here:
Code: |
#include <18LF46K22.h>
#fuses WDT
#fuses WDT1
#fuses MCLR
#fuses INTRC
#FUSES IESO
#FUSES FCMEN
// CPU-CLOCK
#byte OSCCON = 0xFD3
#byte OSCCON2 = 0xFD2
#byte OSCTUNE = 0xF9B
void Main(void) {
OSCCON = 0b00000010; // needs <10 µA
OSCCON2 = 0b00000000; // needs <10 µA
OSCTUNE = 0b00000000; // needs <10 µA
// setup_oscillator(OSC_31250);// needs 370µA!
// setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);
while(1) {
output_high(PIN_D5);
delay_cycles(10);
output_low (PIN_D5);
disable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
//clear_interrupt(INT_TIMER1);
sleep();
delay_cycles(1);
//disable_interrupts(INT_TIMER1);
output_high(PIN_D5);
delay_cycles(200);
output_low (PIN_D5);
}
} |
PIC18(L)F4XK22
Datasheet Page 25: D4 => Enhanced CCP2 PWM output.
Datasheet Page 178: CCP2MX=0 => B3 / CCP2MX=1 => C1
No comment about CCP2 / D4 anywhere else in the datasheet
CCS: ////////Fuses:.........CCP2B3,CCP2C1.......CCP2C0,CCP2D.........2CCP3E0,CCP3B5, but nothing with D4 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sat Dec 03, 2011 3:43 am |
|
|
The point is that most watchdog have the watchdog automatically running if enabled. On this chip, it doesn't. The sleep mode is designed for _super_ low power, and defaults to stopping _everything_. As I said, look at 'OSC_IDLE_MODE' in the setup_oscillator instruction. You 'OR' this with the oscillator mode you select, and this enables the oscillator to stay running in idle mode. Then the WDT will run, but sleep draws a little more power.
Best Wishes |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Sat Dec 03, 2011 4:54 am |
|
|
Thanks Ttelmah. I am not able to aktivate the WDT as I want, but it works very well like this:
(Current consumtion is about 1 µA or less while sleep)
Code: |
#include <18LF46K22.h>
#fuses NoWDT
#fuses MCLR
#fuses INTRC
// CPU-CLOCK
#byte OSCCON = 0xFD3
#byte OSCCON2 = 0xFD2
#byte OSCTUNE = 0xF9B
// Voltage reference
#byte VREFCON0 = 0xF42
void Main(void) {
setup_comparator(NC_NC_NC_NC);
setup_ADC(ADC_OFF);
SETUP_DAC(DAC_OFF);
SETUP_WDT(WDT_Off);
SET_TIMER0(T0_OFF);
SET_TIMER2(T2_DISABLED);
SET_TIMER3(T3_DISABLED);
SET_TIMER4(T4_DISABLED);
SET_TIMER5(T5_DISABLED);
SET_TIMER6(T6_DISABLED);
SETUP_CCP1(CCP_OFF );
SETUP_CCP2(CCP_OFF );
SETUP_CCP3(CCP_OFF );
SETUP_CCP4(CCP_OFF );
SETUP_CCP5(CCP_OFF );
SETUP_SPI(SPI_DISABLED);
VREFCON0=0b00010000;
set_Tris_A(0b00000000);output_a(0);
set_Tris_B(0b00000000);output_b(0);
set_Tris_C(0b00000000);output_c(0);
set_Tris_D(0b00000000);output_d(0);
set_Tris_E(0b00000000);output_e(0);
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_1);
OSCCON = 0b10000011;
OSCCON2 = 0b00000000;
OSCTUNE = 0b00000000;
while(1) {
output_high(PIN_D5);
delay_cycles(10);
output_low (PIN_D5);
disable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER1);
clear_interrupt(INT_TIMER1);
set_timer1(65000);
sleep();
delay_cycles(1);
disable_interrupts(INT_TIMER1);
output_high(PIN_D5);
delay_cycles(20);
output_low (PIN_D5);
}
} |
(Was it not the idea of the WDT, that I can programm the biggest rubbish, one thing is everytime certain: WDT makes a reset if not cleared erverytime. I can´t understand, that a WDT makes no reset if I write #fuses NoWDT) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sat Dec 03, 2011 5:12 am |
|
|
Code: |
#include <18LF46K22.h>
#fuses WDT1
#fuses MCLR
#fuses INTRC_IO
#use delay(CLOCK=4000000);
void Main(void) {
setup_oscillator(OSC_4MHZ);
while(1) {
output_high(PIN_D5);
delay_cycles(10);
output_low (PIN_D5);
//Down to low speed oscillator, staying on when asleep
setup_oscillator(OSC_31250 | OSC_INTRC | OSC_IDLE_MODE);
sleep();
delay_cycles(1); //This instruction is prefetched when you sleep
//Use a NOP here - delay_cycles(1) gives this.
//Back up to normal oscillator
setup_oscillator(OSC_4MHZ);
output_high(PIN_D5);
delay_cycles(200);
output_low (PIN_D5);
}
}
|
Best Wishes |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Sat Dec 03, 2011 10:34 pm |
|
|
This code gives me only one peak on skope, then sleeping for ever............ |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19498
|
|
Posted: Sun Dec 04, 2011 4:11 am |
|
|
With the idle enabled, it should work.
However some compilers do unnecessary fiddling with the bits.
So:
Code: |
#include <18LF46K22.h>
#fuses WDT1
#fuses MCLR
#fuses INTRC_IO
#use delay(CLOCK=4000000);
#byte OSCTUNE = getenv("SFR:OSCTUNE")
#bit INTSRC=OSCTUNE.7
void Main(void) {
setup_oscillator(OSC_4MHZ);
while(1) {
output_high(PIN_D5);
delay_cycles(10);
output_low (PIN_D5);
//Down to low speed oscillator, staying on when asleep
setup_oscillator(OSC_31250 | OSC_INTRC | OSC_IDLE_MODE);
INTSRC=0; //select LFINTOSC
sleep();
delay_cycles(1); //This instruction is prefetched when you sleep
//Use a NOP here - delay_cycles(1) gives this.
//Back up to normal oscillator
setup_oscillator(OSC_4MHZ);
output_high(PIN_D5);
delay_cycles(200);
output_low (PIN_D5);
}
}
|
Which forces the chip into running on the LF oscillator before switching.
That should work with all compiler versions....
It _should_ have worked for you, with 4.120, with just:
Code: |
#include <18LF46K22.h>
#fuses WDT1
#fuses MCLR
#fuses INTRC_IO
#use delay(CLOCK=4000000);
void main()
{
setup_oscillator(OSC_4MHZ | OSC_INTRC | OSC_IDLE_MODE);
while(1) {
output_high(PIN_D5);
delay_cycles(10);
output_low (PIN_D5);
sleep();
delay_cycles(1); //This instruction is prefetched when you sleep
//Use a NOP here - delay_cycles(1) gives this.
output_high(PIN_D5);
delay_cycles(200);
output_low (PIN_D5);
}
}
|
Rather puzzled that it doesn't.....
You are testing directly on a hardware chip, and not an ICD?. Some simulators, and some ICD's don't support watchdog operation. Check the 'exclusions' list in their data, just in case.....
Best Wishes |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Mon Dec 05, 2011 9:11 am |
|
|
Both give just one pulse on my scope.....
I am programming with Pickit3, remove it, connect power, (make a reset) and look on my scope.
I don´t understand those things. I tried hundreds of settings with no success.
I give up now.
Maybe the chip is not O.K. ( I don´t think so because a lot of protection circuits on board), there is a bug on chip and/ or a problem with reset.
Even I have a perfect reset circuit as told in Datasheet, just the µC, caps and ESD protection on board, it makes with some settings a difference in current consumption while sleep if I had made a reset with removing Ubat (120µ...240µA) or without (ca 1µA). The µC with its complex software behaves absolute same in both cases only difference in Power consumption while sleep. I can´t find the problem here too.
If I don´t write 500 times different values in the CCP2 register after reset before using ccp2, it sometimes did not work after reset and I am not the only one with those problems:
http://www.ccsinfo.com/forum/viewtopic.php?t=44564&highlight=18f45k22
I had never such problems with other chips (PIC18LF252,PIC18LF23K22...) before, I think, that this chip was not a good choice.... |
|
|
buchtsucht
Joined: 14 May 2010 Posts: 20
|
|
Posted: Mon Dec 05, 2011 11:18 pm |
|
|
And I forgot to to say:
Thanks for your help, Ttelmah |
|
|
|