From 7446bd874823bb058d872fa0718ff774379e8118 Mon Sep 17 00:00:00 2001 From: Roland Sahlsten Date: Tue, 8 May 2012 06:43:34 +0000 Subject: git-svn-id: https://svn.spreadspace.org/mur.sat@403 7de4ea59-55d0-425e-a1af-a3118ea81d4c --- software/mpu/src/adc.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 software/mpu/src/adc.c (limited to 'software/mpu/src/adc.c') diff --git a/software/mpu/src/adc.c b/software/mpu/src/adc.c new file mode 100644 index 0000000..1c1f45a --- /dev/null +++ b/software/mpu/src/adc.c @@ -0,0 +1,250 @@ +/***************************************************************************** + * main.c: Main C file for NXP LPC13xx Family Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.07.20 ver 1.00 Preliminary version, first Release + * +*****************************************************************************/ +#include "LPC13xx.h" /* LPC13xx Peripheral Registers */ +#include "adc.h" + +volatile uint32_t ADCValue[ADC_NUM]; +volatile uint32_t ADCIntDone = 0; + +#if BURST_MODE +volatile uint32_t channel_flag; +#endif + +#if ADC_INTERRUPT_FLAG +/****************************************************************************** +** Function name: ADC_IRQHandler +** +** Descriptions: ADC interrupt handler +** +** parameters: None +** Returned value: None +** +******************************************************************************/ +void ADC_IRQHandler (void) +{ + uint32_t regVal; + + LPC_ADC->CR &= 0xF8FFFFFF; /* stop ADC now */ + regVal = LPC_ADC->STAT; /* Read ADC will clear the interrupt */ + if ( regVal & 0x0000FF00 ) /* check OVERRUN error first */ + { + regVal = (regVal & 0x0000FF00) >> 0x08; + /* if overrun, just read ADDR to clear */ + /* regVal variable has been reused. */ + switch ( regVal ) + { + case 0x01: + regVal = LPC_ADC->DR0; + break; + case 0x02: + regVal = LPC_ADC->DR1; + break; + case 0x04: + regVal = LPC_ADC->DR2; + break; + case 0x08: + regVal = LPC_ADC->DR3; + break; + case 0x10: + regVal = LPC_ADC->DR4; + break; + case 0x20: + regVal = LPC_ADC->DR5; + break; + case 0x40: + regVal = LPC_ADC->DR6; + break; + case 0x80: + regVal = LPC_ADC->DR7; + break; + default: + break; + } + LPC_ADC->CR &= 0xF8FFFFFF; /* stop ADC now */ + ADCIntDone = 1; + return; + } + + if ( regVal & ADC_ADINT ) + { + switch ( regVal & 0xFF ) /* check DONE bit */ + { + case 0x01: + ADCValue[0] = ( LPC_ADC->DR0 >> 6 ) & 0x3FF; + break; + case 0x02: + ADCValue[1] = ( LPC_ADC->DR1 >> 6 ) & 0x3FF; + break; + case 0x04: + ADCValue[2] = ( LPC_ADC->DR2 >> 6 ) & 0x3FF; + break; + case 0x08: + ADCValue[3] = ( LPC_ADC->DR3 >> 6 ) & 0x3FF; + break; + case 0x10: + ADCValue[4] = ( LPC_ADC->DR4 >> 6 ) & 0x3FF; + break; + case 0x20: + ADCValue[5] = ( LPC_ADC->DR5 >> 6 ) & 0x3FF; + break; + case 0x40: + ADCValue[6] = ( LPC_ADC->DR6 >> 6 ) & 0x3FF; + break; + case 0x80: + ADCValue[7] = ( LPC_ADC->DR7 >> 6 ) & 0x3FF; + break; + default: + break; + } +#if BURST_MODE + channel_flag |= (regVal & 0xFF); + if ( (channel_flag & 0xFF) == 0xFF ) + { + /* All the bits in have been set, it indicates all the ADC + channels have been converted. */ + LPC_ADC->CR &= 0xF8FFFFFF; /* stop ADC now */ + } +#endif + ADCIntDone = 1; + } + return; +} +#endif + +/***************************************************************************** +** Function name: ADCInit +** +** Descriptions: initialize ADC channel +** +** parameters: ADC clock rate +** Returned value: None +** +*****************************************************************************/ +void ADCInit( uint32_t ADC_Clk ) +{ + /* Disable Power down bit to the ADC block. */ + LPC_SYSCON->PDRUNCFG &= ~(0x1<<4); + + /* Enable AHB clock to the ADC. */ + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13); + + /* Unlike some other pings, for ADC test, all the pins need + to set to analog mode. Bit 7 needs to be cleared according + to design team. */ +#ifdef __JTAG_DISABLED + LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x8F; /* ADC I/O config */ + LPC_IOCON->JTAG_TDI_PIO0_11 |= 0x02; /* ADC IN0 */ + LPC_IOCON->JTAG_TMS_PIO1_0 &= ~0x8F; + LPC_IOCON->JTAG_TMS_PIO1_0 |= 0x02; /* ADC IN1 */ + LPC_IOCON->JTAG_TDO_PIO1_1 &= ~0x8F; + LPC_IOCON->JTAG_TDO_PIO1_1 |= 0x02; /* ADC IN2 */ + LPC_IOCON->JTAG_nTRST_PIO1_2 &= ~0x8F; + LPC_IOCON->JTAG_nTRST_PIO1_2 |= 0x02; /* ADC IN3 */ +#ifdef __SWD_DISABLED + LPC_IOCON->ARM_SWDIO_PIO1_3 &= ~0x8F; + LPC_IOCON->ARM_SWDIO_PIO1_3 |= 0x02; /* ADC IN4 */ +#endif +#endif + LPC_IOCON->JTAG_TDI_PIO0_11 = 0x02; // Select AD0 pin function + LPC_IOCON->JTAG_TMS_PIO1_0 = 0x02; // Select AD1 pin function + LPC_IOCON->JTAG_TDO_PIO1_1 = 0x02; // Select AD2 pin function + LPC_IOCON->JTAG_nTRST_PIO1_2 = 0x02; // Select AD3 pin function +// LPC_IOCON->ARM_SWDIO_PIO1_3 = 0x02; // Select AD4 pin function + LPC_IOCON->PIO1_4 = 0x01; // Select AD5 pin function + LPC_IOCON->PIO1_10 = 0x01; // Select AD6 pin function + LPC_IOCON->PIO1_11 = 0x01; // Select AD7 pin function + + LPC_ADC->CR = ((SystemCoreClock/LPC_SYSCON->SYSAHBCLKDIV)/ADC_Clk-1)<<8; + + /* If POLLING, no need to do the following */ +#if ADC_INTERRUPT_FLAG + NVIC_EnableIRQ(ADC_IRQn); + LPC_ADC->INTEN = 0x1FF; /* Enable all interrupts */ +#endif + return; +} + +/***************************************************************************** +** Function name: ADCRead +** +** Descriptions: Read ADC channel +** +** parameters: Channel number +** Returned value: Value read, if interrupt driven, return channel # +** +*****************************************************************************/ +uint32_t ADCRead( uint8_t channelNum ) +{ +#if !ADC_INTERRUPT_FLAG + uint32_t regVal, ADC_Data; +#endif + + /* channel number is 0 through 7 */ + if ( channelNum >= ADC_NUM ) + { + channelNum = 0; /* reset channel number to 0 */ + } + LPC_ADC->CR &= 0xFFFFFF00; // clear channel selection + LPC_ADC->CR |= (1 << 24) | (1 << channelNum); + /* switch channel,start A/D convert */ +#if !ADC_INTERRUPT_FLAG + while ( 1 ) /* wait until end of A/D convert */ + { + regVal = *(volatile unsigned long *)(LPC_ADC_BASE + + ADC_OFFSET + ADC_INDEX * channelNum); + /* read result of A/D conversion */ + if ( regVal & ADC_DONE ) + { + break; + } + } + + LPC_ADC->CR &= 0xF8FFFFFF; /* stop ADC now */ + if ( regVal & ADC_OVERRUN ) /* save data when it's not overrun, otherwise, return zero */ + { + return ( 0 ); + } + ADC_Data = ( regVal >> 6 ) & 0x3FF; + return ( ADC_Data ); /* return A/D conversion value */ +#else + return ( channelNum ); /* if it's interrupt driven, the ADC reading is + done inside the handler. so, return channel number */ +#endif +} + +/***************************************************************************** +** Function name: ADC0BurstRead +** +** Descriptions: Use burst mode to convert multiple channels once. +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void ADCBurstRead( void ) +{ + if ( LPC_ADC->CR & (0x7<<24) ) + { + LPC_ADC->CR &= ~(0x7<<24); + } + /* Test channel 5,6,7 using burst mode because they are not shared + with the JTAG pins. */ + LPC_ADC->CR &= ~0xFF; + /* Read all channels, 0 through 7. */ + LPC_ADC->CR |= (0xFF); + LPC_ADC->CR |= (0x1<<16); /* Set burst mode and start A/D convert */ + return; /* the ADC reading is done inside the + handler, return 0. */ +} + +/********************************************************************************* +** End Of File +*********************************************************************************/ -- cgit v1.2.3