lab1

LAB 1 การส่งข้อมูลแบบไบต์

    1  วิธีการคิด

          ในใบงานนี้เงื่อนไขในการเขียนโปรแกรม คือทำให้ LED สว่างโดยเลื่อนข้อมูลไปวิ่งทางซ้ายและทางขวา โดยไม่มีการกด switch ใดๆและจะใช้ DPTR
เป็นตัว เก็บข้อมูลแล้วนำข้อมูลนั้นไปไว้ไน register A แล้วจึงนำข้อมูลในregister A ออกพอร์ต P1 ในใบงานนี้จะต้องทำการต่อ IC 74HCT245 และ LED
ภายนอกที่ตำแหน่งด้านขวาที่จุดไข่ปลาและที่ jumper J3ต้อง open เพื่อทำการ กำหนดทิศทางให้เป็น Output ด้วย

    2 ขั้นตอนการเขียนโปรแกรม

    ; ******************************************************************
    ; **	 PROGRAM   LAB1.ASM		 **
    ; ** 	LED  LEFT &  RIGHT			 **
    ; ** 	PORT 1  OUT			 **
    ; ******************************************************************

        ORG	0000H		;เริ่มต้นที่ตำแหน่ง 0000H
INIT: 		MOV	A,#00H		;นำค่าคงที่ 00 ไว้ที่ Register  A
        MOV	R0,#16D		;กำหนดให้ R0  มีค่าเท่ากับ 16 เป็น counter
        MOV	DPTR,#TABLE	;นำค่าแอดเดรสที่ตำแหน่งที่ LABLE TABLE ไว้ที่ DPTR
MAIN:		MOV 	A,#00H
        MOVC	A,@A+DPTR	;นำข้อมูลที่  @A+DPTR (00+ ADDR_ TABLE) ไว้Register  A
        MOV	P1,A		;นำข้อมูลใน Register  A ออกที่P1
        ACALL	DELAY		;หน่วงเวลา
        INC	DPTR		;เพิ่มค่า DPTR ขึ้นหนึ่ง (จริงๆ ใช้ INC A จะประหยัดเนื้อที่
                    ; และไม่ต้องกลับไป ให้ MOV  A,#00H อีก แต่ในที่นี้อยากให้รู้จัก
                    ;กับการใช้งาน DPTR )
        DJNZ	R0,MAIN		;ลดค่า R0 จนเป็น 0
        SJMP	INIT		;กระโดดไปที่OK
DELAY: 		MOV	R1,#0AFH		;นำค่า 0A ไว้ที่R1
DELAY_1:		MOV	R2,#0FFH		;นำค่า FF ไว้ที่R2
        DJNZ	R2,$		;ลดค่า R2
        DJNZ	R1,DELAY_1	;ลดค่า R1 จนเป็นศูนย์
        RET			;กลับสู่โปรแกรม

TABLE:    		DB 01H,02H,04H,08H		;ข้อมูลที่เป็นตาราง
        DB 10H,20H,40H,80H		; ข้อมูลที่เป็นตาราง
        DB 80H,40H,20H,10H		; ข้อมูลที่เป็นตาราง
        DB 08H,04H,02H,01H		; ข้อมูลที่เป็นตาราง

      ***เข้าไปดูตัวอย่างโปรแกรมอีกรูปแบ

    *** หมายเหตุ      การเขียนโปรแกรม อาจจะใช้วิธีการอื่นๆ อีกมากมายแบบที่เป็นตัวอย่างนี้เป็นแบบง่ายๆนักศึกษาควร จะปรับปรุ่ง โดยไม่จำเป็นต้องจองเนื้อที่
ที่ TABLE ถึง 16 ตำแหน่งแต่ทำการกำหนดที่ Reister A โดยการ เพิ่มหรือลดค่า Register A ก่อนทำการ + กับค่า DPTR และกำหนด R0 ,#08H
อย่าลืม คำสั่ง DEC  DPTRไม่มีใน MCS-51 หรืออาจจะใช้คำสั่ง   RRA  RLA  RLCA หรือ  RLCA ก็ได้

    3 ขั้นตอนการโปรแกรม

        - เมื่อเขียนโปรแกรมและเซฟเป็น LAB1.ASM แล้ว
        - ทำการแอสแซมเบอร์โดยใช้คำสั่ง 	SXA51   -L  LAB1.ASM
        - เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
        - จากการแอสแซมเบอร์จะได้ไฟล์   LAB1.HEX  และ LAB1.LST
        - ให้นำไฟล์ที่เป็น  LAB1.HEX ไปโปรแกรม
        - โดยใช้คำสั่ง EZ  LAB1.HEX   -C1  (-C2 กรณีต่อกับ COM2)
        - ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4 ผลการทดลอง

        จากการทดลองใบงานที่1  ผลการทดลองเป็นไปตามเงื่อนไขคือ LED จะแสดงเป็นไฟวิ่งซ้ายขวาเรียงกัน

    5 สรุปผล  ข้อเสนอแนะและปัญหา

         จากการเขียนโปรแกรมในใบงานนี้ทำให้ทราบถึงการนำเอา คำสั่งที่เกี่ยวกับ DPTR มาใช้งานในการเก็บค่าแบบตาราง และรูปแบบการเขียนแบบ
ต่างๆ แต่กำหนดเงื่อนไขเดียวกันได้


LAB 2
 การใช้โปรแกรมเปิดตารางข้อมูล Look Up Table

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
     ในใบงานนี้เงื่อนไขในการเขียนโปรแกรม คือทำให้ LED แสดงผลตามข้อมูลที่ได้กำหนดจากตารางในโปรแกรมนี้จะใช้ register DPTR
เป็นตัวเก็บฐานแอดเดรส (16บิต)และนำค่าข้อมูลใน register A(8 บิต)ที่ได้จากRegister R1 เป็นตัวบวกกับค่าแอดเดรสที่ DPTR  และนำข้อมูลที่
ได้ จากตำแหน่งแอดเดรสนั้นไปเก็บไว้ไน register A แล้วจึงนำข้อมูลใน register A ออกไปที่พอร์ต P1 หลังจากนั้นจะเพิ่มค่าของของ Register R1
ขึ้นซึ่งข้อมูลใน register R1จะส่งให้กับ Register A อีกครั้งหนึ่ง เนื่องจากค่าใน register Aจะต้องมีการเปลี่ยนแปลงตลอดเมื่อทำคำสั่งทางคณิตศาสตร์

    2 ขั้นตอนการเขียนโปรแกรม

; ******************************************************************
; ** 		PROGRAM LAB2.ASM 	**
; ** 		LED DISPLAY LEFT & RIGHT          **
;** 		LOOK  UP  TABLE	                    **
; ******************************************************************
            ORG 	0000H
            MOV	P1,#00H
            MOV 	DPTR,#TABLE	 ;นำค่าแอดเดรสตำแหน่งของ TABLE มาเก็บไว้ที่ DPTR (16 บิต)
    LEFT: 		MOV 	A,#00H 	     	;ทำการ Clear Reg. A = 00H
            MOV 	R1,#00H     	;ทำการ Clear R1 = 00H (ตำแหน่ง Adds RAM 00H =00H )
            MOV 	R0,#07D     	;เริ่มกำหนด R0 = 07H คือรูปแบบ Display LED 8 รูปแบบ
    LEFT1: 		MOV 	A,R1 	      	;กำหนดให้ R1เป็นตัวเริ่มต้นนับจำนวนรูปแบบแล้วส่งให้ Reg. A
            MOVC 	A,@A+DPTR   	;นำค่า Data (8 บิต) ที่ตำแหน่ง ADDR  A+TABLE
            MOV 	P1,A 	      	; รอบที่ 1 P1=0000 0001 รอบที่ 2 จะได้ข้อมูลตามตาราง
            ACALL 	DELAY 	      	;เรียกโปรแกรมย่อยหน่วงเวลาหน่อย (ก็ดูไม่ทัน X-TAL 11.059 MHz)
            INC 	R1 	      	;เพิ่มค่าที่ R1 (เพื่อนำไปให้ Reg. A ใช้ในการบวกกับ DPTR)
            DJNZ 	R0,LEFT1     	;ลดค่า R0 ลง 1 ถ้า R0 ไม่เป็น 0 กระโดดไปที่ LEFT1
    RIGHT: 		CLR 	A 	       	;R0 จากคำสั่งที่ผ่านมาถ้าเป็น "0" เริ่มส่วนของ RIGHTต่อ
            MOV 	R4,#07D
            MOV 	P1,#00H
            RIGHT1: 	MOV 	A,R1
            MOVC 	A,@A+DPTR
            MOV 	P1,A
            ACALL 	DELAY
            DEC 	R1
            DJNZ 	R4,RIGHT1
            SJMP 	LEFT 		;วนกลับไปทำส่วนของโปรแกรม LEFT ใหม่อีก
    **************       โปรแกรมย่อย DELAY    **
    DELAY: 		MOV 	R2,#0FFH 	;
    DELAY1: 		MOV 	R3,#0FFH
            DJNZ 	R3,$
            DJNZ 	R2,DELAY1
            RET
    TABLE: 		DB 	01H,02H,04H,08H      ;เป็นข้อมูลที่สามารถกำหนดให้แสดงรูปแบบตามต้องการได้
            DB 	00010000B,00100000B,01000000B,10000000B
            END

    *** หมายเหตุ อย่าลืม คำสั่ง DEC  DPTR ไม่มีใน MCS-51

    3 ขั้นตอนการโปรแกรม

        - เมื่อเขียนโปรแกรมและเซฟเป็น LAB2.ASM แล้ว
        - ทำการแอสแซมเบอร์โดยใช้คำสั่ง 	SXA51   -L  LAB2.ASM
        - เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
        - จากการแอสแซมเบอร์จะได้ไฟล์   LAB2.HEX  และ LAB2.LST
        - ให้นำไฟล์ที่เป็น  LAB2.HEX ไปโปรแกรม
        - โดยใช้คำสั่ง EZ  LAB2.HEX   -C1  (-C2 กรณีต่อกับ COM2)
        - ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4 ผลการทดลอง

    จากการทดลองใบงานที่ 2  ผลการทดลองเป็นไปตามเงื่อนไขคือ LED จะแสดงเป็นไฟวิ่งซ้ายขวาเรียงกัน

    5 สรุปผล  ข้อเสนอแนะและปัญหา

     จากการเขียนโปรแกรมในใบงานนี้ทำให้ทราบถึงการนำเอา คำสั่งที่เกี่ยวกับ DPTR มาใช้งานในการเก็บค่าแบบตาราง และรูปแบบการเขียนแบบต่างๆ
แต่แต่กำหนดเงื่อนไขเดียวกันได้


LAB 3
สวิตช์อินพุตควบคุมการหมุนข้อมูล

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด

     ในใบงานนี้เงื่อนไขในการเขียนโปรแกรม คือ ให้ LED เลื่อนเป็นไปวิ่งซ้ายขวา โดยมีการกด switch SW1 SW2 โดยขั้นแรกต้องทำการกำหนด
พอร์ตที่ใช้เป็นสวิตซ์ ในที่นี้จะใช้พอร์ต P3.0,P3.1 ในโปรแกรมจะต้องมีการตรวจสอบตลอดเวลา คือ ตรวจสอบทั้ง P3.0 และ P3.1 เมื่อบิตใดบิตหนึ่ง
เป็นศูนย์จะกระโดดไปทำตามคำสั่งคือ ให้ LEDแสดงเป็นไฟวิ่งไปทางซ้ายหรือขวา ในใบงานนี้จะต้องทำการต่อ IC 74HCT245 และ LED ภายนอกที่ตำแหน่ง
ด้านขวาที่จุดไข่ปลา

    2 ขั้นตอนการเขียนโปรแกรม

    ; ******************************************************************
    ; **	 PROGRAM   LAB3.ASM		 **
    ; ** 	LED  LEFT &  RIGHT			 **
    ; ** 	PORT P3.0  P3.1  IN     PORT 1  OUT                **
    ; ******************************************************************

        ORG    	0000H		;เริ่มต้นที่แอดเดรส 0000H
        SETB	P3.0		;เพื่อกำหนดให้เป็นอินพุต
        SETB	P3.1		;เพื่อกำหนดให้เป็นอินพุต
SW2:   		MOV    	P1,#00H		;นำค่า 00 ออกที่ P1
        JNB	P3.0, DELAY_D 	;เช็คสัญญาณรบกวนจากสวิตช์
        JNB    	P3.0,LEFT		;ตรวจสอบ P3.0 ถ้าเป็น 0 ไปที่ LEFT
        JNB	P3.1, DELAY_D
        JNB    	P3.1,RIGHT	; ตรวจสอบ P3.1 ถ้าเป็น 0 ไปที่ RIGHT
        AJMP    	SW2		;กระโดดไปที่ SW2
LEFT:	   	MOV    	A,#00H		;นำค่า 00 ไว้ที่ A
        MOV     	A,#01H		;นำค่า 01 ไว้ที่ A
        MOV 	R0,#08D		;นำค่า 08 ไว้ที่ R0
LEFT1:  		MOV 	P1,A		;นำข้อมูลใน A ออกพอร์ต P1
        ACALL   	DELAY		;หน่วงเวลา
        RL	A		;เลื่อนข้อมูลใน A ไปทางซ้าย
        JNB	P3.1,DELAY_D
        JNB    	P3.1,RIGHT	; ตรวจสอบ P3.1 ถ้าเป็น 0 ไปที่ RIGHT
        DJNZ 	R0,LEFT1		;ลดค่าจนเป็นศูนย์
        AJMP    	LEFT		;กระโดดกลับไปที่ LEFT

RIGHT:  		MOV     	A,#00H		; นำค่า 00 ไว้ที่ A
        MOV     	A,#80H		; นำค่า 80 ไว้ที่ A
        MOV    	R6,#08D		; นำค่า 08 ไว้ที่ R0
RIGHT1:  		MOV     	P1,A		; นำข้อมูลใน A ออกพอร์ต P1
        ACALL  	DELAY		; หน่วงเวลา
        RR     	A		; เลื่อนข้อมูลใน A ไปทางขวา
        JNB	P3.0,DELAY_D
        JNB     	P3.1,RIGHT	; ตรวจสอบ P3.1 ถ้าเป็น 0 ไปที่ RIGHT
        DJNZ   	R6,RIGHT1	; ลดค่าจนเป็นศูนย์
        AJMP   	RIGHT1		; กระโดดกลับไปที่ RIGHT1

DELAY_D: 	MOV    	R3,#0FH		;นำค่า 0F ไว้ที่ R3
        DJNZ   	R3,$		;ลดค่า R3 ด้วยตัวมันเอง
        RET			;กลับสู่โปรแกรมโดยไม่มีเงื่อนไข

DELAY:  		MOV    	R1,#0FFH		;นำค่าFF ไว้ที่ R1
DELAY1: 		MOV    	R2,#0AFH		;นำค่า AF ไว้ที่ R2
        DJNZ    	R2,$		;ลดค่า R2 ด้วยตัวมันเอง
                    DJNZ    	R1,DELAY1	;ลดค่า R1 จนเป็นศูนย์
        RET			;กลับสู่โปรแกรมโดยไม่มีเงื่อนไข

    *** หมายเหตุ      การเขียนโปรแกรมในการกำหนดให้เป็นอินพุตต้องมีการกำหนดที่ พอร์ตก่อนโดยกำหนด
