• AVR Freaks

Helpful ReplyHot!Switching ADC Channels on a PIC24F16KM202

Page: 12 > Showing page 1 of 2
Author
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
2018/11/20 14:55:40 (permalink)
0

Switching ADC Channels on a PIC24F16KM202

[EDIT]  I literally cannot make this post with my code in it, even when inserted as a picture, other than my Get_Analog_Temperature() function.  Adding any of the others or trying to post in code tags triggers the firewall.  So I guess just look at the attachments.
 
Hi all,
 
So I'm having a problem with the ADC on a PIC24F16KM202 I'm trying to trace down, using XC16 v1.31.
 
This firmware is reading from two analog channels.  The main channel is a brightness control giving me an analog voltage on AN19 that I am converting to an LED brightness.  The other is a thermal sensor (a MCP9700) on AN9. 
Most of the time AN19 is the channel being read, I'm updating my temperature every second, switching the analog channel over to AN9 when I do so, and switching back to AN19 on the next read.
 
Here's the function I'm using for the switching and the read:
I'd love to post the code, but the firewall won't let me, so have a screencapture:
 
 
What I'm finding is that I am often (maybe 1/3 of the time?  Sometimes more) getting some kind of effect between the channels.  I confirmed this by printing out my ADC average whenever I call this function to read the thermal sensor. 
I'd love to post the code, but the firewall won't let me, so have a screencapture:
 
 
The result of the UART transmission of this function is below:
R:414
R:414
R:452
R:414
R:414
R:452
R:414
R:452
R:452
R:414
R:414
R:414
R:452
414 is the correct reading for this channel for the voltage I am giving.  452 are the "bad" readings I'm getting that are throwing my averaging off.  In this case this takes me from reading about 84C to 96C. I've noticed if I turn down the voltage coming in from the brightness control, these values swing to the other direction:
R:414
R:388
R:414
R:414
R:388
R:414
R:388
R:414
R:414
R:414
R:388
R:414
R:388

