Friday, May 29, 2020

Introduction to analog to digital converter module

Introduction

An analog to digital converter (ADC) module converts an analog voltage to a digital binary equivalence value. In PIC16F887 the built-in ADC module use a successive approximation type. I has up to 14 analog channels with reference voltage selection. The ADC resolution is 10-bit, made up of two distinct 8-bit registers.

Some pins of PortA and PortB could be used for analog inputs.

Introduction to analog to digital converter module
Analog input pins of PIC16F887


There are two option of ADC clocks, MCU clock and the ADC built-in RC oscillator (FRC). The FRC gives a frequency of 500 kHz maximum. Using the MCU clock with the maximum clocking frequency, the ADC could complete the conversion time at 100 nano seconds.

Introduction to analog to digital converter module
A simplified scheme of ADC module in PIC16F887.
An original detailed block diagram could be found
in PIC16F887 datasheet.

ADC module takes up to 12 cycles to complete the conversion to make the 10-bit result ready. Since the 10-bit result consists of two 8-bit registers. It could be arranged in two margins, left or right. 

Up on the completion, an interrupt flag relates to ADC is set. With this advantage, we can use interrupt routine to process the analog to digital conversion.

There are some registers to work with ADC module:
  • Input output port register (PORTx),
  • Port direction register (TRISx),
  • ANSEL and ANSELH registers,
  • ADCON0 and ADCON1 register,
  • related interrupt registers,
  • ADC result registers.
Some registers listed above have already discussed in previous posts. So we are listing some not-ready-listed registers.

Introduction to analog to digital converter module
This register set the analog inputs pins of some of PortA and PortE. Setting any bit to '1', assigning the corresponding pin to analog input. By default they are '1'.

Introduction to analog to digital converter module

ANSELH controls the analog input pin at PortB. It has only 6 analog input pins while the remaining two are digital. By default, they are set to '1'.

Introduction to analog to digital converter module

This is the first register to control the operation of ADC module.
  • ADC Conversion Clock Select bits ADCS[1:0], is a two-bit clock selection for ADC. The clock source for ADC could fed from MCU clock with the 2, 8 and 32 clock division. Another clock source could fed from internal ADC oscillator with the maximum frequency of 500 kHz. Setting ADCS to 0x03, the ADC clock is fed from it's internal oscillator.
  • Analog Channel Select bits CHS[3:0], could select between the 14 analog input channels. These bits could select the reference capacitor for analog comparator and the 0.6 V fixed voltage reference.
  • ADC Conversion Status bits GO/nDone, initiate a start of conversion when it's set to '1'. It will clear to '0' when the conversion completed. We can also use this bit to check the status of the conversion.
  • ADC Enable bit ADON, turn on the ADC module when set to '1'. Otherwise it's turned off.

Introduction to analog to digital converter module

ADCON1 configures additional setting of the ADC operation.
  • ADC Conversion Result format Select bit ADFM, arranges the margin of the ADC conversion result. It effect the ADRESL and ADRESH register. When it's '0' (default) the result is right justified. 
  • Negative voltage reference bit VCFG1, set the negative voltage reference for ADC. Setting it to '1', the negative voltage reference must supply to VREF- pin. By default, it's '0' and the negative voltage reference pin is internally wired to VSS of the MCU.
  • Positive voltage reference bit VCFG0, set the positive voltage reference for ADC. Setting it to '1', the positive voltage reference must supply to VREF+ pin. By default, it's '0' and the positive voltage reference pin is internally wired to VDD of the MCU.
Introduction to analog to digital converter module
The ADC Result High Register ADRESH, store the result of ADC conversion. In the picture above, it's assumed that the result format is right justified (ADFM=1). 

Introduction to analog to digital converter module
ADRESL is a pair register with ADRESH. Joining them together to make a 10-bit ADC resolution. In this picture we assume that the result format is right justified (ADFM=1).

Programming the ADC in XC8