ให้เป็น "1" โดยใช้คำสั่ง SETB  P3.X ก่อน (ดูวิธีการเป็นอินพุตพอร์ต)

>>>>   การเขียนโปรแกรมแนวทาง  look up table  กรุณา Click

    3 ขั้นตอนการโปรแกรม

        - เมื่อเขียนโปรแกรมและเซฟเป็น LAB3.ASM แล้ว
        - ทำการแอสแซมเบอร์โดยใช้คำสั่ง 	SXA51   -L  LAB3.ASM
        - เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
        - จากการแอสแซมเบอร์จะได้ไฟล์   LAB3.HEX  และ LAB3.LST
        - ให้นำไฟล์ที่เป็น  LAB3.HEX ไปโปรแกรม
        - โดยใช้คำสั่ง EZ  LAB3.HEX   -C1  (-C2 กรณีต่อกับ COM2)
        - ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4 ผลการทดลอง
    จากการทดลองในใบงานที่3 ผลการทดลองเป็นไปตามเงื่อนไขของโปรแกรมที่เขียนขึ้น คือ เมื่อกดสวิตซ์ที่ P3.0 แล้ว LED จะวิ่งไปทางขวา
และเมื่อกดสวิตซ์ที่ P3.1 จะวิ่งไปทางซ้ายมือ โดยจะใช้คำสั่ง JNB คือ ตรวจสอบว่าบิตเป็นศูนย์หรือไม่ ถ้าเป็นให้กระโดดไปทำตามคำสั่งที่กำหนด

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


LAB 4
Stepping  Motor  Control

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
Stepping  Motor  Control

    คำสั่ง
CJNE    (Compare and jump if Not Equai) คำสั่งนี้จะทำให้ซีพียูทำการกระโดดไปยังแอดเดรสปลายทาง เมื่อค่าข้อมูลที่นำมาเปรียบเทียบไม่เท่ากัน
CJNE A, direct, rel	กำหนดให้ซีพียูกระโดดไปยังแอดเดรสปลายทางตามค่าสัมพัทธ์  (Rel) เมื่อค่าของรีจิสเตอร์ A  ไม่เท่ากับค่าในหน่วยความจำข้อมูล

    ตัวอย่าง :	CJNE  A, 20H,LEFT ; จะกระโดดไปยังตำแหน่งLEFT เมื่อค่าในรีจิสเตอร์ A ไม่เท่ากับข้อมูลในหน่วยความจำข้อมูลที่แอดเดรส 20H

    Step	Phase1	Phase2	Phase3	Phase4		Step	Phase1	Phase2	Phase3	Phase4
      1	   1	   0	   0	   0		   1	    1	    1	    0	    0
      2	   0	   1	   0	   0		   2	    0	    1	    1	    0
      3	   0	   0	   1	   0		   3	    0	    0	    1	    1
      4	   0	   0	   0	   1		   4	    1	    0	    0	    1
              แบบ 1 PHASE					         แบบ  2PHASE

   จากรูปเราใช้แอลอีดีเป็นตัวแสดงผลแทนสเต็บปิ่งมอเตอร์เราจะเขียนแยก การอธิบายโปรแกรมดังนี้

    ; ******************************************************************
    ; **	 PROGRAM   LAB4.ASM		                    **
    ; ** 	STEPING MOTER   CONTROL                            **
    ; ******************************************************************
                          ORG     	00H
    SW_RIGHT	BIT	P3.0
    SW_LEFT		BIT	P3.1
    SW_1PHASE 	BIT	P3.2
    SW_2PHASE	BIT	P3.3
                     DATA	     EQU        20H

*****  ุ ทำการกำหนดชื่อของสวิตช์ที่จะใช้เป็นตัวเลือกรูปแบบการขับและทิศทางการหมุน DATA คือแอดเดรสที่เก็บสถานะของการกดสวิตช์

    ุ ทำการกำหนดรูปแบบการขับเพื่อกำหนดเป็นตารางใช้สำหรับส่วน LOOK UP TABLE ดูได้จากตารางการขับแบบ 1 เฟสและ 2เฟส
เราสามารถเขียนโปรแกรมกำหนด  L1 L2 L3 L4 ได้ดังนี้

    PHASE1L:		DB	00001000B, 00000100B, 00000010B, 00000001B
    PHASE1R:	DB	01H,02H,04H,08H
    PHASE2L:		DB	00001100B, 00000110B, 00000011B, 00001001B
    PHASE2R:	DB	09H,03H,06H,0CH
ุ
        ต่อมาเรากำหนดส่วนที่เป็นสวิทช์เลือกเสียก่อนจากรูปเราสามารถนำมาเขียนโปรแกรมได้โดยขั้นตอนคือต้องเลือกการขับก่อนแล้วเลือกทิศทาง
การหมุน ผลข้อมูลที่ได้นำไปกำหนดบิตที่ข้อมูลตำแหน่งแอดเดรส 20 H

SCAN_PHASE:	JNB 	SW_1PHASE,PHASE1
        JNB	SW_2PHASE,PHASE2
        SJMP	SCAN_PHASE
            .
                 PHASE1:	CLR	06H
        SETB	07H         ; ADDR 20H
        MOV	P1,20H
        SJMP	SCAN_DIR

    1phase	2phase	Left	Right	ไม่สน	ไม่สน	ไม่สน	ไม่สน
    07H	06H	05H	04H	03H	02H	01H	00H

    *****   หน่วยความจำตำแหน่ง 20 H  เป็นส่วนที่สามารถเข้าแบบบิตและไบต์ได้

    ุตรวจสอบทิศทางการหมุนของมอเตอร์

SCAN_DIR:	JNB	SW_1PHASE,SCAN_PHASE
        JNB	SW_2PHASE,SCAN_PHASE
        JNB	SW_LEFT,LEFT
        JNB	SW_RIGHT,RIGHT
        SJMP	SCAN_DIR

.**** เป็นการตรวจสอบการกดสวิทช์ทุกตัวเพื่อตรวจสอบว่ามีการกดเพื่อเปลี่ยนแปลงข้อมูลหรือไม่
            .
LEFT:		CLR	04H
        SETB	05H       ;ADDR 20H
        SJMP	DIS_1LEFT	;เรียกโปรแกรมย่อย DIS_1LEFT เพื่อกำหนดค่าเริ่มต้นให้กับรีจีสเตอร์  DPTR
;**********************   1 PHASE LEFT***************************
    DIS_1LEFT:	MOV	A,#10100000B
                                    CJNE	A,DATA,DIS_2LEFT
                                    MOV	DPTR,#PHASE_1L
                                    SJMP	DISP_MOTOR

ุ 	นำข้อมูลออกพอร์ตโดยการนำข้อมูลจาก LOOK UP TABLE คือ ที่ตำแหน่งแอดเดรสที่ PHASE_1L จากคำสั่ง MOV A,@A+DPTR
โดยนำข้อมูลที่ได้ที่อยู่ในรีจิสเตอร์ A มาทำการ OR กับข้อมูลที่ DATA หรือข้อมูลที่แอดเดรส 20H

            ORL A, DATA   (หัวโปรแกรม DATA     EQU      20H )

    ;****  DISPLAY & MOTOR DRIVE   ****
    DISP_MOTOR:	MOV	R0,#04H
            MOV	R1,#00H
            MOV	A,#00H
               LOOP:		MOV	A,R1
            MOVC	A,@A+DPTR
            ORL	A,DATA
            MOV	P1,A
            ACALL	 DELAY
            INC	R1
            JNB	SW_1PHASE,SCAN_PHASE
            JNB	SW_RIGHT,RIGHT
            DJNZ	R0,LOOP
            SJMP	DISP_MOTOR

    ข้อมูล ที่ 20H	1	0	1	0	0	0	0	0
    ข้อมูลที่ Reg A	0	0	0	0	1	0	0	0
    ผลลัทพ์ ORL Reg A	1	0	1	0	1	0	0	0
    แสดงผล LED      1Phase	-	L	-           step1	-	-	-

     *********เอาหล่ะ!  มาเขียนโปรแกรมใช้งานจริงๆกันดีกว่า

    2  การเขียนโปรแกรม

;*********************************************************************
;***         PROGRAM  STEPPING MOTOR  CONTROL          ***
;** *                    DESIGN  BY  CH.ADISAK                           ***
;*********************************************************************
               ORG	00H
                                SW_1PHASE    BIT     	P3.3
                                SW_2PHASE    BIT     	P3.2
                                SW_LEFT          BIT     	P3.1
                                SW_RIGHT       BIT     	P3.0
            DATA	               EQU	20H
                        SETB	SW_1PHASE
                SETB	SW_2PHASE
                SETB	SW_LEFT
                SETB	SW_RIGHT
                MOV	P1,#00000000B
                MOV	DATA,#00000000B
                CLR	A

;**********************  SELECT PHASE ****************************

        SCAN_PHASE:        	JNB	SW_1PHASE,PHASE1
            JNB	SW_2PHASE,PHASE2
            SJMP	SCAN_PHASE

        PHASE1:     	MOV	DATA,#00H
        CLR	06H
                                SETB	07H
                                MOV	P1,DATA
                                SJMP	SCAN_DIR

        PHASE2:                	MOV	DATA,#00H
            CLR	07H
            SETB	06H
            MOV	P1,DATA
            SJMP	SCAN_DIR

    ;*******************************   SELECT DIR  ************************************
        SCAN_DIR:			JNB	SW_1PHASE,SCAN_PHASE
                JNB	SW_2PHASE,SCAN_PHASE
                JNB	SW_LEFT,LEFT
                JNB	SW_RIGHT,RIGHT
                SJMP	SCAN_DIR
    LEFT:		CLR	04H
                                    SETB	05H
                                    MOV	P1,DATA
                                    SJMP	DIS_1LEFT

    RIGHT:			CLR	05H
                SETB	04H
                MOV	P1,DATA
                SJMP	DIS_1RIGHT

;******************************************  MOV  INDEX  Reg. DPTR  **************************
        ;**********************   1 PHASE LEFT***************************
    DIS_1LEFT:	MOV	A,#10100000B
                                    CJNE	A,DATA,DIS_2LEFT
                                    MOV	DPTR,#PHASE_1L
                                    SJMP	DISP_MOTOR
        ;**********************   1 PHASE  RIGHT**************************
    DIS_1RIGHT:		MOV	A,#10010000B
                CJNE	A,DATA,DIS_2RIGHT
                MOV	DPTR,#PHASE_1R
                SJMP	DISP_MOTOR
        ;**********************  2 PHASE  LEFT****************************
    DIS_2LEFT:	MOV	A,#01100000B
                                    CJNE	A,DATA,SCAN_PHASE
                                    MOV	DPTR,#PHASE_2L
                                    SJMP	DISP_MOTOR

        ;*********************   2 PHASE  RIGHT **************************
    DIS_2RIGHT:		MOV	A,#01010000B
                CJNE	A,DATA,SCAN_PHASE
                MOV	DPTR,#PHASE_2R
                SJMP	DISP_MOTOR

                     ;******************* DISPLAY & MOTOR DRIVE **********************
    DISP_MOTOR:	MOV	R0,#04H
            MOV	R1,#00H
            MOV	A,#00H
               LOOP:		MOV	A,R1
            MOVC	A,@A+DPTR
            ORL	A,DATA
            MOV	P1,A
            ACALL	 DELAY
            INC	R1
            JNB	SW_1PHASE,SCAN_PHASE
            JNB	SW_2PHASE,SCAN_PHASE
            JNB	SW_LEFT,LEFT
            JNB	SW_RIGHT,RIGHT
            DJNZ	R0,LOOP
            SJMP	DISP_MOTOR

;*******************************   SUB  DELAY **********************************************
    DELAY:			MOV	R5,#00H
             DELAY1:                 	MOV	R6,#0FH
                DJNZ	R6,$
                DJNZ	R5,DELAY1
                RET
        PHASE_1L:               DB         08H,04H,02H,01H
        PHASE_1R:               DB         01H,02H,04H,08H
        PHASE_2L:               DB         0CH,06H,03H,09H
        PHASE_2R:               DB         09H,03H,06H,0CH

                                END

    3  ขั้นตอนการโปรแกรม
        - เมื่อเขียนโปรแกรมและ SAVE เป็น LAB4.ASM แล้ว
        - ทำการแอสแซมเบอร์โดยใช้คำสั่ง 	SXA51   -L  LAB4.ASM
        - เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
        - จากการแอสแซมเบอร์จะได้ไฟล์   LAB4.HEX  และ LAB4.LST
        - ให้นำไฟล์ที่เป็น  LAB4.HEX ไปโปรแกรม
        - โดยใช้คำสั่ง EZ  LAB4.HEX   -C1  (-C2 กรณีต่อกับ COM2)
        - ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
    จากการทดลองในใบงานที่ 4 ผลการทดลองเป็นไปตามเงื่อนไขของโปรแกรมที่เขียนขึ้น คือ เมื่อกดสวิตซ์ที่ P3.2 แล้ว จะเป็นการเลือกการขับ
แบบ 1 เฟส  กดสวิตซ์ที่ P3.1 จะวิ่งไปทางซ้ายมือ เมื่อกดสวิตซ์ที่ P3.3 แล้ว จะเป็นการเลือกการขับแบบ 2 เฟส  กดสวิตซ์ที่ P3.0 จะวิ่งไปทางขวามือ
โดยจะใช้คำสั่ง JNB คือ ตรวจสอบว่าบิตเป็นศูนย์หรือไม่ ถ้าเป็นให้กระโดดไปทำตามคำสั่งที่กำหนด

    5 สรุปผล ข้อเสนอแนะและปัญหา
     จากการทดลองทำให้ได้ทราบถึงวิธีการกำหนดพอร์ตที่จะใช้เป็นสวิตซ์โดยเขียนโปรแกรมให้ไมโครคอลโทรเลอร์ตรวจสอบและทำตามเงื่อนไข
และการกำหนดรูปแบบของโปรแกรมโดยวิธีการกรองข้อมูลโดยวิธีทางลอจิกก่อนที่จะทำการแสดงผล ในใบงานนี้เงื่อนไขในการเขียนโปรแกรม คือ ให้
switch SW3 SW4  เป็นการกดเพื่อเลือกวิธีการขับ แบบ 1 เฟส และแบบ 2เฟส ส่วน SW1 SW2 จะเป็นการเลือกทิศทางการหมุน โดยขั้นแรกต้อง
ทำการกำหนดพอร์ตที่ใช้เป็นสวิตซ์ ในที่นี้จะใช้พอร์ต P3.2,P3.3เป็นการเลือกแบบการขับ P3.0,P3,1 เป็บการเลือกทิศทางการหมุน ในโปรแกรมจะต้อง
มีการตรวจสอบตลอดเวลา คือ ตรวจสอบทั้ง P3.0  P3.2,P3.3 และ P3.4 เมื่อพอร์ตใดพอร์ตหนึ่งเป็นศูนย์จะกระโดดไปทำตามคำสั่งคือ ให้ เลือกวิธีการ
ขับและทิศทางการหมุน การทดลองใบงานนี้จะต้องทำการต่อ   IC 74HCT245 และ LED ภายนอกที่ตำแหน่งด้านขวาที่จุดไข่ปลา และที่ JUMPER J3 ต้องOPEN