I've confirmed via multimeter and scope that the voltage on the AN9 pin is NOT changing, so it seems it must be internal to the PIC and is probably my configuration (I just can't seem to determine where).  My ADC Init function is shown below:
I'd love to post the code, but the firewall won't let me, so have a screencapture:


 
Anyone out there have suggestions for what I can try (or what I'm doing wrong) to get these two channels switching and reading properly?
Thanks in advance!
post edited by KTrenholm - 2018/11/20 14:58:18

Attached Image(s)

#1
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/20 15:17:39 (permalink)
0
Is your source impedance below the recommended max of 2.5k?
Have you tried increasing the 72us delay in your code after selecting a new channel?
 

Nearly there...
#2
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/20 16:27:25 (permalink)
0
qhb
Is your source impedance below the recommended max of 2.5k?Have you tried increasing the 72us delay in your code after selecting a new channel? 


Source impedence for both inputs is only 100 Ohm iirc, but I don't have the schematic in front of me at the moment. I'll confirm when I get the chance.

I am providing a 72us delay in Read_ADC if the channel has changed from the previous call.
#3
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/20 16:28:55 (permalink)
0
KTrenholm
....
I am providing a 72us delay in Read_ADC if the channel has changed from the previous call.

I saw it. That was what I asked if you had tried increasing.

Nearly there...
#4
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/20 19:00:46 (permalink)
0
qhb
KTrenholm
....
I am providing a 72us delay in Read_ADC if the channel has changed from the previous call.

I saw it. That was what I asked if you had tried increasing.


Oops, I misread. Yeah I'll try bumping that up, I remember reading somewhere that 72us was safe, but I don't see it in a quick run through the datasheet and ADC reference manual so who knows.
#5
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 07:38:28 (permalink)
0
I tried increasing that delay on switching channels before taking my reads to a wildly excessive 15ms.
Behavior is exactly the same as before.
 
I also looked into the impedance on the inputs.  Both inputs go through an op-amp circuit.  Here's the one for the MCP9700 thermal sensor.  TEMP leads directly to AN9:
   
 
 
I also confirmed that this issue does not occur on my analog brightness input AN19.  Changes to voltage on AN9 have no effect on AN19 unlike what I'm seeing with the voltage on AN19 on AN9.  Readings there are nice and steady, maybe varying by 1 count between sets of readings.

FWIW, AN19 is being read FAR more frequently than AN9.
post edited by KTrenholm - 2018/11/21 07:57:22

Attached Image(s)

#6
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 08:49:25 (permalink)
0
OK. So I've got a "Fix".  It's really more a hack but it does clean the readings up.  Basically, turning it off an on again.
 
When I switch over to my thermal sensor in Read_ADC():
case TEMP_ADC_CH:
            AD1CON1bits.ADON = 0;
            __delay_us(10);
            AD1CON1bits.ADON = 1;
            AD1CHSbits.CH0SA = 0b01001; //AN9
            break;

 
Hardly nice, but it DOES work, and I no longer get interference on AN9 from AN19.  Would love to hear any ideas that aren't this though.  I've also tried lengthening the acquisition time, to nearly 500us, but that didn't do anything.
 
 
#7
Howard Long
Super Member
  • Total Posts : 681
  • Reward points : 0
  • Joined: 2005/04/04 08:50:32
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 09:39:04 (permalink)
0
I have had a fair amount of experience on the PIC24F16KM202's ADC, up to 100kSa/s where I switched channels dynamically. I used the separate trigger and interrupt events from a CCP timer to trigger the conversion and switch the channels during during conversion. Because of the sample rate and Tad timing limitations, I only had a handful of Tads for sampling.
 
Certainly you need a nice low impedance at the inputs, because when you switch there seems to be a "memory" effect from the previous sample/conversion pulling the ADC result.
 
Also, what's the layout like? how close is that 0.1uF cap to the ADC pin & GND, and what's the grounding like? Do you have a copper pour for a ground plane?
 
I also noticed that you're using Vdd as the ADC reference: I had far better performance when using an external Vref or the FVR, but note that the FVR's accuracy isn't good (although its stability seems OK).
 
I like this chip a lot, some nice peripherals on it in a small package. It'd be even better if it had DMA.
 
Here's an Asteroids game I wrote using this chip a while back ;-)  https://www.youtube.com/watch?v=BXOHyjeLAXM
 
 
#8
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 10:16:06 (permalink)
0
Howard Long
Also, what's the layout like? how close is that 0.1uF cap to the ADC pin & GND, and what's the grounding like? Do you have a copper pour for a ground plane?
 

The 0.1uF is maybe 1/2 an inch away from the microcontroller and the GND via is right next to the cap.   We are using a copper pour for the ground plane.
 
Howard Long
I also noticed that you're using Vdd as the ADC reference: I had far better performance when using an external Vref or the FVR, but note that the FVR's accuracy isn't good (although its stability seems OK).
 

How much of an accuracy deviation were you seeing from the FVR?  My readings being only about 10mV off (1 degree C basically) would be okay, but any more than that would be iffy.
 
Howard Long
I like this chip a lot, some nice peripherals on it in a small package. It'd be even better if it had DMA.
 
Here's an Asteroids game I wrote using this chip a while back ;-)  https://www.youtube.com/watch?v=BXOHyjeLAXM
 

 I also generally like using this chip, the two DACs especially have come in handy.  This the the first real issue I've run into on it.
Only thing I really wish it had was some more code space.  I had to run a 128x128 display controller interface off it and bitmap characters for a custom font.  Ate up the space on it real quick.
 
That Asteroids port is rad, btw.



 
post edited by KTrenholm - 2018/11/21 10:58:23
#9
Nikolay_Po
Super Member
  • Total Posts : 1890
  • Reward points : 0
  • Joined: 2012/04/01 13:49:27
  • Location: Russia, Novorossiysk
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 13:32:29 (permalink)
0
Hi, Kyle! TAD should be not less than 600ns, see AD50 parameter in Datasheet. In your code ADC clock are tuned to 16 TCY which is limiting the TCY by 600ns/16=37.5ns. So the CPU speed should be not higher than 1/37.5ns=26.6MHz. If not, you should increase ADCS value.
#10
Nikolay_Po
Super Member
  • Total Posts : 1890
  • Reward points : 0
  • Joined: 2012/04/01 13:49:27
  • Location: Russia, Novorossiysk
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 13:42:34 (permalink)
0
Also, do you need to shift ADC result accumulated value right? The highest possible accumulator value for 16 samples is 1023*16=16368 which is inside the limit of 16-bit integers, even signed. Just scale down by 16 times your ADC_V_PER_COUNT constant.
#11
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 13:42:42 (permalink)
0
Nikolay_Po
Hi, Kyle! TAD should be not less than 600ns, see AD50 parameter in Datasheet. In your code ADC clock are tuned to 16 TCY which is limiting the TCY by 600ns/16=37.5ns. So the CPU speed should be not higher than 1/37.5ns=26.6MHz. If not, you should increase ADCS value.


In my current config:
My FCY is 8MHz, which I'm using for my AD clock.
TCY = 125ns
ADCS = 16 so TAD is (TCY * 16) = 2us
SAMC = 8 so my sample time (TAD * 8) = 16us
 
Isn't my ADCS putting me above the 600ns threshold?
[EDIT]
Mixed up my ADCS and SAMC
 
post edited by KTrenholm - 2018/11/21 13:48:11
#12
Nikolay_Po
Super Member
  • Total Posts : 1890
  • Reward points : 0
  • Joined: 2012/04/01 13:49:27
  • Location: Russia, Novorossiysk
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 14:11:27 (permalink)
4 (1)
So, the problem may be totally different than ADC. Where is voltage regulator for Vdd (how far it is from the Vdd/Vss pin pair)? Have your PIC any loads like a LEDs which are switching between Read_ADC() function calls? Is your circuit on a breadboard?
#13
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 14:23:39 (permalink)
0
The 12 to 3.3v LDO is about 3.5cm away from the PIC. It's a PCB, not breadboarded.
 
I have high power LEDs going but that's on the other end of the board and handled by LED driver ICs, the PIC is just providing the PWM control for the driver.  The only LED driven by the pic itself is a small heartbeat LED toggling at 1Hz.
 
I've scoped the ADC lines in question and there's no noticeable noise on them, so I don't right now think it's a problem external to the PIC.  It seems like it's the ADC doing something like not fully isolating out the brightness pot channel when it reads the temperature sensor channel.
 
#14
qhb
Superb Member
  • Total Posts : 9998
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 14:26:38 (permalink)
0
KTrenholm
  It seems like it's the ADC doing something like not fully isolating out the brightness pot channel when it reads the temperature sensor channel.

That is what the "acquisition time" is meant to fix, which you do appear to be doing correctly.
Another fix you could try is doing a dummy read of an unused analog input that is tied to ground, in between your real reads.
That would fully discharge the internal sampling capacitor.
 
post edited by qhb - 2018/11/21 14:27:45

Nearly there...
#15
Nikolay_Po
Super Member
  • Total Posts : 1890
  • Reward points : 0
  • Joined: 2012/04/01 13:49:27
  • Location: Russia, Novorossiysk
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 14:34:27 (permalink)
0
KTrenholm
The 12 to 3.3v LDO is about 3.5cm away from the PIC. It's a PCB, not breadboarded.

 
OK. Should work well.
 
I have high power LEDs going but that's on the other end of the board and handled by LED driver ICs, the PIC is just providing the PWM control for the driver.

 
Can you disable power LED for test? May it be that power LED return current is shifting LDO and Vdd/Vss potentials together respecting your pots ground?
 
The only LED driven by the pic itself is a small heartbeat LED toggling at 1Hz.

 
Should be no problem because of LDO in vicinity of Vdd/Vss. Isn't it?
 
I've scoped the ADC lines in question and there's no noticeable noise on them, so I don't right now think it's a problem external to the PIC.

 
Where did you connect the ground of the scope probe? To potentiometer ground or to Vss? Are these grounds solidly the same?
 
It seems like it's the ADC doing something like not fully isolating out the brightness pot channel when it reads the temperature sensor channel.

 
If brightness potentiometer actually does brightness control, the influence may be from power LED but the potentiometer signal itself.
#16
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 15:08:46 (permalink)
0
LEDs On/Off does not seem to effect the behavior.
I'm noticing that the read that's skewing my average seems to be the one in ADC1BUF0.  It really does just seem to be a leftover value from the brightness potentiometer.  Maybe for a temporary fix I could simply drop that first value and use the value in ADC1BUF1 twice in my sum before dividing it down for my average.  Would bring me down from a 16-sample average to a 15-sample average but it wouldn't be the end of the world.
 
Unfortunately I'm going to be out of the office until Monday so this is the last I'll have on the matter until then.
 
Thanks for all the suggestions so far though.
#17
Nikolay_Po
Super Member
  • Total Posts : 1890
  • Reward points : 0
  • Joined: 2012/04/01 13:49:27
  • Location: Russia, Novorossiysk
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 17:05:02 (permalink) ☄ Helpfulby KTrenholm 2018/11/26 14:48:32
4 (1)
In my opinion the throwing down of first ADC value of a series is valuable solution and (in case the hardware is OK) may be considered as final. You needn't to duplicate another value. Just follow my recommendations from upper post. It will be enough to divide your current ADC_V_PER_COUNT constant for 15, the number of reading in the sum.
 
P.S. I found your problem cause. The ADC begins to sample the next round before your program disables auto sampling. After 16-th sample conversion the auto sampling feature starts new sampling momentary, well before your program is reacting on interrupt flag. That is why zero buffer position always contain the sample from previous ADC reading function call.
Probably, you need a) disable autosampling; b) clear SAMP to abort already started sampling; c) Abort the conversion (if any) by clearing ADC GO_NOT_DONE bit (or which is in certain ADC model). The clearing of the SAMP bit probably will start next conversion and will fill BUF0 value. I can not say how to reset ADC hardware result buffer pointer for sure except turning ADC off then ON. Just because I haven't used such model.
#18
KTrenholm
Super Member
  • Total Posts : 710
  • Reward points : 0
  • Joined: 2012/08/08 14:04:23
  • Location: Connecticut, USA
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/21 17:08:34 (permalink)
0
Oh my gosh nice spotting that, I hadn't even thought of it. of course now it seems super obvious! Thanks, I'll give that a shot on Monday.
#19
Howard Long
Super Member
  • Total Posts : 681
  • Reward points : 0
  • Joined: 2005/04/04 08:50:32
  • Status: offline
