[ บทความ : เรียนรู้ z80 ] ตอนที่ 13 เรื่อง คำสั่งติดต่อกับ I/O

เรียนรู้ Z80 ตอนที่ 13

คำสั่งติดต่อกับ I/O

ช่วงนี้ก็ใกล้สงกรานต์ วันปีใหม่ของไทยเราแล้วนะครับ พอผ่านวันสงกรานต์ก็เป็นวันครอบครัวอีกต่างหาก ... หวังว่า ทุกคนคงมีความสุขกับปีใหม่ไทยปีนี้นะครับ ... ส่วนบทความของเราตอนนี้เป็นคำสั่งที่เกี่ยวกับ การติดต่อกับ I/O ซึ่ง Z80 นั้น ถูกออกแบบให้สามารถติดต่อกับ I/O ได้ถึง 256 พอร์ต นั่นก็คือ พอร์ตหมายเลข 0 จนถึง 255 (โดยแยกออกจากหน่วยความจำ ของ Z80) คราวนี้ ถ้าถามผมว่า แต่ละพอร์ตนั้นมีหน้าที่ทำอะไรบ้าง ... อืม ... ผมตอบได้เพียงแค่ว่า แต่ละพอร์ตนั้น จะ เป็นส่วนที่ติดต่อกับอุปกรณ์อะไรนั้น ขึ้นอยู่กับ ผู้ออกแบบบอร์ดไงล่ะ ... คราวนี้เราจะอ้างอิง ET-BOARD V6 เป็นหลักใช่ไหม (ที่ผ่านๆ มา มีหลายบทความที่ผมใช้บอร์ดอื่นๆ ทั้งนี้เพราะว่า บอร์ดทั้งหมดเป็นของบริษัท ETT การออกแบบเลยเหมือนๆ กัน พอเขียนโปรแกรม ผมก็สบายหน่อย) เอาล่ะ ว่าแล้วเรามาลองดูคำสั่งที่เกี่ยวกับ I/O กันครับ

ตาราง 13-1 ชุดคำสั่งสำหรับอ่านข้อมูลจาก I/O

Instruction
Source/Target
Flag
Operation
IN
A,(C)
Z, P, S, N=0, H
A = ข้อมูล ณ พอร์ตที่กำหนดโดย C
IN
A,(n)
ไม่มีผลกับ flag
A = ข้อมูล ณ พอร์ตที่ n
IN
B,(C)
Z, P, S, N=0, H
B = ข้อมูล ณ พอร์ตที่กำหนดโดย C
IN
C, (C)
Z, P, S, N=0, H
C = ข้อมูล ณ พอร์ตที่กำหนดโดย C
IN
D, (C)
Z, P, S, N=0, H
D = ข้อมูล ณ พอร์ตที่กำหนดโดย C
IN
E,(C)
Z, P, S, N=0, H
E = ข้อมูล ณ พอร์ตที่กำหนดโดย C
IN
H, (C)
Z, P, S, N=0, H
H = ข้อมูล ณ พอร์ตที่กำหนดโดย C
IN
L, (C)
Z, P, S, N=0, H
L = ข้อมูล ณ พอร์ตที่กำหนดโดย C
INI
ไม่มี
ถ้า B-1 เป็น 0 จะได้ Z=1 ไม่เช่นนั้น Z=0,
N=1
(HL) = ข้อมูลจากพอร์ตที่กำหนดโดย C
B <- B-1
HL <- HL + 1
INIR
ไม่มี
Z=1 และ N=1 เสมอ
(HL) = ข้อมูลจากพอร์ตที่กำหนดโดย C
B <- B-1
HL <- HL + 1
และทำจนกว่า B จะเป็น 0
IND
ไม่มี
ถ้า B-1 เป็น 0 จะได้ Z=1 ไม่เช่นนั้น Z=0,
N=1
(HL) = ข้อมูลจากพอร์ตที่กำหนดโดย C
B <- B-1
HL <- HL - 1
INDR
ไม่มี
Z=1 และ N=1 เสมอ
(HL) = ข้อมูลจากพอร์ตที่กำหนดโดย C
B <- B-1
HL <- HL - 1
และทำจนกว่า B จะเป็น 0