กลับไปหน้าหลัก

    1


LAB 5
Count UP/Count Down

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด

     ในใบงานนี้ตามเงื่อนไขของโปรแกรมที่เขียนขึ้น คือ เมื่อกดสวิตซ์ที่ P3.0 แล้ว จะเป็นการนับขึ้นเมือกดสวิตซ์ที่ P3.1จะเป็นการนับลง

 การเขียนโปรแกรม ขับ  LED 7 SEGMENT
ุ 	 สังเกตการแสดงผลที่แอลอีดีแล้วทำเป็นเลขฐาน 16

    D7(P1.7)	D6(P1.6)	D5(P1.5)	D4(P1.4)	D3(P1.3)	D2(P1.2)	D1(P1.1)	D0(P1.0)
    Pt	g	f	e	d	c	b	a
               *******************************************************************************************************************************
HEX	0	1	2	3	4	5	6	7	8	9
DATA	C0H	F9H	A4H	B0H	99H	92H	82H	F8H	80H	90H
              *******************************************************************************************************************************
จากโปรแกรมเป็นการต่อแอลอีดีแบบ 2 หลักและเขียนโปรแกรมทดสอบเบื้องต้น

        ORG	00H
MAIN:		MOV	R2,#00H
        CLR	A
        MOV	DPTR,#TABLE	;กำหนดค่าฐานแอดเดรสที่ TABLEให้อยู่ในรีจิสเตอร์ DPTR
LOOP:		MOV	A,R2
        MOVC	A,@A+DPTR	;นำค่าที่ได้จาก Reg A ไปรวมกับค่าฐาน ผลลัพท์ เก็บไว้ที่ Reg A
        MOV	P1,A		นำค่าที่รีจิสเตอร์ A ออกพอร์ต P1
        CLR	P3.5		;ให้ DIGIT1 หรือ P3.5 เป็น 0 ทรานซิสเตอร์ PNP นำกระแส
        CLR	P3.4		;ให้ DIGIT0 หรือ P3.4 เป็น 0 ทรานซิสเตอร์ PNP นำกระแส
        ACALL	DELAY
        INC	R2
        CJNE	A,#00H,LOOP	; ตรวจสอบที่รีจิสเตอร์ A เป็น 00H หรือไม่ถ้าไม่เป็นให้ไปที่ LOOP
        SJMP	MAIN		; 00 H ในที่นี้มาจากค่าที่ DB ที่ TABLE ข้างล่างเป็นตัวที่สุดท้าย
DELAY:		MOV	R4,#05		; เอาไว้ตรวจสอบว่าได้แสดงผล 0- 9 หมดแล้ว
DELAY2:		MOV	R0,#0FFH
DELAY1:		MOV	R1,#0FFH
        DJNZ	R1,$
        DJNZ	R0,DELAY1
        DJNZ	R4,DELAY2
        RET
TABLE:		DB		0C0H,0F9H,0A4H,0B0H,99H
        DB		92H,82H,0F8H,80H,90H,00H
        END

                                   LAB4    COUNTER UP  & COUNT DOWN

    2 ขั้นตอนการเขียนโปรแกรม

    ; ******************************************************************
    ; **	 PROGRAM   LAB5.ASM		  **
    ; ** 	COUN UP /COUNT DOWN                     **
    ; ******************************************************************

        ORG	0000H
        SJMP	START

SW_UP		BIT	P3.0	 ; เป็นการกำหนดชื่อเรียกบิต P3.0 เอาเป็นว่าถ้าจะทำอะไรที่ P3.0
SW_DOWN	BIT	P3.1	; ก็ให้เรียก SW_UP ก็แล้วกัน อื่นๆก็เหมือนกัน
DIGIT0		BIT	P3.4
DIGIT1		BIT	P3.5
COUNT		EQU	20H	;กำหนดค่าชื่อ COUNT ให้อยู่ที่แอดเดรส 20 H แบบนี้เป็นไบต์นะ
DATA:		DS	2	;เป็นการจองเนื้อที่ในหน่วยความจำขนาด 2 ไบต์ชื่อ DATA,DATA+1

START:		SETB	SW_UP		;กำหนดให้เป็นอินพุตต้องเซตให้เป็น 1 ยั้งจำได้ไหมว่าทำไม่
        SETB	SW_DOWN
        MOV	COUNT,#00H	;COUNT หรือ 20 H เป็นค่าเริ่มต้น 00H
MAIN:		ACALL	DATA_DIS	;เรียกโปรแกรมย่อย หาค่าข้อมูลใส่ DATA,DATA+1
        ACALL	DISPLAY		;เรียกโปรแกรมแสดงผลค่าที่ DATA,DATA+1
        JNB	SW_UP,UP	;ตรวจสอบการกดคีย์เพิ่มค่าข้อมูลที่ COUNT
        JNB	SW_DOWN,DOWN
        SJMP	MAIN		;จุดเทียนเวียนวน MAIN

UP:		ACALL	DELAY		;เรียกโปรแกรมย่อย DELAY หน่วงเวลาว่ามีการกดจริงหรือเปล่า
        JB	SW_UP,MAIN	;โกหกตรวจดูแล้วบิต P3.0 เป็น 1 กลับไป MAIN
        MOV	R7,COUNT	;เงือนไขข้างบนเป็นจริงให้นำค่า COUNT >>> R7
        CJNE	R7,#100,INC_C	;นับถึง 100 หรือเปล่า เลขมีแค่ 2 หลักนะถ้าไม่ ไป INC_C
        SJMP	START		;ถ้าจริงไปเริ่มต้นใหม่เลย
INC_C:		INC	COUNT		;ไม่ถึง 99 ก็ให้นับเพิ่มที่ COUNT
        JNB	SW_UP,$		;เลิกกดสวิทช์หรือยังถ้ากดยังไม่เลิกกดก็วนที่บรรทัดเดิม
        SJMP	MAIN		;เลิกกดก็กลับไป MAIN PROGRAM

DOWN:		ACALL	DELAY
        JB	SW_DOWN,MAIN
        MOV	R7,COUNT
        CJNE	R7,#00,DEC_C
        MOV	COUNT,#100
        SJMP	MAIN
DEC_C:		DEC	COUNT
        JNB	SW_DOWN,$
        SJMP	MAIN

DATA_DIS:	MOV	DPTR,#TABLE 	;กำหนดค่าฐานแอดเดรสที่ TABLEให้อยู่ในรีจิสเตอร์ DPTR
        MOV	B,#10		;ให้รีจีสเตอร์ B = 10 เอาไว้หารกับ Reg  A ได้หลักสิบที่ Reg A
        MOV	A,COUNT		;เอาค่าการกดสวิตช์ใน COUNT มาเก็บไว้ที่ Reg A
        DIV	AB		;เอาค่าใน B ไปหารค่าใน A เก็บผลลัพท์ไว้ที่ Reg A เศษที่ได้เก็บ Reg B
        MOVC	A,@A+DPTR	;นำค่าที่ได้จาก Reg A ไปรวมกับค่าฐาน ผลลัพท์ เก็บไว้ที่ Reg A
        MOV	DATA,A		;นำค่าที่ได้จากรีจิสเตอร์ A เก็บไว้ที่ หน่วยความจำตำแหน่ง DATA
        MOV	A,B		นำค่าที่ Reg B ไปเก็บไว้ที่ Reg A
        MOVC	A,@A+DPTR	;นำค่าที่ได้จาก Reg A ไปรวมกับค่าฐาน ผลลัพท์ เก็บไว้ที่ Reg A
        MOV	DATA+1,A		;นำค่าที่ได้จากรีจิสเตอร์ A เก็บไว้ที่ หน่วยความจำตำแหน่ง DATA+1
        RET

DISPLAY:	MOV	A,DATA			;นำค่าที่ได้จากหน่วยความจำตำแหน่ง DATA เก็บไว้ที่ รีจิสเตอร์ A
        MOV	P1,A		;นำค่าที่รีจิสเตอร์ A ออกพอร์ต P1
        CLR	DIGIT0		;ให้ DIGIT0 หรือ P3.4 เป็น 0 ทรานซิสเตอร์ PNP นำกระแส
        ACALL	DELAY		;เรียกโปรแกรมย่อยหน่วงเวลา
        SETB	DIGIT0		;ให้ DIGIT0 หรือ P3.4 เป็น 1 ทรานซิสเตอร์ PNP หยุดนำกระแส
        MOV	A,DATA+1		;นำค่าที่ได้จากหน่วยความจำตำแหน่ง DATA +1 เก็บไว้ที่ รีจิสเตอร์ A
        MOV	P1,A		;นำค่าที่รีจิสเตอร์ A ออกพอร์ต P1
        CLR	DIGIT1		;ให้ DIGIT1 หรือ P3.5 เป็น 0 ทรานซิสเตอร์ PNP นำกระแส
        ACALL	DELAY		;เรียกโปรแกรมย่อยหน่วงเวลา
        SETB	DIGIT1		;ให้ DIGIT0 หรือ P3.5 เป็น 1 ทรานซิสเตอร์ PNP หยุดนำกระแส
        RET

DELAY:		MOV	R1,#200
        DJNZ	R1,$
        RET

TABLE:		DB		0C0H,0F9H,0A4H,0B0H,99H
        DB		92H,82H,0F8H,80H,90H
        END

    3 ขั้นตอนการโปรแกรม

        - เมื่อเขียนโปรแกรมและเซฟเป็น LAB5.ASM แล้ว
        - ทำการแอสแซมเบอร์โดยใช้คำสั่ง 	SXA51   -L  LAB5.ASM
        - เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
        - จากการแอสแซมเบอร์จะได้ไฟล์   LAB5.HEX  และ LAB5.LST
        - ให้นำไฟล์ที่เป็น  LAB5.HEX ไปโปรแกรม
        - โดยใช้คำสั่ง EZ  LAB5.HEX   -C1  (-C2 กรณีต่อกับ COM2)
        - ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4 ผลการทดลอง

    จากการทดลองในใบงานที่ 5 ผลการทดลองเป็นไปตามเงื่อนไขของโปรแกรมที่เขียนขึ้น คือเมื่อกดสวิตซ์ที่ P3.0 แล้ว จะเป็นการนับขึ้น
เมือกดสวิตซ์ที่ P3.1 จะเป็นการนับลง

    5สรุปผล  ข้อเสนอแนะและปัญหา


LAB 7
การเขียนโปรแกรมเพื่อทดลองการอินเตอร์รัพท์จากภายนอก

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด

    ขั้นตอนที่ 1
        ส่วนของโปรแกรม
            ORG   	0000H
            SJMP	MAIN
            ORG	0003H
            SJMP	INT_0
            ORG	0013H
            SJMP	INT_1
        MAIN:	SETB	EA
            .
            .
            INT_0:	.
                .
            RETI
            INT_1:	.
            .
            RETI
            END
    **** SJMP  MAIN    ด้วยเหตุผลว่าถ้าหากเขียนโปรแกรมหลักตั้งแต่แอดเดรส 0000H แล้วไปถึงที่แอดเดรส 0003 H โปรแกรมหลักก็จะไป
ทับกับตำแหน่งแอดเดรสของ INT0 และ ถ้าหากโปรแกรมหลักยาวไปถึงแอดเดรส ที่0013H ก็จะไปทับกับตำแหน่งของ INT1
    ในทำนองเดียวกันการกลับจากการเรียกโปรแกรมย่อยของการบริการอินเตอร์รัพท์ต้องใช้คำสั่ง RETI   ; I หมายถึง Return interrupt

    ขั้นตอนที่ 2
     เริ่มต้นโดยการเซตบิต  EA (Enable all) ให้เป็น "1" เพื่อเป็นการอนุญาติให้มีการอินเตอร์รัพท์ได้
      จากขั้นตอนที่ 1 จะเขียนในส่วนของ MAIN   โปรแกรม
            SETB   EA	;ทำการตอบรับการอินเตอร์รัพท์ทั้งหมด

         ขั้นตอนที่ 3
     เลือกการอินเตอร์รัพท์โดยการเซตบิตที่รีจีสเตอร์ IE ที่บิต EX0 หรือที่บิต EX1ว่าจะให้อินเตอร์รัพท์ที่ขาหรือที่ขาอาจจะเซตบิตทั้งสองขาก็ได้
จากขั้นตอนที่ 1 จะเขียนในส่วนของ MAIN  โปรแกรม

                           SETB	EX0	; ให้อินเตอร์รัพท์ที่ขา  จะกระโดดไปที่แอดเดรส 0003H
            SETB	EX1	; ให้อินเตอร์รัพท์ที่ขา  จะกระโดดไปที่แอดเดรส 0013H

     ขั้นตอนที่1 และขั้นตอนที่2 สามารถเขียนรวมได้เป็น

            MOV 	IE,#10000101B ; ทำการเซตบิต EA="1", EX0="1", EX1="1"
            SETB	P3.2	; ทำ P3.2 ให้เป็นอิมพีแดนซ์สูง (INPUT)
            SETB	P3.3	; ทำ P3.3 ให้เป็นอิมพีแดนซ์สูง (INPUT)

    ***  การใช้งานสัญญาณร้องขอการอินเตอร์รัพท์จากภายนอก   และ   (ขา  P3.2 และ P3.3) จะต้องเซตบิต P3.2 และ  P3.3 ให้เป็น "1" ในตอน
เริ่มต้นก่อนเพื่อทำให้เป็นอิมพีแดนซ์สูง โดยใช้คำสั่ง SETB  P3.2 และ SETB  P3.3

    ขั้นตอนที่ 4
     เลือกลักษณะสัญญาณการอินเตอร์รัพท์โดยการเซตบิตที่รีจีสเตอร์ TCON ที่บิต IT0 หรือที่บิต IT1 ว่าจะให้สัญญาณการอินเตอร์รัพท์เป็นลักษณะใด
จากขั้นตอนที่ 1 จะเขียนในส่วนของ MAIN โปรแกรม

    **   การเปลี่ยนระดับสัญญาณเป็นระดับลอจิกต่ำหรือ "0" ให้ดำเนินการทำให้ขาสัญญาณนี้กลับเป็นสถานะลอจิก "1" ก่อนบริการอินเตอร์รัพท์จะ
เสร็จสิ้นเพื่อป้องกันการอินเตอร์รัพ์ซ้ำซ้อน

    **  การเปลี่ยนระดับสัญญาณจาก "1" ไปเป็น "0" โดยทำที่ขอบขาลงต้องรักษาสถานะ "0" ไม่น้อยกว่า 1 แมชชีนไซเคิล
        SETB 	IT0	;ลักษณะสัญญาณ Active Low (ขอบขาลง)
        SETB	IT1	;ลักษณะสัญญาณ Active Low (ขอบขาลง)

          ขั้นตอนที่ 5
     เลือกลำดับความสำคัญการอินเตอร์รัพท์โดยการเซตที่ รีจีสเตอร์ IP บิต
        SETB  IP.2	กำหนดลำดับความสำคัญสูงของสัญญาณ     (External Interrupt 1)
        CLR    IP.0		กำหนดลำดับความสำคัญต่ำของสัญญาณ    (External Interrupt 0)
      หากบิตใดมีการเซตค่าเป็น "1" จะมีลำดับความสำคัญสูง แต่หากไม่มีการเซตบิตใดๆ การจัดความสำคัญสูงกว่า  อยู่แล้วซึ่งเป็นค่าเริ่มต้นของ