Re: Switching ADC Channels on a PIC24F16KM202 2018/11/22 10:41:04 (permalink) ☄ Helpfulby KTrenholm 2018/11/26 14:50:27
0
Nikolay_Po
P.S. I found your problem cause. The ADC begins to sample the next round before your program disables auto sampling. After 16-th sample conversion the auto sampling feature starts new sampling momentary, well before your program is reacting on interrupt flag. That is why zero buffer position always contain the sample from previous ADC reading function call.



I agree with this. In fact, the code as shown is sampling and converting 17 times (SMPI=0b010000). So taking the results ADC1BUF1 to ADC1BUF16 would also work, throwing away the first each time.
 
I could not find a way to properly stop autosampling and conversion in this case by manipulating DONE or SAMP. The FRM for the ADC states:
 

Clearing the ASAM bit while in Automatic Sampling mode will not terminate an ongoing
sample/convert sequence; however, sampling will not automatically resume after a subsequent
conversion.

 
You could turn the ADC off and then on again as required, this will reset the sampling/conversion logic.
 
I have spent some time with this and I believe I've uncovered a further problem. I am not sure how fast you're running your device at, but I noticed that your Tad was set to 33 * Tcy. Although this shouldn't cause a problem, I was seeing that if ASAM or ADON is cleared directly after AD1IF=0 or DONE=1, the last sample makes its way to the buffer but it doesn't appear to be a complete sample/convert, i.e. part of the original problem.
 
