This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

MCB1700 ADC Problem

Hi everyone,

I was trying the ADC polling example (with some mods) and the MCB1760 dev board. For some reason, the ADC value never reaches the max value (0x0FFF). The max value I got was 0x010A for a 3.3V output in the potentiometer, and 0x0000 for 0V.

Proportionally, the values are right, because I did the math for several measurements and were right.

Here is the code:

void adc_thread (void ) {

  open_uart(UART0_ID, 9600, (DATASIZE8|STOPBIT1|PARITYNONE), 100);
  open_adc(200000);
  open_adc_channel(ADC2_ID);

  while (1)
  {
    adc_value = read_adc(ADC2_ID);
    buf[0] = adc_value >> 8;
    buf[1] = adc_value & 0xFF;
    write_uart(UART0_ID, buf, 2);

    value = 3.3 * (float)adc_value;
    value /= 266;

    temp = ADC->ADTRM;

    os_msleep(200);
  }
}

void open_adc(uint32_t rate)
{
  uint32_t temp, adcr;

  // Turn on power and clock
  SC->PCONP |= (1<<12);

  /* set ADCR to 0 to reconfigure the ADC */
  ADC->ADCR = 0;

  //Enable PDN bit
  adcr = ADC_CR_PDN;
  // Set clock frequency
  temp = SystemFrequency / 4;
  /* The APB clock (PCLK_ADC0) is divided by (CLKDIV+1) to produce the clock for
   * A/D converter, which should be less than or equal to 13MHz.
   * A fully conversion requires 65 of these clocks.
   * ADC clock = PCLK_ADC0 / (CLKDIV + 1);
   * ADC rate = ADC clock / 65;
   */
  temp = (temp /(rate * 65)) - 1;
  adcr |=  (temp<<8);

  ADC->ADCR = adcr;
}

void open_adc_channel(adc_channel_t channel)
{
  switch (channel)
  {
  case ADC0_ID:
    PINCON->PINSEL1 |= (1<<14);
    PINCON->PINMODE1 |= (2<<14);
    break;
  case ADC1_ID:
    PINCON->PINSEL1 |= (1<<16);
    PINCON->PINMODE1 |= (2<<16);
    break;
  case ADC2_ID:
    PINCON->PINSEL1 |= (1<<18);
    PINCON->PINMODE1 |= (2<<18);
    break;
  case ADC3_ID:
    PINCON->PINSEL1 |= (1<<20);
    PINCON->PINMODE1 |= (2<<20);
    break;
  case ADC4_ID:
    PINCON->PINSEL3 |= (3<<28);
    PINCON->PINMODE3 |= (2<<28);
    break;
  case ADC5_ID:
    PINCON->PINSEL3 |= (3<<30);
    PINCON->PINMODE3 |= (2<<30);
    break;
  case ADC6_ID:
    PINCON->PINSEL0 |= (2<<6);
    PINCON->PINMODE0 |= (2<<6);
    break;
  case ADC7_ID:
    PINCON->PINSEL0 |= (2<<4);
    PINCON->PINMODE0 |= (2<<4);
    break;
  }
}

uint16_t read_adc(adc_channel_t channel)
{
  uint32_t temp;

  /* wait until the adc goes free */
  //while (!ADC->ADGDR & ADC_GDR_DONE) {
  while (!ADC->ADDR2 & ADC_GDR_DONE) {
    CoYieldTask();
  }

  /* clear the selected channel */
  ADC->ADCR &= ~ADC_CHANNEL_MASK;
  ADC->ADCR |= (1<<channel);

  ADC->ADCR &= ~ADC_CMD_MASK;
  ADC->ADCR |= ADC_CMD_MACRO(ADC_START_NOW);

  /* wait until the adc finishes */
  //while (!ADC->ADGDR & ADC_GDR_DONE) {
  while (!ADC->ADDR2 & ADC_GDR_DONE) {
    CoYieldTask();
  }

  //temp = ADC->ADGDR;
  temp = ADC->ADDR2;
  temp >>= 4;
  temp &= 0x00000FFF;
  return (uint16_t)temp;
}

I'm using a RTOS, that's because the code is inside a while(1).

Thanks in advance,
Mariano.

0