ไมโครคอนโทรลเลอร์จากขั้นตอนที่ 1 จะเขียนในส่วนของ MAIN โปรแกรม

    ** เงื่อนไขของการทดลองในโปรแกรมนี้จะให้แอลอีดีแสดงผลโดยจากวงจรจะให้ SW1 ต่อกับขา INT0 และ SW2 ต่อกับขา INT1 ถ้าหากเริ่มต้น
กดรีเซตจะแสดงโดยให้แอลอีดีกระพริบทั้ง 8 ดวง และถ้าหากมีการกด SW1 จะให้แอลอีดี เลื่อนทางซ้าย 1รอบแล้วกลับไปกระพริบใหม่ และถ้าหากกด SW2
จะให้ แอลอีดีเลื่อนทางขวา 1 รอบ แล้วกลับไปกระพริบใหม่

    2 การเขียนโปรแกรม
                            ;*****************************************************
                            ;**                     INTERRUPT LAB 7		 **
                            ;**      INT0 & INT1 CONTROL  LED DISPLAY    **
                            ;******************************************************

            ORG	00H
            SJMP	MAIN
            ORG	0003H
            SJMP	INT_0
            ORG	0013H
            SJMP	INT_1

        MAIN:	SETB	P3.2
            SETB	P3.3
            SETB	EA
            SETB	EX0
            SETB	EX1
            SETB	IT0
            SETB	IT1

    LOOP:		MOV	P1,#00H
            ACALL	DELAY
            MOV	P1,#0FFH
            ACALL	DELAY
            SJMP	LOOP
    INT_0:		MOV	R1,#08H
            MOV	R2,#00H
            MOV	DPTR,#TABLE
       LOOP_LEFT:  	MOV	A,R2
            MOVC	A,@A+DPTR
            MOV	P1,A
            ACALL	DELAY
            INC	R2
            DJNZ	R1,LOOP_LEFT
            RETI

    INT_1:		MOV     R1,#08H
            MOV     R2,#07H
            MOV     DPTR,#TABLE
 LOOP_RIGHT:		MOV     A,R2
            MOVC   A,@A+DPTR
            MOV     P1,A
            ACALL   DELAY
            DEC     	R2
            DJNZ    	R1,LOOP_RIGHT
            RETI

        ;********    DELAY  SUB   **********
            DELAY:	MOV     	R3,#0FFH
            DELAY1:	MOV     	R4,#0FFH
            DJNZ    	R4,$
            DJNZ    	R3,DELAY1
            RET
            TABLE:	DB      	01H,02H,04H,08H
            DB      	10H,20H,40H,80H
            END

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB7.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB7.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB7.HEX และ LAB7.LST
            -  ให้นำไฟล์ที่เป็น LAB7.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB7.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4 ผลการทดลอง
         จากการทดลองใบงานที่ 7 ผลการทดลองเป็นไปตามเงื่อนไขคือ ถ้าหากเริ่มต้นกดรีเซตจะแสดงโดยให้แอลอีดีกระพริบทั้ง 8 ดวง
และถ้ามีการกด SW1 จะให้แอลอีดี เลื่อนทางซ้าย 1รอบแล้วกลับไปกระพริบใหม่ และถ้ากด SW2  แอลอีดีเลื่อนทางขวา 1 รอบ แล้วกลับไปกระพริบใหม่

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

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์


LAB 8
 CLOCK  PULSE   1  msec , 1  sec  &  1 min

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
       ถ้าใช้งานการอินเตอร์รัพท์โหมด 2 เรากำหนด TH0 = -230 จะได้เวลาประมาณ 230 X 1.085 = 249.55 Usec หรือประมาณ 250 Usec
ถ้าทำ 200 รอบ   250 x200 = 50,000 Usec หรือ 50 msec   ถ้าทำอีก 10 รอบ  =  500 msec  ถ้าทำอีก 2 รอบ  = 1 sec  (ถาม ทำไม ไม่กำหนดให้เป็น 20 รอบ
ตอบ เพราะจะได้กำหนด ครึ่งนาทีกระพริบที่จุด 1 ครั้งไง ) ถ้าทำอีก 60 รอบ  =  1 minสรุปทำทั้งหมด     ((((250 x 200) 10 )2)60)  = 1 min

    2  การเขียนโปรแกรม
        ุ
        DIGIT0		BIT	P3.4
        DIGIT1		BIT	P3.5
        LED_250US	BIT	P1.0
        LED_5ms	BIT	P1.1
        LED_SEC	BIT	P1.2
        LED_MIN	BIT	P1.3
         COUNT_200		EQU	20H
         COUNT_10		EQU	21H
          COUNT_2		EQU	22H
             SEC_60		EQU	23H
         MIN		EQU	24H
                ORG	25H
                DATA:		DS         2 	;การจองเนื้อที่ไว้ 2 ไบต์ในหน่วยความจำข้อมูลที่ไหนก็ได้

        ORG	0000H
        SJMP	START
        ORG	000BH
        SJMP	INT_T0
START:		ACALL	INIT
        MOV	P1,#00H
        MOV	MIN,#05H
MAIN:		SJMP	$
INIT:		CLR	DIGIT0
        CLR	DIGIT1
        MOV	COUNT_200,#200
        MOV	COUNT_10,#10
        MOV	COUNT_2,#2
        MOV	SEC_60,#60
        MOV 	TMOD,#00100010B
        MOV	TL0,#-230
        MOV	TH0,#-230
        SETB	EA		;กำหนดให้มีการอินเตอร์รัพท์ได้ทั้งหมด
        SETB	ET0		;กำหนดให้มีการอินเตอร์รัพท์ที่ TIMER 0
        SETB	TR0    	      	;กำหนดให้เริ่มทำการอินเตอร์รัพท์
        RET

INT_T0:		DJNZ	COUNT_200,END_RETI
        MOV	COUNT_200,#200
        CPL	LED_250US
        DJNZ	COUNT_10,END_RETI
        MOV	COUNT_10,#10
        CPL	LED_5ms
        DJNZ	COUNT_2,END_RETI
        MOV	COUNT_2,#02
        CPL	LED_SEC
        DJNZ	SEC_60,END_RETI
        MOV	SEC_60,#60
        CPL	LED_MIN
        DJNZ	MIN,END_RETI
        CLR 	TR0
END_RETI:	RETI
        END

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB8.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB8.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB8.HEX และ LAB8.LST
            -  ให้นำไฟล์ที่เป็น LAB8.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB8.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
    กำหนด COUNT โดยกำหนดให้ 250 Usec x 200 = 50,000 msec LED กระพริบ 1ครั้งทุก 50,000 Usec หมดรอบทำการ
กำหนด COUNT = 200 ใหม่ 50,000 x 10 = 500,000 msec  ครึ่งวินาทีแล้ว LED_5 msec  ;กระพริบซะหน่อยนับค่า ครึ่งวินาทีหลังต่อ
MOV SEC_60,#60     รวม  1 นาทีนะ  LED จะกระพริบทุกวินาที และทุกนาที จากโปรแกรมตั้งไว้ 5 นาที

    5 สรุปผล ข้อเสนอแนะและปัญหา
    จากการเขียนโปรแกรมในใบงานนี้ทำให้ทราบถึงการนำเอา ส่วนของการอินเตอร์รัทพ์มาใช้งานโดย


LAB 9
TIMER 0-99 Min (FIX)

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
       ถ้าใช้งานการอินเตอร์รัพท์โหมด 2 เรากำหนด TH0 = -230 จะได้เวลาประมาณ 230 X 1.085 = 249.55 Usec หรือประมาณ 250 Usec ถ้าทำ 200 รอบ
250 x200 = 50,000 Usec หรือ 50 msec   ถ้าทำอีก 10 รอบ  =  500 msec  ถ้าทำอีก 2 รอบ  = 1 sec  ถ้าทำอีก 60 รอบ =  1 minสรุปทำทั้งหมด
 ((((250 x 200) 10 )2)60)  = 1 min  CLOCK  TIME   00-99  นาที  จากโปรแกรมเป็นการตั้งเวลาไว้ 5 นาทีหากต้องการเปลี่ยนแปลงเวลาต้องกำหนดที่ MIN
ในส่วนของหน่วยความจำโปรแกรม

    2  การเขียนโปรแกรม

        DIGIT0	      BIT	 P3.4
        DIGIT1	      BIT	 P3.5
        LED_DP	      BIT	 07H	;กำหนดให้อยู่ที่ หน่วยความจำแบบบิตตำแหน่ง 07H ที่แอดเดรส 20H
        COUNT_200	EQU	21H
        COUNT_10	EQU	22H
        COUNT_2	EQU	23H
        SEC_60		EQU	24H
        MIN		EQU	25H
            ORG	26H
        DATA:	DS	2	;การจองเนื้อที่ไว้ 2 ไบต์ในหน่วยความจำข้อมูลที่ไหนก็ได้
            ORG	0000H
            SJMP	START
            ORG	000BH
            SJMP	INT_T0
    START:		ACALL	INIT
            MOV	MIN,#05	;กำหนดหน่วยความจำ MIN ให้เท่ากับ 5 นาที
    MAIN:		ACALL	DATA_DIS
            ACALL	DISPLAY
            SJMP	MAIN

    INIT:		MOV	P1,#0FFH
            SETB	DIGIT0	;ทำให้ทรานซิสเตอร์ PNP  2 ตัวหยุดการทำงาน
            SETB	DIGIT1
            MOV	COUNT_200,#200	;กำหนด COUNT_200 ให้เท่ากับ 200
            MOV	COUNT_10,#10		;
            MOV	COUNT_2,#2
            MOV 	TMOD,#00100010B
            MOV	TL0,#-230
            MOV	TH0,#-230
            SETB	EA
            SETB	ET0
            SETB	TR0
            RET

    INT_T0:	PUSH    PSW
        DJNZ	COUNT_200,END_RETI
        MOV	COUNT_200,#200
        DJNZ	COUNT_10,END_RETI
        MOV	COUNT_10,#10
                      CPL	LED_DP
        DJNZ	COUNT_2,END_RETI
        MOV	COUNT_2,#2
        DJNZ	SEC_60,END_RETI
        MOV	SEC_60,#60
        DJNZ	MIN,END_RETI
        SETB	LED_DP
        CLR 	TR0
END_RETI:	POP	PSW
        RETI

DATA_DIS:	MOV	DPTR,#TABLE
        MOV	B,#10
        MOV	A,MIN
        DIV	AB
        MOVC	A,@A+DPTR
        MOV	DATA,A
        MOV	A,B
        MOVC	A,@A+DPTR
        MOV	C,LED_DP	;นำค่าที่ บิต 07H ไปเก็บไว้ที่ แฟลกทด
        MOV	ACC.7,C		;นำแฟลกทดไปรวมกับรีจีสเตอร์ A ที่บิต 7
        MOV	DATA+1,A
        RET

DISPLAY:	MOV	A,DATA
        MOV	P1,A
        CLR	DIGIT0
        ACALL	DELAY
        SETB	DIGIT0
        MOV	A,DATA+1
        MOV	P1,A
        CLR	DIGIT1
        ACALL	DELAY
        SETB	DIGIT1
        RET
DELAY:		MOV	R1,#200
        DJNZ	R1,$
        RET
TABLE:		DB	0C0H,0F9H,0A4H,0B0H,99H
        DB	92H,82H,0F8H,80H,90H
        END

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB9.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB9.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB9.HEX และ LAB9.LST
            -  ให้นำไฟล์ที่เป็น LAB9.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB9.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
     CLOCK  TIME   00-99  นาที  จากโปรแกรมเป็นการตั้งเวลาไว้ 5 นาทีหากต้องการเปลี่ยนแปลงเวลาต้องกำหนดที่ MIN ในโปรแกรมข้อเสียของโปรแกรม
คือต้องกำหนดเวลาตายตัวที่ส่วนของหน่วยความจำโปรแกรม

    5 สรุปผล ข้อเสนอแนะและปัญหา
    จากการเขียนโปรแกรมในใบงานนี้ทำให้ทราบถึงการนำเอา ส่วนของการอินเตอร์รัทพ์มาใช้งานโดย


LAB 10
TIMER 0-99 Min กำหนดเวลาได้

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
           ตั้งเวลา   00-99  นาที   เอาการทดลองในใบงาน 9 มาแก้ไขและปรับปรุงให้ใช้ได้เพื่อที่จะตั้งเวลาได้ตามกำหนดโดยใช้สวิตช์ เป็นตัวนับขึ้นและนับลง
กำหนดเวลาไว้ล่วงหน้าโดยเก็บค่าไว้ที่หน่วยความจำข้อมูลส่วนอื่นๆในโปรแกรมยังคงเหมือนเดิม   การทำงานให้ กดที่ SW_RESET แล้วเลือกค่าโดยกด SW_UP
หรือ SW_DOWN  เมื่อได้ค่าที่ต้องการแล้วกด  SW_OK โปรแกรมจะเริ่มทำงานในส่วนของการอินเตอร์รัพท์ในโหมด 2

    2  การเขียนโปรแกรม

        SW_UP		BIT	P3.0
        SW_DOWN	BIT	P3.1
        SW_OK		BIT	P3.2
        DIGIT0		BIT	P3.4
        DIGIT1		BIT	P3.5
        LED_DP		BIT	07H
             COUNT_200	EQU	21H
        COUNT_10	EQU	22H
        COUNT_2	EQU	23H
        SEC_60		EQU	24H
        MIN		EQU	25H

            ORG	26H
        DATA:		DS	2

        ORG	0000H
        SJMP	START
        ORG	000BH
        SJMP	INT_T0

START:		SETB	SW_UP
        SETB	SW_DOWN
        SETB	SW_OK
        MOV	MIN,#00H

MAIN:		ACALL	DATA_DIS
        ACALL	DISPLAY
        JNB	SW_UP,UP
        JNB	SW_DOWN,DOWN
        JNB	SW_OK,START_1
        SJMP	MAIN

UP:		ACALL	DELAY
        JB	SW_UP,MAIN
        MOV	R7,MIN
        CJNE	R7,#100,INC_C
        SJMP	START
INC_C:		INC	MIN
        JNB	SW_UP,$
        SJMP	MAIN

DOWN:		ACALL	DELAY
        JB	SW_DOWN,MAIN
        MOV	R7,MIN
        CJNE	R7,#00,DEC_C
        MOV	MIN,#100
        SJMP	MAIN
DEC_C:		DEC	MIN
        JNB	SW_DOWN,$
        SJMP	MAIN

START_1:	ACALL	INIT
MAIN1:		ACALL	DATA_DIS
        ACALL	DISPLAY
        SJMP	MAIN1

INIT:		MOV	P1,#0FFH
        SETB	DIGIT0
        SETB	DIGIT1
        MOV	COUNT_200,#200
        MOV	COUNT_10,#10
        MOV	COUNT_2,#2
        MOV 	TMOD,#00100010B
        MOV	TL0,#-230
        MOV	TH0,#-230
        SETB	EA
        SETB	ET0
        SETB	TR0
        RET

