|
|
View previous topic :: View next topic |
Author |
Message |
madan
Joined: 11 Oct 2003 Posts: 3 Location: New Jersey
|
interrupt generation, code included! |
Posted: Wed Oct 22, 2003 9:47 pm |
|
|
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
|
|
Posted: Wed Oct 22, 2003 10:47 pm |
|
|
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
|
|
Posted: Fri Oct 24, 2003 6:44 am |
|
|
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
|
|
Posted: Fri Oct 24, 2003 10:58 am |
|
|
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
|
|
Posted: Fri Oct 24, 2003 11:23 am |
|
|
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 |
|
|
|
|
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
|