If I insert a short delay of a few us before disabling ASAM & ADON, then it completes correctly. In pretty much all of my implementations, I've been running at FCY=16MHz and Tad=625ns (i.e. Tad = 10 * Tcy). When I used this and removed the delay, I can directly disable ASAM and ADON.
 
So in short, my fixes are:
 
o SMPI=0b01111
o ADCS=0b00001001
o Disable ASAM & ADON after AD1IF=1
o Enable ADON & AD1IF=0 before setting ASAM=1
 
Switching off the ADC isn't exactly very elegant. You might want to re-think your strategy based on these and your own findings. As I alluded to earlier, if this device had DMA it would make stuff like this easier to implement.
 

 

// PIC24FV16KM202 Configuration Bit Settings
 
// 'C' source line config statements
 
// FBS
#pragma config BWRP = OFF // Boot Segment Write Protect (Disabled)
#pragma config BSS = OFF // Boot segment Protect (No boot program flash segment)
 
// FGS
#pragma config GWRP = OFF // General Segment Write Protect (General segment may be written)
#pragma config GCP = OFF // General Segment Code Protect (No Protection)
 
// FOSCSEL
#pragma config FNOSC = FRCPLL // Oscillator Select (Fast RC Oscillator with Postscaler and PLL Module (FRCDIV+PLL))
#pragma config SOSCSRC = DIG // SOSC Source Type (Digital Mode for use with external source)
#pragma config LPRCSEL = HP // LPRC Oscillator Power and Accuracy (High Power, High Accuracy Mode)
#pragma config IESO = ON // Internal External Switch Over bit (Internal External Switchover mode enabled (Two-speed Start-up enabled))
 
