$search
00001 /***************************************************************************** 00002 * adc.c: ADC module file for Philips LPC214x Family Microprocessors 00003 * 00004 * Copyright(C) 2006, Philips Semiconductor 00005 * All rights reserved. 00006 * 00007 * History 00008 * 2005.10.01 ver 1.00 Prelimnary version, first Release 00009 * 00010 ******************************************************************************/ 00011 #include "LPC214x.h" /* LPC21xx definitions */ 00012 #include "type.h" 00013 #include "irq.h" 00014 #include "target.h" 00015 #include "adc.h" 00016 00017 volatile unsigned int ADC0Value[ADC_NUM], ADC1Value[ADC_NUM]; 00018 volatile unsigned int ADC0IntDone = 0, ADC1IntDone = 0; 00019 00020 #if ADC_INTERRUPT_FLAG 00021 /****************************************************************************** 00022 ** Function name: ADC0Handler 00023 ** 00024 ** Descriptions: ADC0 interrupt handler 00025 ** 00026 ** parameters: None 00027 ** Returned value: None 00028 ** 00029 ******************************************************************************/ 00030 void ADC0Handler (void) __irq 00031 { 00032 unsigned int regVal; 00033 00034 IENABLE; /* handles nested interrupt */ 00035 00036 regVal = AD0STAT; /* Read ADC will clear the interrupt */ 00037 if ( regVal & 0x0000FF00 ) /* check OVERRUN error first */ 00038 { 00039 regVal = (regVal & 0x0000FF00) >> 0x08; 00040 /* if overrun, just read ADDR to clear */ 00041 /* regVal variable has been reused. */ 00042 switch ( regVal ) 00043 { 00044 case 0x01: 00045 regVal = AD0DR0; 00046 break; 00047 case 0x02: 00048 regVal = AD0DR1; 00049 break; 00050 case 0x04: 00051 regVal = AD0DR2; 00052 break; 00053 case 0x08: 00054 regVal = AD0DR3; 00055 break; 00056 case 0x10: 00057 regVal = AD0DR4; 00058 break; 00059 case 0x20: 00060 regVal = AD0DR5; 00061 break; 00062 case 0x40: 00063 regVal = AD0DR6; 00064 break; 00065 case 0x80: 00066 regVal = AD0DR7; 00067 break; 00068 default: 00069 break; 00070 } 00071 AD0CR &= 0xF8FFFFFF; /* stop ADC now */ 00072 ADC0IntDone = 1; 00073 return; 00074 } 00075 00076 if ( regVal & ADC_ADINT ) 00077 { 00078 switch ( regVal & 0xFF ) /* check DONE bit */ 00079 { 00080 case 0x01: 00081 ADC0Value[0] = ( AD0DR0 >> 6 ) & 0x3FF; 00082 break; 00083 case 0x02: 00084 ADC0Value[1] = ( AD0DR1 >> 6 ) & 0x3FF; 00085 break; 00086 case 0x04: 00087 ADC0Value[2] = ( AD0DR2 >> 6 ) & 0x3FF; 00088 break; 00089 case 0x08: 00090 ADC0Value[3] = ( AD0DR3 >> 6 ) & 0x3FF; 00091 break; 00092 case 0x10: 00093 ADC0Value[4] = ( AD0DR4 >> 6 ) & 0x3FF; 00094 break; 00095 case 0x20: 00096 ADC0Value[5] = ( AD0DR5 >> 6 ) & 0x3FF; 00097 break; 00098 case 0x40: 00099 ADC0Value[6] = ( AD0DR6 >> 6 ) & 0x3FF; 00100 break; 00101 case 0x80: 00102 ADC0Value[7] = ( AD0DR7 >> 6 ) & 0x3FF; 00103 break; 00104 default: 00105 break; 00106 } 00107 AD0CR &= 0xF8FFFFFF; /* stop ADC now */ 00108 ADC0IntDone = 1; 00109 } 00110 00111 IDISABLE; 00112 VICVectAddr = 0; /* Acknowledge Interrupt */ 00113 } 00114 00115 /****************************************************************************** 00116 ** Function name: ADC1Handler 00117 ** 00118 ** Descriptions: ADC1 interrupt handler 00119 ** 00120 ** parameters: None 00121 ** Returned value: None 00122 ** 00123 ******************************************************************************/ 00124 void ADC1Handler (void) __irq 00125 { 00126 unsigned int regVal; 00127 00128 IENABLE; /* handles nested interrupt */ 00129 00130 regVal = AD1STAT; /* Read ADC will clear the interrupt */ 00131 if ( regVal & 0x0000FF00 ) /* check OVERRUN error first */ 00132 { 00133 regVal = (regVal & 0x0000FF00) >> 0x08; 00134 /* if overrun, just read AD1DRx to clear */ 00135 /* regVal variable has been reused. */ 00136 switch ( regVal ) 00137 { 00138 case 0x01: 00139 regVal = AD1DR0; 00140 break; 00141 case 0x02: 00142 regVal = AD1DR1; 00143 break; 00144 case 0x04: 00145 regVal = AD1DR2; 00146 break; 00147 case 0x08: 00148 regVal = AD1DR3; 00149 break; 00150 case 0x10: 00151 regVal = AD1DR4; 00152 break; 00153 case 0x20: 00154 regVal = AD1DR5; 00155 break; 00156 case 0x40: 00157 regVal = AD1DR6; 00158 break; 00159 case 0x80: 00160 regVal = AD1DR7; 00161 break; 00162 default: 00163 break; 00164 } 00165 AD1CR &= 0xF8FFFFFF; /* stop ADC now */ 00166 ADC1IntDone = 1; 00167 return; 00168 } 00169 00170 if ( regVal & ADC_ADINT ) 00171 { 00172 switch ( regVal & 0xFF ) /* check DONE bit */ 00173 { 00174 case 0x01: 00175 ADC1Value[0] = ( AD1DR0 >> 6 ) & 0x3FF; 00176 break; 00177 case 0x02: 00178 ADC1Value[1] = ( AD1DR1 >> 6 ) & 0x3FF; 00179 break; 00180 case 0x04: 00181 ADC1Value[2] = ( AD1DR2 >> 6 ) & 0x3FF; 00182 break; 00183 case 0x08: 00184 ADC1Value[3] = ( AD1DR3 >> 6 ) & 0x3FF; 00185 break; 00186 case 0x10: 00187 ADC1Value[4] = ( AD1DR4 >> 6 ) & 0x3FF; 00188 break; 00189 case 0x20: 00190 ADC1Value[5] = ( AD1DR5 >> 6 ) & 0x3FF; 00191 break; 00192 case 0x40: 00193 ADC1Value[6] = ( AD1DR6 >> 6 ) & 0x3FF; 00194 break; 00195 case 0x80: 00196 ADC1Value[7] = ( AD1DR7 >> 6 ) & 0x3FF; 00197 break; 00198 default: 00199 break; 00200 } 00201 AD1CR &= 0xF8FFFFFF; /* stop ADC now */ 00202 ADC1IntDone = 1; 00203 } 00204 00205 IDISABLE; 00206 VICVectAddr = 0; /* Acknowledge Interrupt */ 00207 } 00208 #endif 00209 00210 /***************************************************************************** 00211 ** Function name: ADCInit 00212 ** 00213 ** Descriptions: initialize ADC channel 00214 ** 00215 ** parameters: ADC clock rate 00216 ** Returned value: true or false 00217 ** 00218 *****************************************************************************/ 00219 unsigned int ADCInit( unsigned int ADC_Clk ) 00220 { 00221 AD0CR = ( 0x01 << 0 ) | // SEL=1,select channel 0, 1 to 4 on ADC0 00222 ( ( Fpclk / ADC_Clk - 1 ) << 8 ) | // CLKDIV = Fpclk / 1000000 - 1 00223 ( 0 << 16 ) | // BURST = 0, no BURST, software controlled 00224 ( 0 << 17 ) | // CLKS = 0, 11 clocks/10 bits 00225 ( 1 << 21 ) | // PDN = 1, normal operation 00226 ( 0 << 22 ) | // TEST1:0 = 00 00227 ( 0 << 24 ) | // START = 0 A/D conversion stops 00228 ( 0 << 27 ); /* EDGE = 0 (CAP/MAT singal falling,trigger A/D 00229 conversion) */ 00230 AD1CR = ( 0x01 << 0 ) | // SEL=1,select channel 0, 0 to 7 on ADC1 00231 ( ( Fpclk / ADC_Clk - 1 ) << 8 ) | // CLKDIV = Fpclk / 1000000 - 1 00232 ( 0 << 16 ) | // BURST = 0, no BURST, software controlled 00233 ( 0 << 17 ) | // CLKS = 0, 11 clocks/10 bits 00234 ( 1 << 21 ) | // PDN = 1, normal operation 00235 ( 0 << 22 ) | // TEST1:0 = 00 00236 ( 0 << 24 ) | // START = 0 A/D conversion stops 00237 ( 0 << 27 ); /* EDGE = 0 (CAP/MAT singal falling,trigger A/D 00238 conversion) */ 00239 00240 /* If POLLING, no need to do the following */ 00241 #if ADC_INTERRUPT_FLAG 00242 AD0INTEN = 0x11E; // Enable all interrupts 00243 AD1INTEN = 0x1FF; 00244 00245 if ( install_irq( ADC0_INT, (void *)ADC0Handler ) == FALSE ) 00246 { 00247 return (FALSE); 00248 } 00249 if ( install_irq( ADC1_INT, (void *)ADC1Handler ) == FALSE ) 00250 { 00251 return (FALSE); 00252 } 00253 #endif 00254 00255 return (TRUE); 00256 } 00257 00258 /***************************************************************************** 00259 ** Function name: ADC0Read 00260 ** 00261 ** Descriptions: Read ADC0 channel 00262 ** 00263 ** parameters: Channel number 00264 ** Returned value: Value read, if interrupt driven, return channel # 00265 ** 00266 *****************************************************************************/ 00267 unsigned int ADC0Read( unsigned char channelNum ) 00268 { 00269 #if !ADC_INTERRUPT_FLAG 00270 unsigned int regVal, ADC_Data; 00271 volatile unsigned int timeout=0; 00272 #endif 00273 00274 /* channel number is 0 through 7 */ 00275 if ( channelNum >= ADC_NUM ) 00276 { 00277 channelNum = 0; /* reset channel number to 0 */ 00278 } 00279 AD0CR &= 0xFFFFFF00; 00280 AD0CR |= (1 << 24) | (1 << channelNum); 00281 /* switch channel,start A/D convert */ 00282 #if !ADC_INTERRUPT_FLAG 00283 while ( timeout++<5000 ) /* wait until end of A/D convert */ 00284 { 00285 regVal = *(volatile unsigned long *)(AD0_BASE_ADDR 00286 + ADC_OFFSET + ADC_INDEX * channelNum); 00287 /* read result of A/D conversion */ 00288 if ( regVal & ADC_DONE ) 00289 { 00290 break; 00291 } 00292 } 00293 00294 AD0CR &= 0xF8FFFFFF; /* stop ADC now */ 00295 if ( regVal & ADC_OVERRUN ) /* save data when it's not overrun 00296 otherwise, return zero */ 00297 { 00298 return ( 0 ); 00299 } 00300 ADC_Data = ( regVal >> 6 ) & 0x3FF; 00301 return ( ADC_Data ); /* return A/D conversion value */ 00302 #else 00303 return ( channelNum ); /* if it's interrupt driven, the 00304 ADC reading is done inside the handler. 00305 so, return channel number */ 00306 #endif 00307 } 00308 00309 /***************************************************************************** 00310 ** Function name: ADC1Read 00311 ** 00312 ** Descriptions: Read ADC1 channel 00313 ** 00314 ** parameters: Channel number 00315 ** Returned value: Value read, if interrupt driven, return channel # 00316 ** 00317 *****************************************************************************/ 00318 unsigned int ADC1Read( unsigned char channelNum ) 00319 { 00320 #if !ADC_INTERRUPT_FLAG 00321 unsigned int regVal; 00322 unsigned int ADC_Data; 00323 #endif 00324 00325 /* channel number is 0 through 7 */ 00326 if ( channelNum >= ADC_NUM ) 00327 { 00328 channelNum = 0; /* reset channel number to 0 */ 00329 } 00330 AD1CR &= 0xFFFFFF00; 00331 AD1CR |= (1 << 24) | (1 << channelNum); 00332 /* switch channel,start A/D convert */ 00333 #if !ADC_INTERRUPT_FLAG 00334 while ( 1 ) /* wait until end of A/D convert */ 00335 { 00336 regVal = *(volatile unsigned long *)(AD1_BASE_ADDR 00337 + ADC_OFFSET + ADC_INDEX * channelNum); 00338 /* read result of A/D conversion */ 00339 if ( regVal & ADC_DONE ) 00340 { 00341 break; 00342 } 00343 } 00344 00345 AD1CR &= 0xF8FFFFFF; /* stop ADC now */ 00346 if ( regVal & ADC_OVERRUN ) /* save data when it's not overrun 00347 otherwise, return zero */ 00348 { 00349 return ( 0 ); 00350 } 00351 00352 ADC_Data = ( regVal >> 6 ) & 0x3FF; 00353 return ( ADC_Data ); /* return A/D conversion value */ 00354 #else 00355 return ( channelNum ); 00356 #endif 00357 } 00358 00359 /********************************************************************************* 00360 ** End Of File 00361 *********************************************************************************/