目次

A/D変換

 シリアルインタフェースをもつA/D変換ICを
 8048に接続してみます。

 利用するA/D変換ICは、ADC0832。
 ピンアサインは、以下。



 2チャネル分の入力がありますが、インタフェースは
 4信号で扱えます。

 4信号で、アナログからデジタルに変換した値を
 入力するための仕様を、タイミングチャートから
 読み取ります。



 8ビットデータを読み込むシーケンスは、以下。
  1. nCSを'0'に設定。
  2. DIに、START_BIT、SGL/nDIF、ODD/nEVENを転送。(rising_edge)
  3. DOから8ビットデータ入力。(falling_edge、LSB first)
  4. nCSを'1'に設定。
 4信号を、ポート2の上位4ビットに割当てて  プログラムを考えます。4信号のビット割当て  は、次のようにしました。  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

目次

inserted by FC2 system