[ บทความ : ¶ÒÁµÍºà¡ÕèÂǡѺ Z80 ]

ถามตอบเกี่ยวกับ Z80 #2

คำถามนี้มาจาก คุณ "pornchai thong-in"

Q: ถึงพี่ศุภชัยครับ ผมขอเรียนถามพี่หน่อยครับ คือว่าตอนนี้ผมใช้ ET board V 3.5 อยู่ครับ และผมทำการควบคุมไปยังชุดทดลอง CP 3 ครับโดยต่อออกทาง Z-80 Bus ครับ ผมใช้โปรแกรมตามที่คู่มือให้มาครับคือการเขียนโปรแกรมควบคุม LED 8*8 ครับโดยให้ ตัวอักษร A และ B วิ่งจากขวาไปซ้ายครับ โดยใช้โปรแกรมดังนี้ครับ

 
      				ORG 200h 
00B0 = SCAN : EQU 0B0H
00B1= DATA: EQU 0B1H
00B3= CONT: EQU 0B3H
DISINI: LD A, 88H
OUT (CONT), A
DIS: LD HL, TAB
DIS1: LD B, 35H
DIS2: PUSH HL
LD C, 80H
CALL DISCAN
POP HL
DJNZ DIS2
;
INC HL
CP 18H
JR NZ, DIS1
JR DIS
DISCAN: LD A. 0FFH
OUT (DATA), A
LD A, (HL)
OUT (DATA), A
LA A, C
OUT (SCAN), A
;
LD E, 90H DISCAN1 DEC E JR NZ, DISCAN1 ; INC HL RRC C JR NC, DISCAN LD A,(HL) RET TAB: DFB 00H, 00H, 00H, 00H DFB 00H, 00H, 00H. 00H ;BLANK DFB 00H, 00H, 7EH, 09H DFB 09H, 09H, 7EH, 00H ;A DFB 00H, 7EH, 49H, 49H DFB 49H, 36H, 00H, 00H ;B DFB 00H, 00H, 00H, 00H DFB 00H, 00H, 00H, 00H ;BLANK DFB 18H

 

พี่ครับผมใช้โปรแกรมนี้ครับในการรันครับ ทีนี้ผทอยากให้วิ่งกลับกัน้างคือ จากซ้ายไปขวาบ้าางผมต้องแก้ไขโปรแกรมตรงจุดไหนบ้างครับ รบกวนพี่ช่วยแปลโปรแกรมนี้ให้ผมกระจ่างด้วยครับ และช่วยผมดัดแปลงโปรแกรมให้วิ่งกลับด้วยครับ ผมขอขอบคุณอย่างสูงครับ

พรชัย

A:

ก่อนอื่น ผมขอเกริ่นก่อนนะครับว่า ผมแนะนำในสิ่งที่ผม แนะนำได้ และผมทำในสิ่งที่ผมช่วยได้ด้วยนะครับ จากคำถามของคุณ ผมขอไม่ดัดแปลงโปรแกรมให้คุณนะครับ เพราะ ผมไม่ต้องการที่จะทำลาย กระบวนการ เรียนรู้ของคุณ ทั้งนี้ เนื่องจาก เราจะทำอะไรได้สักอย่างหนึ่งนั้น ต้องเริ่มจากการเข้าใจว่า ต้องแก้ปัญหานั้นๆ อย่างไร และทดลองดูว่า ทำได้หรือไม่ ถ้าคุณต้องการความรู้จริงๆ ผมแนะนำให้ได้ครับ ว่าควรจะทำอย่างไร แค่นี้จะเห็นว่า ผมทำให้คุณ ไม่ได้เริ่มต้นคิดว่าจะทำอย่างไร (การลองผิดลองถูกนั้น สร้างประสบการณ์ตรงให้แก่คน) ยิ่งถ้าผมดัดแปลงโปรแกรมให้คุณเข้าไปอีก คุณก็ไม่รู้เลยว่า ผมเขียน หรือแก้โปรแกรมด้วยเหตุผลอะไรบ้าง ทำไม ผมเลือกเขียนเช่นนั้น ...

