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.