|
|
View previous topic :: View next topic |
Author |
Message |
pic_micro
Joined: 07 Feb 2011 Posts: 26
|
Awake from sleep with ADC interrupt |
Posted: Wed Feb 23, 2011 11:21 pm |
|
|
I want to awake the mcu from sleep mode using the adc interrupt and the portb change. I got the portb change work fine, but I could not get the adc interrupt part to awake the processor from sleep.
Is there a special way to do this?
I use the mechatronic demo board with 16f917 processor.
here are my files:
main.c
Code: | include <mechatronic.h>
#include "interrupt.c"
//----------------------------------------------
//Main program start here
void main()
{
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
read_adc(ADC_START_ONLY);
port_b_pullups(0xF0); // Enable pull-ups on pins B4-B7
temp = input_b(); // current value on portb
clear_interrupt(INT_RB); // ensure interrupt is clear before enable interrupt
enable_interrupts(INT_AD);
enable_interrupts(INT_RB4); // enable intertupt b on change b4
enable_interrupts(GLOBAL); // enable global interrupt
while(1)
{
if(!input(SW4)) //if sw4 press, go to sleep
{
printf("\r\n");
printf("Processor is SLEEP\n\r");
sleep();
}
else // else MCU alive.
{
output_high(LED2);
delay_ms(100);
output_low(LED2);
delay_ms(100);
printf("\r\n");
printf("Processor is A LIVE\n\r");
}
}
}
|
interrupt.c
Code: |
//Global variables
int8 x;
int8 temp;
int1 done;
unsigned char adc_result;
//----------------------------------------------
// Interrupt Service Routine
#INT_RB
void interrupt_ISR()
{
x = input_b(); // copy PORTB to x
output_toggle(LED1); // turn led on d7
delay_ms(10);
clear_interrupt(INT_RB); // clear interrupt
}
#INT_AD
void ADC_ISR()
{
adc_result = read_adc();
clear_interrupt(INT_AD);
} |
mechatronic.h file
Code: | /*
File name mechatronic.h, it is an include file
*/
#include <16F917.H>
#device ICD=TRUE ADC=10
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define SW3 PIN_B4
#define SW4 PIN_A5
#define LED1 PIN_D7
#define LED2 PIN_D6
#define FALSE 0
#define TRUE 1
|
|
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Feb 24, 2011 12:37 am |
|
|
Except for the initial read_adc(ADC_START_ONLY), there's no statement, that would start an ADC conversion.
read_adc() is waiting for the conversion to complete and doesn't cause a new interrupt. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19541
|
|
Posted: Thu Feb 24, 2011 3:58 am |
|
|
Code: |
//Main program start here
void main()
{
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
port_b_pullups(0xF0); // Enable pull-ups on pins B4-B7
temp = input_b(); // current value on portb
clear_interrupt(INT_RB); // ensure interrupt is clear before enable interrupt
enable_interrupts(INT_RB4); // enable interrupt b on change b4
enable_interrupts(GLOBAL); // enable global interrupt
while(1)
{
if(!input(SW4)) //if sw4 press, go to sleep
{
printf("\r\n");
printf("Processor is SLEEP\n\r");
//To wake using the ADC, you don't need an ADC int handler, and
//don't want other interrupts enabled.
disable_interrupts(GLOBAL); //prevent handlers being called
disable_interrupt(INT_RB4);
enable_interrupt(INT_AD);
clear_interrupt(INT_AD);
//Now start the ADC conversion
read_ADC(ADC_START_ONLY);
//and immediately sleep - you have _one_ instruction time to do this
sleep();
//Instruction after the sleep is 'prefetched' - should be a NOP
delay_cycles(1);
//When you wake, the ADC has completed the conversion
adc_result=read_adc(ADC_READ_ONLY);
disable_interrupt(INT_AD);
enable_interrupt(INT_RB4);
enable_interrupt(GLOBAL);
}
else // else MCU alive.
{
output_high(LED2);
delay_ms(100);
output_low(LED2);
delay_ms(100);
printf("\r\n");
printf("Processor is A LIVE\n\r");
}
}
}
|
The ADC interrupt triggers 12 cycles of the ADC clock after the conversion is started.
I don't think it'll actually do what you want. The only way to get the ADC interrupt to trigger, is to start a conversion. Nothing will happen from the ADC interrupt while you are asleep otherwise...
You don't want other interrupts enabled while performing a 'sleep' ADC conversion. The whole 'point' of it, is to have the processor 'halted' to get rid of the noise sources. If other interrupts are enabled, they will potentially introduce noise.
You can trigger a ADC conversion using the CCP module, provided this is clocked from an external clock, and this could then wake the chip.
You can though on chips with the comparator, wake on a _comparator_ interrupt, when a voltage goes beyond a specified level. This might be more in line with what you want?.
Best Wishes |
|
|
|
|
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
|