View previous topic :: View next topic |
Author |
Message |
needmoresleep
Joined: 10 Jan 2013 Posts: 5
|
PIC10F322 A/D Converter Problems |
Posted: Thu Jan 10, 2013 1:31 pm |
|
|
OK, I'm new to this so please be gentle
I have a Microchip PIC10F322 Dev Kit (AC103011) and can't get the A/D to work at all. I've tried my code to flash leds without the A/D etc. and that seems ok.
Am I missing something real obvious as this should be pretty basic I think. I've searched the forums but found nothing specific to the 10F3XX series.
Compiler Version: PCM 4.140
Target: PIC10F322
Run Mode: Standard
Target Voltage: 5VDC powered from ICD3
Target Oscillator: 8MHz internal RC
Code: |
#include <10F322.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //No MCLR - Used For I/O
#FUSES NOPROTECT //No Code Protect From Reading
#FUSES NOLVP //No Low Voltage Programming
#FUSES NOLPBOR //No Low Power Brown Out Reset
#FUSES NOWRT //No Program Memory Write Protect
#FUSES NODEBUG //No ICD Debug
#use delay(int=8000000)
#define LED_RED PIN_A0
#define LED_GREEN PIN_A1
#define DELAY 500
#ZERO_RAM
unsigned int8 i;
unsigned int8 value;
void main()
{
SETUP_WDT(WDT_OFF);
SETUP_CLC1(CLC_DISABLED);
set_tris_a(0b1100);
setup_adc_ports(sAN2);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(sAN2);
output_low(LED_RED);
output_low(LED_GREEN);
enable_interrupts(INT_AD);
enable_interrupts(GLOBAL);
do {
//
// for(i=0; i<8; ++i)
// {
// delay_ms(DELAY);
// value = i;
// delay_ms(DELAY);
// output_toggle(LED_GREEN);
// if(value<4)
// output_low(LED_RED);
// if(value>=4)
// output_high(LED_RED);
// }
//
delay_ms(100);
// value = Read_ADC();
value=read_adc(ADC_START_AND_READ);
delay_ms(100);
output_toggle(LED_GREEN);
if(value<127)
output_low(LED_RED);
if(value>=127)
output_high(LED_RED);
value=0;
} while (TRUE);
}
|
Any help would be very much appreciated, and apologies in advance if this is something really obvious, I'm just starting out!
Thanks |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Jan 10, 2013 1:46 pm |
|
|
I looked at this briefly so: there might be more things...
I suggest you remove:
Code: | set_tris_a(0b1100); |
and let the compiler handle that.
Make sure you are providing your ADC with the right TAD (See Datasheet)
Code: | setup_adc(ADC_CLOCK_INTERNAL); |
I see logical issues/problems:
once you read your ADC and set your "LED_RED" to what ever state, your main loop goes back to the FOR loop which ALSO writes to the "LED_RED" so you will overwrite the State of the LED immediatly after you set it, but based on the conditions set by the FOR loop and not the ADC
make your code SMALLER... remove all the Flashing LED code or place that OUTSIDE of the infinite loop... and try to use diferent pins for status and result outputs.... (so that you avoid the logical issues i mentioned above)
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Jan 10, 2013 1:49 pm |
|
|
... i just noticed you had half the program commented out... sorry.
Code: | enable_interrupts(INT_AD); |
where is the ISR? and why are you using this? _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
needmoresleep
Joined: 10 Jan 2013 Posts: 5
|
|
Posted: Thu Jan 10, 2013 3:06 pm |
|
|
Thanks for taking the time to reply Gabriel.
I left the commented code in (for reference), as thats the code I got the LEDS to flash with.
I've tried it with and without setting the tris_a register, prior to posting, but it didn't work either way. In fact I think the LEDs wouldn't flash unless I set them - I think I've read somewhere they default to analog.
enable_interrupts (INT_AD) and enable_interrupts (global) was a last ditch attempt to try to get it working, as I wasn't sure they were needed. Again it didn't seem to work either way.
I wasn't sure if using the internal ADC clock in conjunction with the read_adc(ADC_START_AND_READ) function meant that it tested the 'conversion done' bit in the SFR and therefore waited the required time. I also added (again rightly or wrongly) the use_delay() before and after the read_adc(). |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Thu Jan 10, 2013 3:24 pm |
|
|
havent tested this...
but i cleaned it for you (too much clutter) and changed what i think is wrong...
Code: | #include <10F322.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //No MCLR - Used For I/O
#FUSES NOPROTECT //No Code Protect From Reading
#FUSES NOLVP //No Low Voltage Programming
#FUSES NOLPBOR //No Low Power Brown Out Reset
#FUSES NOWRT //No Program Memory Write Protect
#FUSES NODEBUG //No ICD Debug
#use delay(int=8000000) // <-----------------8MHZ so your TAD is probably wrong.
#define LED_RED PIN_A0
#define LED_GREEN PIN_A1
#define DELAY 500
#ZERO_RAM
unsigned int8 value;
void main()
{
SETUP_ADC_PORTS(sAN2); // Select Analog channels on PIC
SETUP_ADC(ADC_CLOCK_DIV_16); // Should be the right TAD/clock <---8MHZ
output_low(LED_RED);
While(1) // I dont like Do/while
{
delay_ms(100);
value = Read_ADC();
output_toggle(LED_GREEN);// toggle for ON confirmation
if(value<127)
output_low(LED_RED);
if(value>=127)
output_high(LED_RED);
value=0;
}
} |
try that...
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
needmoresleep
Joined: 10 Jan 2013 Posts: 5
|
|
Posted: Thu Jan 10, 2013 4:20 pm |
|
|
Thanks again for your help Gabriel.
I don't think I've fully understood the TAD delays and how the ADC clock influences them. I'll read up some more on them.
If I wanted to setup 2 analog channels (to compare the results) I presume I would add code such as:
Code: |
SETUP_ADC_PORTS(sAN1); //set RA1 as analog I/P
SETUP_ADC_PORTS(sAN2); //set RA2 as analog I/P
set_adc_channel(1); //select ADC channel 1
dealy_uS(100); //a little delay for ADC channel changeover
value1 = Read_ADC(); //store ADC channel 1 value in 'value1'
set_adc_channel(2); //select ADC channel 2
dealy_uS(100); //same as for channel 1
value2 = Read_ADC(); //same as for channel 1
|
Does that look correct? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jan 10, 2013 5:33 pm |
|
|
Quote: | SETUP_ADC_PORTS(sAN1); //set RA1 as analog I/P
SETUP_ADC_PORTS(sAN2); //set RA2 as analog I/P
Does that look correct?
|
No. See this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=42766&start=1
Quote: |
#define LED_GREEN PIN_A1
SETUP_ADC_PORTS(sAN1);
|
The green LED and the analog input are assigned to the same pin.
That's not going to work. Get a larger PIC with more pins. |
|
|
needmoresleep
Joined: 10 Jan 2013 Posts: 5
|
|
Posted: Fri Jan 11, 2013 5:18 am |
|
|
I've tried the single ADC channel code suggested and still it doesn't work
I've also tried setting the ADC clock to DIV_8 (for 1uS) and DIV_32 (for 4uS) and still no joy...
I then tried setting the TRIS_A to 0x04, no joy
and then SETUP_ADC_PORTS(sAN2), again no joy...
Could it be incorrect fuse settings or maybe an issue with the compiler??
Please help |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri Jan 11, 2013 6:13 am |
|
|
Gabrel's code should work, except he doesn't select the ADC channel.
Compiling this with that one change, gives:
Code: |
.................... SETUP_ADC_PORTS(sAN2); // Select Analog channels on PIC
002C: MOVLW 04
002D: MOVWF 08
.................... SETUP_ADC(ADC_CLOCK_DIV_16); // Should be the right TAD/clock <---8MHZ
002E: BSF 1F.5
002F: BCF 1F.6
0030: BSF 1F.7
0031: BSF 1F.0
.................... SET_ADC_CHANNEL(2);
0032: MOVLW 08
0033: MOVWF 41
0034: MOVF 1F,W
0035: ANDLW E3
0036: IORWF 41,W
0037: MOVWF 1F
.................... output_low(LED_RED);
0038: BCF 06.0
0039: BCF 05.0
....................
....................
.................... While(1) // I dont like Do/while
.................... {
....................
.................... delay_ms(100);
003A: MOVLW 64
003B: MOVWF 45
003C: GOTO 004
.................... value = Read_ADC();
003D: BSF 1F.1
003E: BTFSC 1F.1
003F: GOTO 03E
0040: MOVF 1E,W
0041: MOVWF 44
|
Which all looks correct. Sets the right bits to select the channel, correct bits to start conversion, and detect it has finished, etc..
Best Wishes |
|
|
needmoresleep
Joined: 10 Jan 2013 Posts: 5
|
|
Posted: Fri Jan 11, 2013 6:28 am |
|
|
It works
I had thought that the channel needed to be set but I posted the wrong line that I had tested...
"and then SETUP_ADC_PORTS(sAN2), again no joy... "
but I actually tested
SET_ADC_CHANNEL(sAN2);
Which gave me:
0032: MOVLW 10
I changed it to:
SET_ADC_CHANNEL(2);
Which gave me:
0032: MOVLW 08
and it works!!!!
Thank you Ttelmah
And thank you Gabriel
I nearly ran out of time and gave up! |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Fri Jan 11, 2013 6:45 am |
|
|
glad to hear it works!
@Ttelmah: indeed i missed selecting the channel, i just noticed i removed the channel select line when cleaning up his code by mistake... nice catch!
Quick Note:
Test your code--
Code: | dealy_uS(100); //same as for channel 1 |
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Fri Jan 11, 2013 7:07 am |
|
|
That type of 'miss', is the commonest one from reasonably experienced programmers 'typing untested', straight to the board. Have done exactly the same thing on many occasions. I did the 'proof reading', realised this was missing, then thought I'd double check the compiler was generating correct values.
Best Wishes |
|
|
|