目次
前
次
A/D変換
シリアルインタフェースをもつA/D変換ICを
8048に接続してみます。
利用するA/D変換ICは、ADC0832。
ピンアサインは、以下。
2チャネル分の入力がありますが、インタフェースは
4信号で扱えます。
4信号で、アナログからデジタルに変換した値を
入力するための仕様を、タイミングチャートから
読み取ります。
8ビットデータを読み込むシーケンスは、以下。
- nCSを'0'に設定。
- DIに、START_BIT、SGL/nDIF、ODD/nEVENを転送。(rising_edge)
- DOから8ビットデータ入力。(falling_edge、LSB first)
- nCSを'1'に設定。
4信号を、ポート2の上位4ビットに割当てて
プログラムを考えます。4信号のビット割当て
は、次のようにしました。
- P2.7 nCS
- P2.6 CLK
- P2.5 DI
- P2.4 DO
8048からは、3信号を出力するので汎用レジスタの
8ビットのうちの3ビットにnCS、CLK、DIを割当てて
扱いましょう。またDOの扱いも決めておきます。
レジスタは、r2、r3、r4でカウンタ、制御
データと役割分担しておきます。
nCS、CLK、DIの3信号を扱うサブルーチンを定義し
シーケンスをわかりやすくしておきます。
nCSの扱いは、以下。
CS_SET:
; initialize
mov a,#80h
; MSB = 1 and impress
outl P2,a
;
ret
CS_CLR:
; clr
clr a
; MSB = 0 and impress
outl P2,a
;
ret
DIに論理値を出力するコードを定義します。
メモリのMODEに入っている3ビットを転送して
DIに3ビット分の信号を出力。
SND_DIB:
; set pointer
mov r0,#MODE
; expand
mov a,@r0
swap a
rr a
mov r2,a
rl a
mov r3,a
rl a
mov r4,a
; mask
xch a,r2
anl a,#20h
xch a,r2
xch a,r3
anl a,#20h
xch a,r3
xch a,r4
anl a,#20h
xch a,r4
; start bit
xch a,r2
outl P2,a ; CLK = 0
orl a,#20h
outl P2,a ; CLK = 1
anl a,#0bfh
outl P2,a ; CLK = 0
; single or bipolar
xch a,r3
outl P2,a ; CLK = 0
orl a,#20h
outl P2,a ; CLK = 1
anl a,#0bfh
outl P2,a ; CLK = 0
; odd or even
xch a,r4
outl P2,a ; CLK = 0
orl a,#20h
outl P2,a ; CLK = 1
anl a,#0bfh
outl P2,a ; CLK = 0
;
ret
タイミングチャートからスタートビットに続けて
2ビットを転送しています。
3ビットを汎用レジスタr2、r3、r4に展開してから
CLKをL→H→Lとしてエッジを生成。
DOから論理値を入力するコードを定義します。
DO_GET:
; CLK = 1
mov a,#40h
outl P2,a
; CLK = 0
anl a,#0bfh
outl P2,a
; DO
in a,P2
anl a,#10h
; store
mov r4,a
;
ret
DOから8ビットのデータを受取って、レジスタに
保存するには反復処理が必要なので、カウンタに
r2を使い、8ビットをr5に格納します。
AD_GET:
; initialize
mov r2,#8
mov r3,#0
;
AD_GETL:
; shift
xch a,r3
rr a
xch a,r3
; get DO state
call DO_GET
; get
mov a,r4
anl a,#10h
jz AD_GETL1
; set MSB
AD_GETL0:
xch a,r3
orl a,#80h
xch a,r3
AD_GETL1:
djnz r2,AD_GETL
; store
mov r0,#ADR
mov a,r3
mov @r0,a
;
ret
8048のSRAMにA/D変換値を保存する
シーケンスは、以下。
ADC_HND:
; enable nCS
call CS_CLR
; set mode
call SND_DIB
; get 1 byte
call AD_GET
; disable nCS
call CS_SET
;
ret
メモリに保存された8ビットを10進数の3けたに
変換することを考えます。
8ビットの整数で最大値は255。レジスタの値が
100以上、10以上と場合分けして、数値を生成と
いう定石を適用。
100以上だったらレジスタの値から、何回100を
引けるかで、100の位を求められます。
8048では、減算命令がないので、2の補数を
使い加算で減算を代行します。
200を減算するときには、200の2の補数を求めて
それを加算する処理を使います。
コードは、以下。
mov r2,#038h
add a,r2
レジスタaに負の数を加えていき、キャリーが
セットされたら終了します。キャリーがセット
されるまでの回数をカウントすれば、減算での
除算が実現できます。
コードは、以下。
CAL:
; get value
mov a,@r0
;+++ calculate 100 +++
; set counter
mov r2,#0
; set -100
mov r3,#09ch
CAL0:
add a,r3
jc CAL1
inc r2
jmp CAL0
CAL1:
; store 100 digit
xch a,r4
mov a,r2
mov @r1,a
xch a,r4
; adjust
add a,#100
; update pointer : DIGIT10
inc r1
;+++ calculate 10 +++
; set counter
mov r2,#0
; set -10
mov r3,#0f6h
CAL2:
add a,r3
jc CAL3
inc r2
jmp CAL2
CAL3:
; store 10 digit
xch a,r4
mov a,r2
mov @r1,a
xch a,r4
; adjust
add a,#10
; update pointer : DIGIT
inc r1
; store
mov @r1,a
;
ret
変換したい値が入っているアドレスと
変換結果を格納するアドレスを設定後
サブルーチンコールすると考えます。
コーリングシーケンスの例は、以下。
; set pointer
mov r0,#ADR
mov r1,#DIGIT100
;
call CAL
2チャネルのA/D変換を実現するプログラムに
まとめてみます。(表示はなし)
;
; TEST program for 8048 ( PROASM-II )
; Copyright (C) 2018 Kensuke Ooyu
;
INCLUDE 8048.LIB
;*******************
; value and address
;*******************
MODE equ 18h
ADR equ 19h
DIGITA equ 1Ah
DIGITB equ 1Bh
;****************
; define symbols
;****************
ENTRY equ 0h
E_INT equ 3h
E_TIM equ 7h
;*******************
; interrupt vectors
;*******************
org ENTRY
jmp START
; external interrupt
org E_INT
retr
; timer interrupt
org E_TIM
retr
org 10h
;**************
; sub routines
;**************
INIT:
; disable external interrupt
dis i
; disable timer interrupt
dis tcnti
; initialize I/O
mov a,#0
outl p1,a
outl p2,a
ret
CS_SET:
; initialize
mov a,#80h
; MSB = 1 and impress
outl P2,a
;
ret
CS_CLR:
; clr
clr a
; MSB = 0 and impress
outl P2,a
;
ret
SND_DIB:
; set pointer
mov r0,#MODE
; expand
mov a,@r0
swap a
rr a
mov r2,a
rl a
mov r3,a
rl a
mov r4,a
; mask
xch a,r2
anl a,#20h
xch a,r2
xch a,r3
anl a,#20h
xch a,r3
xch a,r4
anl a,#20h
xch a,r4
; start bit
xch a,r2
outl P2,a ; CLK = 0
orl a,#20h
outl P2,a ; CLK = 1
anl a,#0bfh
outl P2,a ; CLK = 0
; single or bipolar
xch a,r3
outl P2,a ; CLK = 0
orl a,#20h
outl P2,a ; CLK = 1
anl a,#0bfh
outl P2,a ; CLK = 0
; odd or even
xch a,r4
outl P2,a ; CLK = 0
orl a,#20h
outl P2,a ; CLK = 1
anl a,#0bfh
outl P2,a ; CLK = 0
;
ret
DO_GET:
; CLK = 1
mov a,#40h
outl P2,a
; CLK = 0
anl a,#0bfh
outl P2,a
; DO
in a,P2
anl a,#10h
; store
mov r4,a
;
ret
AD_GET:
; initialize
mov r2,#8
mov r3,#0
;
AD_GETL:
; shift
xch a,r3
rr a
xch a,r3
; get DO state
call DO_GET
; get
mov a,r4
anl a,#10h
jz AD_GETL1
; set MSB
AD_GETL0:
xch a,r3
orl a,#80h
xch a,r3
AD_GETL1:
djnz r2,AD_GETL
; store
mov r0,#ADR
mov a,r3
mov @r0,a
;
ret
ADC_HND:
; enable nCS
call CS_CLR
; set mode
call SND_DIB
; get 1 byte
call AD_GET
; disable nCS
call CS_SET
;
ret
CAL:
; get value
mov a,@r0
;+++ calculate 100 +++
; set counter
mov r2,#0
; set -100
mov r3,#09ch
CAL0:
add a,r3
jc CAL1
inc r2
jmp CAL0
CAL1:
; store 100 digit
mov r4,a
xch a,r2
mov @r1,a
xch a,r4
; adjust
add a,#100
; update pointer : DIGIT10
inc r1
;+++ calculate 10 +++
; set counter
mov r2,#0
; set -10
mov r3,#0f6h
CAL2:
add a,r3
jc CAL3
inc r2
jmp CAL2
CAL3:
; store 10 digit
mov r4,a
xch a,r2
mov @r1,a
xch a,r4
; adjust
add a,#10
; update pointer : DIGIT
inc r1
; store
mov @r1,a
;
ret
;**************
; main routine
;**************
org 100h
START:
call INIT
MAIN:
; set mode
mov a,#4
; perform A/D conversion
call ADC_HND
; set pointer
mov r0,#ADR
mov r1,#DIGITA
; convert digit
call CAL
; set mode
mov a,#5
; perform A/D conversion
call ADC_HND
; set pointer
mov r0,#ADR
mov r1,#DIGITB
; convert digit
call CAL
;
jmp MAIN
end
リストは、次のようになりました。
0000 ;
0000 ; TEST program for 8048 ( PROASM-II )
0000 ; Copyright (C) 2018 Kensuke Ooyu
0000 ;
0000 INCLUDE 8048.LIB
0000 list
0000
0000 ;*******************
0000 ; value and address
0000 ;*******************
0018 MODE equ 18h
0019 ADR equ 19h
001A DIGITA equ 1Ah
001B DIGITB equ 1Bh
0000
0000 ;****************
0000 ; define symbols
0000 ;****************
0000 ENTRY equ 0h
0003 E_INT equ 3h
0007 E_TIM equ 7h
0000
0000 ;*******************
0000 ; interrupt vectors
0000 ;*******************
0000 org ENTRY
0000 2400 + jmp START
0002
0002 ; external interrupt
0002 org E_INT
0003 93 + retr
0004
0004 ; timer interrupt
0004 org E_TIM
0007 93 + retr
0008
0008 org 10h
0010 ;**************
0010 ; sub routines
0010 ;**************
0010 INIT:
0010 ; disable external interrupt
0010 15 + dis i
0011
0011 ; disable timer interrupt
0011 35 + dis tcnti
0012
0012 ; initialize I/O
0012 2300 + mov a,#0
0014 39 + outl p1,a
0015 3A + outl p2,a
0016
0016 83 + ret
0017
0017 CS_SET:
0017 ; initialize
0017 2380 + mov a,#80h
0019 ; MSB = 1 and impress
0019 3A + outl P2,a
001A ;
001A 83 + ret
001B
001B CS_CLR:
001B ; clr
001B 27 + clr a
001C ; MSB = 0 and impress
001C 3A + outl P2,a
001D ;
001D 83 + ret
001E
001E SND_DIB:
001E ; set pointer
001E B818 + mov r0,#MODE
0020 ; expand
0020 F0 + mov a,@r0
0021 47 + swap a
0022 77 + rr a
0023 AA + mov r2,a
0024 E7 + rl a
0025 AB + mov r3,a
0026 E7 + rl a
0027 AC + mov r4,a
0028 ; mask
0028 2A + xch a,r2
0029 5320 + anl a,#20h
002B 2A + xch a,r2
002C 2B + xch a,r3
002D 5320 + anl a,#20h
002F 2B + xch a,r3
0030 2C + xch a,r4
0031 5320 + anl a,#20h
0033 2C + xch a,r4
0034 ; start bit
0034 2A + xch a,r2
0035 3A + outl P2,a ; CLK = 0
0036 4320 + orl a,#20h
0038 3A + outl P2,a ; CLK = 1
0039 53BF + anl a,#0bfh
003B 3A + outl P2,a ; CLK = 0
003C ; single or bipolar
003C 2B + xch a,r3
003D 3A + outl P2,a ; CLK = 0
003E 4320 + orl a,#20h
0040 3A + outl P2,a ; CLK = 1
0041 53BF + anl a,#0bfh
0043 3A + outl P2,a ; CLK = 0
0044 ; odd or even
0044 2C + xch a,r4
0045 3A + outl P2,a ; CLK = 0
0046 4320 + orl a,#20h
0048 3A + outl P2,a ; CLK = 1
0049 53BF + anl a,#0bfh
004B 3A + outl P2,a ; CLK = 0
004C ;
004C 83 + ret
004D
004D DO_GET:
004D ; CLK = 1
004D 2340 + mov a,#40h
004F 3A + outl P2,a
0050 ; CLK = 0
0050 53BF + anl a,#0bfh
0052 3A + outl P2,a
0053 ; DO
0053 0A + in a,P2
0054 5310 + anl a,#10h
0056 ; store
0056 AC + mov r4,a
0057 ;
0057 83 + ret
0058
0058 AD_GET:
0058 ; initialize
0058 BA08 + mov r2,#8
005A BB00 + mov r3,#0
005C ;
005C AD_GETL:
005C ; shift
005C 2B + xch a,r3
005D 77 + rr a
005E 2B + xch a,r3
005F ; get DO state
005F 144D + call DO_GET
0061 ; get
0061 FC + mov a,r4
0062 5310 + anl a,#10h
0064 C66A + jz AD_GETL1
0066 ; set MSB
0066 AD_GETL0:
0066 2B + xch a,r3
0067 4380 + orl a,#80h
0069 2B + xch a,r3
006A AD_GETL1:
006A EA5C + djnz r2,AD_GETL
006C ; store
006C B819 + mov r0,#ADR
006E FB + mov a,r3
006F A0 + mov @r0,a
0070 ;
0070 83 + ret
0071
0071 ADC_HND:
0071 ; enable nCS
0071 141B + call CS_CLR
0073 ; set mode
0073 141E + call SND_DIB
0075 ; get 1 byte
0075 1458 + call AD_GET
0077 ; disable nCS
0077 1417 + call CS_SET
0079 ;
0079 83 + ret
007A
007A CAL:
007A ; get value
007A F0 + mov a,@r0
007B
007B ;+++ calculate 100 +++
007B ; set counter
007B BA00 + mov r2,#0
007D ; set -100
007D BB9C + mov r3,#09ch
007F CAL0:
007F 6B + add a,r3
0080 F685 + jc CAL1
0082 1A + inc r2
0083 047F + jmp CAL0
0085 CAL1:
0085 ; store 100 digit
0085 AC + mov r4,a
0086 2A + xch a,r2
0087 A1 + mov @r1,a
0088 2C + xch a,r4
0089 ; adjust
0089 0364 + add a,#100
008B ; update pointer : DIGIT10
008B 19 + inc r1
008C
008C ;+++ calculate 10 +++
008C ; set counter
008C BA00 + mov r2,#0
008E ; set -10
008E BBF6 + mov r3,#0f6h
0090 CAL2:
0090 6B + add a,r3
0091 F696 + jc CAL3
0093 1A + inc r2
0094 0490 + jmp CAL2
0096 CAL3:
0096 ; store 10 digit
0096 AC + mov r4,a
0097 2A + xch a,r2
0098 A1 + mov @r1,a
0099 2C + xch a,r4
009A ; adjust
009A 030A + add a,#10
009C ; update pointer : DIGIT
009C 19 + inc r1
009D ; store
009D A1 + mov @r1,a
009E ;
009E 83 + ret
009F
009F ;**************
009F ; main routine
009F ;**************
009F org 100h
0100 START:
0100 1410 + call INIT
0102
0102 MAIN:
0102 ; set mode
0102 2304 + mov a,#4
0104 ; perform A/D conversion
0104 1471 + call ADC_HND
0106 ; set pointer
0106 B819 + mov r0,#ADR
0108 B91A + mov r1,#DIGITA
010A ; convert digit
010A 147A + call CAL
010C
010C ; set mode
010C 2305 + mov a,#5
010E ; perform A/D conversion
010E 1471 + call ADC_HND
0110 ; set pointer
0110 B819 + mov r0,#ADR
0112 B91B + mov r1,#DIGITB
0114 ; convert digit
0114 147A + call CAL
0116 ;
0116 2402 + jmp MAIN
0118
0118 end
HEXファイルは、次のようになります。
:020000002400DA
:010003009369
:010007009365
:1000100015352300393A8323803A83273A83B81869
:10002000F04777AAE7ABE7AC2A53202A2B53202BC3
:100030002C53202C2A3A43203A53BF3A2B3A4320E0
:100040003A53BF3A2C3A43203A53BF3A8323403ABB
:1000500053BF3A0A5310AC83BA08BB002B772B145A
:100060004DFC5310C66A2B43802BEA5CB819FBA0E9
:1000700083141B141E1458141783F0BA00BB9C6B16
:10008000F6851A047FAC2AA12C036419BA00BBF6CA
:0F0090006BF6961A0490AC2AA12C030A19A183CF
:10010000141023041471B819B91A147A2305147140
:08011000B819B91B147A24028E
:00000001FF
目次
前
次