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

interrupt generation, code included!

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



Joined: 11 Oct 2003
Posts: 3
Location: New Jersey

View user's profile Send private message

interrupt generation, code included!
PostPosted: Wed Oct 22, 2003 9:47 pm     Reply with quote

Hi,
I am trying to read the A/D channel values using RS232. I am using RA3 as reference. The PIC16F874A should send out the A/D channel data (5 channels totally) when it detects an interrupt (L-H signal) on pin RB0/INT. Could you tell if I am specifying the interrupt correctly and my source code will work as it is supposed to? Here is my source code:

************************************************************
#include <16F874A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

//-------------------------------
// GLOBALS
void putch(unsigned char byte);
char got_interrupt;
#define REF_VOLTAGE 4
#define MAX_A2D 0x3ff
#define VOLTS_PER_BIT REF_VOLTAGE/MAX_A2D
#bit INTF_BIT = 0x0B.1

//-----------------------------
// FUNCTION PROTOTYPES

#int_ext
void int_router(void);

void main() {

int i, value;

// Make pin B0 into an input.
output_float(PIN_B0);
// Wait for inputs to settle.
delay_us(10);

// Initialize the variables used by the interrupt routine,
// before enabling interrupts.
got_interrupt = FALSE;

ext_int_edge(L_TO_H);


// Make sure the external interrupt flag bit is cleared
// before enabling external interrupts.
INTF_BIT = 0;

enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);


// Wait in this loop. Check the got_interrupt flag to see
// if an interrupt occurred. If so, display the count.
// Then clear the flag, wait 50 ms to avoid any "bounce"
// (multiple interrupts) when we press the pushbutton switch,
// which puts Ground on pin B0. Then re-enable interrupts.

while(1)
{

#asm
clrwdt;
#endasm

if(got_interrupt == TRUE)
{


// Clear the global flag which was set in the interrupt
// routine.
got_interrupt = FALSE;

// Wait for interrupt to settle.
delay_us(50);

// Clear any interrupt which might have occurred during the
// debounce period.
INTF_BIT = 0;

// Then re-enable interrupts.
enable_interrupts(INT_EXT);

// Send data through UART depending on the format select
// PIN (PIN B1)
if ( input(PIN_B1) )
{
printf("Reading Channel Data:");

setup_adc_ports( ANALOG_RA3_REF );
setup_adc( ADC_CLOCK_INTERNAL );

for (i=0; i <= 5; i++)
{
//skip channel#3 (Used for
//external reference)
if (i == 3) i++;
set_adc_channel( i );
delay_ms(10);
value = Read_ADC();

//Convert to floating point
value = (float)value * VOLTS_PER_BIT;
printf("\n \r CH %d: %2x", i,value);
}
}

}
}

}

//========================
//interrupt router procedure
#int_ext
void int_router(void)
{

got_interrupt = TRUE;
disable_interrupts(INT_EXT);

}


//void putch(unsigned char byte)
//{
// #BYTE
// TXREG = byte;

//}

*************************************************************

Thanks
Mach
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Oct 22, 2003 10:47 pm     Reply with quote

Quote:
Hi,
I am trying to read the A/D channel values using RS232. I am using RA3 as reference. The PIC16F874A should send out the A/D channel data (5 channels totally) when it detects an interrupt (L-H signal) on pin RB0/INT. Could you tell if I am specifying the interrupt correctly and my source code will work as it is supposed to? Here is my source code:

It would have been better if you had asked about a specific problem.


Code:
#define REF_VOLTAGE 4
#define MAX_A2D 0x3ff
#define VOLTS_PER_BIT REF_VOLTAGE/MAX_A2D

The equation above will evaluate to 0.
If you want a floating point result, you need to specify (or cast)
the REF_VOLTAGE and MAX_A2D values as floating point.



I'm not sure why you're using interrupts. If this is your entire
program, then you don't need to use interrupts. You can just
wait for Pin B0 to go high, in a while() loop. Break out of
the loop when it goes high.

Code:
#asm
clrwdt;
#endasm

CCS has a C function which does this. You should use it:

restart_wdt();

Code:
//Convert to floating point
value = (float)value * VOLTS_PER_BIT;
printf("\n \r CH %d: %2x", i,value);

Because VOLTS_PER_BIT evalutes to 0 (see comments above)
you will always display a value of 0.


