adc4simul.c - Simultaneous sampling of 4 channels (only for PIC24 CPUs without DMA)ΒΆ

Simultaneously samples four channels and uses a timer used to trigger conversions. Ping-pong buffering is used. Conversion results are printed to screen. (HEX values and voltages are printed.) This is only for PIC24 CPUs without DMA.

 
#include "pic24_all.h"
#include "stdio.h"

#ifdef _DMA0IF
# warning "This processor selection has the DMA module; this code example is incompatible with a PIC24 CPU that has DMA."
int main(void) {
  return 0;
}
#else
 

setup an output to help us measure ADC IRQ responses

#define CONFIG_LED2()       CONFIG_RB5_AS_DIG_OUTPUT()
#define LED2                _LATB5

#define   ADC_LEN           10
#define   ADC_NSTEPS        1024
#define   ADC_12BIT_FLAG    0

uint16_t              au16_buffer[8];
volatile  uint16_t    au16_sum[8];
volatile  uint8_t     u8_gotData;

/***
 *** HERE IS THE CODE!
 ***
 ***/
void _ISR _ADC1Interrupt (void) {
  static uint8_t      u8_adcCount=64;
  uint8_t             u8_i;
  uint16_t*           au16_adcHWBuff = (uint16_t*) &ADC1BUF0;
 

If ADC is writing in the 2nd half of the buffer, so determine which half of the buffer is valid (and caused this interrupt), then fetch that half into our local array of ADC results.

  if (AD1CON2 & ADC_ALT_BUF_STATUS_2) {
    for ( u8_i=0; u8_i<8; u8_i++) {
      au16_buffer[u8_i] += au16_adcHWBuff[u8_i];
    } //end for()
  } else {
    for ( u8_i=8; u8_i<16; u8_i++) {
      au16_buffer[u8_i-8] += au16_adcHWBuff[u8_i];
    } //end for()
  } // end if-else

  _AD1IF = 0;                   //clear the interrupt flag

we got the data, so start the sampling process again

  SET_SAMP_BIT_ADC1();

  u8_adcCount--;
  if (u8_adcCount==0) {
    u8_adcCount = 64;
    u8_gotData = 1;
    for ( u8_i=0; u8_i<8; u8_i++) {
      au16_sum[u8_i] = au16_buffer[u8_i];
      au16_buffer[u8_i] = 0;
    } //end for()
  };
 

toggle an LED so we can measure how often ADC IRQs are coming in

  LED2 = !LED2;
}

int main (void) {
  uint8_t   u8_i;
  uint16_t  u16_pot;
  uint32_t  u32_ticks;
  float   f_pot;

  configBasic(HELLO_MSG);
 

make RA0/AN0/VREF+ a digital input to kill the pullup and set the TRISA bit, then make it ANALOG so the ADC will work

  CONFIG_RA0_AS_ANALOG();
  CONFIG_RA1_AS_ANALOG();
  CONFIG_RB0_AS_ANALOG();
  CONFIG_RB12_AS_ANALOG();

  CONFIG_LED2();

  u8_gotData = 0;
 

configure T2/T3 as 32-bit timer to trigger every 1/64 second

  T3CONbits.TON = 0;
  T2CONbits.TON = 0;
  T2CON = T2_32BIT_MODE_ON | T2_PS_1_1 | T2_SOURCE_INT;
  TMR3 = 0;
  TMR2 = 0;
  u32_ticks = usToU32Ticks(15625, getTimerPrescale(T2CONbits)) - 1;     // # of ticks for 1/64 seconds
  PR3 = u32_ticks>>16;
  PR2 = u32_ticks & 0xFFFF;
  T2CONbits.TON = 1;

  configADC1_Simul4ChanIrq(12, ADC_CH123_POS_SAMPLEA_AN0AN1AN2, ADC_CONV_CLK_10Tcy );
  SET_SAMP_BIT_ADC1();

  while (1) {
    while (!u8_gotData) {
      doHeartbeat();
    }
    u8_gotData = 0;
    for ( u8_i=0; u8_i<4; u8_i++) {
      u16_pot = au16_sum[u8_i];
      f_pot = (3.3 / 1023 / 64 ) * u16_pot;
      printf("r");
      outChar( '0'+u8_i );
      printf(":0x%04X=%1.3fV  ",  u16_pot, (double) f_pot );
    } //end for()
    printf("\n");
  } //endof while()
} // endof main()
#endif