You are on page 1of 5

LPCOpen LPC13xx ADC

If we want to measure some analog values with our microcontroller


we have to convert them with the internal Analog Digital Converter
of the LPC1313. In our example we will start some AD conversions on
different channels and send them via the UART to a computer.

The UART part of this program is described in another blog article


and can be found there in detail. The ADC part is described here.
All Important information about the UART, the ADC and the ICON
Register can be found in the User Manual for the lpc1313.

Si queremos medir algunos valores analógicos con nuestro


microcontrolador, debemos convertirlos con el convertidor digital
analógico interno del LPC1313. En nuestro ejemplo, iniciaremos
algunas conversiones AD en diferentes canales y las enviaremos a
través de UART a una computadora.

La parte UART de este programa se describe en otro artículo de blog


y se puede encontrar allí en detalle. La parte de ADC se describe
aquí. Toda la información importante sobre el UART, el ADC y el
ICON Register se puede encontrar en el Manual de usuario para el
lpc1313.

// Tobias Markus
#include "chip.h"
#include <cr_section_macros.h>
#include <stdlib.h>
#include <string.h>

STATIC const PINMUX_GRP_T pinmuxing[] = {


{(uint32_t)IOCON_PIO1_6,
(IOCON_FUNC1 | IOCON_RESERVED_BIT_6 | IOCON_RESERVED_BIT_7
| IOCON_MODE_INACT)}, /*RXD*/
{(uint32_t)IOCON_PIO1_7,
(IOCON_FUNC1 | IOCON_RESERVED_BIT_6 | IOCON_RESERVED_BIT_7
| IOCON_MODE_INACT)}, /*TXD*/
{(uint32_t)IOCON_PIO0_11,
(IOCON_FUNC2 | IOCON_RESERVED_BIT_6 | IOCON_ADMODE_EN
| IOCON_FILT_DIS)}, /* PIO0_11 used for AD0 */
{(uint32_t)IOCON_PIO1_0,
(IOCON_FUNC2 | IOCON_RESERVED_BIT_6 | IOCON_ADMODE_EN
| IOCON_FILT_DIS)}, /* PIO1_0 used for AD1 */
{(uint32_t)IOCON_PIO1_1,
(IOCON_FUNC2 | IOCON_RESERVED_BIT_6 | IOCON_ADMODE_EN
| IOCON_FILT_DIS)}, /* PIO1_1 used for AD2 */
{(uint32_t)IOCON_PIO1_3,
(IOCON_FUNC2 | IOCON_RESERVED_BIT_6 | IOCON_ADMODE_EN
| IOCON_FILT_DIS)}, /* PIO1_3 used for AD4 */
{(uint32_t)IOCON_PIO1_4,
(IOCON_FUNC1 | IOCON_RESERVED_BIT_6 | IOCON_ADMODE_EN
| IOCON_FILT_DIS)}, /* PIO1_4 used for AD5 */
{(uint32_t)IOCON_PIO1_10,
(IOCON_FUNC1 | IOCON_RESERVED_BIT_6 | IOCON_ADMODE_EN
| IOCON_FILT_DIS)}, /* PIO1_10 used for AD5 */
};

static ADC_CLOCK_SETUP_T ADCSetup;

const uint32_t OscRateIn = 12000000;


volatile uint32_t msTicks=0;

void SysTick_Handler(void)
{
msTicks++;
}

__INLINE static void Delay (uint32_t dlyTicks) {


uint32_t curTicks;

curTicks = msTicks;
while ((msTicks - curTicks) < dlyTicks);
}

static void Init_Board_PinMux(void)


{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_IOCON);
Chip_IOCON_SetPinMuxing(LPC_IOCON,pinmuxing,
sizeof(pinmuxing)/sizeof(PINMUX_GRP_T));
}

static uint16_t readADC(uint8_t channel)


{
uint16_t data;
Chip_ADC_EnableChannel(LPC_ADC, channel, ENABLE);
Chip_ADC_SetStartMode(LPC_ADC, ADC_START_NOW,
ADC_TRIGGERMODE_RISING);
while (Chip_ADC_ReadStatus(LPC_ADC, channel,
ADC_DR_DONE_STAT) != SET);
Chip_ADC_ReadValue(LPC_ADC, channel, &data);
Chip_ADC_EnableChannel(LPC_ADC, channel, DISABLE);
return data;
}

