前回に引き続き、AT89S52のシリアル通信に挑戦してみました。
シリアル通信で重要な、クロック原ですが、AT80S52の水晶原発振は12MHzとしました。本来は、11.0592MHzなどが一番いいと思いますが、手持ちがなかったので、12MHz水晶発振子で行くことにしました。
8051オリジナルでは、原発振の12クロックを1マシンサイクルとしてタイマ回路につなぎます。AT89S52では、6クロックを1マシンサイクルとしてタイマー回路に送ります。
12MHzでの上限値ボーレート4800bpsに設定し、8データビット、パリティなし、1ストップビットの8N1の設定としています。
シリアル通信UARTのモードをモード1にSCONの設定を行います。
mov SCON, #0x50 ;UARTはモード1に設定、受信イネーブル
;SCON=01010000B
タイマー回路の先頭では原発振を1/1あるいは1/2に切り替えるSMOD1があります。PCONの7ビット目に当たります。デフォルトは"0"(1/2)ですが、4800bpsにするためにSMOD1を"1"(1/1)設定します。
mov PCON, #0x90 ;PCON SMOD1(7bit目)="1" 1*12MHz
;PCON=10X10000B
シリアル通信では、タイマー1を占有します。タイマー1(TMODで)は8ビット自動リドードモードに設定します。
mov TMOD, #0x20 ;タイマー1を8ビット自動リロードモードに設定
;TMOD=00100000B
分周器TH1及びTL1の値は次の式で求められます。
分周値=256-(SMOD1:1or2)×原発振)/(6*32*ボーレート)
256を引いている意味は、カウント値はカウントアップしてオーバーフローし、カウント値を再読み込みしカウントアップを繰り返すためです。
6の値は、前述の6クロックを1マシンサイクルで実行するためです。
分周値=256-(1*12000000)/(6*32*4800)=256-13(13.02)=243
16進に変換して、0xf3(243)
mov a, #0xf3 ;タイマーカウンターセット f3H=256-(1*12000000)/(6*32*4800bps)
mov TH1, a
mov TL1, a
送受信方式は、ポーリング方式で、受信フラグ(RI=SCON(B0))及び送信フラグ(TI=SCON(B1))を常にチェックする方式です。
なお、チェックフラグ RI,TIは手動でクリアする必要があります。
入出力するデータは、SBUF(0x99)にセットされます。
1文字入力、1文字出力は次ようになりました。
getchar: ;1文字シリアル入力
jnb ri, . ;SCONのRI(0bit目)が"1"なるまでループ
mov a, SBUF ;SBUFバッファーからaに格納
clr ri ;SCONのRI(0bit目)をクリア
ret ;復帰
putchar: ;1文字シリアル出力
clr ti ;SCONのTI(1bit目)をケリア
mov SBUF, a ;aからSBUFバッファーに格納
jnb ti, . ;SCONのTI(1bit目)が"1"なるまでループ
ret ;復帰
なお、 jnb ri, . は loop: jnb ri, loop と同じです
回路図は下記の通りです。
USB-シリアル通信アダプターは、以前使用した「KKHMF 2個 USB to UART TTL RS232 PL2303HX ワイヤーアダプタ変換ケーブルRaspberry Pi Arduino用(amazon)」を使用しました。
下記のプログラムは、シリアル端末にメッセージを出力したのち、>の後、入力された文字をエコーバックします。
ボーレートは4800bps、8N1設定です。
; AT89S52 Serial communication by Pinecone 2024/10/09
;
; AT89S52 cpu
; Flash ROM 8Kbyte
; RAM 256byte
; External clock 12MHz
; assembler
; program start 000H
; main 100H
;
; assemblers ASxxxx and ASlink V5.50
; file name AT89S52_serial01.asm
; $ as8051 -l -s -o AT89S52_serial01.asm
; $ aslink -i AT89S52_serial01
; program download $sudo avrdude -C avrdude.AT89 -p s52 -c usbasp -P usb -U flash:w:AT89S52_serial01.hex:i
;
.area TEST(ABS)
.org 0x0000
ljmp main
.org 0x0100
;ボーレート4800bps 8N1
main:
mov sp, #0x6f ;RAMエリア0030H-007F スタックポインタSPは上位方向(プラス)に移動
mov PCON, #0x90 ;PCON SMOD1(7bit目)="1" 1*12MHz
;PCON=10X10000B
mov SCON, #0x50 ;UARTはモード1に設定、受信イネーブル
;SCON=01010000B
mov TMOD, #0x20 ;タイマー1を8ビット自動リロードモードに設定
;TMOD=00100000B
mov a, #0xf3 ;タイマーカウンターセット f3H=256-(1*12000000)/(6*32*4800bps)
mov TH1, a
mov TL1, a
setb TR1 ;タイマー1スタート
mov DPTR, #start_msg ;メーセージ先頭アドレスをDPTRにセット
lcall msgout ;メッセージをシリアルで出力
mov a, #'> ;> プロンプトをaにセット
lcall putchar ;1文字シリアル出力
loop: ;入力されたデータをエコーバック
lcall getchar ;1文字シリアル入力
lcall putchar ;1文字シリアル出力
sjmp loop ;無限にループ
; ****** サブルーチン *****
msgout: ;DPTRにセットされたメッセージを0x00になるまでシリアル出力
clr a ;オフセットをクリア
movc a, @A+DPTR ;a←a(オフセット)+DPTR
jz msgout_end ;a=0x00 goto msgout
inc DPTR ;DPTR=DPTR+1
lcall putchar ;1文字シリアル出力
sjmp msgout ;ループ
msgout_end:
ret ;復帰
getchar: ;1文字シリアル入力
jnb ri, . ;SCONのRI(0bit目)が"1"なるまでループ
mov a, SBUF ;SBUFバッファーからaに格納
clr ri ;SCONのRI(0bit目)をクリア
ret ;復帰
putchar: ;1文字シリアル出力
clr ti ;SCONのTI(1bit目)をケリア
mov SBUF, a ;aからSBUFバッファーに格納
jnb ti, . ;SCONのTI(1bit目)が"1"なるまでループ
ret ;復帰
start_msg:
.str "AT89S52 Uart communication Test !"
.db 0x0d,0x0a,0x00
.end
アセンブリ、リンクします。
$ as8051 -l -s -o AT89S52_serial01.asm
$ aslink -i AT89S52_serial01
ASlink >> -i
ASlink >> AT89S52_serial01
書き込みします。
$ sudo avrdude -C avrdude.AT89 -p s52 -c usbasp -P usb -U flash:w:AT89S52_serial01.hex:i
[sudo] **** のパスワード:
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.01s
avrdude: Device signature = 0x1e5206 (probably s52)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "AT89S52_serial01.hex"
avrdude: writing flash (358 bytes):
Writing | ################################################## | 100% 0.38s
avrdude: 358 bytes of flash written
avrdude: verifying flash memory against AT89S52_serial01.hex:
avrdude: load data flash data from input file AT89S52_serial01.hex:
avrdude: input file AT89S52_serial01.hex contains 358 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 0.10s
avrdude: verifying ...
avrdude: 358 bytes of flash verified
avrdude: safemode: Fuses OK (E:FF, H:FF, L:FF)
avrdude done. Thank you.
シリアル端末でチェックします。
リセットしたのちメッセージと、入力したキーをエコーバックします。
AT89S52 Uart communication Test !
>abcdefg