Jump to content

Recommended Posts

Can any one help me to find the error on this program, It compiles OK but I cannot see any data in adres registers when I run the program. I only need to check analogue values in one channel (AN0).

Thank you

samith

 

 

 

#include <system.h>

 

 

#pragma CLOCK_FREQ 4000000

//#pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _CP_OFF

 

unsigned int Read_adc(unsigned char ch);

unsigned short adcvalue;

void Adc_init();

 

void main()

{

//Initialise PortB

trisb = 0; //configure port B

portb = 0; //clear port B

//initiolise portA

trisa= 1; //porta as input

 

 

Adc_init();

 

while(1)

 

{

unsigned int val; //Adc value

val=Read_adc(0); //read channel 0

 

}

 

portb=adcvalue;

}

 

//AD intiolisation

void Adc_init()

 

{

set_bit( adcon1, ADFM ); // AD result needs to be right justified

 

//clear_bit(adcon1,ADCS2); //this register only used for 877A

 

clear_bit( adcon1, PCFG0 ); // one analogue in put

set_bit( adcon1, PCFG1 ); // Vref+ = Vdd

set_bit( adcon1, PCFG2 ); // Vref- = Vss

set_bit(adcon1, PCFG3);

 

clear_bit( adcon0, CHS0 ); // Channel 0

clear_bit( adcon0, CHS1 ); //

clear_bit( adcon0, CHS2 ); //

 

set_bit( adcon0, ADCS1 ); // Select Tad = 32 * Tosc (this depends on the Xtal here 10 MHz, should work up to 20 MHz)

clear_bit(adcon0,ADCS0);

 

 

 

}

 

 

 

unsigned int Read_adc(unsigned char ch)

{

if(ch>4) return 0;

 

clear_bit( adcon0, CHS0 ); // Channel 0

clear_bit( adcon0, CHS1 ); //

clear_bit( adcon0, CHS2 ); //

delay_us(100);

set_bit(adcon0,ADON);

 

set_bit(adcon0,GO); // Start conversion

 

while(adcon0.GO==1);

clear_bit(adcon0,ADON);

MAKESHORT(adcvalue,adresl,adresh);

return adcvalue;

 

}

Share this post


Link to post
Share on other sites

Is you problem with the simulator or reality (running on a PIC)? I think there is a problem with the simulator for the A-to-D in version 7 that there is a patch available for. If you search through the topics you should be able to find it.

Edited by trossin

Share this post


Link to post
Share on other sites

I tried the simulator and the real microcontroller, still no luck? program looks ok to me. I am using sourceboost 6.95v not 7. I only got the licence for 6.95. Any suggestions? thank you.

Share this post


Link to post
Share on other sites

Hi Samith,

 

Have you tried leaving the ADC turned on all the time.

 

Turning it off before reading the result registers may turn off the latch drivers even though they retain their values.

 

Worth a try.

 

Cheers

 

Reynard

Share this post


Link to post
Share on other sites

Hi Samith,

 

Not sure what you are trying to achieve but I have made a few subtle changes to your code so that the lower 8-bits of the adc value are placed on Port B. See if that works on your hardware.

 

Regards

 

davidb

 

 
#include <system.h>
#pragma CLOCK_FREQ 4000000
//#pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _CP_OFF
unsigned int Read_adc(unsigned char ch);
void Adc_init();
void main()
{
//Initialise PortB
trisb = 0; //configure port B
portb = 0; //clear port B
//initialise portA
trisa = 1; //porta as input
Adc_init();
while(1)
{
 unsigned short val; //10-bit Adc value
 val = Read_adc(0); //read channel 0 into val
 portb = (unsigned char) val; // Can only show lower 8 bits on port
}
}