int main(void) {

SysTick_Config(72000000 / 1000);

/* Setup UART */
Init_Board_PinMux();
Chip_UART_Init(LPC_USART);
Chip_UART_SetBaud(LPC_USART, 115200);
Chip_UART_ConfigData(LPC_USART,
(UART_LCR_WLEN8 | UART_LCR_SBS_1BIT));
Chip_UART_TXEnable(LPC_USART);

NVIC_SetPriority(UART0_IRQn, 1);
NVIC_EnableIRQ(UART0_IRQn);

/* Setup ADC */
Chip_ADC_Init(LPC_ADC, &ADCSetup);
uint16_t dataADC[6];
uint8_t buffer[4];
uint8_t i;

while(1)
{
for(i=0;i<4;i++)
{
buffer[i] = 0;
}

dataADC[0] = readADC(ADC_CH0);
dataADC[1] = readADC(ADC_CH1);
dataADC[2] = readADC(ADC_CH2);
dataADC[3] = readADC(ADC_CH4);
dataADC[4] = readADC(ADC_CH5);
dataADC[5] = readADC(ADC_CH6);

for(i=0;i<6;i++)
{
itoa(dataADC[i],buffer,10);
Chip_UART_SendBlocking(LPC_USART,buffer,
strlen(buffer));
Chip_UART_SendBlocking(LPC_USART,(uint8_t*) " ",1);
}
Chip_UART_SendBlocking(LPC_USART,(uint8_t*) "\n",1);
Delay(1000);

}
return 0 ;
}

First we generate a data structure for the pin muxing to configure the IOCON Register. If you
want to know which settings you have to set to get a specific pin function you have to look it up
in the User Manual mentioned above. In the lpcopen chip layer there are defines like shown in
the structure so you can directly use the name of the configuration from the user manual. In
the Init_Board_PinMux(void) function we enable the clock for the IOCON Register and apply
our IOCON configuration.

Primero generamos una estructura de datos para el pin Muxing para configurar el Registro
IOCON. Si desea saber qué configuraciones debe configurar para obtener una función de pin
específica, debe buscarla en el Manual de usuario mencionado anteriormente. En la capa de
chips lpcopen hay definiciones como las que se muestran en la estructura para que pueda usar
directamente el nombre de la configuración del manual del usuario. En la función
Init_Board_PinMux (void) habilitamos el reloj para el Registro IOCON y aplicamos nuestra
configuración IOCON.

We use the uint16_t readADC(uint8_t channel) function to start an ADC conversion on the
given channel and return the result. All Chip_ADC functions need the base address of the ADC
which is given with LPC_ADC. Now we first enable the given ADC channel. Afterwards we set
The Startmode of the ADC with Chip_ADC_SetStartMode. Now we check with the
Chip_ADC_ReadStatus if the ADC_DR_DONE_STAT signial is set. When it is set we read the
ADC value with the Chip_ADC_ReadValue function. this function needs the channel and the
data buffer. Now we disable the channel and return the ADC value.

We use the uint16_t readADC(uint8_t channel) function to start an ADC conversion on the given
channel and return the result. All Chip_ADC functions need the base address of the ADC which
is given with LPC_ADC. Now we first enable the given ADC channel. Afterwards we set The
Startmode of the ADC with Chip_ADC_SetStartMode. Now we check with the
Chip_ADC_ReadStatus if the ADC_DR_DONE_STAT signial is set. When it is set we read the
ADC value with the Chip_ADC_ReadValue function. this function needs the channel and the
data buffer. Now we disable the channel and return the ADC value.
In the main function we first configure the systick timer and then apply the PinMux and init and
configure the UART. In the next step we setup the ADC with the Chip_ADC_Init function which
needs the ADC base address and a ADCSetup pointer.

Since we want to readout six ADC values we make an array witch 6 elements. The buffer
variable is used to convert the values to a human readable ASCII format.

In the main loop we first delete the buffer than read the adc data from 6 channels. After this step
we convert each of the six values to the ASCII format with the itoa function and send them via
the UART. each value is separated by a whitespace and each new value set by a newline. Then
we wait 1s and the main loop starts again.
The code above can be used to develop some easy measurement task with the lpc1313. Our it
can be seen as an example on how to use the ADC peripheral.

En la función principal, primero configuramos el temporizador de sincronización y luego


aplicamos el PinMux e iniciamos y configuramos el UART. En el siguiente paso configuramos el
ADC con la función Chip_ADC_Init que necesita la dirección base del ADC y un puntero
ADCSetup.

Como queremos leer seis valores de ADC, hacemos una matriz con 6 elementos. La variable del
buffer se usa para convertir los valores a un formato ASCII legible por humanos.

En el ciclo principal, primero eliminamos el buffer que leemos los datos de adc de 6 canales.
Después de este paso, convertimos cada uno de los seis valores al formato ASCII con la función
itoa y los enviamos a través de UART. cada valor está separado por un espacio en blanco y cada
nuevo valor establecido por una nueva línea. Luego esperamos 1s y el ciclo principal comienza
de nuevo.

El código anterior puede usarse para desarrollar alguna tarea de medición fácil con lpc1313.
Nuestro puede verse como un ejemplo sobre cómo usar el periférico ADC.

You might also like