March 29, 2024, 03:16:08 PM

ADC

Started by e3402, June 26, 2015, 12:35:52 PM

Previous topic - Next topic

e3402

Hi,
Is there a code sample for ADC in LPC 1343?


e3402

#2
Thanks John,
However I am using IAR, and when I tried to create new project written in C, it requires a main block I have found a code for ADC but it has not a main block how can I add this code to a main block? Here is the code that I found.

/**************************************************************************/
/*!
    @file     adc.c
    @author   K. Townsend (microBuilder.eu)
    @date     22 March 2010
    @version  0.10
   
    @section Description
   
    SW-based single-channel A/D conversion.  If you wish to convert
    multiple ADC channels simultaneously, this code will need to be
    modified to work in BURST mode.
    @section Example
    @code
    #include "core/cpu/cpu.h"
    #include "core/adc/adc.h"
    void main (void)
    {
      cpuInit();
      adcInit();
      uint32_t results = 0; 
      while(1)
      {
        // Get A/D conversion results from A/D channel 0
        results = adcRead(0);
      }
    }
    @endcode
    @section LICENSE
    Software License Agreement (BSD License)
    Copyright (c) 2010, microBuilder SARL
    All rights reserved.
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:
    1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
    3. Neither the name of the copyright holders nor the
    names of its contributors may be used to endorse or promote products
    derived from this software without specific prior written permission.
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**************************************************************************/

#include "adc.h"

static bool _adcInitialised = false;
static uint8_t _adcLastChannel = 0;

/**************************************************************************/
/*!
    @brief Returns the conversion results on the specified ADC channel.
    This function will manually start an A/D conversion on a single
    channel and return the results. 
    @param[in]  channelNum
                The A/D channel [0..7] that will be used during the A/D
                conversion.  (Note that only A/D channel's 0..3 are
                configured by default in adcInit.)
    @return     0 if an overrun error occured, otherwise a 10-bit value
                containing the A/D conversion results.
    @warning    Only AD channels 0..3 are configured for A/D in adcInit.
                If you wish to use A/D pins 4..7 they will also need to
                be added to the adcInit function.
*/
/**************************************************************************/
uint32_t adcReadSingle (uint8_t channelNum)
{
  if (!_adcInitialised) adcInit();

  uint32_t regVal, adcData;

  /* make sure that channel number is 0..7 */
  if ( channelNum >= 8 )
  {
    // ToDo: Change this to throw an exception back
    channelNum = 0;
  }

  /* Deselect all channels */
  ADC_AD0CR &= ~ADC_AD0CR_SEL_MASK;

  /* Start converting now on the appropriate channel */
  ADC_AD0CR |= ADC_AD0CR_START_STARTNOW | (1 << channelNum);
            
  /* wait until end of A/D convert */
  while ( 1 )         
  {
    // Get data register results for the requested channel
    switch (channelNum)
    {
      case 0:
        regVal = (*(pREG32(ADC_AD0DR0)));
        break;
      case 1:
        regVal = (*(pREG32(ADC_AD0DR1)));
        break;
      case 2:
        regVal = (*(pREG32(ADC_AD0DR2)));
        break;
      case 3:
        regVal = (*(pREG32(ADC_AD0DR3)));
        break;
      case 4:
        regVal = (*(pREG32(ADC_AD0DR4)));
        break;
      case 5:
        regVal = (*(pREG32(ADC_AD0DR5)));
        break;
      case 6:
        regVal = (*(pREG32(ADC_AD0DR6)));
        break;
      case 7:
        regVal = (*(pREG32(ADC_AD0DR7)));
        break;
      default:
        regVal = (*(pREG32(ADC_AD0DR0)));
        break;
    }

    /* read result of A/D conversion */
    if (regVal & ADC_DR_DONE)
    {
      break;
    }
  }

  /* stop ADC */
  ADC_AD0CR &= ~ADC_AD0CR_START_MASK;

  /* return 0 if an overrun occurred */
  if ( regVal & ADC_DR_OVERRUN )
  {
    return (0);
  }

  /* return conversion results */
  adcData = (regVal >> 6) & 0x3FF;
  return (adcData);
}

