|
|
View previous topic :: View next topic |
Author |
Message |
Josep Robert
Joined: 27 Mar 2018 Posts: 25
|
PIC18F47K42, Timer1 interrupt and sleep. |
Posted: Wed Oct 28, 2020 7:09 am |
|
|
While porting a code from PIC18LF47K40 to PIC18F47K42 that has the double of ram I found a problem that simplifying a lot is the following.
When I enable_interrupts(INT_TIMER1) regardless of disable_interrupts(GLOBAL) once the times fires for the first time the while(TRUE) loop starts looping without sleeping.
Same code with previous PIC18LF47K40 works fine.
I’ve disassembled the code and didn’t find nothing strange done by the compiler.
The fuses are in their the defaults.
Could someone help me?
Thank you in advance!
Code: |
// PIC18F47K42, Timer1 interrupt and sleep...
// Migrating from PIC18LF47K40
#case
#include <18F47K42.h>
#use delay(clock = 16MHZ, internal)
#define LED PIN_B5
#define PIN_TEST PIN_C2
#INT_TIMER1
void timer1_isr()
{
delay_cycles(1);
}
void main()
{
output_low(LED); delay_ms(500); output_high(LED); delay_ms(500);
setup_timer_1(T1_SOSC | T1_DIV_BY_8); // External xtall 32768Hz
//set_timer1(0x0000); // After 16s PIN_TEST starts to toggle every 2us. 0x0000...0xffff at 32768/8 Hz => 16s.
set_timer1(0x8000); // After 8s PIN_TEST starts to toggle every 2us. 0x8000...0xffff at 32768/8 Hz => 8s.
enable_interrupts(INT_TIMER1); // Without this line sleep works fine. <<<<<<<<<<<<<<<<<<<<<<<<<<<<
disable_interrupts(GLOBAL); // disable doesn't avoid it.
while(TRUE)
{
output_toggle(PIN_TEST); // Toggles every 2us => sleep doesn't work.
sleep();
delay_cycles(1);
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Wed Oct 28, 2020 8:25 am |
|
|
The problem is that the Timer1 interrupt gets set, and you have nothing to
clear it.
Timer1, is one of the peripherals that can wake the chip from sleep, so
once this triggers, it can't go to sleep.
Code: |
while(TRUE)
{
output_toggle(PIN_TEST); // Toggles every 2us => sleep doesn't work.
sleep();
delay_cycles(1);
clear_interrupts (INT_TIMER1);
}
|
Adding the clear, allows the chip to go back to sleep if this interrupt
woke you. Without the clear the interrupt is permanently set once it triggers
so you can't then sleep.
In fact having an enable_interrupts(GLOBAL), would have allowed
the sleep to re-occur, with the interrupt handler then being called after
the wake up, and clearing the interrupt for you. Just with a slight extra
delay when this happens. Without the global enabled, the handler is never
called, so the interrupt is never cleared....
In either case though you will have an 'extra' wake up triggered by the
timer. |
|
|
Josep Robert
Joined: 27 Mar 2018 Posts: 25
|
|
Posted: Fri Oct 30, 2020 5:13 am |
|
|
Thank you very much for your immediate help.
Now works fine.
Regards.
Code: |
// PIC18F47K42, Timer1 interrupt and sleep...
// Migrating from PIC18LF47K40
#case
#include <18F47K42.h> // 20/10/2020 1r 18F47K42 "sense L" provat.
#use delay(clock = 16MHZ, internal)
#define LED PIN_B5
#define PIN_TEST PIN_C2
#INT_TIMER1
void timer1_isr()
{
set_timer1(0x8000);
output_toggle(PIN_TEST); // Toggle pin every 8 seconds.
delay_cycles(1);
}
void main()
{
output_low(LED); delay_ms(500); output_high(LED); delay_ms(500);
setup_timer_1(T1_SOSC | T1_DIV_BY_8); // External xtall 32768Hz
set_timer1(0x8000); // From 0x8000 to 0xffff at 32768/8 Hz => 8s.
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
output_high(PIN_TEST);
while(TRUE)
{
sleep();
delay_cycles(1);
}
}
|
|
|
|
|
|
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
|