|
|
View previous topic :: View next topic |
Author |
Message |
ALEKANELENO
Joined: 26 Jul 2011 Posts: 4
|
PIC24F08KA101 ADC CH SEL problem |
Posted: Tue Jul 26, 2011 5:06 pm |
|
|
I'm trying to use AN0 and AN1. When I call "set_adc_channel(0)" nothing happens, but the AN0 input is correctly digitized with a "set_adc_channel(1)" call. I cannot access AN1 at all. From the disassembly listing, the various ADC registers appear to be correctly set---I've tried different ways to set them but the problem persists. Similar code worked fine with the PIC18F4455. The spec errata mentions "silicon" problems with these pins---is this another manifestation? _________________ ab |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Tue Jul 26, 2011 6:37 pm |
|
|
Post a small compilable example with your version of PCD so we can compile it too and check the assembly.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
ALEKANELENO
Joined: 26 Jul 2011 Posts: 4
|
|
Posted: Wed Jul 27, 2011 9:47 am |
|
|
Sorry for the delay...had to cut this down to bare bones and check if problem persisted.
Code: |
#include <24F08KA101.h>
#DEVICE ADC=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES FRC_PLL //Internal osc + PLL
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOPR //Pimary oscillator disabled
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOCKSFSM //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES PUT //Power Up Timer
#FUSES BORV_MID
#FUSES MCLR //Master Clear pin enabled
#FUSES ICSP3 //ICD uses PGC3/PGD3 pins
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#DEFINE sAN0 0
#DEFINE sAN0 1
//#DEFINE SPI_CLK_DIV_4 0x001E
#use delay(int=32M)
#use fast_io(A)
#use fast_io(B)
//Software SPI for DAC write MASTER
#use spi(STREAM=DAC_WR,DO=PIN_B8,CLK=PIN_B9,ENABLE=PIN_A6,ENABLE_ACTIVE=0,SAMPLE_RISE,BITS=16)
void Lev_Disp(signed int16);
#INLINE void DAC4912_WR(int16);
int16 i,tgl,idat,odat,odtt,ocfgA,ocfgB;
int1 dacgA,dacgB;
signed int16 levA,levB;
int16 AD1CON1,AD1CON2,AD1CON3,AD1CHS,AD1PCFG,AD1CSSL;
#locate AD1CON1=0x0320
#locate AD1CON2=0x0322
#locate AD1CON3=0x0324
#locate AD1CHS=0x0328
#locate AD1PCFG=0x032C
#locate AD1CSSL=0x0330
void Lev_Disp(signed int16 amp)
{
Output_Bit(PIN_B0,0);
Output_Bit(PIN_B1,0);
Output_Bit(PIN_B2,0);
if(amp>255) Output_Bit(PIN_B0,1);
if(amp>127) Output_Bit(PIN_B1,1);
if(amp>63) Output_Bit(PIN_B2,1);
return;
}
void DAC4912_WR(int16 config)
{
int16 wrdata;
wrdata = config | odat<<2;
spi_xfer(DAC_WR,wrdata,16);
Output_Bit(PIN_B7,0); // load DAC
Delay_Cycles(1);
Output_Bit(PIN_B7,1);
return;
}
void main()
{
set_tris_A(0x0000);
set_tris_B(0x4010);
// setup_spi(SPI_Slave|SPI_CLK_DIV_4); // hardware SPI (8 MHz)
// setup_adc(ADC_CLOCK_DIV_2|ADC_TAD_MUL_8); // Tad = 125 ns, 750 ns acq delay
AD1CON3 = 0x0601; // ADC_TAD_MUL_6
AD1CON1 = 0x80E0;
// setup_adc_ports(sAN0|sAN1);
AD1PCFG = 0xFFFC;
AD1CSSL = 0;
AD1CON2 = 0;
setup_wdt(WDT_OFF);
setup_timer1(TMR_INTERNAL|TMR_DIV_BY_1); // 62.5 ns/count
setup_timer2(TMR_DISABLED);
setup_timer3(TMR_DISABLED);
set_adc_channel(0);
ocfgA = 0x3000; // DAC A config preset (A/UNBUF/X1/ACTIVE)
ocfgB = 0xB000; // DAC B config preset (B/UNBUF/X1/ACTIVE)
Output_Bit(PIN_B7,1); // preset DAC load
delay_ms(1000);
tgl = 1;
for(i=0;i<4096;i++) // check level display and audio output
{
levA = i>>3; // 0<j<512
Lev_Disp(levA);
set_timer1(0);
if(tgl) odat = 642; // generate output square wave
else odat = 382; // +- 130
tgl = !tgl; // toggle output sign
if(i<2048) DAC4912_WR(ocfgA); // CHA output
else DAC4912_WR(ocfgB); // CHB output
while(get_timer1()<5120); // wait until loop time = 320 us
}
Output_Bit(PIN_B0,0); // reset LEDs
Output_Bit(PIN_B1,0);
Output_Bit(PIN_B2,0);
delay_ms(1000);
i = 0; // initialize loop things
tgl = 1;
while(1) // loop indefinitely
{
set_timer1(0); // start loop timer @ 62.5 ns/count
idat = read_adc();
// idat = odtt;
if(i%4==0) // every 250 us (2 kHz)
{
if(tgl) odtt = 640; // generate output square wave
else odtt = 384; // for testing DAC
tgl = !tgl; // toggle output sign
}
odat = idat;
DAC4912_WR(0x3000); // CHA output(A/UNBUF/X1/ACTIVE)
// DAC4912_WR(0xB000); // CHB output(B/UNBUF/X1/ACTIVE)
levA = (signed)odat - 512;;
Lev_Disp(levA);
while(get_timer1()<1024); // wait until accum loop time = 64 us (15625 Hz)
i++; // increment delay loop counter
if(i>63) i = 0; // reset delay loop counter
} // END OF MAIN LOOP
} |
_________________ ab |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Jul 27, 2011 10:20 am |
|
|
Well, that's not exactly as short as it can be, but one thing comes right off the top...
You're using RA0 and RA1...
And you're setting PORTA TRIS to 0x0000 which is all output.
Wouldn't 0x0003 be a better choice?
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
ALEKANELENO
Joined: 26 Jul 2011 Posts: 4
|
|
Posted: Wed Jul 27, 2011 11:00 am |
|
|
OK...just tried changing trisA to 0003...no effect...the data sheet says that AD1PCFG overrides anyway...the original code actually used the standard io (that had no effect either). Sorry about the length...this is the minimum code needed to operate the board. I forgot to mention that according to the "About" I'm running PCD v4.100...can't see any notation on the CD. Incidentally, my 24F08KA101.h is apparently missing some ADC and SPI defines. Thank you for your prompt help. _________________ ab |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Jul 27, 2011 11:57 am |
|
|
Hmmm, I'm using 4.122
I also just realized, I don't see anywhere in your code a "set_adc_channel(1);"
However, keep in mind, you need a time delay after that to satisfy the ADC charge time...
AND, you need to satisfy the input impedance needs as well.
If you do not (or your soldering has an open on channel_1) then it's very possible to read the result of CH0 when reading CH1 because the S/H capacitor didn't get adjusted to the new value as you'd expect.
Check your circuit.
Check your soldering.
Get a meter/scope and verify you have something on AN1 that's different from AN0.
Maybe post your schematic so we can review that next. The LST output for set_adc_channel looks correct over here.
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
ALEKANELENO
Joined: 26 Jul 2011 Posts: 4
|
|
Posted: Wed Jul 27, 2011 3:28 pm |
|
|
"Hmmm, I'm using 4.122" Would that make any difference -- were the header problems fixed?
"set_adc_channel(0 OR 1);" is near the beginning, after the timer setup calls.
In this "bare-bones" code there's > 2s delay after the ADC channel is selected and the Auto-Sample delay bits are set to 6 (or 8) Tad (750-1000 ns). I cannot find a spec for setting channels wait time (so I typically put some code in). The AN0 and AN1 pins are driven directly from an op-amp (very low Zout).
Bingo! Per your suggestion I scoped the inputs and tried a couple of different boards -- and discovered CHA and CHB were reversed on the board!
After making the appropriate code changes it all works as expected. I had the sneaky feeling that the solution was staring me in the face.
Thank you very much.
Incidentally, I noticed an oddity in the disassembly listing -- "setup_adc_ports(sAN0|sAN1)" produces (among the expected stuff) a "setm.w 0x032a" instruction. But 0x032a is not a register I can find listed (in the PIC24F16KA102 Family Data Sheet). Also, the PIC24F Family Reference Manual says to set AD1CSSL (0x0330) to zero in this instance. However, none of this makes any difference.
Best regards, _________________ ab |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Wed Jul 27, 2011 4:24 pm |
|
|
ALEKANELENO wrote: |
Bingo! Per your suggestion I scoped the inputs and tried a couple of different boards -- and discovered CHA and CHB were reversed on the board!
|
Oops! Glad you found it though.
Quote: |
Incidentally, I noticed an oddity in the disassembly listing -- "setup_adc_ports(sAN0|sAN1)" produces (among the expected stuff) a "setm.w 0x032a" instruction. But 0x032a is not a register I can find listed (in the PIC24F16KA102 Family Data Sheet). Also, the PIC24F Family Reference Manual says to set AD1CSSL (0x0330) to zero in this instance. However, none of this makes any difference.
|
Report it if you think it's an error. (I didn't look, so I can't agree in that sense.)
Cheers,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Jul 28, 2011 12:05 am |
|
|
Quote: | "setup_adc_ports(sAN0|sAN1)" produces (among the expected stuff) a "setm.w 0x032a" instruction |
You are talking about a bug in an old version. It has been fixed since long. |
|
|
|
|
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
|