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

// 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.

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.

 

 

 

Dieser Beitrag wurde unter ARM lpc1xxx, Mikrocontroller abgelegt und mit , , , , , , , , , , , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.