INT_T0:		PUSH    PSW
        DJNZ	COUNT_200,END_RETI
        MOV	COUNT_200,#200
        DJNZ	COUNT_10,END_RETI
        MOV	COUNT_10,#10
        CPL	LED_DP
        DJNZ	COUNT_2,END_RETI
        MOV	COUNT_2,#2
        DJNZ	SEC_60,END_RETI
        MOV	SEC_60,#60
        DJNZ	MIN,END_RETI
        SETB	LED_DP
        CLR 	TR0
END_RETI:	POP	PSW
        RETI

DATA_DIS:	MOV	DPTR,#TABLE
        MOV	B,#10
        MOV	A,MIN
        DIV	AB
        MOVC	A,@A+DPTR
        MOV	DATA,A
        MOV	A,B
        MOVC	A,@A+DPTR
        MOV	C,LED_DP
        MOV	ACC.7,C
        MOV	DATA+1,A
        RET

DISPLAY:	MOV	A,DATA
        MOV	P1,A
        CLR	DIGIT0
        ACALL	DELAY
        SETB	DIGIT0
        MOV	A,DATA+1
        MOV	P1,A
        CLR	DIGIT1
        ACALL	DELAY
        SETB	DIGIT1
        RET

DELAY:		MOV	R1,#200
        DJNZ	R1,$
        RET

TABLE:		DB	0C0H,0F9H,0A4H,0B0H,99H
        DB	92H,82H,0F8H,80H,90H
        END
    ** หมายเหตุ การที่จะนำไปควบคุมอุปกรณ์ไฟฟ้าภายนอกเพียงเพิ่มคำสั่ง   SETB  P3.X หลังจากนับเวลาครบเท่านั้นเองสามารถดูได้
จากโปรเจคที่ภาคโปรเจค ท้ายเล่ม

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB10.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB10.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB10.HEX และ LAB10.LST
            -  ให้นำไฟล์ที่เป็น LAB10.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB10.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
     CLOCK  TIME   00-99  นาที  จากโปรแกรมหากต้องการเปลี่ยนแปลงเวลากดที่ SW_RESET แล้วเลือกค่าโดยกด SW_UP หรือ SW_DOWN
เมื่อได้ค่าที่ต้องการแล้วกด  SW_OK โปรแกรมจะเริ่มทำงาน

    5 สรุปผล ข้อเสนอแนะและปัญหา
    จากการเขียนโปรแกรมในใบงานนี้ทำให้ทราบถึงการนำเอา ส่วนของการอินเตอร์รัทพ์มาใช้งานในส่วนของการอินเตอร์รัพท์ในโหมด 2


LAB 11
อนุกรม(ส่ง) พอร์ต

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
     การส่งข้อมูลแบบอนุกรมก่อน การส่งข้อมูลแบบอนุกรมจะใช้สายเพียงเส้นเดียวในการส่งข้อมูล หรือรับข้อมูล (คำว่าเส้นเดียวหมายความว่า
สายส่ง 1 เส้น (TxD)สายรับ 1 เส้น (RxD) และสายกราวด์ร่วม 1 เส้น (Ground) ) การส่งข้อมูลแบบอนุกรม มีความเร็วในการส่งข้อมูลเรียกว่า Baud Rate
มีหน่วยเป็นบิตต่อวินาที เช่นหากบอกว่ามีการติดต่อด้วยความเร็ว 9600 Bit/sec ก็หมายความว่ามีการส่งข้อมูล จำนวน 9600 บิตในเวลา 1 วินาที
ในไมโครคอนโทรลเลอร์ที่เราใช้อยู่นั้นจะมีส่วนที่ทำหน้าที่ติดต่อแบบอนุกรมอยู่แล้วที่ตำแหน่งขา P3.0 และ P3.การรับข้อมูลจากพอร์ต COM2 ของ
ไมโครคอมพิวเตอร์ใครอยากจะใช้ DOS ส่งข้อมูลก็ได้ใช้  ภาษา PASCAL,BASIC หรือ ภาษาC เขียนส่งมาก็ได้แต่การทดลองในที่นี้ได้ใช้
ProComm  PLUS V1.1B บางที่ก็ใช้ Hyper Terminal ที่มีอยู่บน Windows อยู่แล้วบอร์ดทดลองก็อย่าลืม ต่อแอลอีดี 8 ดวงไว้ที่พอร์ต P1
เพื่อจะใช้แสดงผลด้วย

    ให้เลือก Hypertrm ใส่ชื่อแล้วกด OK

เลือกจะติดต่อที่พอร์ต COMไหนแล้วกำหนด Baud ret เป็น 9600 BPS

    2 การเขียนโปรแกรม

            ORG	0000H
            ACALL	INIT	;เรียกโปรแกรมย่อยสำหรับเซสค่ารีจิสเตอร์ที่เกี่ยวกับการส่งข้อมูลทางอนุกรม
    MAIN:		ACALL	RECEIVE		;เรียกโปรแกรมย่อยส่งข้อมูล
            SJMP	MAIN
    INIT:		MOV	IE,#00000000B		;Clear การอินเตอร์รัพท์
            MOV	TMOD,#00100000B 	 ;Timer1  8bit  Auto Reload
            MOV	TL1,#0FDH
            MOV	TH1,#0FDH		;กำหนด Baud ret 9600 BPS
            MOV	SCON,#01010000B		;Serial  maod1
            SETB	TR1			;ให้ Timer1 เริ่มทำงาน
            RET

    RECEIVE:		JNB	RI,$		;คอยจนกว่าบิต RI จะเป็นเซต 1 แสดงว่ารับข้อมูลเสร็จสิ้นเก็บไว้ที่ SBUF
            CLR	RI		;ทำการ Clear bit  RI โดย software
            MOV	A,SBUF		;นำค่าข้อมูลที่ได้จากการรับมาไว้ที่  Register A
            MOV	P1,A		;แสดงผลโดยนำข้อมูลที่ Register A ออกพอร์ต P1
            RET
            END

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB11.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB11.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB11.HEX และ LAB11.LST
            -  ให้นำไฟล์ที่เป็น LAB11.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB11.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
     จากโปรแกรมทำการทดลองโดยเปิดโปรแกรม ProComm แล้วทดลองพิมพ์อะไรก็ได้ สังเกตแอลอีดีที่ต่อกับพอร์ต P1จะแสดงผลเป็น ASCII CODE
 ก็ลองเปิดตารางดูเอาก็แล้วกัน

    5 สรุปผล ข้อเสนอแนะและปัญหา
    เมื่อใช้ Timer1 เป็นตัวสร้างอัตราการรับส่งข้อมูลของพอร์ตอนุกรมในโหมด 1 ต้องควบคุมไม่ให้ Timer1ส่งสัญญาณอินเตอร์รัพต์ อัตราการรับและ
