|
|
View previous topic :: View next topic |
Author |
Message |
mitsaras
Joined: 24 Nov 2008 Posts: 9
|
PIC16f819 Analog to Digital conversion |
Posted: Tue Mar 03, 2009 6:47 am |
|
|
Hello,
I generated a code which suppose to read a signal using pins PIN_A0, PIN_A1 and PIN_A2. These are my 3 inputs. The main task is to read the signal and turn on or off a LED. Because the A/D resolution is 10bit, I said that if the input signal on PIN_A0 is greater than 511 (somewhere in the middle cos 1023 max) then make output PIN_B0 high, and if less than 511 make the same pin_B0 low. The same applies to the other 2 inputs.
The problem is that if any of those inputs become high then all outputs become high!
But I wanted for example if PIN_A1 is high, only PIN_B1 to be high and so on !
The code is given below:
Code: | #include <16F819.h> //header file for device
#device ADC=10 //resolution of ADC
#use delay (clock=8000000)
//fuse settings to configure device
//i.e. NO WDT - NO Watchdog Timer, INTRC_IO Internal clock used, pins available for I/O
#fuses NOWDT,INTRC_IO, NOPUT, NOMCLR,NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG,NOPROTECT
//Interrupt Service Routine
// the compiler will gerenate code to jump to the function when the interrupt is detected.
//It will generate code to save and restore the machine state, and will clear the interrupt flag.
#INT_TIMER0
void isr()
{
long AC_CAP = 0;
long DC_CAP = 0;
long CURRENT = 0;
// code for isr
set_ADC_channel( PIN_A0 ); //enable AC Capacitor ADC
delay_us(100);
AC_CAP = read_adc(); //read ADC
if (AC_CAP > 511) //if value > 2.5V LED ON
output_high(PIN_B0);
delay_ms (0);
if (AC_CAP < 511) //if value > 2.5 LED OFF
output_low(PIN_B0);
delay_ms (0);
///////////////////////////////
set_ADC_channel( PIN_A1 ); //enable DC Capacitor ADC
delay_us(100);
DC_CAP = read_adc(); //read ADC
if (DC_CAP > 511) //if value > 2.5V LED ON
output_high(PIN_B1);
delay_ms (0);
if (DC_CAP < 511) //if value < 2.5V LED OFF
output_low(PIN_B1);
delay_ms (0);
////////////////////////////////
set_ADC_channel( PIN_A2 ); //enable current ADC
delay_us(100);
CURRENT = read_adc(); //read ADC
if (CURRENT > 511) //if value > 2.5V LED ON
output_high(PIN_B2);
delay_ms (0);
if (CURRENT < 511) //if value < 2.5V LED OFF
output_low(PIN_B2);
delay_ms (0);
//////////////////////////////////
}
void main() {
setup_oscillator(OSC_8MHZ); //use internal 8MHz clock
SETUP_TIMER_0(RTCC_DIV_2);
setup_timer_1(T1_DISABLED); //TIMER 1 NOT USED
setup_timer_2(T2_DISABLED,0,1); //timer 2 not used, period, postcale
setup_ADC_ports( NO_ANALOGS ); //ALL PORTS DIGITAL
setup_ADC( ADC_CLOCK_DIV_16 ); //SET adc CLOCK, SHOULD BE BETWEEN 1.6us AND 6.4us (1/8MHz X 16 = 2us)
enable_interrupts(INT_TIMER0); //TIMER 0 TO CAUSE INTERRUPT
enable_interrupts(GLOBAL); //Enable interrupts
do
{
//dummy code executed while waiting for interrupt
} while (TRUE);
} |
Regards
Mitsaras |
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 03, 2009 9:22 am |
|
|
Lots of faults.....
Start with your use of the timer interrupt.
You have this set to run off the master clock/8. It'll interrupt every 512 machine instructions. You are then sitting in the interrupt using long delays (a total of 300uSec at least), which is more time than the interrupt will take....
You to interrupt at a _much_ lower frequency, and also shorten the delays as much as possible. Even better, get rid of them entirely. Use a state machine, and perform just one job at a time in the interrupt (first time, select the channel, second time, start the ADC, third time, read the ADC, then perform the first test etc.). A search here will find example code for this approach.
Then, look at the manual for the value that the set_adc_channel function expects. Does it expect pin numbers?.
Fnally, look at how to use an 'else' statement.
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
|