To access to the ADC module, we must setting up the ADC module and work with the conversion process.
To set up the ADC module:
  1. set the related pin to input
  2. By default those related pins are analog inputs. But we can do it optionally, by setting any bits of the ANSEL and ANSELH register. These two registers contain the analog and digital pins selection as listed above.
  3. Select the ADC clock source by setting the ADCS bits of the ADCON0 register.
  4. Since there are 14 analog channels. Only one active channel is selected for reading the analog voltage value. So we must select one channel by setting the 4-bit CHS bits of the ADCON0 register. 
  5. Turn on the ADC module by setting the ADON bit of the ADCON0 register to '1'.
  6. Two resolution register ADRESL and ADRESH pair store the conversion result. We must set it to right or left justification as preferred by assigning the value to ADFM bit of the ADCON1 register.
  7. Select the voltage reference by setting any value to the VCFG1 and VCFG0 bits of the ADCON1 register.     
To start a conversion:
  1. If we are not yet select the analog channel, do it with the CHS bits.
  2. Wait for some period to make the capacitor properly work
  3. Set the GO/nDone bit to '1' to start the conversion
  4. Wait for the completion by checking the GO/nDone bit.
  5. Get the result from ADRESH and ADRESL register pair.

Programming Example

In this example I read an analog voltage value from AN12 input channel. The result is display in decimal (0 to 1023 for 10-bit value) on a multiplexed SSD.
The ADC clock is driven from its dedicated internal oscillator. The analog value is fed from a POT ranging from 0 to +5 V. The voltage references is internally wired to VSS and VDD of the MCU.

Introduction to analog to digital converter module
Schematic diagram. RB0 or AN12 is an analog input reading pin, reading an analog
value from the POT. The POT works with a passive low pass filter withe any
calculation. The result is displayed on a 4-digit multiplexed SSD ranging from
0 to 1023 in decimal value.

Source code is here.

#include<xc.h>
// PIC16F887 Configuration Bit Settings
// CONFIG1
#pragma config FOSC = XT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = ON
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config IESO = ON
#pragma config FCMEN = ON
#pragma config LVP = ON
// CONFIG2
#pragma config BOR4V = BOR40V
#pragma config WRT = OFF
/*_XTAL_FREQ use for __delay*/
#define _XTAL_FREQ 4000000

void driveDisplays(unsigned int cnt){
 unsigned char ssd[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,
 0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
 //Digit 4 1000's
 PORTD=0x00;
 PORTC=ssd[cnt/1000];
 PORTD=0x01;
 __delay_ms(10);
 //Digit 3 100's
 PORTD=0x00;
 PORTC=ssd[(cnt%1000)/100];
 PORTD=0x02;
 __delay_ms(10);
 //Digit 2 10's
 PORTD=0x00;
 PORTC=ssd[(cnt%100)/10];
 PORTD=0x04;
 __delay_ms(10);
 //Digit 1 1's
 PORTD=0x00;
 PORTC=ssd[cnt%10];
 PORTD=0x08;
 __delay_ms(10);
}
unsigned int readADC(void){
    GO=1;
    while(GO);
    __delay_ms(10);
    return (ADRESH<<8)+ADRESL;
}
void main(void){
    unsigned int adcResult;
    /*Analog and digital Port 
     Configuration*/
    PORTB=0x00;
    PORTC=0x00;
    PORTD=0x00;
    TRISB=0x01;
    TRISC=0x00;
    TRISD=0x00;
    /*Result is right justify*/
    ADFM=1;
    /*By default is analog,
     but again set it to analog*/
    ANS12=1;
    /*Select FRC Clock of ADC module*/
    ADCON0bits.ADCS=0x03;
    /*Turn on ADC Module*/
    ADON=1;
    /*Select AN12 RB0*/
    ADCON0bits.CHS=0b1100;
    /*initiate a conversion*/
    GO=1;
    /*Wait until GO=0 "done"*/
    while(GO);
    while(1){
        adcResult=readADC();
        driveDisplays(adcResult);
    }
}

Introduction to analog to digital converter module
A simulation screen shot. The analog reading is 921 in decimal.















No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (56) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (47) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (71) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)