จากตัวอย่างโปรแกรมที่คุณส่งมานั้น มันอาศัยลวดลาย (pattern) จากตารางข้อมูล ซึ่งอยู่ในช่วง TAB: มาดูตัวแรก

DFB 00H, 00H, 7EH, 09H
DFB 09H, 09H, 7EH, 00H ;A

เมื่อเขียนเป็นลวดลายก็ได้เป็น

00000000
00000000
01111110
00001001
00001001
00001001
01111110
00000000

จะเห็นว่า เป็นตัวอักษร A (ดูเลข 1) แล้วในโปรแกรมมันมีบรรทัด

> DIS: LD HL, TAB
> DIS1: LD B, 35H
> DIS2: PUSH HL
> LD C, 80H
> CALL DISCAN
> POP HL
> DJNZ DIS2
> ;
> INC HL

จะเห็นว่ามีการกำหนดให้ HL ชี้ไปที่ตารางลวดลาย แล้วมีการเรียกฟังก์ชัน DISCAN ซึ่งเขียนเอาไว้ว่า

> DISCAN: LD A. 0FFH
> OUT (DATA), A
> LD A, (HL)
> OUT (DATA), A
> LA A, C <--- ผมว่าน่าจะเป็น LD A,C
> OUT (SCAN), A
> ;
> LD E, 90H
> DISCAN1 DEC E
> JR NZ, DISCAN1
> ;
> (*) INC HL
> RRC C
> JR NC, DISCAN
> LD A,(HL)
> RET

จะเห็นว่า ในตอนแรกนั้น มีการกำหนดให้ A เป็น FFh หรือ 11111111 แล้วส่งออกพอร์ต (DATA) แล้วทำการ Load ข้อมูลที่ชี้โดย HL ดังที่เขียนเอาไว้ว่า LD A,(HL) แล้วก็ทำการส่งข้อมูลชุดแรก นั่นคือ 00000000 (ดูลวดลายได้จากด้านบน) แล้ว โปรแกรมทำการส่ง ออกไปที่พอร์ต จากตรงนี้จะเห็นว่า มีการส่งข้อมูลจากตัวแรก ออกไปที่พอร์ต ... ให้สังเกตที่บรรทัด (*) นะครับ มันทำการ เพิ่มค่า HL ดังนั้น ในรอบถัดไป ข้อมูลที่น่าจะออกพอร์ตก็น่าจะเป็น 00000000 แล้วก็ ต่อไปเรื่อยๆ ใช่ไหม ... จากทั้งหมด จะเห็นว่ามันวิ่งจากหน้าไปหลัง แล้วถ้าเราเปลี่ยนให้ HL ชี้ไปที่ข้อมูลตัวสุดท้าย แล้วเปลี่ยนเป็น ลดค่า HL จะหลายเป็นว่า มันเปลี่ยนลำดับจากข้อมูลชุดแรกมาเป็นข้อมูลตัวสุด (หรือที่คุณเรียกว่าวิ่งกลับนั่นแหละครับ) แต่เท่านี้ยังไม่เพียงพอครับ ที่คุณต้องจัดการเพิ่มอีกคือเรื่อง ของการทำ select พอร์ต ซึ่งมีคำสั่ง LD A,C แล้วก็ คำสั่ง ถัดไป เป็นการส่งออกพอร์ต SCAN (น่าจะเป็น decode) ถ้าสังเกตเพิ่มอีก บรรทัดที่ต่อจาก (*) จะเป็นการ RRC C ซึ่งเป็น การหมุนบิต เพื่อเลือกพอร์ต ดังนั้น ถ้าคุณปรับ 2 จุดนี้ ผลลัพธ์ที่ออกมานั้น ก็น่าจะวิ่งกลับได้แล้วล่ะครับ พยายามเข้านะครับ


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