Thursday, 4 December 2014

Programming ADC in LPC 2138 (using LM35) using LCD and UART

        ADC INTERFACING WITH LPC2138

       An analog-to-digital converter (ADC, A/D, or A to D) is a device that converts a  continuous physical quantity (voltage) to a digital number that represents the            quantity's amplitude.
       ADC is widely used in data acquisition, an increasing number of microcontrollers have an on-chip ADC peripheral, just like timers and USART. An on-chip ADC eliminates the need for an external ADC connection, which leaves more pins for other I/O activities.
ADC Features:
·       It is a 8-bit ADC.
·       The converted output binary data is held by two special function registers called ADCL and ADCH.
·       We have three options for Vref, Vref can be connected to AVCC (Analog Vcc), internal 2.56V reference, or external AREF pin.
·       The conversion time is dictated by the crystal frequency connected to the XTAL pins and ADC bits.
       The resolution of the converter indicates the number of discrete values it can produce over the range of analog values. The resolution determines the magnitude of the quantization error and therefore determines the maximum possible average signal to noise ratio for an ideal ADC without the use of oversampling. The values are usually stored electronically in binary form, so the resolution is usually expressed in bits.
       The values can represent the ranges from 0 to 255 (i.e. unsigned integer) or from −128 to 127 (i.e. signed integer), depending on the application.


Resolution can also be defined electrically, and expressed in volts. The minimum change in voltage required to guarantee a change in the output code level is called the least significant bit (LSB) voltage. The resolution Q of the ADC is equal to the LSB voltage. The voltage resolution of an ADC is equal to its overall voltage measurement range divided by the number of discrete values:


Normally, the number of voltage intervals is given by


Where M is the ADC's resolution in bits.
ADC Registers

UART
       A universal asynchronous receiver/transmitter, is a piece of computer hardware that translates data between parallel and serial forms. UARTs are commonly used in conjunction with communication standards such as EIA, RS-232, RS-422 or RS-485. The universal designation indicates that the data format and transmission speeds are configurable.
     A UART is usually an individual (or part of an) integrated circuit used for serial communications over a computer or peripheral device serial port. UARTs are now commonly included in microcontrollers.
LM35 TEMPERATURE SENSOR
      LM 35 has been chosen as the temperature sensor as it has the following properties. The LM35 does not require any external calibration or trimming to provide typical accuracies of ±1⁄4°C at room temperature and ±3⁄4°C over a full −55 to +150°C temperature range. It is also of low cost and it can be glued to any surface.
PIN CONFIGURATION
         P0.0 and P0.1 are connected to transmitter and receiver for data transmission and reception.
         P0.2 to P0.4 are used as RS, R/W and Enable bits and connected to LCD display.
          P0.8 to P0.15 are connected to data pins in LCD
          P0.27 are connected to LM35 (temperature sensor).
   
CODE
/* FOSC = 12MHz
CCLK = 60MHz
PCLK = 15MHz
*/
#include <LPC213X.H>