//AD intialisation
void Adc_init()
{
set_bit( adcon1, ADFM ); // AD result needs to be right justified
//clear_bit(adcon1,ADCS2); //this register only used for 877A
clear_bit( adcon1, PCFG0 ); // one analogue in put
set_bit( adcon1, PCFG1 ); // Vref+ = Vdd
set_bit( adcon1, PCFG2 ); // Vref- = Vss
set_bit(adcon1, PCFG3);
clear_bit( adcon0, CHS0 ); // Channel 0
clear_bit( adcon0, CHS1 ); //
clear_bit( adcon0, CHS2 ); //
set_bit( adcon0, ADCS1 ); // Select Tad = 32 * Tosc (this depends on the Xtal here 10 MHz, should work up to 20 MHz)
clear_bit(adcon0,ADCS0);
}
unsigned int Read_adc(unsigned char ch) // ch not required as already fixed in function
{
unsigned short adcvalue;

if(ch>4) return 0;
clear_bit( adcon0, CHS0 ); // Channel 0
clear_bit( adcon0, CHS1 ); //
clear_bit( adcon0, CHS2 ); //
delay_us(100);
set_bit(adcon0,ADON);
set_bit(adcon0,GO); // Start conversion
while(adcon0.GO == 1);
// clear_bit(adcon0,ADON); // Leave converter running

MAKESHORT(adcvalue,adresl,adresh);
return adcvalue; // Return 10-bit adc value
} 

Share this post


Link to post
Share on other sites

Hi Samith,

 

Have you tried leaving the ADC turned on all the time.

 

Turning it off before reading the result registers may turn off the latch drivers even though they retain their values.

 

Worth a try.

 

Cheers

 

Reynard

yes I tried ADC swithced on all the time but I don't see anything in the adres registers. any other clues appreciated.

Share this post


Link to post
Share on other sites

Hi Samith,

 

Not sure what you are trying to achieve but I have made a few subtle changes to your code so that the lower 8-bits of the adc value are placed on Port B. See if that works on your hardware.

 

Regards

 

davidb

 

#include <system.h>
#pragma CLOCK_FREQ 4000000
//#pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _CP_OFF
unsigned int Read_adc(unsigned char ch);
void Adc_init();
void main()
{
//Initialise PortB
trisb = 0; //configure port B
portb = 0; //clear port B
//initialise portA
trisa = 1; //porta as input
Adc_init();
while(1)
{
 unsigned short val; //10-bit Adc value
 val = Read_adc(0); //read channel 0 into val
 portb = (unsigned char) val; // Can only show lower 8 bits on port
}
}

//AD intialisation
void Adc_init()
{
set_bit( adcon1, ADFM ); // AD result needs to be right justified
//clear_bit(adcon1,ADCS2); //this register only used for 877A
clear_bit( adcon1, PCFG0 ); // one analogue in put
set_bit( adcon1, PCFG1 ); // Vref+ = Vdd
set_bit( adcon1, PCFG2 ); // Vref- = Vss
set_bit(adcon1, PCFG3);
clear_bit( adcon0, CHS0 ); // Channel 0
clear_bit( adcon0, CHS1 ); //
clear_bit( adcon0, CHS2 ); //
set_bit( adcon0, ADCS1 ); // Select Tad = 32 * Tosc (this depends on the Xtal here 10 MHz, should work up to 20 MHz)
clear_bit(adcon0,ADCS0);
}
unsigned int Read_adc(unsigned char ch) // ch not required as already fixed in function
{
unsigned short adcvalue;

if(ch>4) return 0;
clear_bit( adcon0, CHS0 ); // Channel 0
clear_bit( adcon0, CHS1 ); //
clear_bit( adcon0, CHS2 ); //
delay_us(100);
set_bit(adcon0,ADON);
set_bit(adcon0,GO); // Start conversion
while(adcon0.GO == 1);
// clear_bit(adcon0,ADON); // Leave converter running

MAKESHORT(adcvalue,adresl,adresh);
return adcvalue; // Return 10-bit adc value
}

hi davidb,

I tried what you advised to do but still no luck. what actually I am trying to do is to connect virtual power supply to AN0 and change it 0 to 5V. then I am trying to get the digital result from the bortB, this is just a part of a project to get the 10 bit digital result for analogue input at the AN0 input. Am I doing right? any other advices welcome.

Hi Samith,

 

Not sure what you are trying to achieve but I have made a few subtle changes to your code so that the lower 8-bits of the adc value are placed on Port B. See if that works on your hardware.

 

Regards

 

davidb

 

