การติดต่อเอาท์พุตที่เป็น LED


      LED (Light Emitting Diode) เป็น ไดโอดประเภทหนึ่งซื่งสามารถเปล่งแสงได้เมื่อมีกระแสไหลผ่านตัวมันโดยการใช้งานก็จะคล้ายกับไดโอดโดยจะทำกระแสได้ก็ต่อเมื่อได้รับไออัสตรง นอกจากนี้สิ่งที่ควรระวังในการใช้งานLED คือ LED จะรับแรงดันไบอัสกลับได้น้อยมาก ดังนั้นในการใช้งานเพื่อป้องกันการต่อผิดขั่วอาจใช้ไดโอดต่ออนุกรมด้ยก็จะเป็นการปลอดภัย นอกจากนี้ ไม่ควรต่อ LED เข้ากับแหล่งจ่ายแรงดันสูงๆโดยตรง เพราะจะทำให้ LED ไหม้ได้จึงควรต่อตัวต้านทานจำกัดกระแสไว้ด้วยเสมอ ยกเว้นในระบบที่มีแรงดันหรือกระแสต่ำๆ
      ลักษณะการต่อ LED จะมี 2 ลักษณะคือ ต่อในลักษณะให้ LED สว่างในสภาวะลอจิก 1 ดังรูป ก.และต่อให้สว่างในสภาวะลอจิก 1ดังรูป ข. ซึ่งทั้ง 2 แบบจะมีกระแสไหลในทิศทางที่แตกต่างกัน โดยในกรณีรูป ก. LED จะสว่างเมื่อเอาท์พุตเป็นลอจิก 1 โดยไอซี จะทำการจ่ายกระแสผ่านตัวต้านทานและ LED ลงกราวน์ เราเรียกกระแสในลักษณะนี้ว่ากระแสซอร์ส(Source Current) คือเป็นกระแสที่จ่ายจากตัวไอซีออกมา ส่วนรูป ข. LED จะสว่างเมื่อเอาท์พุตของไอซีมีสภาวะลอจิก 0 โดยไอซีจะดึงกระแสจากแหล่งจ่ายไฟ ผ่าน LED และตัวต้านทานเข้ามาในตัวไอซีเราเรียกกระแสในลักษณะนี้ว่า กระแสซิงค์(Sink Current) ดังนั้นการจะเลือกต่อแบบใดขึ้นอยู่กับความสามารถในการจ่ายกระแสหรือดึงกระแสของไอซีเพราะไอซีแต่ละเบอร์จะมีความสามารถในการจ่ายกระแส (Source Current) และดึงกระแส(Sink Current) ไม่เท่ากัน

รูปแสดงการต่อ LED ในสภาวะต่างๆ

      ในกรณีความสามารถในการจ่ายกระแสไม่พอ ก็จะใช้ไอซีที่เป็น บัพเฟอร์ เช่น 74LS244 หรือ 74LS245 เข้ามาต่อคั่นกลางระหว่างไอซีและตัวอุปกรณ์เพื่อให้มีความสามารถในการจ่ายกระแสได้สูงขึ้น โดยทั่วไป LED จะต้องการกระแสระหว่าง 10mA ถึง 20mA โดยถ้าจ่ายกระแสต่ำกว่านี้ LED จะไม่สว่างและถ้าสูงกว่า 20 mA ก็อาจทำให้ LED ร้อนจนอาจเสียหายได้ สำหรับแรงดันที่ตกคร่อม LED ในขณะสว่างจะมีค่าประมาณ 2.5โวลท์ เราสามารถนำมาคำนวณหาค่าความต้านทานที่มาต่อจำกัดกระแสได้ โดย


ตัวอย่าง ถ้าใช้แหล่งจ่ายไฟเลี้ยง 5V และต้องการให้มีกระแสไหลผ่าน LED 10mA ในขณะที่แรงดันตกคร่อม LED ในขณะนำกระแสเท่ากับ 2.5 V


ตัวต้านทานที่นำมาต่อจำกัดกระแสควรมีค่าประมาณ 250Ω

โดยทั่วไปในงานควบคุมเราจะต่อ LED เข้ากับพอร์ตเอาท์พุตแบบ D-FlipFlop เพื่อให้คงสถานะแรงดันค้างไว้ในได้ตามตัวอย่างดังรูป