// FOSC
#pragma config POSCMOD = NONE // Primary Oscillator Configuration bits (Primary oscillator disabled)
#pragma config OSCIOFNC = CLKO // CLKO Enable Configuration bit (CLKO output signal enabled)
#pragma config POSCFREQ = HS // Primary Oscillator Frequency Range Configuration bits (Primary oscillator/external clock input frequency greater than 8MHz)
#pragma config SOSCSEL = SOSCHP // SOSC Power Selection Configuration bits (Secondary Oscillator configured for high-power operation)
#pragma config FCKSM = CSECMD // Clock Switching and Monitor Selection (Clock Switching is enabled, Fail-safe Clock Monitor is disabled)
 
// FWDT
#pragma config WDTPS = PS32768 // Watchdog Timer Postscale Select bits (1:32768)
#pragma config FWPSA = PR128 // WDT Prescaler bit (WDT prescaler ratio of 1:128)
#pragma config FWDTEN = OFF // Watchdog Timer Enable bits (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config WINDIS = OFF // Windowed Watchdog Timer Disable bit (Standard WDT selected(windowed WDT disabled))
 
// FPOR
#pragma config BOREN = BOR3 // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware, SBOREN bit disabled)
#pragma config RETCFG = OFF // (Retention regulator is not available)
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config I2C1SEL = PRI // Alternate I2C1 Pin Mapping bit (Use Default SCL1/SDA1 Pins For I2C1)
#pragma config BORV = V18 // Brown-out Reset Voltage bits (Brown-out Reset set to lowest voltage (1.8V))
#pragma config MCLRE = ON // MCLR Pin Enable bit (RA5 input pin disabled, MCLR pin enabled)
 
// FICD
#pragma config ICS = PGx1 // ICD Pin Placement Select bits (EMUC/EMUD share PGC1/PGD1)
//#pragma config ICS = PGx3 // ICD Pin Placement Select bits (EMUC/EMUD share PGC3/PGD3)
 
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
 
#include <xc.h>
#include <stdint.h>
#include <string.h>
 
#define FCY 16000000
#include <libpic30.h>
 
#define ADC_DATA_SIZE 256
static uint16_t _au16ADCData[ADC_DATA_SIZE];
 