ตาราง 13-2 ชุดคำสั่งสำหรับเขียนข้อมูลจาก I/O

Instruction
Source/Target
Flag
Operation
OUT
(C),A
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน A ไปที่พอร์ตหมายเลข C
OUT
(n) ,A
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน A ไปที่พอร์ตหมายเลข n
OUT
(C) , B
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน B ไปที่พอร์ตหมายเลข C
OUT
(C), C
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน C ไปที่พอร์ตหมายเลข C
OUT
(C), D
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน D ไปที่พอร์ตหมายเลข C
OUT
(C), E
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน E ไปที่พอร์ตหมายเลข C
OUT
(C), H
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน H ไปที่พอร์ตหมายเลข C
OUT
(C), L
ไม่มีผลกับ flag
ส่งข้อมูลที่เก็บใน L ไปที่พอร์ตหมายเลข C
OUTI
ไม่มี
ถ้า B-1 เป็น 0 จะได้ Z=1 ไม่เช่นนั้น Z=0,
N=1
ส่งข้อมูลที่เก็บใน (HL) ไปที่พอร์ตหมายเลข C
B <- B-1
HL <- HL + 1
OTIR
ไม่มี
Z=1 และ N=1 เสมอ
ส่งข้อมูลที่เก็บใน (HL) ไปที่พอร์ตหมายเลข C
B <- B-1
HL <- HL + 1
และทำจนกว่า B จะเป็น 0
OUTD
ไม่มี
ถ้า B-1 เป็น 0 จะได้ Z=1 ไม่เช่นนั้น Z=0,
N=1
ส่งข้อมูลที่เก็บใน (HL) ไปที่พอร์ตหมายเลข C
B <- B-1
HL <- HL - 1
OTDR
ไม่มี
Z=1 และ N=1 เสมอ
ส่งข้อมูลที่เก็บใน (HL) ไปที่พอร์ตหมายเลข C
B <- B-1
HL <- HL - 1
และทำจนกว่า B จะเป็น 0

เป็นอย่างไรบ้างครับ กับชุดคำสั่งที่เกี่ยวข้องกับการติดต่อกับ I/O ... ถ้าสังเกตดูจะเห็นว่า ทั้งในกลุ่มของ INPUT และ OUTPUT จะมีการสั่งการได้ 2 ลักษณะ คือ แบบอาศัย Register แล้วส่งไปยังพอร์ต หรืออ่านจากพอร์ตมา เก็บใน Register กับแบบที่มีการส่งข้อมูลจากหน่วยความจำไปที่พอร์ต และอ่านจากพอร์ตมาเก็บในหน่วยความจำ โดย แบบหลังนี้จะทำงานเป็นกลุ่มข้อมูล ซึ่งรูปแบบการทำงานลักษณะแบบนี้ผมได้เคยอธิบายไปแล้ว ... (ขอไม่อธิบายเพิ่มเติมล่ะกันครับ ... ใครที่จำไม่ได้ก็อ่านได้จากบทความเก่าๆ นะครับ :D) ...