Code:
//void putch(unsigned char byte)
//{
// #BYTE
// TXREG = byte;
//}

In this code, you're not using the CCS putc() function.
You're just writing directly to the TXREG without checking
to see if it's available. (which the CCS putc() function does).
So you could possibly over-write a byte that's already in TXREG,
if you write to it very often.
madan



Joined: 11 Oct 2003
Posts: 3
Location: New Jersey

View user's profile Send private message

PostPosted: Fri Oct 24, 2003 6:44 am     Reply with quote

Thanks for your suggestions. I have changed my program to the code below and it seems to work. When a signal goes high on pin RB0, the PIC is sending the 6 channel ADC data through RS232. But the problem is when I apply +5 volts on RB0, the program is sending data continuously. This should not be the case. I want the PIC to send data only once when RB0 signal goes from low to high and again wait for this signal to go from low to high. Also can you tell me if this is the right way to read the A/D channel data!

Here is my code:
#include <16F874A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

//-------------------------------




static float VOLTS_PER_BIT=0.0039;



void main()
{

int i;
float value;

// Make pin B0 into an input.
output_float(PIN_B0);


// Wait in this loop. Check the got_interrupt flag to see
// if an interrupt occurred. If so, display the count.
// Then clear the flag, wait 50 ms to avoid any "bounce"
// (multiple interrupts) when we press the pushbutton switch,
// which puts Ground on pin B0. Then re-enable interrupts.
while(TRUE)
{
while(!input(PIN_B0));


// Send data through UART depending on the format select PIN (PIN B1)

printf("Reading Channel Data:");

setup_adc_ports( ANALOG_RA3_REF );
setup_adc( ADC_CLOCK_INTERNAL );

for (i=0; i <= 6; i++)
{
//skip channel#3 (Used for external reference)
if (i == 3) i++;
set_adc_channel( i );
delay_ms(10);
value = Read_ADC();

//Convert to floating point
value = (float)value * VOLTS_PER_BIT;
printf("\n \r CH %d: %2E", i,value);
}
}



}
Roger Courtney



Joined: 15 Oct 2003
Posts: 3
Location: Cleveland, Ohio

View user's profile Send private message

PostPosted: Fri Oct 24, 2003 10:58 am     Reply with quote

madan wrote:
Thanks for your suggestions. I have changed my program to the code below and it seems to work. When a signal goes high on pin RB0, the PIC is sending the 6 channel ADC data through RS232. But the problem is when I apply +5 volts on RB0, the program is sending data continuously. This should not be the case. I want the PIC to send data only once when RB0 signal goes from low to high and again wait for this signal to go from low to high. Also can you tell me if this is the right way to read the A/D channel data!

Here is my code:
#include <16F874A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

//-------------------------------




static float VOLTS_PER_BIT=0.0039;



void main()
{

int i;
float value;

// Make pin B0 into an input.
output_float(PIN_B0);


// Wait in this loop. Check the got_interrupt flag to see
// if an interrupt occurred. If so, display the count.
// Then clear the flag, wait 50 ms to avoid any "bounce"
// (multiple interrupts) when we press the pushbutton switch,
// which puts Ground on pin B0. Then re-enable interrupts.
while(TRUE)
{
while(!input(PIN_B0));


// Send data through UART depending on the format select PIN (PIN B1)

printf("Reading Channel Data:");

setup_adc_ports( ANALOG_RA3_REF );
setup_adc( ADC_CLOCK_INTERNAL );

for (i=0; i <= 6; i++)
{
//skip channel#3 (Used for external reference)
if (i == 3) i++;
set_adc_channel( i );
delay_ms(10);
value = Read_ADC();

//Convert to floating point
value = (float)value * VOLTS_PER_BIT;
printf("\n \r CH %d: %2E", i,value);
}
}



}


After converting and sending the data, add:
while(input(PIN_B0));
this will force the program to wait until the input pin goes low again before
cycling.
_________________
rnc
madan



Joined: 11 Oct 2003
Posts: 3
Location: New Jersey

View user's profile Send private message

PostPosted: Fri Oct 24, 2003 11:23 am     Reply with quote

Yas after I add while(input(PIN_B0)) at the end of the loop, as suggested, I see that once I toggle the RB0 input, I receive the A/D channel data printed exactly two times on the screen! Any suggestions!

Mach
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