/****************LCD DIRECTIVES***************/
#define LCD_CLEAR             0x01
#define CURSOR_OFF          0x0C
#define FIRST_ROW              0x80
#define SECOND_ROW         0xC0
#define Enable_Pulse()          IOSET0|=1<<EN;Delay_ms(1);IOCLR0=1<<EN;Delay_ms(1);
/*Pin Configuration for LCD*/
#define                  RS                                   2
#define                  RW                                  3
#define                  EN                                   4
/*********************************************/
/**************Function Prototypes************/
void UART0_Init(void);
void UART0_Write(unsigned char value);
void UART0_Write_Text(unsigned char msg[]);
unsigned char UART0_Read(void);
void Lcd_Init(void);
void Lcd_Cmd(unsigned char value);
void Lcd_Write(unsigned char value);
void Lcd_Write_Text(unsigned char msg[]);
void Lcd_Data_Shift(unsigned char value);
void ADC0_Init(void);
unsigned int ADC0_Read(void);
void Delay_ms(unsigned long times);
unsigned long adc_data;
int main()
{
          unsigned char msg[] = "EMBEDDED LAB";
          unsigned char LM35_Temperature[] = "TEMP. MONITOR";
          unsigned char data_received[] = "TEMP VALUE:";
          unsigned char ones,tens,hundreds,thousands;
          unsigned long temp;
          Lcd_Init();
          UART0_Init();
          Delay_ms(10);
          UART0_Write_Text(msg);
          UART0_Write(10);
          UART0_Write(13);
          Lcd_Write_Text(msg);
          Lcd_Cmd(SECOND_ROW);
          Lcd_Write_Text(LM35_Temperature);
          UART0_Write_Text(LM35_Temperature);
          UART0_Write(10);
          UART0_Write(13);
          Delay_ms(500);
          Lcd_Cmd(LCD_CLEAR);
          Lcd_Write_Text(data_received);
          Lcd_Cmd(SECOND_ROW);
         
          ADC0_Init();
          while(1)
          {
                    adc_data = ADC0_Read();
                    adc_data = adc_data*3300;
                    adc_data = adc_data/1023;     //Value of Voltage in Milli Volts
                    /*Display Text on LCD*/
                    temp = adc_data;
                    ones = temp % 10;
                    temp = temp / 10;
                    tens = temp % 10;
                    temp = temp / 10;
                    hundreds = temp % 10;
                    temp = temp / 10;
                    thousands = temp % 10;
                    ones |= 0x30;
                    tens |= 0x30;
                    hundreds |= 0x30;
                    thousands |= 0x30;
                    Lcd_Cmd(SECOND_ROW);
                    Lcd_Write(thousands);
                    Lcd_Write(hundreds);
                    Lcd_Write(tens);
                    Lcd_Write('.');
                    Lcd_Write(ones);
                    Lcd_Write(' ');
                    Lcd_Write('C');
                    Delay_ms(10);
          }        
}

/****************Function Definition**********/
/****************Delay Function***************/
void Delay_ms(unsigned long times)
{
          unsigned long i,j;
          for(j=0;j<times;j++)
                    for(i=0;i<7500;i++);
}
/*****************LCD Functions***************/
void Lcd_Init(void)
{
          PINSEL0 = 0x00;
          IODIR0 |= (1<<RS);                                              //RS Pin as Output Pin
          IODIR0 |= (1<<RW);                                             //RW Pin as Output Pin
          IODIR0 |= (1<<EN);                                              //EN Pin as Output Pin
          IODIR0 |= 0x0000FF00;                   //P0.8 to P0.15 as Data Line of LCD
          Lcd_Cmd(0x38);                      //Send 8-bit initialization command to lcd
          Delay_ms(10);
          Lcd_Cmd(CURSOR_OFF);                                 //Cursor OFF
          Delay_ms(10);
          Lcd_Cmd(LCD_CLEAR);
          Delay_ms(1);
          Lcd_Cmd(FIRST_ROW);
}
void Lcd_Data_Shift(unsigned char value)
{
          /*
          This Function will shift the eight bit data stored in variable value,
          to the Port Pin P0.8 to P0.15 Successfully.
          */
          unsigned char i;
         
          for(i=0;i<8;i++)
          {
                    if(value & 0x01)
                    {
                              IOSET0 |= (1<<(i+8));
                    }
                    else
                    {
                              IOCLR0 |= (1<<(i+8));
                    }
                    value = value >> 1;
          }
}

void Lcd_Cmd(unsigned char value)
{
          /*Configure LCD for receiving Command Data*/
          IOCLR0 |= (1<<RS);
          IOCLR0 |= (1<<RW);
          IOSET0 |= (1<<EN);
          Lcd_Data_Shift(value);
          Enable_Pulse();
}
void Lcd_Write(unsigned char value)
{
          /*Configure LCD for receiving Display Data*/
          IOSET0 |= (1<<RS);
          IOCLR0 |= (1<<RW);
          IOSET0 |= (1<<EN);
          Lcd_Data_Shift(value);
          Enable_Pulse();
}
void Lcd_Write_Text(unsigned char msg[])
{
while(*msg)
          {
          Lcd_Write(*msg);
msg++;
          }
}