void InitADC(void)
{
AD1CON1bits.ADSIDL=1; // 1 => Discontinues module operation when device enters Idle mode
AD1CON1bits.MODE12=0; // 0 => 10-bit A/D operation
AD1CON1bits.FORM=0b00; // 0b00 => Absolute decimal result, unsigned, right justified
AD1CON1bits.SSRC=0b0111; // 0b0111 => Internal counter ends sampling and starts conversion (auto-convert)
AD1CON1bits.ASAM=0; // 0 => Sampling begins when the SAMP bit is manually set

AD1CON2bits.PVCFG=0b00; // 0b00 => AVdd
AD1CON2bits.NVCFG0=0; // 0 => AVss
AD1CON2bits.BUFREGEN=0; // 0 => A/D result buffer is treated as a FIFO
AD1CON2bits.BUFM=0; // 0 => Starts filling the buffer at address, ADC1BUF0, and each sequential address on successive interrupts (FIFO mode)
// AD1CON2bits.SMPI=0b10000; // 0b10000 => Interrupts at the completion of the conversion for each 17th sample
AD1CON2bits.SMPI=0b01111; // 0b01111 => Interrupts at the completion of the conversion for each 16th sample

AD1CON3bits.ADRC=0; // 0 => Clock is derived from the system clock
AD1CON3bits.SAMC=0b01000; // 0b01000 => Auto-Sample Time Select bits, 8 Tad
// AD1CON3bits.ADCS=0b00100000; // 0b00100000 => A/D Conversion Clock Select bits, Tad = 33 * Tcy
AD1CON3bits.ADCS=0b00001001; // 0b00001001 => A/D Conversion Clock Select bits, Tad = 10 * Tcy

AD1CON5bits.BGREQ=1; // 1 => Band gap is enabled when the A/D is enabled and active

IFS0bits.AD1IF=0;
IEC0bits.AD1IE=0;
AD1CON1bits.ADON=1;
}
 
uint16_t ReadADC(uint8_t u8Ch)
{
static volatile uint16_t au16[16]; // For debugging
uint16_t u16ADCVal=0;
int i;
volatile uint16_t *pu16ADCBuf=&ADC1BUF0;
 
AD1CHSbits.CH0NA=0;
AD1CHSbits.CH0SA=u8Ch;
 
IFS0bits.AD1IF=0;
AD1CON1bits.ADON=1;
AD1CON1bits.ASAM=1;
while (!IFS0bits.AD1IF)
{
Nop();
}
AD1CON1bits.ASAM=0;
AD1CON1bits.ADON=0;

memcpy((void *)au16,(void *)&ADC1BUF0,sizeof(au16)); // For debugging
 
Nop();
Nop();
Nop();

for (i=0;i<16;i++)
{
u16ADCVal+=*pu16ADCBuf++;
}
return u16ADCVal>>4;
}
 
int main(void)
{
    CLKDIVbits.RCDIV=0b000; // 0b000 -> 1:1, so 16MHz FCY if FNOSC == FRCPLL

// CCP5 is used as a diagnostic timer
CCP5CON1Lbits.CCSEL=0; // 0 => Output Compare/PWM/Timer peripheral (exact function is selected by the MOD<3:0> bits)
CCP5CON1Lbits.MOD=0b0000; // 0b0000 => 16-Bit/32-Bit Timer mode, output functions are disabled
CCP5CON1Lbits.T32=1; // 1 => Uses 32-bit time base for timer, single edge output compare or input capture function
CCP5CON1Lbits.TMRPS=0b00; // 0b00 => 1:1 Prescaler
CCP5CON1Lbits.CLKSEL=0b00; // 0b000 => System clock (TCY)
CCP5TMRH=0;
CCP5TMRL=0;
CCP5PRH=0xFFFF;
CCP5PRL=0xFFFF;
CCP5CON1Lbits.CCPON=1;

InitADC();
 
// Set up DAC for use as an ADC source
TRISBbits.TRISB12=1; // 1 => Input (for analogue usage) DAC1OUT is on RB12/AN12 pin
ANSBbits.ANSB12=1; // 1 => Analogue pin
DAC1CONbits.DACFM=0; // 0 => Data is right justified (data stored in DACxDAT<7:0>)
DAC1CONbits.DACOE=1; // 1 => Data is right justified (data stored in DACxDAT<7:0>)
DAC1CONbits.DACREF=0b10; // 0b10 => AVdd
DAC1DAT=128; // 128 => ~=Vref/2
DAC1CONbits.DACEN=1;
 
while (1)
{
int i;

for (i=0;i<ADC_DATA_SIZE;i++)
{
if ((i & 1)!=0)
{
_au16ADCData[i]=ReadADC(0b01100); // 0b01100 => AN12/RB12/DAC1OUT
}
else
{
_au16ADCData[i]=ReadADC(0b11010); // 0b11010 => Internal Band Gap Reference (VBG)
}
}
Nop();
}
return 0;
}
 

 
 
post edited by Howard Long - 2018/11/24 04:18:47
#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2019 APG vNext Commercial Version 4.5