รูปแสดงการเชื่อมต่อ Z80 เข้ากับ LED

      โดยการต่อในลักษณะดังกล่าวจะใช้ไอซี 74LS374 ซึ่งภายในจะมีD-Flip-Flop 8 ตัวต่อขา CLK ร่วมกัน โดยมีตัวต้านทานแบบชุด(R-Pack)ซึ่งภายในจะมีตัวต้านทาน 8 ตัว ต่อเพื่อจำกัดกระแสที่ไหลผ่าน LED (สมมุติว่าต่อ LED 8 ตัวเข้ากับ Q0 – Q7)สำหรับหมายเลขของพอร์ตจะได้จากการต่อขา A0 – A7 โดยจากวงจร ขา A3 ต้องเป็น 1 นอกนั้นต้องเป็น 0 ซึ่งจะได้หมายเลขของพอร์ตเอาท์พุต = 0000 1000B =08H ถ้าเขียนโปรแกรมควบคุมการทำงานเป็น

      LD A,04AAH ; A = 10101010B
      OUT (08H),A ; ส่งข้อมูลจาก A ออกไปที่พอร์ต 08H

      การทำงานของโปรแกรมคือ คำสั่งแรก Z80 จะกำหนดค่ารีจิสเตอร์ A ภายในตัว Z80 ให้มีค่าเป็น 10101010 คำสั่งที่สองจะเป็นการส่งข้อมูลจากรีจิสเตอร์ A ออกไปที่พอร์ตหมายเลข 08H โดยZ80 จะส่งข้อมูล 1010 10101ไปรอที่ขาข้อมูลD7 – D0 แล้วสร้างสัญญาณให้ขาแอดเดรส A0 – A7 มีสถานะเป็น 0000 1000 ทำให้ไอซีถอดรหัส 74LS138 ที่ต่ออยู่กับขาแอดเดรสมีเอาท์พุตเป็นลอจิก 0 ต่อจากนั้น Z80 จะส่งสัญญาณติดต่อหน่วยความจำและสัญญาณเขียนข้อมูล โดยทำให้ขา IORQ และ ขาWR มีสถานนะเป็นลอจิก 0 ทำให้เอาท์พุตของไอซีเกท ต่างๆ เป็นลอจิก 0 ไปกระตุ้นขาCLK ทำให้ไอซี74LS374 เก็บค่าข้อมูลเข้าไปจึงทำให้ LED ที่ต่ออยู่ที่ขา Q0 ถึง Q7 มีสถานะตามข้อมูล 1010 1010 ที่ส่งออกมาคือจะติดและดับสลับกันไป ถ้าเราควบคุมให้ข้อมูลที่รีจิสเตอร์ A มีค่าเปลี่ยนไปแล้วส่งค่าออกไปที่พอร์ต ก็จะทำให้ LED เกิดติด – ดับตามข้อมูลที่เปลี่ยนแปลง สามารถเขียนโปรแกรมในลักษณะไฟวิ่งได้หลายรูปแบบตามต้องการ

ตัวอย่าง โปรแกรมไฟวิ่งอย่างง่ายๆ
       LD A,01H     ; A = 0000 0001H
LOOP: OUT(08H),A  ; ส่งข้อมูลออกพอร์ตเอาท์พุต หมายเลข 08H
       CALL DELAY  ; หน่วงเวลา
       RLC A       ; หมุนข้อมูลในรีจิสเตอร์ A ไปทางซ้าย 1 บิต
       JR LOOP     ; กลับไปวนทำซ้ำใหม่
DELAY: LD B,FFH    ; ให้ B เป็นตัวนับรอบ
AGAN: NOP
       DJNZ AGAIN ; ให้กระโดดไปทำซ้ำที่ AGAIN ใหม่จนกว่า B = 0
       RET

       ในกรณีต้องการให้วิ่งเพียง 1 รอบแล้วหยุดอาจใช้วิธีนับรอบการวิ่ง โดยใช้รีจิสเตอร์ B แต่วิธีนี้ต้องมีการเก็บค่า BC ไว้ก่อนที่จะเข้าสู่โปรแกรมหน่วงเวลา ดังนี้

       LD B,08H      ; ให้ B เป็นตัวนับมีค่า = 8
       LD A,01H      ; A = 0000 0001H
LOOP: OUT(08H),A    ; ส่งข้อมูลออกพอร์ตเอาท์พุต หมายเลข 08H
       RUSH BC      ; เก็บค่า BC ไว้ในสแตก
       CALL DELAY   ; หน่วงเวลา
       POP BC       ; คืนค่า BC จากสแตก
       RLC A        ; หมุนข้อมูลในรีจิสเตอร์ A ไปทางซ้าย 1 บิต
       DJNZ LOOP  ; หยุดการทำงาน