#include <system.h>
#pragma CLOCK_FREQ 4000000
//#pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _LVP_OFF & _PWRTE_OFF & _CP_OFF
unsigned int Read_adc(unsigned char ch);
void Adc_init();
void main()
{
//Initialise PortB
trisb = 0; //configure port B
portb = 0; //clear port B
//initialise portA
trisa = 1; //porta as input
Adc_init();
while(1)
{
 unsigned short val; //10-bit Adc value
 val = Read_adc(0); //read channel 0 into val
 portb = (unsigned char) val; // Can only show lower 8 bits on port
}
}

//AD intialisation
void Adc_init()
{
set_bit( adcon1, ADFM ); // AD result needs to be right justified
//clear_bit(adcon1,ADCS2); //this register only used for 877A
clear_bit( adcon1, PCFG0 ); // one analogue in put
set_bit( adcon1, PCFG1 ); // Vref+ = Vdd
set_bit( adcon1, PCFG2 ); // Vref- = Vss
set_bit(adcon1, PCFG3);
clear_bit( adcon0, CHS0 ); // Channel 0
clear_bit( adcon0, CHS1 ); //
clear_bit( adcon0, CHS2 ); //
set_bit( adcon0, ADCS1 ); // Select Tad = 32 * Tosc (this depends on the Xtal here 10 MHz, should work up to 20 MHz)
clear_bit(adcon0,ADCS0);
}
unsigned int Read_adc(unsigned char ch) // ch not required as already fixed in function
{
unsigned short adcvalue;

if(ch>4) return 0;
clear_bit( adcon0, CHS0 ); // Channel 0
clear_bit( adcon0, CHS1 ); //
clear_bit( adcon0, CHS2 ); //
delay_us(100);
set_bit(adcon0,ADON);
set_bit(adcon0,GO); // Start conversion
while(adcon0.GO == 1);
// clear_bit(adcon0,ADON); // Leave converter running

MAKESHORT(adcvalue,adresl,adresh);
return adcvalue; // Return 10-bit adc value
}

Share this post


Link to post
Share on other sites

Hi Samith,

 

You say you are trying to use the virtual power supply which suggests that you are using the SourceBoost IDE and plugins.

 

I tend to use real hardware with MPLAB and ICD3 or PicKit2/PicKit3, depending on what I am doing, so I am not really the best person to help with simulation problems. There was a bug in the recent release of the simulator for V7.05 but I am not sure if the version for V6.95 worked O.K.

 

If you can try it on the real hardware then I believe the modified code should work. It looks correct but I haven't tested it so I could have missed something. BTW, you cannot display the 10-bit result on an 8-bit port as you are suggesting!

 

If you are using real hardware and an external voltage source then be careful how you apply the voltage to the analogue port, it is very easy to damage it by overvolting. This will usually kill the internal protection diode resulting in the ADC reading sticking at some value.

 

If you are using an external voltage source then use a potential divider/input current limiting resistor. External Schottky clamping diodes (BAT54S) across the rails to the AN input together with the current limiting resistor can provide additional protection.

 

If you think you may have damaged the port then try another one (change the channel settings as well).

 

Are you sure that your processor is running? Add a bit of code to flash a heartbeat LED on one of the other port pins just to make sure.

 

Although there is no reason why the 877 shouldn't work there or more modern and cheaper micros. The PIC16F887 is very similar and even that is getting long in the tooth.

 

Lastly, there is no need to quote the whole reply everytime, just quote the relevent parts if necessary.

 

Good luck

 

davidb

Share this post


Link to post
Share on other sites

Hi Samith,

 

You have commented out the config data which is not a good idea if you are using a 10MHz crystal.

The pragma says you are using 4MHz ? Have you set the ocillator speed in the "Settings/Clock Rate" menu. The compiler needs a clock rate to compute correct delay_us() etc.

 

Putting "val" out to the portb instead of "adcvalue" as David shows is better programming.

 

You code works using a PIC16F873A and 8MHz crystal on my EasyPIC5 board.

 

Cheers

 

Reynard

 

ps. I left the ADC turned ON for my testing.

Share this post


Link to post
Share on other sites

Reynard,

 

You have commented out the config data which is not a good idea if you are using a 10MHz crystal.

 

Looks like I missed the most obvious problem! But why comment the config out? The default values - RC Oscillator, LVP on etc. will not work so they must be changed elsewhere.

 

My suggestion of using a heartbeat would be useful to sort these sort of obvious problems out in the early stages.

 

davidb

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...