I have written a test program that will take a voltage(square pulse of 4V max for 1 second and 2V min for 1 second and then repeat) and check if it is more than 3 volts or less than 3 volts.
My understanding of ADCON registers is nowhere near complete.
Can anyone please spare the time and please check the program listed below and tell me if it is wrong.
#pragma config OSC = INTIO67 #pragma config FCMEN = OFF #pragma config IESO = OFF // CONFIG2L#pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT enabled)#pragma config BOREN = OFF #pragma config BORV = 3 // Brown-out Reset Voltage bits (Minimum setting)// CONFIG2H#pragma config WDT = OFF #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)// CONFIG3H#pragma config CCP2MX = PORTC #pragma config PBADEN = OFF #pragma config LPT1OSC = OFF #pragma config MCLRE = ON // CONFIG4L#pragma config STVREN = ON #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)#pragma config XINST = OFF #include <p18f4520.h>#include <delays.h>#define vref 5.00void adc_INIT();int adc_READ(int);void main(){int digital;float voltage;
OSCCON =0x72;// Set internal oscillator frequency to 8 MHz
adc_INIT();while(1){
digital = adc_READ(1);
voltage = digital*(((float)vref)/((float)1023));
TRISB =0;// Set Port B as Output if(voltage >3.0){
LATBbits.LATB0=1;// RB_0 is high}elseif(voltage <3.0){
LATBbits.LATB1=1;// RB_1 is high}}}void adc_INIT(){
TRISA =0xFF;// Set Port A as the input port
ADCON1 =0x0D;// Set AN0 and AN1 as Analog Input
ADCON0 =0x05;// Select Channel 1 (AN1) and set AD Module ON (ADON = 1)
ADCON2 =0x92;// Right justified, 4*Tad, Fosc/32}int adc_READ(int channel){int digital;
ADCON0 |=0x02;// while(ADCON0bits.GO==1){
digital =(ADRESH*256)|(ADRESL);}return(digital);}
You did not mention what is going wrong, even though the logic above is a little weird. You are raising to the high level different uC pins at opposite conditions (at above lines 50 and 54), but you are not resetting them anywhere. Try working with just one pin, either switching to high or low level at each condition. Another unusual stuff is that you are updating TRISB at the loop, whereas it is expected to be at the init(), running just once.
TRISBbitsB1 =0;// Set Port B bit 1 as Output
TRISBbitsB2 =0;// Set Port B bit 2 as Output
PORTB =0;while(1){
digital = adc_READ(1);if(digital >=0x199){
LATBbits.LATB1=1;// RB_1 is high}elseif(voltage <2.0){
LATBbits.LATB1=0;// RB_1 is low }
voltage = digital*(((float)vref)/((float)1023));if(voltage >=2.0){
LATBbits.LATB2=1;// RB_2 is high}elseif(voltage <2.0){
LATBbits.LATB2=0;// RB_2 is low }}}void adc_INIT(){
TRISA =0xFF;// Set Port A as the input port
ADCON1 =0x0D;// Set AN0 and AN1 as Analog Input
ADCON0 =0x05;// Select Channel 1 (AN1) and set AD Module ON (ADON = 1)
ADCON2 =0x92;// Right justified, 4*Tad, Fosc/32}
This works fine for channel 1(RA1/AN1/ pin no. 3 ) which is supplied with a square wave of 4V peak from function generator at frequency 0.5 Hz and 50% duty cycle and I get two leds(connected to RB1 and RB2) blinking on and off at 1 sec interval. But when I change to channel2 adc_READ(2) and ADCON0 to 0x09 and ADCON1 to 0x0B I don't get any output.
And also is it possible to take to analog inputs simultaneously maybe by somehow implementing parallel processing.
Review commands if and else if at above lines 10 and 14; it doesn`t make any sense evaluating different variables to determine whether output will turn high or low.
Review commands if and else if at above lines 10 and 14; it doesn`t make any sense evaluating different variables to determine whether output will turn high or low.
If it is possible I recommend to set ADC to generate predefined output pattern, e.g. the ramp (digital values from 0 to MAX with step = +1).
Then whatever the analog input is, the ADC generates the ramp output. This can be used to verify many things, i.e. PCB design, clock architecture, ADC malfunction and idelay values (in FPGA).