1.
2016
Lab4
ANALOG
TO
DIGITAL
CONVERTER
(ADC)
ARIEL
TONATIUH
ESPINDOLA
PIZANO
1459342
2. Microcontroller Units Tongji University 2
Analog to Digital Converter
1. Implementation with 7-segments led.
2. 8-bit conversion
3. 10-bit conversion
Objective
The aim of this practice is to understand how the ADC work either with 8-bit or 10-bit conversion
using interruptions or polling method. Use the C and Assembly language to develop the code.
1. Implementation with 7-segments led (Common cathode)
In order to visualize the result of the conversion is necessary to work with either LEDs or 7-
segment display. In this case the choice was using one of the 7 segments display bar installed
on the development board to represent numbers of 3 or 4 digits long.
1.1 Algorithm
It is demanded a whole port from the MCU to represent a number or a character on a 7 segment
display. If we wanted to show a 4-digit number, we would have to use 3 more displays and so
other ports. Due to this limitation provided by the chip a technique is applied to solve the
problem, time division multiplexing.
The idea is to interleave the inputs to their respective slot of time as shown in the Figure 1.1.1.
This can be implemented by setting a time delay for every slot and by shifting the input
selection.
Figure 1.1.1.- Multiplexing four inputs.
Step by step algorithm
1. Establish the number of inputs
2. Define the vector of data
3. Initialize the input selector
4. Display the first element of the array and hold a time (width of the slot)
5. Shift the selector to the next input
6. If the selector has reached the last input, go back to the step 3.
7. This can be done infinitely.
3. Microcontroller Units Tongji University 3
Pseudo-code
Inputs [4]
Infinite loop:
loop i=1:4(selctor)
Output = input[i]
Delay(time)
i=i+1
end
end
Figure 1.1.2.- Flow chart of the algorithm described above.
2. Analog to Digital 8-bit conversion
Write a program to perform 8-bit analog to digital conversion made by the ADC of the MCU and
display the result in the 7-segment LEDs as varying the input voltage.
2.1 Algorithm
The steps to use the ADC to complete conversions are as follows:
1. ADC Initialization
a. Select the input clock source and the divide ratio used to generate the internal
clock, ADCK.
b. Select sample time and low-power configuration.
c. Select conversion trigger (hardware or software).
d. Continuous or only-once conversion configuration.
e. Enable or disable conversion complete interrupts.
f. Select the input channel on which conversions will be performed.
2. Start ADC conversion
a. Wait for the status register 7th
bit COCO (Conversion complete)
3. Get the result
a. From the ADC1RL and ADC1RH registers.
• 1.a y 1.b are configured by ADCCFG register.
• 1.c are configured by ADCSC2 register.
no
Start
Display
element
I
>N?
Delay
Increment
selector
yes
Reset
selector
4. Microcontroller Units Tongji University 4
• 1.e and 1.f are configured by the ADCSC2 register.
Flow chart
Figure 2.1.1.- Initialization flow chart of the ADC as an example taken from the MC09S08AW60
datasheet.
Registers configuration 8-bit conversion with interruption enabled
APCTL1 = 0x02
• Pin control 2: AD2 pin I/O disabled.
ADC1SC2 = 0x00
• 0:3 Reserved (00)
• Compare function greater than disabled (0)
• Conversion trigger select, Software triggered selected (0)
• Conversion active, conversion no in progress (0)
•
ADC1CFG = 0xE0
• 0:1 Input clock select, Bus clock (00)
• 2:3 Conversion mode selection, 8-bit (00)
• 4 Long sample time configuration, short sample time(0)
• 5:6 Clock divide select ADIV, input clock/8 (11)
• 7 Low power configuration enabled (1)
5. Microcontroller Units Tongji University 5
ADC1SC1 = 0x61
• 4:0 input channel (0001)
• 5 ADCO Continuous conversion enabled (1)
• 6 AIEN Interrupt enabled (1)
• 7 COCO Conversion complete flag (Only read)
Figure 2.1.2.- Debugging the code for the 8-bit ADC conversion.
Assembly code for the 8-bit conversion:
; Include derivative-specific definitions
INCLUDE 'derivative.inc'
;
; export symbols
;
XDEF _Startup
ABSENTRY _Startup
; Interruptions
ORG Vadc1
JMP Read
;
; variable/data section
;
ORG Z_RAMStart ; Insert your data definition here
SPLIT: DC.B $00,$00,$00
CNT: DS.B 1
ENABLE: DS.B 1
ADC_DATA: DS.B 1
KBVALUE: DS.B 1
COND: DC.B $FF
6. Microcontroller Units Tongji University 6
KBTABLE: ; table for 8-segments LED
DC.B $00,$3F,$01,$06,$02,$5B,$03,$4F
DC.B $04,$66,$05,$6D,$06,$7D,$07,$07
DC.B $08,$7F,$09,$6F
DC.B $FF
;
; code section
;
ORG ROMStart
_Startup:
LDHX #RAMEnd+1 ; initialize the stack pointer
TXS
CLI ; enable interrupts
LDA #$52
STA SOPT
BSR SETUP_PTS
BSR SETUP_CGR
BSR SETUP_ADC
LDHX #$0000
mainLoop:
NOP
;BRCLR 7,ADC1SC1,*
Read: LDA ADC1RL
;LDA #$7B
STA ADC_DATA
LDX #100 ; DIVIDE OVER 100
DIV ; A <- (H:A) / X; H<- Reminder
LDHX #$0002
STA SPLIT,X ; SPLIT[2]
DECX ; X--;
PSHX ; SAVE X
LDHX #$000A ; DIVISOR
LDA ADC_DATA
DIV ; DIVIDE OVER 10
LDHX #$000A
DIV ; DIVIDE AGAIN OVER 10
PSHH ;
PULA
LDHX #$0000
PULX ; GET X ;
STA SPLIT,X ; SPLIT[1]
DECX ; X--;
PSHX ; SAVE X
LDHX #$000A
LDA ADC_DATA
DIV ; DIVIDE OVER 10
PSHH
PULA
LDHX #$0000
PULX
STA SPLIT,X ; SPLIT[0]
MOV #$03,CNT
7. Microcontroller Units Tongji University 7
MOV #$01,ENABLE
LDHX #$0000
TDM_LOOP:
LDA SPLIT,X
;LDA #$3F
STA KBVALUE
JSR ENCODE
STA PTDD
LDA ENABLE
STA PTED
LSLA
STA ENABLE
BSR Delay
INCX
DBNZ CNT,TDM_LOOP
BRA mainLoop
SETUP_PTS:
LDA #$FF
STA PTDDD ; PORTD OUTPUT SEGMENTS
STA PTEDD ; PORTE OUTPUT ENABLES
STA PTDDS
STA PTEDS
LDA #$00
STA PTDD
STA PTED
RTS
SETUP_CGR:
LDA #$78
STA ICGC1
LDA #$00
STA ICGC2
BRCLR 3,ICGS1,*
RTS
SETUP_ADC:
LDA #$02 ; DISABLE IO FOR PIN-B1
STA APCTL1
LDA #$00
STA ADC1SC2
LDA #$E0
STA ADC1CFG ; CONFIG ADC 8-BIT
LDA #$61
STA ADC1SC1 ; SET INTERRUPT AND ADC CH 1
RTS
;********************************************************
; INPUT: Accumulator a*times(100 cycles)
; OUTPUT: doesn't alter X nor A registers (due to Stack)
Delay:
PSHX
PSHA
8. Microcontroller Units Tongji University 8
LDX #!100
LDA #$A
LOOP: NOP
DBNZX LOOP
DBNZA LOOP
PULA
PULX
RTS
; *******************************************************
; ENCODER
ENCODE: PSHH
PSHX
LDHX #$0000
ENC1:
LDA KBTABLE,X
CBEQ COND,ENC3
CMP KBVALUE ; if not, compare
BNE ENC2 ; if not eq, jump to ENC2
INCX
LDA KBTABLE,X
BRA RETURN
ENC2:
INCX
INCX
BRA ENC1
ENC3:
LDA #$FF; ; FF for undefined value
RETURN: PULX
PULH
RTS
3. Analog to Digital 10-bit conversion
Write a program to perform 10-bit analog to digital conversion made by the ADC of the MCU and
display the result in the 7-segment LEDs as varying the input voltage.
𝐿𝑒𝑣𝑒𝑙𝑠 = 2!"#$
3.1 Algorithm
The
logic
is
the
same
to
the
section
2.1.
To
deal
with
a
10-‐bit
conversion
changes
the
way
to
perform
arithmetic
operations
in
assembly
such
as
DIV
which
store
the
result
of
the
division
in
the
accumulator
(A)
and
the
remainder
in
the
high
parte
of
the
index
register
(H).
𝐷𝐼𝑉
𝐴 =
𝐻: 𝐴
𝑋
𝐻 = 𝑅𝑒𝑚𝑖𝑛𝑑𝑒𝑟
𝐴 < −(𝐻: 𝐴)/𝑋, 𝐻(𝑟𝑒𝑚𝑖𝑛𝑑𝑒𝑟)
9. Microcontroller Units Tongji University 9
In
order
to
get
a
vector
which
later
on
will
be
used
as
an
input
of
the
TDM
system
described
in
first
section,
the
problem
may
turn
out
as
follows:
Given
a
1023
to
split:
1. 1023 / 1000, take the integer 1
2. 1023 / 100 % 10, result in 0
3. 1023 / 10 %10, result in 2
4. 1023 /1 %10, result in 3
Then:
𝐼 = {1,0,2,3}
As
described
above
it
is
the
procedure
to
then
go
into
the
TDM
algorithm
and
finally
display
the
result
on
the
7-‐segment
displays
now
for
10
bits.
C code for 10-bit analog to digital conversion
void main(void)
{
unsigned char convert_value;
unsigned int high_value;
unsigned int value;
unsigned char aa;
unsigned char i;
unsigned char SM_SBUFF[4];
unsigned char
SM_LED_Num[17]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,
0x71,0x00};
SEG_DD = 0xFF;
DIG_DD = 0xFF;
SEG_DS = 0xFF;
DIG_DS = 0xFF;
SEG_VAL = 0x00;
DIG_VAL = 0x00;
SOPT_COPE = 0;
Clock_Init();
ADC0_Init();
EnableInterrupts;
for(;;)
{
while(!AD1SC1_COCO)
{
;
10. Microcontroller Units Tongji University 10
}
high_value = ADC1RH;
convert_value = ADC1RL;
value = (high_value<<8) | convert_value;
SM_SBUFF[3] = value/1000;
SM_SBUFF[2] = value/100%10;
SM_SBUFF[1] = value/10%10;
SM_SBUFF[0] = value%10;
aa = 0x01;
for(i=0;i<4;i++)
{
PTDD = SM_LED_Num[SM_SBUFF[i]];
PTED = aa;
aa = aa<<1;
delay(1);
}
}//end of for(;;)
}//end of main
Assembly code for 10-bit analog to digital conversion
;
; variable/data section
;
ORG Z_RAMStart ; Insert your data definition
here
SPLIT: DC.B $00,$00,$00,$00
CNT: DS.B 1
ENABLE: DS.B 1
ADC_DATA: DS.W 1
DIVISOR: DC.W $1000
KBVALUE: DS.B 1
COND: DC.B $FF
KBTABLE: ; table for 8-segments LED
DC.B $00,$3F,$01,$06,$02,$5B,$03,$4F
DC.B $04,$66,$05,$6D,$06,$7D,$07,$07
DC.B $08,$7F,$09,$6F
DC.B $FF
;
; code section
;
ORG ROMStart
_Startup:
LDHX #RAMEnd+1 ; initialize the stack pointer
11. Microcontroller Units Tongji University 11
TXS
CLI ; enable interrupts
LDA #$52
STA SOPT
SETUP_PTS:
LDA #$FF
STA PTDDD ; PORTD OUTPUT SEGMENTS
STA PTEDD ; PORTE OUTPUT ENABLES
STA PTDDS
STA PTEDS
LDA #$00
STA PTDD
STA PTED
SETUP_CGR:
LDA #$78
STA ICGC1
LDA #$00
STA ICGC2
BRCLR 3,ICGS1,*
SETUP_ADC:
LDA #$02 ; DISABLE IO FOR PIN-B1
STA APCTL1
LDA #$00
STA ADC1SC2
LDA #$E8
STA ADC1CFG ; CONFIG ADC 10-BIT
LDA #$21
STA ADC1SC1 ; SET POLLING AND ADC CH 1
LDHX #$0000
mainLoop:
NOP
LDHX #$0000
BRCLR 7,ADC1SC1,*
NOP
Read: LDA ADC1RH
STA ADC_DATA,X
PSHA
INCX
LDA ADC1RL
STA ADC_DATA,X
;------- perform data/4----
PULH
BSR Divide_1000
LDHX #$0003 ; SPLIT[3]
STA SPLIT,X
DECX ; X--;
PSHX ; SAVE X
12. Microcontroller Units Tongji University 12
BSR Read_data
LDX #100 ; DIVISOR
DIV ; DIVIDE OVER 100
LDHX #$000A
DIV ; DIVIDE AGAIN OVER 10
PSHH ; SAVE REMINDER
PULA
CLRH
PULX ; GET X ;
STA SPLIT,X ; SPLIT[2]
DECX ; X--;
PSHX ; SAVE X
BSR Read_data
LDX #10 ; DIVISOR
DIV ; DIVIDE OVER 10
LDHX #$000A
DIV ; DIVIDE AGAIN OVER 10
;DIV ; A <- (H:A) / X; H<- Reminder
PSHH ; SAVE REMINDER
PULA
CLRH
PULX ; GET X ;
STA SPLIT,X ; SPLIT[1]
DECX ; X--;
PSHX ; SAVE X
BSR Read_data
LDX #10
DIV ; DIVIDE AGAIN OVER 10
PSHH ; SAVE REMINDER
PULA
CLRH
PULX ; GET X ;
STA SPLIT,X ; SPLIT[0]
MOV #$04,CNT
MOV #$01,ENABLE
LDHX #$0000
TDM_LOOP:
LDA SPLIT,X
STA KBVALUE
JSR ENCODE
STA PTDD
LDA ENABLE
STA PTED
LSLA
STA ENABLE
BSR Delay
INCX
DBNZ CNT,TDM_LOOP
13. Microcontroller Units Tongji University 13
BRA mainLoop
Read_data: ; for div
LDHX #$0000
LDA ADC_DATA,X
PSHA
INCX
LDA ADC_DATA,X
PULH
RTS
Divide_1000:
LDX #$04
DIV
PSHA ; save result of data/4
CLRH
;--- perform 1000/4 -------
LDA #$03
PSHA
PULH
LDA #$E8
DIV
PSHA ; save result of data/1000
; ---- finally data/4 divided by 1000/4
CLRH
PULX
PULA
DIV ; now in A is data/1000
RTS
;********************************************************
; INPUT: Accumulator a*times(100 cycles)
; OUTPUT: doesn't alter X nor A registers (due to Stack)
Delay:
PSHX
PSHA
LDX #!100
LDA #$A
LOOP: NOP
DBNZX LOOP
DBNZA LOOP
PULA
PULX
RTS
; *******************************************************
; ENCODER
ENCODE: PSHH
PSHX
LDHX #$0000
ENC1:
14. Microcontroller Units Tongji University 14
LDA KBTABLE,X
CBEQ COND,ENC3
CMP KBVALUE ; if not, compare
BNE ENC2 ; if not eq, jump to ENC2
INCX
LDA KBTABLE,X
BRA RETURN
ENC2:
INCX
INCX
BRA ENC1
ENC3:
LDA #$FF; ; FF for undefined value
RETURN: PULX
PULH
RTS
Results with Video attached to the e-mail: