Thursday, 5 January 2012

ADC Tutorial on LPC2148


 
If DONE is 1 (meaning the conversion is complete), these 10 bits will contain a binary numberrepresenting the results of our analog to digital conversion. It works by measuring the voltage onthe analog input pin divided by the voltage on the Vref pin. Zero means that the voltage on theanalog input pin was less than, equal to or close to GND (Vssa), and 0x3FF (or 0011 1111 1111)indicates that the voltage on the analog input pin was close to, equal to or greater than the thevoltage on the Vref pin. Anything value between these two extremes will be returned as a 10-bitnumber (between 0 and 1023).Before we can read the results from the A/D Data Register, we first need to perform thefollowing steps (to start the actual conversion process by re-configuring ADCR):
1. Stop any current conversions and deselect all channels
This can be accomplished by modifying the A/D Control Register (see ADCR above) as follows:
AD0CR &= ~(adcr_start_mask|adcr_sel_mask);
What you are doing here is setting the START bits in ADCR to 000 (stopping any conversions)and disabling any channels that may have been previously selected. This essentially 'resets' ourADC to a blank, inactive state.
2. Select the channel you wish to use in your conversion
Since we have previously deselected all channels, we need to re-enable the specific channel thatwe wish to use in this conversion. In this particular case, we can enable channel 3 with thefollowing line of code:
AD0CR |=chn;AD0CR |=adc0_start;
3. Manually tell the ADC to start converting
The ADC can be configured to start in two ways: Manually (as we will do here), or when somesort of internal hardware event occurs such as an external interrupt (for example when a buttonconnected to an EINT pin is pressed), or some other form of interrupt. (For details on starting theconversion when an interrupt occurs, please see chapter 17 of the LPC21XX User's Manual.Interrupts will also be covered in a later tutorial.)In our case, the easiest solution is to simply tell the ADC to start converting manually, which isas simple as setting the appropriate START bits (26..24) in the ADC Control Register (seeADCR above). To start converting now, we need to send 001 to the three-bit START block inADCR, which can be done with the following line of code .
AD0CR |=adc0_start;
4. Wait for the conversion to complete
 
Now that the analog to digital converter is properly configured and has been started (on channel3 in this case), we can wait for the results on the appropriate AD Data Register ... ADDR3 in thisparticular case. As we mentioned above, we know when a conversion is complete because bit 31(DONE) of ADDR0..7 will be set to 1. As such, we simply need to wait until we encounter a 1value on this bit, which can be done with the following line of code:
while(!(AD0DR & (0x80000000)));
This will cause the code to endlessly loop until the conversion is complete, and then move on tothe next line once the conversion is finished.
5. Read the 10-bit conversion results
The last step (now that we know the conversion is complete) is simply to read the 10-bit valuestored in the appropriate ADDR register, and do whatever we need to do with it. This last stepcan be accomplished by reading bits 6 through 15 (15..6) of ADDR3 (since we are using Channel3 in this example), and then'shifting' the resultsto the right 6 places to give a normal 10-bitvalue:
i=((AD0DR)&(0x0000FFC0))>>6 ;
That's all that's involved in manually starting an A/D conversion and reading the results. If youwish to continually read the results of the ADC, you can simply place the appropriate code in amethod/function and continually call it, as we are doing in the example.
6.Display the result on the lcd
Since all the values are distributed in the range of 0 – 1023 and with reference to ‘Vref’(which is3.3V), the following self explanatory code will demonstrate how its done.
val=(float) (val*1000/0x3ff)*3.3;/*Vref = 3.3V*/Dis_Value[0]=(unsigned char)(val/1000) + 0x30;Dis_Value[2]=(unsigned char)(val/100%10) + 0x30;Dis_Value[3]=(unsigned char)(val/10%10) + 0x30;Dis_Value[4]=(unsigned char)(val%10) + 0x30;
And you can use our lcd program to display the result from here :

CODE:
#include<lpc213x.h>
#define adc_pin 1<<30
#define pdn_bit 1<<21
#define adcr_start_mask 7<<24
#define adcr_sel_mask 0x000000FF
#define adc0_start 1<<24
void init_adc0(unsigned char,unsigned char);
unsigned char chn;
unsigned int read_adc0();
void delay(int);
unsigned char Dis_Value[5];
 main()
{
unsigned int val;
init_adc0(3,3); /*pass channel number and clkdiv*/
Dis_Value[1]=46; /*ascii value for '.' */
while(1)
{
val=read_adc0();
lcd_init();
lcd_clear();
lcd_gotoxy(0,0);
val=(float) (val*1000/0x3ff)*3.3; /*Vref = 3.3V*/
Dis_Value[0]=(unsigned char)(val/1000) + 0x30;
Dis_Value[2]=(unsigned char)(val/100%10) + 0x30;
Dis_Value[3]=(unsigned char)(val/10%10) + 0x30;
Dis_Value[4]=(unsigned char)(val%10) + 0x30;
lcd_print(Dis_Value); /*display the result on LCD*/
delay(1000); /*display the result for some amount of time*/
}
}
void init_adc0(unsigned char ch,unsigned char clk_div)
{
chn=1<<ch;PINSEL1= (PINSEL1 & (~(3<<28)))|(1<<28); /*Select the AD0.3 of P0.30*/
PCONP |= 0x00001000; /*Poweron the A/D converter 0 */ 
AD0CR =(1<<ch) | ( ((clk_div-1))<<8 ) | pdn_bit ; /*configuerthe A/D control register of A/D 0*/
}
unsigned int read_adc0()
{
unsigned int i=0; 
AD0CR &= ~(adcr_start_mask|adcr_sel_mask);
/*stop the A/D converter by masking the start bits and channel selection bit*/ 
AD0CR |=chn; /*Select the A/D channel */ 
AD0CR |=adc0_start; /*Start the A/D conversion*/
while(!(AD0DR & (0x80000000)));
/*Wait for the conversion to get over by monitoring the 28th bit of A/D data register*/ 
AD0CR &= ~(adcr_start_mask|adcr_sel_mask); /*Stop the conversion by masking the start bits*/
i=((AD0DR)&(0x0000FFC0))>>6 ;
/*Capture the result by shifting the bits to 6 places right*/
                return(i);
}/*delay routine for the display purpose*/
void delay(int cnt)
{
int i=0,j=0;
for(i=0;i<=cnt;i++)
for(j=0;j<=35;j++);
}

No comments:

Post a Comment