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 CCS Technical Support

#INT_AD NOT WORKING

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



Joined: 06 Mar 2007
Posts: 92
Location: Pune,India

View user's profile Send private message AIM Address Yahoo Messenger

#INT_AD NOT WORKING
PostPosted: Sat Mar 31, 2007 12:23 am     Reply with quote

Dear Sir,
here i am using 16f684, MPLAB 7.5 Ver. & CCS PCM C Compiler, Version 3.249, 34534.

In this i am using ADC channel 0 & 1 for temperature sensing.
here i want to use #INT_AD isr,but it is not working.
but if i wrote programme without #INT_AD isr i.e. in main() it works fine.
plz tell me what is wrong with my code
see following code

/*************************************************/
#if defined(__PCM__)
#include <16F684.h>

#fuses INTRC_IO,NOWDT,PUT,NOMCLR,PROTECT,NOCPD,NOBROWNOUT,NOPROTECT,NOIESO,NOFCMEN
//Internal RC Osc, no CLKOUT,No Watch Dog Timer,Power Up Time ON,Internal MCLR,Code Protect ON,No EE protection,Brownout detect OFF,
#device ADC=10
#use delay(clock=8000000)

void fun1();
void fun2();

unsigned int16 TEMP1_VALUE,TEMP2_VALUE;

void main()
{

/**************** PORT SETTINGS ***********************/

PORT_A_PULLUPS(FALSE); // External Pull-ups used.ss
SET_TRIS_A(0X0B); // I/P = RA0,RA1,RA3. O/P = RA2,RA4,RA5.
SET_TRIS_C(0X10); // I/P = RC4. O/P = RC0,RC1,RC2,RC5.

/**************** COMPARATOR SETTINGS ***************/
SETUP_COMPARATOR(NC_NC_NC_NC);

/**************** INTERRUPT SETTINGS *****************/

ENABLE_INTERRUPTS(GLOBAL);
ENABLE_INTERRUPTS(INT_TIMER0); //enable timer0 interrupt

/**************** ADC SETTINGS *********************/

SETUP_ADC_PORTS(sAN0 |sAN1| VSS_VDD ); // PIN A0 IS ANALOG & ALL OTHER DIGITAL
SETUP_ADC( ADC_CLOCK_INTERNAL ); // INTERNAL CLOCK FOR ADC
ENABLE_INTERRUPTS(INT_AD); //enable ADC interrupt

while(TRUE)
{
fun1();
fun2();


}


}

/****************** this will works without using #INT_AD isr ******************/
void fun1()
{

SET_ADC_CHANNEL(1); // CHANNEL_1 FOR Temperature I/P.
TEMP_VALUE = READ_ADC(); // SOC & EOC
if(TEMP1_VALUE <= 827) // check Temp. below 35 degree C.(Vol. at Pin = 2.1v for 35 degree & Max = 2.6v)
{
OUTPUT_HIGH(PIN_C2);
}
else
OUTPUT_LOW(PIN_C2);
}
void fun2()
{

SET_ADC_CHANNEL(0); // CHANNEL_0
Temp2_VALUE = READ_ADC(); // SOC & EOC

}

/**************************************************/

/*************** Not working *******************/
#INT_AD
void ADC_isr()
{
SET_ADC_CHANNEL(1); // CHANNEL_1 FOR Temperature I/P.
TEMP_VALUE = READ_ADC(); // SOC & EOC
if(TEMP1_VALUE <= 827) // check Temp. below 35 degree C.(Vol. at Pin = 2.1v for 35 degree & Max = 2.6v)
{
OUTPUT_HIGH(PIN_C2);
}
else
OUTPUT_LOW(PIN_C2);
SET_ADC_CHANNEL(0); // CHANNEL_0
Temp2_VALUE = READ_ADC(); // SOC & EOC

}

/****************************************************************/
_________________
Thank You,
With Best Regards,
Deepak.
Ttelmah
Guest







PostPosted: Sat Mar 31, 2007 2:30 am     Reply with quote

You only get an interrupt from the ADC, when it has _finished_ a conversion. Something needs to trigger the conversion to take place (it is not automatic...).
Now your 'working' code, has problems. There needs to be a pause between selecting an ADC channel, and readng it. The ADC input, behaves as an internal capacitor in the chip, with a series resistor. It takes _time_ for the ADC capacitor to charge to a newly selected voltage. Read the chip's data sheet. This explains how to calculate the time needed.
Typically, something in the order of 10 to 12uSec, must be allowed after selecting the channel, before taking a reading.
Now on the interrupt driven version, there are then further problems.
First, something needs to trigger the ADC conversion to occur. This can be another piece of code in the main, or can be triggered by the CCP module.
Then when the conversion has occured, it is _too late_ to select the channel. The ADC conversion has already occured. Ideally, the channel should be selected after the last conversion completes, to again allow the charging time.
Then, in the routine, you are incorrectly using 'read_adc' The 'read_adc' routine, actually performs three operations when called without a value:
1) Trigger a conversion
2) Wait for conversion to complete
3) Read the result.
You can select the individual parts of this separately, by adding a command value to the routine. So:
read_adc(ADC_START_ONLY);
will trigger an ADC conversion, without waiting for this to complete (if you called this in the main, a few uSec latter, an int_adc, would occur when the conversion was completed.

read_adc(ADC_READ_ONLY);
will return the ADC value only. This is what is needed in an interrupt routine.

Now I have to ask, what you hope to 'gain' from using an ADC interrupt?. In general, at 8MHz, calling an interrupt handler, and returning from it, will take a minimum of perhaps 25uSec. This is longer than the complete ADC conversion takes, if performed in the 'main' code.
The ADC interrupt, is useful, to give synchronous reading of the ADC, when used with the CCP module, but otherwise is unlikley to gain you anything.

Best Wishes
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