View previous topic :: View next topic |
Author |
Message |
anson
Joined: 27 Apr 2009 Posts: 6
|
AD issue for 16F877A |
Posted: Wed Apr 29, 2009 5:28 am |
|
|
hi guys, does anyone have any idea why my PIC only can work when the R0 input voltage is bigger than 1 V? |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Wed Apr 29, 2009 5:37 am |
|
|
Repeat the question and specify details.
Question you asked is like this: Can anybody tell mi why my car doesn't work. |
|
|
anson
Joined: 27 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 29, 2009 5:43 am |
|
|
sorry man. what i mean is when the input voltage of R0 is less than 1V the PIC totally not working, but while i increase the voltage more than 1V , then it can work. i dont know how to solve it. |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Wed Apr 29, 2009 5:50 am |
|
|
Well first of all, do you measure voltage directly on pin?
How is your reference voltage specified?
How did you set the conversion clock?
If you have VDD-VSS reference and 255 resolution than the minimal voltage, that would register on pin would be in case of 5V power: 5V / 255 = 0,0196 volts. |
|
|
anson
Joined: 27 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 29, 2009 5:55 am |
|
|
yap. i use Vdd which is 5V as my reference voltage and since for PIC 16F877A the ADC results is a 10 bits number so for my case is 5/0x3FF. and i connect RA0 directly to the input voltage. i think i should not float it right? |
|
|
anson
Joined: 27 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 29, 2009 5:58 am |
|
|
here is my code
Code: | void adinitial_voltage(void)
{
// unsigned int AD_data[5]={0,0,0,0,0};
unsigned int i=0,j=0,temp=0;
for(j=0;j<=4;++j)
{
ADCON0=0B01000001;
ADCON1=0B11101110;
ADGO=1;
while(ADGO);
adresult.adre[0]=ADRESL;
adresult.adre[1]=ADRESH;
AD_data[j]=adresult.y1;
}
// unsigned char AD_max=AD_data[0];
// unsigned char AD_min=AD_data[0];
//ADC=0;
//for(i=0;i<18;i++)
//{
// if(AD_data[i]>AD_max)
// {
// AD_max=AD_data[i];
// }
// else if(AD_data[i]<AD_min)
// {
// AD_min=AD_data[i];
// }
// ADC+=AD_data[i];
//}
//ADC=ADC-AD_max-AD_min;
//
for(j=0;j<=4;++j)
if(AD_data[j]>AD_data[j+1])
{temp=AD_data[j];AD_data[j]=AD_data[j+1];AD_data[j+1]=temp;}
ADC=(int)temp*5/0x3FF;
// for(j=0;j<=3;++j)
// if(AD_data[j]<AD_data[j+1])
// {temp=AD_data[j];AD_data[j]=AD_data[j+1];AD_data[j+1]=temp;}
// ADC=((AD_data[0]+AD_data[1]+AD_data[2])/3)/213.20008328128253175098896523006*1000;
// A=ADC*10;
bai=ADC%1000/100;
shi=ADC%100/10;
ge=ADC%10;
// bai=A%10;
// shi=A%1;
// ge=A%1*10;
// delay(1);
}
|
|
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Wed Apr 29, 2009 6:13 am |
|
|
Well first thing I noticed is that all variables are integers.
To be sure that AD is working correctly try to display non-converted value from AD. If this is OK, than problem is in conversion. ;) |
|
|
anson
Joined: 27 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 29, 2009 6:21 am |
|
|
yes, i just display the int number for simple. but what i dont understand is why the input voltage must be more than 1V? when RA0=0.9V,LCD displays nothing, but when RA0=1.1V,LCD displays 'voltage=1'. do you know why? |
|
|
bungee-
Joined: 27 Jun 2007 Posts: 206
|
|
Posted: Wed Apr 29, 2009 7:56 am |
|
|
Try this:
Code: | #include <16F877A.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=8000000)
#include <LCD.C>
void main()
{
int16 adc_value;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
lcd_init();
while (1)
{
adc_value=read_adc();
printf(lcd_putc," Val=%Lu",adc_value);
delay_ms(500);
}
} |
If you have different freq. change code accordingly. |
|
|
Guest
|
|
Posted: Wed Apr 29, 2009 8:20 am |
|
|
Anson,
Just as a matter of style, I'd like to make a few comments:
1. You posted a very imcomplete, and cryptic description of your problem
2. You posted an very incomplete piece of code with 90% of it commented out
3. You didn't even do the most basic troubleshooting yourself
You basically came to the forum and said "this doesn't work... why?"
Have all basic communications and troubleshooting skills gone right out the window??
Dave |
|
|
anson
Joined: 27 Apr 2009 Posts: 6
|
|
Posted: Wed Apr 29, 2009 7:02 pm |
|
|
to above:
1. ok, now let me intro my issue again from starting. Basically what I want to do is using PIC to do the ADC for my current detector. Since now I am testing the ADC function, so I just connect the R0 PIN to input signal. And in order to make sure that the R0 PIN isn't floating, I connect a 4Koms resistor to it.
2. The code I post is the AD part and I think there should have no problem with the LCD display, so I didn't upload it. While I have attached my whole program below without all the commented lines.
3. Of course I had done some troubleshooting. Except the hardware connection checking, I have tried quite a lot ways to do the ADC, this you should see from the code which are commented out.
4. Hope this time I have made a clear description.
5. The crystal oscillator I used is 4MHz, capacitor is 22pF.
Code: |
#include<pic.h>
union adres
{int y1;
unsigned char adre[2];
}adresult;
unsigned int ADC=0;
unsigned int AD_data[5]={0,0,0,0,0};
void adinitial_voltage(void);
const char TABLE[]={'0','1','2','3','4','5','6','7','8','9'};
const char data[3]={'0','0','0'};
#define rs RA1
#define rw RA2
#define e RA3
const char voltage[ ]={'V','O','L','T','A','G','E','='};
unsigned char ge=0,shi=0,bai=0;
void init();
void lcd_init();
void lcd_dis();
void write_voltage();
void write(char x);
void lcd_enable();
void delay();
void main()
{
unsigned char a;
init();
while(1)
{
adinitial_voltage();
lcd_init();
for(a=10;a>=1;a--)
{
PORTD=0X80;
lcd_enable();
delay(20);
write_voltage();
PORTD=TABLE[bai];
lcd_dis();
PORTD=TABLE[shi];
lcd_dis();
PORTD=TABLE[ge];
lcd_dis();
}
}
}
void init()
{
ADCON1=0X0;
TRISA=0B00000001;
TRISD=0X00;
}
void lcd_init()
{
PORTD=0X1;
lcd_enable();
PORTD=0X38;
lcd_enable();
PORTD=0X0c;
lcd_enable();
PORTD=0X06;
lcd_enable();
}
void write_voltage()
{
unsigned char i;
for(i=0;i<=7;i++)
{
write(voltage[i]);
}
}
void write(char x)
{
PORTD=x;
lcd_dis();
}
void lcd_enable()
{
rs=0;
rw=0;
e=0;
delay();
e=1;
}
void lcd_dis()
{
rs=1;
rw=0;
e=0;
delay();
e=1;
}
void delay()
{
int i;
for(i=0;i<50;i++);
}
void adinitial_voltage(void)
{
unsigned int i=0,j=0,temp=0;
for(j=0;j<=4;++j)
{
ADCON0=0B01000001;
ADCON1=0B11101110;
ADGO=1;
while(ADGO);
adresult.adre[0]=ADRESL;
adresult.adre[1]=ADRESH;
AD_data[j]=adresult.y1;
}
for(j=0;j<=4;++j)
if(AD_data[j]>AD_data[j+1])
{temp=AD_data[j];AD_data[j]=AD_data[j+1];AD_data[j+1]=temp;}
ADC=(int)temp*5/0x3FF;
bai=ADC%1000/100;
shi=ADC%100/10;
ge=ADC%10;
}
|
to Bungee: I will try to edit my own code to make it work in case of Bulabula... really appreciate for your help. And maybe you can have a look at my whole program when you are free. Since I just want to make it simple so that when I do the testing I just input a DC value and display the integer number only. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|