Laboratory Exercise 5 - Analog to Digital Conversion The purpose of this lab is to control the blinking speed of an LED through the Analog to Digital Conversion (ADC) module on PIC16 by varying the input voltage on pin RA0. What is ADC? There are 8 specific I/O pins on PIC16 that can be configured to take an analog input and convert it into a 10 bit digital number. 1 In another word, user can supply voltage to one of the pins, and convert this input to a digital value which can then be converted to obtain the value of the voltage. The 10 bit binary number gives a range of 0 1023 or 0 (2^10 1). If we set the reference voltage at 5V then 0 5 volts can be represented as 0 1023 in the digital format. For example 5V would be represented by 1023, and 2.5V would be represented by 512. The formula to calculate the digital value is X = (Vin / Vfullscale ) * (2^n 1) Eg. X = ( 2.5 / 5 ) * 1023 = 512 ADC registers There are in total four registers for A/D conversion in PIC6: Since the PIC16 is an 8 bit microcontroller, the 10 bit result of the ADC is stored in two registers: ADRESH and ADRESL. The result is stored in two forms: left justified or right justified. By setting ADFM bit in ADCON1, the user can manipulate the storing form of the result. 1 Look up section 7.3.2 of the Course Notes for pins that are capable of taking analog inputs.
When the result is left justified, the high 8 bits are stored in ADRESH, and the 7 th and 6 th bit of the ADRESL contains the low 2 bits. The rest are set to 0. ADCON0: The first two bits ADCS1 and ADCS0 are required to select the A/D clock. So for a 20 MHz clock, one would select 10 for Fosc/32. The next three bits of ADCON0 is channel select. Since PIC16 offers 8 input channels, the ADC module needs to know which channel the user wishes to select, and convert. We look up the following table to make channel selection:
Bit 2 of ADCON0 is the GO/DONE bit. Setting this bit high starts the A/D conversion and it is automatically cleared by hardware when it is complete. Bit 0 is ADON. When the bit is set it turns on the A/D, and when cleared it turns off. So it needs to be set high when A/D is desire. ADCON1: We already looked at bit 7 ADFM which is used to select the format of conversion result. Bit 6 4 is unimplement. Bit 3 0 is PCFG 3 0 which is used to select A/D port configuration. PCFG3: PCFG0 AN7 RE2 AN6 RE1 AN5 RE0 AN4 RA5 AN3 RA3 AN2 RA2 AN1 RA1 AN0 RA0 V REF+ V REF- 0000 A A A A A A A A V DD V SS 0001 A A A A V REF+ A A A RA3 V SS 0010 D D D A A A A A V DD V SS 0011 D D D A V REF+ A A A RA3 V SS 0100 D D D D A D A A V DD V SS 0101 D D D D V REF+ D A A RA3 V SS 011x D D D D D D D D V DD V SS 1000 A A A A V REF+ V REF- A A RA3 RA2 1001 D D A A A A A A V DD V SS 1010 D D A A V REF+ A A A RA3 V SS 1011 D D A A V REF+ V REF- A A RA3 RA2 1100 D D D A V REF+ V REF- A A RA3 RA2 1101 D D D D V REF+ V REF- A A RA3 RA2 1110 D D D D D D D A V DD V SS 1111 D D D D V REF+ V REF- D A RA3 RA2 This table looks complicated, but if we break it down, it offers us four options: 1. Setting a pin to analogue input. 2. Setting a pin to be digital input. 3. Setting the positive reference for the converter (Vref+).
4. Setting the Negative reference for the converter (Vref ). For this lab, we require RA0 to be the only analogue input, and set rest to digital input 2. Also we take Vdd and Vss to be reference voltage of 0 to 5V. Thusly, by looking up the above table we see that PCFG3 0 should be set as 1110. Sometimes a different reference voltage is desired, that is why the Microcontroller comes with an A2D module: The two potentiometers allow the user to set different voltage reference levels on pin RA2 and RA3. Short JP4 and JP5 to enable them. A/D Process (taken from Datasheet): 1. Configure the A/D module: Configure analog pins, voltage reference and digital I/O (ADCON1) Select result format (ADFM bit ADCON1) Select A/D input channel (ADCON0 CHS2:CHS0) Select A/D conversion clock (ADCON0 ADCS1:ADCS0) Turn on A/D module (ADCON0 ADON / bit 0) Configure the TRISA register for the analog inputs 2. Wait the required acquisition time (if required) 3. Start conversion Set the GO/DONE bit (ADCON0) 4. Wait for A/D conversion to complete, by polling for the GO/DONE bit to be cleared. 5. Read A/D result register pair (ADRESH:ADRESL) 2 It is often desired in codes that do not require ADC to set all pins to digital input.
Exercise: Write a piece of code that controls the blinking speed of an LED through the Analog to Digital Conversion (ADC) module on PIC16 by varying the input voltage on pin RA0. We use PORTD1 to control the LED. First construct a MAPLAB project and name is ADC, construct a main.asm and save it under the project source files. In the code, first switch to bank 1. TRISD1 is cleared to set the direction of the pins to output. Since the Microcontroller comes with a Debug module with LED already linked to PORTD1, no external LED is needed. Also set TRISA0 to make it an input pin. ADCON1 is used to set the voltage reference of the pins. They should be set to Vdd and Vss. It is also used to configure input analog pins. movlw b'00001110' movwf ADCON1 ;All digital input expect RA0, reference voltage Vdd Vss Now switch back to bank 0 and set ADCON0. Only one analog channel may be read at one time. Set bit 5:3 to 000 to select RA0. bcf STATUS,RP0 movlw b'11000001' movwf ADCON0 ;clock selected, ADC module turned on The configuration is complete. Setting the GO/DONE bit of ADCON0 (bit1) starts the A/D conversion. Completion is indicated when the bit is cleared. MainLoop bsf ADCON0,2 ;start conversion and wait for it to complete btfsc ADCON0,2 goto $ 2 Now blink PORTD1 and go back for looping:. bsf PORTD,1 ;toggle PORTD1 call DelayAD clrf PORTD call DelayAD goto MainLoop
Now to control the blinking speed of the LED we manipulate the DelayAD constants by using the A/D conversion result. DelayAD movfw ADRESH ;delay functions based on A/D result movwf Delay2 ;move 8 MSb from A/D result to Delay2 Delay incf Delay2,f ;make sure no overflows occur btfsc STATUS,Z decf Delay2,f decfsz Delay1, f goto Delay decfsz Delay2, f goto Delay return One thing to keep in mind is that we need to make sure that overflow does not occur. Try taking out this part of code and see what happens. Instead of staying constantly on and blinking slowly at the other, the LED blinks slowly at both extremes. This is because the DECFSZ instructions in the delay loop decrement Delay2 before testing it. When the A/D result is brought to 0, the DECFSZ instruction makes Delay2 overflow to 255, making the delay very long. To prevent this, we increment Delay2 by 1 unless it is already at a maximum. Circuit used to implement the potentiometer to control the input voltage is demonstrated below: After compiling and loading the code, the user should be able to control the blinking speed of RD1 LED light on Microcontroller by turning the potentiometer.