ส่งข้อมูลจะมาจากอัตราการเกิดโอเวอร์โฟลว์ของ Timer1 และค่าของบิต SMOD ที่อยู่ในรีจิสเตอร์ PCON(รีจิสเตอร์ PCON ไม่สามารถอ้างตำแหน่งแบบบิต
 การเซตค่าให้ใช้คำสั่งทางลอจิกของการ OR เช่น ORL  PCON,#10000000B เท่ากับการเซตบิต 7อง PCON สำหรับการเคลียร์ให้ใช้การ AND เช่น
 ANL PCON,#01111111B  เท่ากับการเคลียร์บิต 7 ของ PCON ) เมื่อใช้ Timer1 สร้างอัตรารับและส่งข้อมูลจะต้องทำให้ไม่มีการร้องขออินเตอร์รัพต์
ที่เกิดจาก Timer1(โดยการควบคุมที่รีจิสเตอร์ IE)เราจะใช้ Timer1 ทำงานในลักษณะของตัวจับเวลาหรือตัวนับอย่างใดอย่างหนึ่ง สำหรับการใช้งานทั่วไป
เราจะกำหนดให้ Timer1ทำงานในลักษณะของตัวจับเวลาในโหมดAuto-reload (มีค่าการควบคุมใน TMOD = 0010XXXX)


LAB 12
อนุกรม(รับ-ส่ง) พอร์ต

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
     การทดลอง   โปรแกรมการรับและแสดงผลโดยไมโครคอนโทรลเลอร์ทำการส่งข้อมูลกลับไปที่ไมโครคอมพิวเตอร์ใช้วิธีการรับข้อมูลจากพอร์ต COM2
ของไมโครคอมพิวเตอร์และจะกลับไปแสดงผลที่ไมโครคอมพิวเตอร์อีกครั้งที่หน้าจอมอนิเตอร์  ใครอยากจะใช้ DOS ส่งและรับข้อมูลก็ได้ใช้  ภาษา PASCAL,BASIC
หรือ ภาษา C เขียนส่งและรับมาก็ได้แต่การทดลองในที่นี้ได้ใช้  ProComm  PLUS V1.1B หรือ Hyper Terminal ที่มีอยู่บน Windows เหมือนเดิม

        ORG	0000H
        ACALL	INIT
    MAIN:	ACALL	RECEIVE
        ACALL	SEND
        SJMP	MAIN
    INIT:	MOV	IE,#00000000B
        MOV	TMOD,#00100000B
        MOV	TH1,#0FDH
        MOV	TL1,#0FDH
        MOV	SCON,#01010000B
        SETB	TR1
        RET

    SEND:	MOV	SBUF,A	;นำข้อมูลที่Register A ไว้ที่ SBUF เพื่อส่งข้อมูลออกไป
        JNB	 TI,$	;ส่งข้อมูลออกไปรอจนกว่าบิต TI เซตเป็น 1 แสดงว่าส่งข้อมูลหมดแล้ว 1 ไบต์
        CLR	TI	;Clear Bit TI เพื่อรอการส่งข้อมูลไบต์ใหม่
        RET
    RECEIVE:	JNB	RI,$	;รอรับข้อมูลจากคอมพิวเตอร์และเช็คที่บิต RI ว่าทำการเซตหรือยัง
        CLR	RI	;หลังจากรับข้อมูลจนครบทำการ clear บิต RI
        MOV	A,SBUF 	 ;นำค่าที่ได้จาก BUFFER ไว้ที่รีจิสเตอร์ A
        MOV	P1,A	;นำค่าที่รีจิสเตอร์ A ออกที่แสดงผลที่พอร์ต P1
        RET
        END

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB12.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB12.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB12.HEX และ LAB12.LST
            -  ให้นำไฟล์ที่เป็น LAB12.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB12.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
     จากโปรแกรมทำการทดลองโดยเปิดโปรแกรม ProComm แล้วทดลองพิมพ์อะไรก็ได้ สังเกตแอลอีดีที่ต่อกับพอร์ต P1 จะแสดงผลเป็น ASCII CODE
โดยจะแสดงผลกลับไปที่จอมอนิเตอร์ด้วย

    5 สรุปผล ข้อเสนอแนะและปัญหา


LAB 13
อนุกรม(รับ-ส่ง) เก็บข้อมูลในหน่วยความจำแสดงผลที่พอร์ต

เขียนและทดลองโดย...อดิศักดิ์ ชิณะวงศ์

    1  วิธีการคิด
     การทดลองเป็นโปรแกรมการรับและแสดงผลโดยการส่งข้อมูลจากไมโครคอนโทรลเลอร์ไปที่ไมโครคอมพิวเตอร์แล้วส่งข้อมูลจากไมโครคอมพิวเตอร์
กลับมาที่ไมโครคอนโทรเลอร์ และเก็บไว้ที่หน่วยความจำ (กำหนดให้เก็บไว้ที่ DATA) แล้วตรวจสอบการส่งข้อมูลโดยการกดคีย์ ENTER จะทำให้แอลอีดีแสดงผล
ตามข้อมูลที่ไมโครคอมพิวเตอร์ได้ส่งข้อมูลที่เก็บไว้ในหน่วยความจำแรม

    2 การเขียนโปรแกรม

    CR	EQU	0DH	;กำหนดค่ารหัส ASCII Carriage Return เริ่มที่จุดเริ่มต้นซ้ายมือสุด
    LF	EQU	0AH	; กำหนดค่ารหัส ASCII  Line Feed หรือสั่งให้ขึ้นบรรทัดใหม่

        ORG       25H		;
    DATA:	DS	10H	;จองเนื้อที่ที่หน่วยความจำ 16 ไบต์
        ORG	0000H
    START:	ACALL	INIT		;เรียกโปรแกรมย่อยการเซตค่ารีจิสเตอร์ที่จะใช้กับการส่งข้อมูลแบบอนุกรม
        MOV	DPTR,#SHOW	;กำหนดค่าที่รีจิสเตอร์ DPTR เพื่อเริ่มต้นตำแหน่งแอดเดรสที่จะนำข้อมูล
        ACALL	DISPLAY		; ออกไปแสดงผล
        MOV	R1,#25H		;กำหนดตำแหน่งแอดเดรสเริ่มต้นของแรมภายในที่เก็บข้อมูลไว้ที่ R1
;**************** MAIN  PROGRAM *************************
    MAIN:	ACALL	RECEIVE		;เรียกโปรแกรมย่อยการรับข้อมูลจากไมโครคอมพิวเตอร์
        ACALL	SEND		; เรียกโปรแกรมย่อยการส่งข้อมูลจากไมโครคอนโทรเลอร์
        ACALL	MEM		;เรียกโปรแกรมย่อยแสดงผลข้อมูลที่รับได้ในหน่วยความจำทั้งหมด
        SJMP	MAIN		;กลับไปเริ่มต้นใหม่หลังแสดงผลที่รับได้ทั้งหมดในหน่วยความจำ
;********* ****ININITIAL REGISTER  ********************
    INIT:	MOV	IE,#00000000B		;** เป็นส่วนของโปรแกรมที่กำหนดค่าเริ่มต้นของ
        MOV	TMOD,#00100000		;**รีจิสเตอร์ที่ใช้ในการรับส่งข้อมูลแบบอนุกรม
        MOV	TL1,#0FDH		;**โดยในโปรแกรมที่เราทดลองนี้ไม่ได้ใช้การอินเตอร์รัพท์
        MOV	TH1,#0FDH		;**แต่อาศัยการตรวจสอบการเซตที่รีจิสเตอร์ RI และ TI
        MOV	SCON,#01010000B		;**จึงกำหนดให้ Reg. IE = 0 และใช้การกำหนดอัตราการ
        SETB	TR1			;**รับส่งโดยใช้ Timer 1
        RET

    MEM:	CJNE	A,#0DH,END_MEM	;ตรวจสอบว่าข้อมูลที่รับได้เป็นรหัส ASCII  " enter " หรือไม่
                    ;ถ้าไม่เป็นให้กลับไป MAIN PROGRAM และรับข้อมูลเพิ่ม ถ้าใช่ ให้นำข้อมูลทั้งหมดไปแสดงผล
        MOV	R1,#25H		;กำหนดค่าแอดเดรสเริ่มต้นของหน่วยความจำ
        SJMP	OUT_DATA	;นำไปแสดงผล
        END_MEM:	RET
; *********   แสดงผลข้อมูลที่รับได้ ***********
       OUT_DATA:	MOV	A,@R1		;นำค่าข้อมูลที่ ตำแหน่งแอดเดรสที่ชี้โดย R1
        CJNE	A,#2AH,OUT	;ถ้ารหัส ASCII ไม่เท่า  " * " ให้แสดงผลที่ OUT
        SJMP	START		;ถ้าเท่าให้กลับไปเริ่มต้นโปรแกรมใหม่
    OUT:	MOV	P1,A		;นำค่าข้อมูลจากรีจิสเตอร์ A ออกที่พอร์ต
        ACALL	DELAY
        INC	R1		;เพิ่มค่าข้อมูลที่รีจิสเตอร์ R1+ 1
        SJMP	OUT_DATA  	;กลับไปแสดงผลที่ แอดเดรสที่ชี้โดย R1 ต่อ

    SEND:	MOV	SBUF,A		;นำค่าที่รีจิสเตอร์ A ไปเก็บไว้ที่รีจิสเตอร์ SBUF
        JNB	TI,$		;ตรวจสอบการส่งข้อมูลจนบิต TI เซตแสดงว่าข้อมูลส่งหมดแล้ว
        CLR	TI		;clear TI เพื่อรอส่งข้อมูลใหม่
        RET

         RECEIVE:	JNB	RI,$ 	;ตรวจสอบการรับข้อมูลจนบิต RI เซตแสดงว่าข้อมูลรับได้หมดแล้ว
        CLR	RI	;clear RI เพื่อรอรับข้อมูลใหม่
        MOV	A,SBUF	;นำค่าที่รีจิสเตอร์ SBUF ไปเก็บไว้ที่รีจิสเตอร์  A
        MOV	@R1,A	;นำค่าที่รีจิสเตอร์ A ไปเก็บไว้ที่แอดเดรสที่ชี้โดย R1
        MOV	P1,A	;นำค่าที่รีจิสเตอร์ A ออกพอร์ต P1
        INC	R1	;เพิ่มค่าข้อมูลที่รีจิสเตอร์ R1
        RET
;***************** โปรแกรมแสดงผล  *********************
          DISPLAY:	MOV	A,#00		;
        MOVC	A,@A+DPTR	;
        ACALL	SEND		;ส่งข้อมูลไปที่ไมโครคอมพิวเตอร์
        JZ	END_SHOW	;ถ้าพบข้อมูลเป็น 00H หมายความข้อมูลที่ส่งหมดแล้ว
        INC	DPTR		;ไม่ใช่ 00H ก็ส่งค่าที่ตำแหน่งแอดเดรสถัดไป
        SJMP	DISPLAY
       END_SHOW:	RET

               DELAY:	MOV	R0,#04H
             DELAY1:	MOV	R2,#0FFH
             DELAY2:	MOV	R3,#0FFH
        DJNZ	R3,$
        DJNZ	R2,DELAY2
        DJNZ	R0,DELAY1
        RET
               SHOW:	DB	CR,LF," HELLO  7DAYS  WITH  MICROCONTROLER  ",CR,LF  ;ข้อมูลที่จะส่งครั้งแรก
        DB	"  KEY DATA  PREES  ",CR,LF				;เป็นรหัส ASCII CODE
        DB	00H	;ข้อมูลที่ใช้สำหรับตรวจสอบการหมดของข้อมูลที่จะส่ง
        END

    ** ุ ข้อสังเกตจากการทดลอง

    ในการทดลองหลังจากป้อนข้อมูลและกดคีย์ ENTER แล้ว ให้ลองถอดสาย RS232 ออกสังเกตว่าแอลอีดีจะยังแสดงผลตามข้อมูลที่เราป้อนเก็บไว้
ในหน่วยความจำแรม  แต่ถ้าหากเราทำการกดสวิตช์รีเซตจะทำให้ข้อมูลหายไปทั้งหมด   จะต้องทำการแก้ไขโดยใช้ไอซีหน่วยความจำชนิด EEPROM

    3 ขั้นตอนการโปรแกรม
            -  เมื่อเขียนโปรแกรมและเซฟเป็น LAB13.ASM แล้ว
            -  ทำการแอสแซมเบอร์โดยใช้คำสั่ง SXA51 -L LAB13.ASM
            -  เมื่อมีข้อผิดพลาดให้ทำการแก้ไขให้สมบูรณ์
            -  จากการแอสแซมเบอร์จะได้ไฟล์ LAB13.HEX และ LAB13.LST
            -  ให้นำไฟล์ที่เป็น LAB13.HEX ไปโปรแกรม
            -  โดยใช้คำสั่ง EZ LAB13.HEX -C1 (-C2 กรณีต่อกับ COM2)
            -  ทำการทดสอบโปรแกรมว่าถูกต้องตามเงื่อนไขหรือไม่

    4  ผลการทดลอง
    ทำการทดลองโดยเปิดโปรแกรม ProComm แล้วพิมพ์อะไรก็ได้ สังเกตแอลอีดีที่ต่อกับพอร์ต P1จะแสดงผลเป็น ASCII CODEโดยจะแสดง
ที่จอมอนิเตอร์ด้วย  ถ้าหากต้องการจบข้อมูลให้กดคีย์  *  แล้วกด ENTER จะทำให้ชุดทดลองทำงานตามข้อมูลที่ป้อนจนเมื่อเจอข้อมูล  2AH (*) จะทำให้โปรแกรม
จบข้อมูลแล้วกลับไปเริ่มต้นโปรแกรมใหม่

    5 สรุปผล ข้อเสนอแนะและปัญหา
      ตามโปรแกรมข้างล่างแก้ไขเพิ่มเติมถ้าหากไม่ต้องการย้อนกลับไปเริ่มต้นโปรแกรมใหม่ โดยจะทำให้มีการทำงานหมุนวนข้อมูลตามที่ป้อนให้ที่หน่วยความจำ

           OUT_DATA:	MOV	A,@R1
            CJNE	A,#2AH,OUT
            MOV	R1,#25H
            SJMP	OUT_DATA
    OUT:		MOV	P1,A
            ACALL	DELAY
            INC	R1
            SJMP	OUT_DATA


pj01

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 1  Power Supply ที่ใช้ในการทดลอง

            จากวงจรเป็นแหล่งจ่ายไฟแบบคงที่ 3 ชุดคือ 17 โวลท์ 5 โวลท์ และ 12 โวลท์ โดยการออกแบบลายวงจรจะให้อุปกรณ์ทุกชิ้นวางอยู่บนแผ่นปรินท์ทั้งหมด
    ตามคุณสมบัติของหม้อแปลง ได้เขียนในคู่มือไว้ที่ 1.3 แอมป์ที่ 13 โวลท์ ไอซี 7805 และ 7812 จะต้องควําหน้าลง เพราะจะได้ติดกับแผ่นระบายความร้อน

PCB01.zip


project02

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 2  แยกชิ้นชุดฝึกเอามาใช้งานจริงดีกว่า


pj03

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 3  สร้างและทดลอง Switch Matrixl

PCB03.zip

การทดลองและใช้งาน

    ทดสอบหาค่าคีย์โค๊ดกันก่อน

        ORG  	000H
        MOV	P1,#00H		;ให้  PORT 1 เท่ากับ 00000000B เสียก่อน
        MOV	P3,#0FFH		ทำให้ PORT 3 เป็นอินพุตต้องให้เป็น "1" เสียก่อน
    MAIN:	MOV	P3,#11111110B      	;ให้เริ่มต้น P3.0 เป็น "0" เสียก่อนเป็นแถวแรก
        MOV	A,P3		;นำค่าที่รับได้จาก PORT 3 มาเก็บไว้ที่  Reg A
        JNB	P3.3,SHOW       	;ตรวจสอบ POPT 3 ว่าบิตไหนเป็น "0" หรือไม่ถ้าใช้ให้ไปแสดงผลเพื่อดูค่า KEY CODE
        JNB	P3.4,SHOW
        JNB	P3.5,SHOW
        JNB	P3.7,SHOW
        MOV	P3,#11111101B	;ให้เลื่อนบิต  P 3.1 เป็น 0 เป็นแถวที่สอง
        MOV	A,P3
        JNB	P3.3,SHOW     	;ตรวจสอบ POPT 3 ว่าบิตไหนเป็น "0" หรือไม่ถ้าใช้ให้ไปแสดงผลเพื่อดูค่า KEY CODE
        JNB	P3.4,SHOW
        JNB	P3.5,SHOW
        JNB	P3.7,SHOW
        MOV	P3,#11111011B	;ให้เลื่อนบิต  P 3.1 เป็น 0 เป็นแถวที่สาม
        MOV	A,P3
        JNB	P3.3,SHOW 	;ตรวจสอบ POPT 3 ว่าบิตไหนเป็น "0" หรือไม่ถ้าใช้ให้ไปแสดงผลเพื่อดูค่า KEY CODE
        JNB	P3.4,SHOW
        JNB	P3.5,SHOW
        JNB	P3.7,SHOW
        SJMP	MAIN
    SHOW:	MOV	P1,P3   		;นำค่าที่ได้จากพอร์ต 3 มาแสดงผลที่ พอร์ต 1 แสดงเป็นค่า KEY CODE ของสวิตช์ตัวนั้นๆ
        SJMP	MAIN
        END

        ; *****************************************************
        ;**   	KEY MATRIX  Port 3 IN Port1 OUT	    **
        ;**      		อดิศักดิ์  ชิณะวงศ์ 		    **
        ;******************************************************

                            ORG     0000H
; ** เตรียมพอร์ตต่างๆให้พร้อมที่จะทำงาน ถ้าอินพุตก็ให้เป็น 1 เอาต์พุตก็ให้เป็น 0 **
        MOV     P1,#00H
        MOV     P3,#0FFH
        MOV     R1,#00H
        MOV     DPTR,#TABLE
        MOV     A,#00H

; **  ให้แถวที่1 เป็น "0" แล้วตรวจสอบแต่ละหลักว่าเป็น "0" ที่หลักไหนแล้วเปรียบเทียบกับค่า KEY CODE แล้วนำไปแสดงผลเป็น
;**   LOOK UP TABLE จะให้แสดงอย่างไรก็แล้วแต่ที่กำหนด  **
    SCAN:		MOV     P3,#11111110B
    SCAN_R1:        	MOV     R1,P3
    SCAN_R1C1:      	CJNE    R1,#0F6H,SCAN_R1C2
            MOV     A,#01H
            SJMP    DISPLAY

    SCAN_R1C2:      	CJNE    R1,#0EEH,SCAN_R1C3
            MOV     A,#04H
            SJMP    DISPLAY

    SCAN_R1C3:      	CJNE    R1,#0DEH,SCAN_R1C4
            MOV     A,#07H
            SJMP    DISPLAY

    SCAN_R1C4:      	CJNE    R1,#7EH,SCAN_R2
            MOV     A,#0AH
            SJMP    DISPLAY
; **  ให้แถวที่2 เป็น "0" แล้วตรวจสอบแต่ละหลักว่าเป็น "0" ที่หลักไหนแล้วเปรียบเทียบกับค่า KEY CODE แล้วนำไปแสดงผลเป็น
;**   LOOK UP TABLE จะให้แสดงอย่างไรก็แล้วแต่ที่กำหนด  **

            SCAN_R2:        	MOV     P3,#11111101B
            MOV     R1,P3

            SCAN_R2C1:      	CJNE    R1,#0F5H,SCAN_R2C2
            MOV     A,#02H
                                SJMP    DISPLAY

    SCAN_R2C2:      	CJNE    R1,#0EDH,SCAN_R2C3
                                MOV     A,#05H
            SJMP    DISPLAY

     SCAN_R2C3:      	CJNE    R1,#0DDH,SCAN_R2C4
            MOV     A,#08H
            SJMP    DISPLAY

    SCAN_R2C4:      	CJNE    R1,#7DH,SCAN_R3
            MOV     A,#00H
            SJMP    DISPLAY

; **  ให้แถวที่3 เป็น "0" แล้วตรวจสอบแต่ละหลักว่าเป็น "0" ที่หลักไหนแล้วเปรียบเทียบกับค่า KEY CODE แล้วนำไปแสดงผลเป็น
;**   LOOK UP TABLE จะให้แสดงอย่างไรก็แล้วแต่ที่กำหนด  **

           SCAN_R3:        	MOV     P3,#11111011B
            MOV     R1,P3

    SCAN_R3C1:      	CJNE    R1,#0F3H,SCAN_R3C2
            MOV     A,#03H
            SJMP    DISPLAY

    SCAN_R3C2:      	CJNE    R1,#0EBH,SCAN_R3C3
            MOV     A,#06H
            SJMP    DISPLAY

    SCAN_R3C3:      	CJNE    R1,#0DBH,SCAN_R3C4
            MOV     A,#09H
            SJMP    DISPLAY

     SCAN_R3C4:      	CJNE    R1,#7BH,SCAN
            MOV     A,#0BH
            SJMP    DISPLAY
            SJMP    SCAN

    DISPLAY:                	MOVC    A,@A+DPTR
            MOV	P1,A
    TABLE:   		DB      00H,01H,02H,03H
            DB      04H,05H,06H,07H
            DB      08H,09H,0AH,0BH
            SJMP    SCAN
            END

download  ลาย PCB และข้อมูลของ  Key Matrix


project04

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 2  LED Matrix Display

download  ลาย PCB และข้อมูลของLED Matrix


project05

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 05  ตั้งเวลา 0-99 นาที

        SW_UP		BIT	P3.0
        SW_DOWN	BIT	P3.1
        SW_OK		BIT	P3.2
        DIGIT0		BIT	P3.4
        DIGIT1		BIT	P3.5
        LED_DP		BIT	07H
        LOAD		BIT	P3.7
        RELAY		BIT	P3.3
             COUNT_200	EQU	21H
        COUNT_10	EQU	22H
        COUNT_2		EQU	23H
        SEC_60		EQU	24H
        MIN		EQU	25H

            ORG	26H
        DATA:	DS	2

        ORG	0000H
        SJMP	START
        ORG	000BH
        SJMP	INT_T0

START:		CLR	LOAD
        CLR	RELAY
        SETB	SW_UP
        SETB	SW_DOWN
        SETB	SW_OK
        MOV	MIN,#00H

MAIN:		ACALL	DATA_DIS
        ACALL	DISPLAY
        JNB	SW_UP,UP
        JNB	SW_DOWN,DOWN
        JNB	SW_OK,START_1
        SJMP	MAIN

UP:		ACALL	DELAY
        JB	SW_UP,MAIN
        MOV	R7,MIN
        CJNE	R7,#100,INC_C
        SJMP	START
INC_C:		INC	MIN
        JNB	SW_UP,$
        SJMP	MAIN

DOWN:		ACALL	DELAY
        JB	SW_DOWN,MAIN
        MOV	R7,MIN
        CJNE	R7,#00,DEC_C
        MOV	MIN,#100
        SJMP	MAIN
DEC_C:		DEC	MIN
        JNB	SW_DOWN,$
        SJMP	MAIN

START_1:		ACALL	INIT

MAIN1:		ACALL	DATA_DIS
        ACALL	DISPLAY
        SJMP	MAIN1

INIT:		MOV	P1,#0FFH
        SETB	DIGIT0
        SETB	DIGIT1
        MOV	COUNT_200,#200
        MOV	COUNT_10,#10
        MOV	COUNT_2,#2
        MOV 	TMOD,#00100010B
        MOV	TL0,#-230
        MOV	TH0,#-230
        SETB	EA
        SETB	ET0
        SETB	TR0
        RET

INT_T0:		PUSH    PSW
        DJNZ	COUNT_200,END_RETI
        MOV	COUNT_200,#200
        DJNZ	COUNT_10,END_RETI
        MOV	COUNT_10,#10
        CPL	LED_DP
        DJNZ	COUNT_2,END_RETI
        MOV	COUNT_2,#2
        DJNZ	SEC_60,END_RETI
        MOV	SEC_60,#60
        DJNZ	MIN,END_RETI
        SETB	LED_DP
        CLR 	TR0
        SETB	LOAD
        SETB	RELAY
        SETB	DIGIT0
        SETB	DIGIT1
        SJMP	$
END_RETI:	POP	PSW
        RETI

DATA_DIS:	MOV	DPTR,#TABLE
        MOV	B,#10
        MOV	A,MIN
        DIV	AB
        MOVC	A,@A+DPTR
        MOV	DATA,A
        MOV	A,B
        MOVC	A,@A+DPTR
        MOV	C,LED_DP
        MOV	ACC.7,C
        MOV	DATA+1,A
        RET

DISPLAY:		MOV	A,DATA
        MOV	P1,A
        CLR	DIGIT0
        ACALL	DELAY
        SETB	DIGIT0
        MOV	A,DATA+1
        MOV	P1,A
        CLR	DIGIT1
        ACALL	DELAY
        SETB	DIGIT1
        RET

DELAY:		MOV	R1,#200
        DJNZ	R1,$
        RET
TABLE:		DB	0C0H,0F9H,0A4H,0B0H,99H
        DB	92H,82H,0F8H,80H,90H
        END

PCB05.zip


project06

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 2  สร้างและทดลอง stepping motor control

 การทดลองเรื่อง Stepping  Motor  Control

    CJNE	(Compare and jump if Not Equai)
        คำสั่งนี้จะทำให้ซีพียูทำการกระโดดไปยังแอดเดรสปลายทาง เมื่อค่าข้อมูลที่นำมาเปรียบเทียบไม่เท่ากัน

    CJNE A, direct, rel	กำหนดให้ซีพียูกระโดดไปยังแอดเดรสปลายทางตามค่าสัมพัทธ์  (Rel) เมื่อค่าของรีจิสเตอร์ A  ไม่เท่ากับค่าในหน่วย
        ความจำข้อมูล

    ตัวอย่าง :	CJNE	A, 20H,LEFT  ; จะกระโดดไปยังตำแหน่งLEFT เมื่อค่าในรีจิสเตอร์ A ไม่เท่ากับข้อมูลในหน่วยความจำข้อมูลที่แอดเดรส 20H

    CJNE A, direct, rel		เปรียบเทียบค่าที่ Reg A กับค่าในหน่วยความจำถ้าไม่เท่ากันกระโดดไปที่ตำแหน่ง rel
    CJNE	A, #data, rel	เปรียบเทียบค่าที่ Reg A กับค่าข้อมูลคงที่ถ้าไม่เท่ากันให้กระโดดไปที่ตำแหน่ง re
    CJNE	Rn, #data, rel 	เปรียบเทียบค่าในตำแหน่งหน่วยความจำ R0-R7กับค่าข้อมูลคงที่ถ้าไม่เท่ากระโดดไปที่ตำแหน่ง rel
    CJNE @Rn, #data, rel	เปรียบเทียบค่าข้อมูลในตำแหน่งหน่วยความจำที่ชี้โดย R0-R1กับค่าคงที่ถ้าไม่เท่ากระโดดไปที่ตำแหน่ง rel

   จากรูปเราใช้แอลอีดีเป็นตัวแสดงผลแทนสเต็บปิ่งมอเตอร์เราจะเขียนแยก      การอธิบายโปรแกรมดังนี้
    ; ******************************************************************
    ; **	 PROGRAM   LAB3.ASM		                    **
    ; ** 	STEPING MOTER   CONTROL                            **
    ; ******************************************************************
                    ORG     	00H
    SW_RIGHT	BIT	P3.0
    SW_LEFT	BIT	P3.1
    SW_1PHASE 	BIT	P3.2
    SW_2PHASE	BIT	P3.3
    DATA	     	EQU        	20H

ุ 	ทำการกำหนดรูปแบบการขับเพื่อกำหนดเป็นตารางใช้สำหรับส่วน LOOK UP TABLE ดูได้จากตารางการขับแบบ 1 เฟสและ 2เฟส เราสามารถเขียน

โปรแกรมกำหนด  L1 L2 L3 L4 ได้ดังนี้

    PHASE1L: 	DB 	00001000B, 00000100B, 00000010B, 00000001B
    PHASE1R: 	DB	01H,02H,04H,08H
    PHASE2L:		DB         	00001100B, 00000110B, 00000011B, 00001001B
    PHASE2R:	DB	09H,03H,06H,0CH

    ต่อมาเรากำหนดส่วนที่เป็นสวิทช์เลือกเสียก่อนจากรูปเราสามารถนำมาเขียนโปรแกรมได้โดยขั้นตอนคือต้องเลือกการขับก่อนแล้วเลือกทิศทางการหมุน
ผลข้อมูลที่ได้นำไปกำหนดบิตที่ข้อมูลตำแหน่งแอดเดรส 20 H

SCAN_PHASE:	JNB 	SW_1PHASE,PHASE1
        JNB	SW_2PHASE,PHASE2
        SJMP	SCAN_PHASE

PHASE1:		CLR	06H
        SETB	07H         ; ADDR 20H
        MOV	P1,20H
        SJMP	SCAN_DIR

ุ 	ตรวจสอบทิศทางการหมุนของมอเตอร์

SCAN_DIR:	JNB	SW_1PHASE,SCAN_PHASE
        JNB	SW_2PHASE,SCAN_PHASE
        JNB	SW_LEFT,LEFT
        JNB	SW_RIGHT,RIGHT
        SJMP	SCAN_DIR
            .
            .
LEFT:		CLR	04H
        SETB	05H       		;ADDR 20H
        SJMP	DIS_1LEFT	;เรียกโปรแกรมย่อย DIS_1LEFT เพื่อกำหนดค่าเริ่มต้นให้กับ รีจีสเตอร์  DPTR

;**********************   1 PHASE LEFT***************************
    DIS_1LEFT:	MOV	A,#10100000B
            CJNE	A,DATA,DIS_2LEFT
            MOV	DPTR,#PHASE_1L
            SJMP	DISP_MOTOR

ุ นำข้อมูลออกพอร์ตโดยการนำข้อมูลจาก LOOK UP TABLE คือ ที่ตำแหน่งแอดเดรสที่ PHASE_1L จากคำสั่ง MOV A,@A+DPTR โดยนำข้อมูลที่ได้ที่อยู่ใน
รีจิสเตอร์ A มาทำการ OR กับข้อมูลที่ DATA หรือข้อมูลที่แอดเดรส 20H  ORL A, DATA   (หัวโปรแกรม DATA     EQU      20H )

        ;****  DISPLAY & MOTOR DRIVE   ****
    DISP_MOTOR:	MOV	R0,#04H
            MOV	R1,#00H
            MOV	A,#00H
               LOOP:		MOV	A,R1
            MOVC	A,@A+DPTR
            ORL	A,DATA

ุ เอาหล่ะ!  มาเขียนโปรแกรมใช้งานจริงๆกันดีกว่า

                                ORG   00H

                                SETB    P3.4
                                SETB    P3.5
                                SETB    P3.6
                                SETB    P3.7

        MOV	P1,#00000000B
        MOV	20H,#00000000B
                                CLR     	A

;**********************  SELECT PHASE ****************************

        SCAN_PHASE:        	JNB      	P3.0,PHASE1
                                   JNB      	P3.1,PHASE2
                                   SJMP     	SCAN_PHASE

    PHASE1:		MOV     	20H,#00H
            CLR     	02H
            SETB    	03H
            MOV	P1,20H
            SJMP	SCAN_DRI

        PHASE2:                 	MOV	20H,#00H
            CLR     	03H
            SETB    	02H
            MOV	P1,20H
            SJMP	SCAN_DRI

    ;**************************************************************************
        SCAN_DRI:              	JNB     P3.0,SCAN_PHASE
            JNB     P3.1,SCAN_PHASE
            JNB     P3.2,LEFT
            JNB     P3.3,RIGHT
            SJMP    SCAN_DRI

        LEFT:			CLR     	00H
            SETB    	01H
            MOV	P1,20H
            SJMP	DIS_1LEFT

        RIGHT		CLR     	01H
            SETB   	00H
            MOV	P1,20H
            SJMP	DIS_1RIGHT

        ;**********************   1 PHASE LEFT***************************
        DIS_1LEFT:             	MOV     	A,#00001010B
            CJNE	A,20H,DIS_2LEFT
            MOV	DPTR,#PHASE_1L
            SJMP	DISP_MOTOR

        ;**********************   1 PHASE  RIGHT**************************
        DIS_1RIGHT:		MOV     	A,#00001001B
            CJNE	A,20H,DIS_2RIGHT
            MOV	DPTR,#PHASE_1R
            SJMP	DISP_MOTOR

        ;**********************  2 PHASE  LEFT****************************
        DIS_2LEFT:		MOV     	A,#00000110B
            CJNE	A,20H,SCAN_PHASE
            MOV	DPTR,#PHASE_2L
            SJMP	DISP_MOTOR

        ;*********************   2 PHASE  RIGHT **************************
        DIS_2RIGHT:		MOV     	A,#00000101B
            CJNE	A,20H,SCAN_PHASE
            MOV	DPTR,#PHASE_2R
            SJMP	DISP_MOTOR

                 ;******************* DISPLAY & MOTOR DRIVE **********************

        DISP_MOTOR:		MOV     	R0,#04H
            MOV	R1,#00H
            MOV	A,#00H
    LOOP:		MOV     	A,R1
            MOVC	A,@A+DPTR
            ORL     	A,20H
            MOV	P1,A
            ACALL   	DELAY
            INC     	R1
            JNB     	P3.0,SCAN_PHASE
            JNB     	P3.1,SCAN_PHASE
            JNB     	P3.2,LEFT
            JNB     	P3.3,RIGHT
            DJNZ	R0,LOOP
            SJMP	DISP_MOTOR

        DELAY_D:		MOV     	R4,#0FFH
            DJNZ	R4,$
            RET

        DELAY:                          	MOV     	R5,#0H
        DELAY1:		MOV     	R6,#07H
            DJNZ	R6,$
            DJNZ	R5,DELAY1
            RET

    PHASE_1L:	DB	80H,40H,20H,10H
    PHASE_1R:	DB	10H,20H,40H,80H
    PHASE_2L:	DB	0C0H,60H,30H,90H
    PHASE_2R:	DB	90H,30H,60H,0C0H

                                        END

download  ลาย PCB Mainboard


project07

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 07  สร้างเครื่องโปรแกรม AT89C51 AT89C52 AT89C53

download  ลาย PCB Mainboard


project08

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 08  ควบคุมเครื่องใช้ไฟฟ้าผ่านพอร์ตอนุกรม

โปรแกรมไอซีAT89C2051

;*************************************************************************
;****    	Computer PC & MCS51 control  RS232 port	         ***
;****             http:// www.geocities.com/adisak_51	            ***
;*************************************************************************

    CR	EQU	0DH		;Carriage return
    LF	EQU	0AH		;Line  feed
        ORG       25H
DATA:		DS	50H		;Start  data  address  25h
        ORG	0000H
NEW_START:	MOV	P1,#00H		;P1 = 00000000B

START:		ACALL	INIT		;ทำการเซตค่าเริ่มต้นของส่วนที่ติดต่อกับพอร์ตอนุกรม
        MOV	DPTR,#SHOW	;กำหนดค่า DPTR =แอดเดรสของ SHOW
        ACALL	DISPLAY		;ทำส่วนแสดงผลการติดต่อที่หน้าจอ
        MOV	R1,#25H		;R1= 25H เป็นค่าแอดเดรสเริ่มต้น

MAIN:		ACALL	RECEIVE		;เรียกโปรแกรมรับข้อมูลจาก พอร์ต RS232
        ACALL	SEND		;ส่งข้อมูลที่รับได้ไปแสดงที่หน้าจอคอมพิวเตอร์ด้วย
        SJMP	MAIN		;วนกลับไปรับข้อมูลต่อไปอีก

;************  กำหนดค่าต่างๆ ในการติดต่อกับพอร์ตอนุกรม ************
INIT:		MOV	IE,#00000000B
        MOV	TMOD,#00100000B
        MOV	TL1,#0FDH
        MOV	TH1,#0FDH
        MOV	SCON,#01010000B
        SETB	TR1
        RET

OUT_DATA:	MOV	A,@R1
        CJNE	A,#2BH,ADD	;ข้อมูลมีค่าเท่ากับ "+" ถ้าไม่เท่าให้แสดงข้อมูลต่อไป
        MOV	R1,#28H		;R1 มีค่าเท่ากับ 28H  เพื่อกำหนดแอดเดรสเริ่มต้นใหม่
        SJMP	OUT_DATA	;ถ้าข้อมูลมีค่าเท่ากับ "+" ให้วนทำข้อมูลเดิมใหม่
ADD:		MOV	P1,A		;ถ้าข้อมูลมีค่าไม่เท่ากับ "+" ให้แสดงผลค่าต่อไป
        ACALL	DELAY
        INC	R1
        ACALL 	CHEAK
        SJMP	OUT_DATA

MUL:		DEC	R1
        MOV	20H,@R1
MUL_1:		MOV	P1,20H
        ACALL 	CHEAK
        SJMP	MUL_1
CHEAK:		PUSH	ACC
        MOV	A,SBUF
        CLR	RI
        CJNE	A,#00011011B,RET_CHEAK
        ACALL	CLEAR
        SJMP	NEW_START
RET_CHEAK:	POP	ACC
        RET
CLEAR:		MOV	R5,#50H
        MOV	R0,#25H
CLEAR_1:	MOV	@R0,#00H
        INC	R0
        DJNZ	R5,CLEAR_1
        RET

;**********  ส่งค่าข้อมูลจาก MCS51 ไปที่ RS232 *********
SEND:		MOV	SBUF,A
        JNB	TI,$
        CLR	TI
        RET

;**********  รับค่าข้อมูลจาก RS232 เข้ามาที่ MCS51 *********
RECEIVE:	JNB	RI,$
        CLR	RI
        MOV	A,SBUF
        MOV	@R1,A
        MOV	P1,A
        CJNE	A,#0DH,END_RECE		; "ENTER"ให้ไปตรวจสอบว่าเป็นคีย์ " *, + ,ESC "
        ACALL	CHEAK_KEY
END_RECE:	INC	R1
        RET

CHEAK_KEY:	DEC	R1
        MOV	A,@R1
        CJNE	A,#2BH,MUL_KEY		; ไม่เท่ากับเครื่องหมาย "+"ให้ไปตรวจสอบว่าเป็นคีย์ " * "
        MOV	R1,#28H
        SJMP	OUT_DATA		;มีค่าเท่ากับ"+"เรียกโปรแกรมย่อยการนำข้อมูลออกพอร์ต

MUL_KEY:	CJNE	A,#2AH,ESC_KEY		;ตรวจสอบว่าเป็นคีย์ "* " หรือไม่ ถ้าเป็นไป MUL
        SJMP	MUL

ESC_KEY:	CJNE	A,#1BH,END_CHEAK	;ตรวจสอบว่าเป็นคีย์ "ESC " หรือไม่
        ACALL	CLEAR
        AJMP	NEW_START

END_CHEAK:	INC	R1
        RET

    ;*******  ค่าที่แสดงหน้าจอเริ่มต้นการติดต่อ ********
DISPLAY:		MOV	A,#00
        MOVC	A,@A+DPTR
        ACALL	SEND
        JZ	END_SHOW
        INC	DPTR
        SJMP	DISPLAY
END_SHOW:	RET

DELAY:		MOV	R4,25H
DELAY2:		MOV	R2,26H
DELAY1:		MOV	R3,27H
        DJNZ	R3,$
        DJNZ	R2,DELAY1
        DJNZ	R4,DELAY2
        RET

SHOW:		DB	CR,LF," HELLO  7DAYS  WITH  MICROCONTROLER  ",CR,LF
        DB		     "        Design  by  http://www.geocities.com/adisak_51       ",CR,LF
        DB		00H
        END

    นำโปรแกรม MAK01.EXE เปิดใช้งาน ส่วนโปรแกรมที่เหลืออีก 2 ไฟล์ COPY ไว้ที่ C:\WINDOWS\SYSTEM

    ขั้นตอนการใช้งานของโปรแกรม

    1 	เลือกที่ปุ่ม เลือกพอร์ต กำหนดพอร์ตที่ปุ่มเลือกพอร์ต COM1 หรือ COM2 แล้วคลิกที่เมาส์
    2 	เลือกที่ปุ่ม บิต/วินาที กำหนดค่า  Baud ret เป็น 9600 BPS แล้วคลิกที่เมาส์
    3 	เลือกที่ปุ่มชุดสวิตช์ หรือ ชุดข้อมูล ว่าจะ เปิด-ปิดเครื่องใช้ไฟฟ้า หรือทำไฟวิ่ง
    4 	หลังจากนั้นทำการกดปุ่มรีเซตที่บอร์ดจะแสดงผลเป็นข้อมูลแนะนำที่หน้าจอคอมพิวเตอร์
    5 	ถ้าเลือกใช้งานไฟวิ่ง ให้กำหนดจำนวนชุดที่จะส่งออกว่ามีจำนวนเท่าไร ใช้เมาส์คลิกเลือกช่องจำนวนข้อมูล โดยโปรแกรมกำหนด
         การป้อนข้อมูลได้ไม่เกิน  80  ค่า และใช้เมาส์คลิกที่ช่องอินพุต แล้วป้อนข้อมูล จะแสดงผลข้อมูลและลำดับที่ป้อนจนครบจำนวน
         โปรแกรมจะแจ้งสิ้นสุดการป้อนโปรแกรมให้เอง ให้คลิกที่ปุ่ม ส่งออก เลือกที่ปุ่มแสดงผล
    6 	เลื่อนแถบปรับความเร็ว หากต้องการแก้ไขข้อมูลหลังจากทดลองที่แสดงผลที่หน้าจอ (ยังไม่ส่งออกพอร์ตRS232) แล้วให้เลือกที่ปุ่ม แก้ไขข้อมูล
        แล้วเลือกลำดับที่จะแก้ไข และจะแก้เป็นค่าเท่าใด หลังจากแก้ข้อมูลเสร็จแล้วให้เลือกที่ปิดการแก้ไข
    7 	หลังจากพอใจในเวลาและรูปแบบแล้วให้เลือกที่ปุ่ม ส่งออก แล้วเลือก ปุ่มออกพอร์ต RS232
    8 	ถ้าต้องการแก้ไขข้อมูลบางตำแหน่งและความเร็ว ให้เลือกปุ่ม แก้ไขความเร็ว แถบความเร็วจะกำหนดให้มีความเร็วมากที่สุด  ต้องเลือนแถบปรับ
        ความเร็วใหม่ทุกครั้ง แล้วส่งออกเหมือนข้อที่ 5 และข้อที่ 6
    9	ถ้าต้องการแก้ไขใหม่ทั้งหมดหลังจากส่งข้อมูลออกพอร์ต RS232 ไปแล้วให้เลือกที่ปุ่มล้างข้อมูลเดิม โปรแกรมจะเริ่มทำงานใหม่ สังเกตได้จาก
        แอลอีดีทุกตัวจะต้องดับ ถ้าดับไม่หมดให้กดปุ่มล้างข้อมูลซ้ำอีกครั้ง
    10	ถ้าต้องการเลือกใช้งานปิด-เปิด เครื่องใช้ไฟฟ้า ใช้เมาส์คลิกที่ ปุ่มล้างข้อมูลเดิม ก่อนแล้วไปที่ปุ่มชุดสวิตช์  สังเกตได้จากแอลอีดีทุกตัวจะต้องดับ
        ให้เลือกว่าจะเปิดหรือปิดตำแหน่งไหน หลังจากเลือกหมดแล้วให้คลิกที่ปุ่ม บันทึก แล้วออกจากโปรแกรมสวิตช์โดยกดที่ปุ่ม ปิดชุดสวิตช์
    11 	หากโปรแกรมหรือบอร์ดเกิดข้อผิดพลาด ให้เลือกปุ่มแก้ไขความเร็ว ปรับความเร็วใหม่ แล้วให้ส่งออกที่พอร์ต RS232 อีกครั้ง ถ้าหากไม่ได้ผล
        ให้กดที่ปุ่มรีเซตของบอร์ดจะใช้งานได้ปกติ
    12	หลังจากที่โปรแกรมเสร็จแล้วให้ถอดสาย RS232ออกได้ ข้อมูลจะยังคงอยู่ที่บอร์ด หากต้องการแก้ไขสามารถนำสายมาต่อ แล้วส่งข้อมูลใหม่ได้

download โปรแกรมทดลอง


project09

 108 Project

                                สร้างและทดลองโดย...อดิศักดิ์  ชิณะวงศ์
       Project 09  กดเปิด - กดปิดควบคุมเครื่องใช้ไฟฟ้า 5 ช่อง

            ; **************************************************************
            ; ** 		JOB 09.ASM  	                   **
            ; **************************************************************
                    ORG	000H
        LOAD_1        	BIT    P1.0   ; กำหนดให้ LOAD_1 เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT1.0
        LOAD_2        	BIT    P1.1   ; กำหนดให้ LOAD_2 เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT1.1
        LOAD_3        	BIT    P1.2   ; กำหนดให้ LOAD_3 เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT1.2
        LOAD_4        	BIT    P1.3   ; กำหนดให้ LOAD_4 เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT1.3
        LOAD_5        	BIT    P1.4   ; กำหนดให้ LOAD_5 เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT1.4
        STROBE	   	BIT    P1.5   ; กำหนดให้ สัญญาณ SIG_STROBE เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT1.5
        SW_CONT1   	BIT    P3.0   ; กำหนดให้ SW_CONT1  เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT P3.0
        SW_CONT2   	BIT    P3.1   ; กำหนดให้ SW_CONT2  เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT P3.1
        SW_CONT3   	BIT    P3.2   ; กำหนดให้ SW_CONT3  เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT P3.2
        SW_CONT4   	BIT    P3.3   ; กำหนดให้ SW_CONT4  เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT P3.3
        SW_CONT5   	BIT    P3.4   ; กำหนดให้ SW_CONT5  เป็นชื่อของตำแหน่งขาที่ต่อกับ PORT P3.4

        MOV	P3,#0FFH		       ;กำหนดให้เป็นอินพุตต้องให้ลอจิก "1"ที่ขาพอร์ต
        MOV	P1,#00H 		       ;กำหนดให้พอร์ต 1 เป็นลอจิก "0"ทุกขา
    SW_1:	JNB     SW_CONT1,CHK_LOAD1   ;ตรวจสอบบิต P3.0 ว่าเป็น "0" หรือไม่ ถ้าเป็นให้กระโดดไปที่เลเบลชื่อ CHK_LOAD1
    SW_2: 	JNB     SW_CONT2,CHK_LOAD2   ;ตรวจสอบบิต P3.1 ว่าเป็น "0" หรือไม่ ถ้าเป็นให้กระโดดไปที่เลเบลชื่อ CHK_LOAD2
    SW_3: 	JNB     SW_CONT3,CHK_LOAD3   ;ตรวจสอบบิต P3.2 ว่าเป็น "0" หรือไม่ ถ้าเป็นให้กระโดดไปที่เลเบลชื่อ CHK_LOAD3
    SW_4: 	JNB     SW_CONT4,CHK_LOAD4   ;ตรวจสอบบิต P3.3 ว่าเป็น "0" หรือไม่ ถ้าเป็นให้กระโดดไปที่เลเบลชื่อ CHK_LOAD4
    SW_5: 	JNB     SW_CONT5,CHK_LOAD5   ;ตรวจสอบบิต P3.4 ว่าเป็น "0" หรือไม่ ถ้าเป็นให้กระโดดไปที่เลเบลชื่อ CHK_LOAD5
        SJMP   SW_1		       ;ไปเริ่มต้นวนการตรวจสอบการกดคีย์ใหม่

    CHK_LOAD1:	ACALL 	DELAY_D 	;เรียกโปรแกรมย่อย DELAY_D เพื่อหน่วงเวลาแล้วตรวจว่ากดจริงหรือไม่
            JB    	SW_CONT1,SW_2 	; ตรวจสอบบิต P3.0 อีกครั้งว่าเป็นกดจริงหรือไม่  ถ้าไม่เป็นจริงให้กระโดดไปที่  SW_2
               CPL	LOAD_1 	       	;จากคำสั่งข้างบนถ้าเงื่อนไขเป็นจริงให้กลับสถานะของบิต P1.0 (LOAD_1)
                            ACALL	SIG_STROBE	;เรียกสัญญาณ SIG_STROBE ให้เกิดที่ขา P1.5
            JNB 	SW_CONT1,$ 	;ตรวจสอบการปล่อยคีย์ถ้าไม่ปล่อยให้วนที่เดิม ($ ทำวนที่บรรทัดเดิม)
                            SJMP  	SW_2		;กระโดดกลับไปที่ เลเบล SW_2 หากมีการปล่อยคีย์แล้ว

    CHK_LOAD2:	ACALL 	DELAY_D 	;เรียกโปรแกรมย่อย DELAY_D เพื่อหน่วงเวลาแล้วตรวจว่ากดจริงหรือไม่
            JB    SW_CONT2,SW_3 	; ตรวจสอบบิต P3.1 อีกครั้งว่าเป็นกดจริงหรือไม่  ถ้าไม่เป็นจริงให้กระโดดไปที่  SW_3
            CPL 	LOAD_2 	       	;จากคำสั่งข้างบนถ้าเงื่อนไขเป็นจริงให้กลับสถานะของบิต P1.1 (LOAD_2)
                            ACALL	SIG_STROBE	;เรียกสัญญาณ SIG_STROBE ให้เกิดที่ขา P1.5
            JNB 	SW_CONT2,$ 	;ตรวจสอบการปล่อยคีย์ถ้าไม่ปล่อยให้วนที่เดิม ($ ทำวนที่บรรทัดเดิม)
                            SJMP  	SW_3		;กระโดดกลับไปที่ เลเบล SW_3 หากมีการปล่อยคีย์แล้ว

    CHK_LOAD3:	ACALL 	DELAY_D 	;เรียกโปรแกรมย่อย DELAY_D เพื่อหน่วงเวลาแล้วตรวจว่ากดจริงหรือไม่
            JB    SW_CONT3,SW_4 	; ตรวจสอบบิต P3.2 อีกครั้งว่าเป็นกดจริงหรือไม่  ถ้าไม่เป็นจริงให้กระโดดไปที่  SW_4
            CPL 	LOAD_3 	       	;จากคำสั่งข้างบนถ้าเงื่อนไขเป็นจริงให้กลับสถานะของบิต P1.2 (LOAD_3)
                            ACALL	SIG_STROBE	;เรียกสัญญาณ SIG_STROBE ให้เกิดที่ขา P1.5
            JNB 	SW_CONT3,$ 	;ตรวจสอบการปล่อยคีย์ถ้าไม่ปล่อยให้วนที่เดิม ($ ทำวนที่บรรทัดเดิม)
                            SJMP  	SW_4		;กระโดดกลับไปที่ เลเบล SW_4 หากมีการปล่อยคีย์แล้ว

    CHK_LOAD4:	ACALL 	DELAY_D 	;เรียกโปรแกรมย่อย DELAY_D เพื่อหน่วงเวลาแล้วตรวจว่ากดจริงหรือไม่
            JB    SW_CONT4,SW_5 	; ตรวจสอบบิต P3.3 อีกครั้งว่าเป็นกดจริงหรือไม่  ถ้าไม่เป็นจริงให้กระโดดไปที่  SW_5
            ACALL	SIG_STROBE	;เรียกสัญญาณ SIG_STROBE ให้เกิดที่ขา P1.5
            CPL 	LOAD_4 	       	;จากคำสั่งข้างบนถ้าเงื่อนไขเป็นจริงให้กลับสถานะของบิต P1.3 (LOAD_4)
                            JNB 	SW_CONT4,$ 	;ตรวจสอบการปล่อยคีย์ถ้าไม่ปล่อยให้วนที่เดิม ($ ทำวนที่บรรทัดเดิม)
                            SJMP  	SW_5		;กระโดดกลับไปที่ เลเบล SW_5 หากมีการปล่อยคีย์แล้ว

    CHK_LOAD5:	ACALL 	DELAY_D 	;เรียกโปรแกรมย่อย DELAY_D เพื่อหน่วงเวลาแล้วตรวจว่ากดจริงหรือไม่
            JB    SW_CONT5,SW_1 	; ตรวจสอบบิต P3.4 อีกครั้งว่าเป็นกดจริงหรือไม่  ถ้าไม่เป็นจริงให้กระโดดไปที่  SW_1
            CPL 	LOAD_5 	       	;จากคำสั่งข้างบนถ้าเงื่อนไขเป็นจริงให้กลับสถานะของบิต P1.4 (LOAD_5)
                            ACALL	SIG_STROBE	;เรียกสัญญาณ SIG_STROBE ให้เกิดที่ขา P1.5
            JNB 	SW_CONT5,$ 	;ตรวจสอบการปล่อยคีย์ถ้าไม่ปล่อยให้วนที่เดิม ($ ทำวนที่บรรทัดเดิม)
                            SJMP  	SW_1		;เริ่มต้นกระโดดกลับไปทำที่ เลเบล SW_1 ใหม่หากมีการปล่อยคีย์แล้ว

    ;******* STROBE  SIGNAL ********
    SIG_STROBE:	SETB 	STROBE
            ACALL 	DELAY_D
            CLR	STROBE
            RET

    ;******** DELAY DEBOUNCE ********
       DELAY_D: 	MOV R1,#90H 	  ;ส่วนของโปรแกรมย่อยหน่วงเวลาเพื่อทดสอบว่าเป็นการกด สวิตช์จริงหรือไม่
       DELAY_1: 	MOV R2,#0FFH
            DJNZ R2,$
            DJNZ R1,DELAY_1
            RET


project10

108 Project
สร้างและทดลองโดย...อดิศักดิ์ ชิณะวงศ์ [image] Project 10 โซลิสเตทรีเลย์ 8 ช่อง
download pcb


http://www.geocities.com/adisak_51/lab1.html