DELAY: LD B,FFH     ; ให้ B เป็นตัวนับรอบของลูปด้านนอก
DELAY1: LD C,FFH    ; ให้ C เป็นตัวนับรอบของลูปด้านใน
DELAY2: NOP        ; กำหนดให้ซีพียู อยู่เฉยๆ
       DEC C        ; ลดค่า C ลง 1
       JR NZ,DELAY2 ; ถ้า C ยังไม่เป็น 0 ให้วนรอบใน DELAY 2
       DJNZ DELAY1 ; ให้กระโดดไปทำซ้ำที่ DELAY1 ใหม่จนกว่า B = 0
       RET

       โดยโปรแกรมใหม่นี้ได้เพิ่มเวลาหน่วงให้มากขึ้นโดยการให้วนรอบแบบ ลูปซ้อนลูปคือ ในแต่ละรอบของ B จะต้องวนรอบภายในของ C =FF รอบ การปรับค่าเวลาหน่วงทำได้โดยการปรับค่าจำนวนรอบของ B และ C และสังเกตว่า ก่อนจะเรียกโปรแกรมย่อยจะมีการเก็บค่า BC เดิมเอาไว้ในสแตกโดยใช้คำสั่ง PUSH BC และเมื่อกลับสู่โปรแกรมหลักก็จะนำค่าเดิมของ BC ที่เก็บในสแตกกลับคทนมาด้วยคำสั่ง POP BC
       การตรวจสอบการวิ่งของ LED นอกจากจะตรวจสอบจากจำนวนรอยบแล้วเรายังมีวิธีตรวจสอบจากคำสั่ง BIT n,A ที่จะใช้ตรวจสอบว่าขณะนี้ บิตดังกล่าวของรีจิสเตอร์ A เป็น 0 หรือ 1 ได้ โดยเขียนโปรแกรมดังนี้

      LD A,01H       ; A = 0000 0001H
LOOP: OUT(08H),A    ; ส่งข้อมูลออกพอร์ตเอาท์พุต หมายเลข 08H
      EX AF,AF       ; เก็บค่า AF
      CALL DELAY    ; หน่วงเวลา
      EX AF,AF       ; คืนค่า AF
      RLC A          ; หมุนข้อมูลในรีจิสเตอร์ A ไปทางซ้าย 1 บิต
      BIT 4,A         ; ตรวจสอบว่าเลข 1 วิ่งมาถึง บิต 4 หรือยัง
      JR Z LOOP2    ; ถ้ายัง(คือ ค่าของบิต 4 ยังเป็น 0)ให้วนกลับไปทำต่อ
      HALT           ; หยุดการทำงาน
DELAY: LD BC,8000H ; ให้ BC เป็นตัวนับรอบ
DELAY1: DEC BC      ; ลดค่า BC
      LD A,B         ; โหลดข้อมูลจาก B มาให้ A เพื่อกระทำการ OR
      LD A,B         ; โหลดข้อมูลจาก B มาให้ A เพื่อกระทำการ OR
      OR C          ; ตรวจสอบค่า BC ว่าเท่ากับ 0000 หรือยัง
      JR NZ,DELAT1   ; ถ้า BC ยังไม่เป็น 0 ให้วนกลับไปทำซ้ำที่ DELA 1
      RET

      จากโปรแกรมจะเห็นว่า เราจะใช้คำสั่ง BIT 4,A ตรวจสอบการวิ่งของ LED ว่าวิ่งวนมาถึงบิต 4 หรือยัง ถ้ายังก็จะอนุญาตให้วิ่งต่อไปได้แต่ถ้าถึงแล้วก็จะหยุดการทำงาน
      สำหรับการเขียนโปรแกรมหน่วงเวลาจะใช้ BC เป็นตัวนับซึ่งการตรวจสอบว่า BC เป็นศูนย์หรือไม่จะต้องใช้วิธีนำมา OR โดยใช้รีจิสเตอร์ A เป็นตัวช่วย(เพราะคำสั่งลดค่า DEC BC จะไม่มีผลต่อแฟลก) ดังนั้นก่อนเข้าโปรแกรมหน่วงเวลา เราจึงต้องเก็บค่าข้อมูลในรีจิสเตอร์ A เสียก่อน โดยการใช้คำสั่ง EX AF,AF ซึ่งจะเป็นการเก็บฝากไว้ในรีจิสเตอร์สำรองจากนั้นเมื่อทำโปรแกรมย่อยเสร็จสิ้น ก่อนจะทำโปรแกรมหลักต่อก็จะทำการคืนค่ากลับมาด้วยคำสั่ง EX AF,AF อีกครั้ง เพื่อสลับเอาข้อมูลที่ฝากไว้ในรีจิสเตอร์สำรองกลับคืนมาดังเดิม

หมายเหตุ
      การเก็บและคืนค่ารีจิสเตอร์ก่อนเข้าโปรแกรมย่อยและออกจากโปรแกรมย่อยนี้เขียนไว้ในส่วนของโปรแกรมย่อยก็ได้