/**************************************************************************/
/*!
    @brief Returns the conversion results on the specified ADC channel.
    This function will manually start an A/D conversion on a single
    channel and return the results.  If ADC Averaging is enabled
    (via ADC_AVERAGING_ENABLE) the specified number of values will be
    samples from the ADC and the average value will be returned.
    @param[in]  channelNum
                The A/D channel [0..7] that will be used during the A/D
                conversion.  (Note that only A/D channel's 0..3 are
                configured by default in adcInit.)
    @return     0 if an overrun error occured, otherwise a 10-bit value
                containing the A/D conversion results.
    @warning    Only AD channels 0..3 are configured for A/D in adcInit.
                If you wish to use A/D pins 4..7 they will also need to
                be added to the adcInit function.
*/
/**************************************************************************/
uint32_t adcRead (uint8_t channelNum)
{
  if (!_adcInitialised) adcInit();

  #if ADC_AVERAGING_ENABLE
    uint32_t adcTotal, i;
    adcTotal = 0;
    for (i=0; i<ADC_AVERAGING_SAMPLES;i++)
    {
      adcTotal += adcReadSingle(channelNum);
    }
    return adcTotal/ADC_AVERAGING_SAMPLES;
  #else
    return adcReadSingle(channelNum);
  #endif
}

/**************************************************************************/
/*!
    @brief      Initialises the A/D converter and configures channels 0..3
                for 10-bit, SW-controlled A/D conversion.
    @return     Nothing
*/
/**************************************************************************/
void adcInit (void)
{
  /* Disable Power down bit to the ADC block. */
  SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_ADC);

  /* Enable AHB clock to the ADC. */
  SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_ADC);

  /* Digital pins need to have the 'analog' bit set in addition
     to changing their pin function */

  /* Set AD0 to analog input */
  IOCON_JTAG_TDI_PIO0_11 &= ~(IOCON_JTAG_TDI_PIO0_11_ADMODE_MASK |
                              IOCON_JTAG_TDI_PIO0_11_FUNC_MASK |
                              IOCON_JTAG_TDI_PIO0_11_MODE_MASK);
  IOCON_JTAG_TDI_PIO0_11 |=  (IOCON_JTAG_TDI_PIO0_11_FUNC_AD0 &
                              IOCON_JTAG_TDI_PIO0_11_ADMODE_ANALOG);

  /* Set AD1 to analog input */
  IOCON_JTAG_TMS_PIO1_0 &=  ~(IOCON_JTAG_TMS_PIO1_0_ADMODE_MASK |
                              IOCON_JTAG_TMS_PIO1_0_FUNC_MASK |
                              IOCON_JTAG_TMS_PIO1_0_MODE_MASK);
  IOCON_JTAG_TMS_PIO1_0 |=   (IOCON_JTAG_TMS_PIO1_0_FUNC_AD1 &
                              IOCON_JTAG_TMS_PIO1_0_ADMODE_ANALOG);

  /* Set AD2 to analog input */
  IOCON_JTAG_TDO_PIO1_1 &=  ~(IOCON_JTAG_TDO_PIO1_1_ADMODE_MASK |
                              IOCON_JTAG_TDO_PIO1_1_FUNC_MASK |
                              IOCON_JTAG_TDO_PIO1_1_MODE_MASK);
  IOCON_JTAG_TDO_PIO1_1 |=   (IOCON_JTAG_TDO_PIO1_1_FUNC_AD2 &
                              IOCON_JTAG_TDO_PIO1_1_ADMODE_ANALOG);

  /* Set AD3 to analog input */
  IOCON_JTAG_nTRST_PIO1_2 &= ~(IOCON_JTAG_nTRST_PIO1_2_ADMODE_MASK |
                               IOCON_JTAG_nTRST_PIO1_2_FUNC_MASK |
                               IOCON_JTAG_nTRST_PIO1_2_MODE_MASK);
  IOCON_JTAG_nTRST_PIO1_2 |=  (IOCON_JTAG_nTRST_PIO1_2_FUNC_AD3 &
                               IOCON_JTAG_nTRST_PIO1_2_ADMODE_ANALOG);

  /* Note that in SW mode only one channel can be selected at a time (AD0 in this case)
     To select multiple channels, ADC_AD0CR_BURST_HWSCANMODE must be used */
  ADC_AD0CR = (ADC_AD0CR_SEL_AD0 |                     /* SEL=1,select channel 0 on ADC0 */
              (((CFG_CPU_CCLK / SCB_SYSAHBCLKDIV) / 1000000 - 1 ) <<  8 ) |   /* CLKDIV = Fpclk / 1000000 - 1 */
              ADC_AD0CR_BURST_SWMODE |                 /* BURST = 0, no BURST, software controlled */
              ADC_AD0CR_CLKS_10BITS |                  /* CLKS = 0, 11 clocks/10 bits */
              ADC_AD0CR_START_NOSTART |                /* START = 0 A/D conversion stops */
              ADC_AD0CR_EDGE_RISING);                  /* EDGE = 0 (CAP/MAT signal falling, trigger A/D conversion) */

  /* Set initialisation flag */
  _adcInitialised = true;

  /* Set last channel flag to 0 (initialised above) */
  _adcLastChannel = 0;

  return;
}