/***************UART-0 Functions**************/
void UART0_Init(void)
{
       PINSEL0 = 0x00000005;                                    //P0.0 as TX0 and P0.1 as RX0
          U0LCR = 0x83;                                           //Enable access to Divisor Latches
          //and Set 8 bit Character Length with 1 Stop bit and Parity Disabled
          //Access to Divisor Latches is Enabled, in order to write Baud Rate Generator Registers
          //Values to be written in Baud Rate Registers U0DLM and U0LL
          /*
          Formula is
     Baud_Rate = PCLK*MulVal / [(16*(256*U0DLM+U0DLL)*(MulVal + DivAddVal))]
          Example:-
          MulVal = 1;
          DivAddVal = 0;
          Baud_Rate = 9600;
          PCLK = 15MHz
          U0DLM = 0;
          Hence,
          U0DLL = 15000000/(9600*16) = 97.65625 = 98
          U0DLL = 98 = 0x62
          */
          U0DLM = 0x00;
          U0DLL = 0x62;                          //Baud Rate of 9600
          U0LCR = 0x03;                         //Disable Access to Divisor Latches
}
void UART0_Write(unsigned char value)
{
/*       THRE bit can be extracted by this U0LSR & 0x20
          THRE = 0 means data is present.
          THRE = 1 means register is empty.
          In order to transmit data, we have to wait will the THRE = 1,
          then only we can transmit data.
          */
          while(!(U0LSR&0x20));               //THRE = 0 stay here
          U0THR = value;
}
void UART0_Write_Text(unsigned char msg[])
{
          while(*msg)
          {
                    UART0_Write(*msg);
                    msg++;
          }
}
unsigned char UART0_Read(void)
{
          /*Receiver Data Ready = U0LSR.0 bit
          RDR bit can be extracted by this U0LSR & 0x01
          RDR = 0 means no Data is Received in U0RBR
          RDR = 1 means that Data is present in U0RBR
          */
          while(!(U0LSR & 0x01));                               //RDR = 0 stay here
          return (U0RBR);
}
/*****************ADC Functions***************/
void ADC0_Init(void)
{
          /*************Initialize ADC AD0.0*************/
          AD0CR = 1<<21;                                             //A/D is Operational
          AD0CR = 0<<21;                                          //A/D is in Power Down Mode
          PCONP = (PCONP &0x001817BE) | (1UL<<12);
          PINSEL0 = 0x00;
          PINSEL1 = 0x00400000;                             //P0.27 is Configured as Analog to Digital Converter Pin AD0.0
           AD0CR = 0x00200401;                                                    //CLKDIV=4,Channel-0.0 Selected,A/D is Operational
          /*
          A/D Clock = PCLK /(CLKDIV+1);
          */
}
unsigned int ADC0_Read(void)
{
unsigned long adc_data;
AD0CR |= 1UL<<24;                                  //Start Conversion
          do
          {
          adc_data = AD0GDR;
          }while(!(adc_data & 0x80000000));
          //Wait untill the DONE bits Sets
          AD0CR &= ~0x01000000;                          //Stops the A/D Conversion  
          adc_data = adc_data >> 6;
          adc_data = adc_data & 0x3FF;    //Clearing all other Bits
return (adc_data);
}

OUTPUT:




   




5 comments:

  1. it is showing garbage values

    ReplyDelete
  2. please tell me the component in stimulation used

    ReplyDelete
  3. thank you for this work. i couldn't have made ADC to work properly until i find this link. best wishes

    ReplyDelete
    Replies
    1. how did u get.. im getting garbage values
      and idk whether adc is converting or not also..

      Delete
  4. Can you please explain how add 3 lm35 sensors to take the average temperature

    ReplyDelete