คราวนี้ก็เป็นเรื่องของตัวอย่างบ้างล่ะ ... ปัญหาของผมตอนนี้ก็คือว่า พอผมเปิดคู่มือบอร์ดของ ET-V6, ET-V4 และ ET-V3.5 นั้นมีการออกแบบตำแหน่งของพอร์ตที่ติดต่อกับ LED (Flag LED) ไม่เหมือนกัน ... อืม ... ผมเองต้องการเขียนโปรแกรม สำหรับ สั่งให้หลอด LED บนบอร์ดนั้น ติด/ดับ สลับกันไปเรื่อยๆ ... เอาล่ะ เขียนโปรแกรมเป็น 3 ตัวก็ได้ ... แต่ อ้าว ... บอร์ด ET-V3.5 ของ ผมมีอันเป็นไปเสียแล้วครับ ... (เศร้าๆ ของมันเก่ามากน่ะครับ มันก็เลยเสีย แบบว่าลาย print มันพองมากๆ อาจจะทำให้เกิด noise เวลา download โปรแกรมมันเลยแน่นิ่งไปเลย ....) เอาเป็นว่า ผมลงตัวอย่างโปรแกรม 2 ตัวล่ะกันครับ เป็นของ ET-V6 กับ ET-V4 มาดูโปรแกรม และผลลัพธ์ของ ET-V6 กันก่อนครับ


	;
	; Filename : IO1.asz
	; Author   : Supachai Budsaratij   (raek@se-ed.net)
	; Date     : 04/08/2001
	; Hardware : ET-Board V6 (Z80 Mode)
	;
	            INCL    "etv6.inz"         ; Include header for ET-V6


	P_DIGIT     EQU     S8255_PA
	P_SEGM      EQU     S8255_PB
	P_LEDFLAG   EQU     6

	            ORG     UMEM_ORG        ; Start at UMEM_ORG

	main        LD      D,0
	            LD      BC,1

	; --- Move light
	loop        LD      A,P_LEDFLAG     ; Select LED FLAG device
	            OUT     (P_DIGIT),A     ;
	            LD      A,D             ; Send the data to LED
	            OUT     (P_SEGM),A   ;
	;--- Delay
	            LD      HL,8000h
	delay       SBC     HL,BC
	            JP      NZ,delay

	;--- Swap the pattern of the LED.
	            LD      A,0FFh
	            SUB     D
	            LD      D,A
	;--- Do again
	            JR      loop

	            END

,

คราวนี้มาดูโปรแกรมสำหรับ ET-V4 กันบ้างครับ


	;
	; Filename : IO1a.asz
	; Author   : Supachai Budsaratij   (raek@se-ed.net)
	; Date     : 04/08/2001
	; Hardware : ET-Board V4
	;
	            INCL    "etv4.inz"         ; Include header for ET-V4

	            ORG     UMEM_ORG        ; Start at UMEM_ORG

	main        LD      D,0
	            LD      BC,1

	; --- Move light
	loop        LD      A,D             ; Send the data to LED
	            OUT     (LED_FLAG),A   ;
	;--- Delay
	            LD      HL,8000h
	delay       SBC     HL,BC
	            JP      NZ,delay

	;--- Swap the pattern of the LED.
	            LD      A,0FFh
	            SUB     D
	            LD      D,A
	;--- Do again
	            JR      loop

	            END

,

จบแล้วล่ะครับ คำสั่งเกี่ยวกับการติดต่อกับ I/O หวังว่า ตัวอย่างโปรแกรมตอนนี้คงทำให้ผู้สนใจ Z80 พอจะมีกำลังใจเขียน โปรแกรมกันบ้างนะครับ ... ในคราวหน้า ผมจะเขียนถึงคำสั่งที่เกี่ยวกับ การกระทำทางตรรกศาสตร์ (ก็พวก AND, OR, NOT พวกนั้นแหละครับ) ... อ๊ะๆ ก่อนจาก ... ใครที่ใช้ ET-V6 อยู่ลองเอาโปรแกรมนี้ไปลอง RUN ดูสิครับ ...

	;
	; Filename : IO2.asz
	; Author   : Supachai Budsaratij   (raek@se-ed.net)
	; Date     : 04/08/2001
	; Hardware : ET-Board V6 (Z80 Mode)
	;
	            INCL    "etv6.inz"         ; Include header for ET-V6


	P_DIGIT     EQU     S8255_PA
	P_LEDFLAG   EQU     6

	            ORG     UMEM_ORG        ; Start at UMEM_ORG

	main        LD      D,0
	            LD      BC,1

	; --- Move light
	loop        LD      A,P_LEDFLAG     ; Select LED FLAG device
	            OUT     (P_DIGIT),A     ;
	            LD      A,D             ; Send the data to LED
	            OUT     (P_LEDFLAG),A   ;
	;--- Delay
	            LD      HL,8000h
	delay       SBC     HL,BC
	            JP      NZ,delay

	;--- Swap the pattern of the LED.
	            LD      A,0FFh
	            SUB     D
	            LD      D,A
	;--- Do again
	            JR      loop

	            END


ตอนนี้ Bye bye ครับ



เขียนโดย : ศุภชัย บุศราทิจ
Author : Supachai Budsaratij
e-mail : raek@se-ed.net
วันที่ทำการปรับปรุง : ๘ เม.ย. ๒๕๔๔, ๑๓ เม.ย. ๒๕๔๔