Chuyên trang chia sẻ kiến thức về PIC, AVR. Các bản vẽ Proteus dành cho PIC. Hướng dẫn học PIC.







T0_ISR:
CPL P1.5
RETI
E0_ISR:
INC R7 ; tăng R7 lên 1
CJNE R7,#20,TIEP ; so sánh R7 với 20, nếu chưa bằng thì nhảy tới nhản TIEP còn nếu bằng rồi thì gọi chương trình TIEPTUC
ACALL TIEPTUC ; gọi chương trình TIEPTUC
TIEP: CJNE R7,#40,TIEP1 ; so sánh R7 với 40
ACALL TIEPTUC ; gọi chương trình tiếp tục
TIEP1: CJNE R7,#60,TIEP2 ; so sánh R7 với 60
ACALL TIEPTUC ; gọi chương trình TIEPTUC
TIEP2: CJNE R7,#80,TIEP3 ; so sánh R7 với 80
ACALL TIEPTUC ; gọi chương trình TIEPTUC
TIEP3: CJNE R7,#100,EXIT ; so sánh R7 với 100
MOV R7,#0 ; xóa R7 về 0
ACALL TIEPTUC ; gọi chương trình TIEPTUC
EXIT: RETI ; quay về từ ngắt
Trong chương trình TIEPTUC chúng ta sẻ cho dừng băng truyền nhưng ở đây mình chỉ làm mô phỏng nên mình thay cái động cơ điều khiển băng truyền là một con led khi led sáng thì báo hiệu là đang dừng băng truyền. Trong main chúng ta nạp các giá trị ban đầu cho phép ngắt và tách số BCD rồi hiển thị lên LED dùng phương pháp quét led ( nói sơ qua về phương pháp quét led cho một số bác chưa biết hiểu: chúng ta nối các chân a,b,c,d,e,f,g,dp của led chục và led đơn vị lại với nhau, và ta gửi tín hiệu ra led để hiển thị giá trị cần hiển thị và dĩ nhiên là nếu chúng ta cho phép cả hai led thì cả hai led đều hiển thị một số, cho nên trong một lúc chúng ta chỉ cho phép một led sáng. Ví dụ khi muốn hiển thị số 15 thì ta cần led chục hiển thị số 1 còn led đơn vị hiển thị số 5 vậy thì đầu tiên ta gửi tín hiệu cho sáng số 1 rồi tắt led đơn vị và cho phép led chục, delay một khoảng thời gian rồi gửi tiếp tín hiệu cho sáng số 5 rồi tắt led chục và cho phép led đơn vị) quét led nghĩa là cho trong một trạng thái chỉ có một led được sáng cứ như thế led chục sáng số 1 và tắt led đơn vị, delay một khoảng thời gian rồi tắt led chục và cho led đơn vị sáng số 5 rồi delay một khoảng thời gian, tốc độ sáng led là khoảng 24hình/s như thế thì mắt chúng ta có không thể nhận biết được sự thay đổi đó và có cảm giác là nó đang hiển thị số 15. Giải thuật tách số đếm trong R7 như thế này: chúng ta nạp cho B một giá trị là 10 và lấy R7 chuyển vào A rồi lấy A chia cho B như thế phần nguyên sẻ nằm trong A ( tức là số chục lưu trong A ) còn phần dư nằm trong B ( tức là số đơn vị nằm trong B), như vậy là ta đã tách được số chục và số đơn vị ra, chúng ta chuyển số hàng chục ra port0 rồi cho led chục tích cực và tắt led đơn vị, rồi chuyển B và A rồi xuất nó ra port0 và cho phép led đơn vị sáng và tắt led chục.ORG 0000H ; điểm vào reset
LJMP MAIN ; gọi chương trình chính
ORG 000BH ; vecter timer 0
LJMP T0_ISR ; gọi chương trình ngắt timer 0
ORG 0003H ; vecter ngắt ngoài 0
LJMP E0_ISR ; gọi chương trình ngắt ngoài 0
ORG 001BH ; vecter timer 1
LJMP T1_ISR ; gọi chương trình ngắt timer 1
ORG 0030H ; điểm vào chương trình chính
MAIN: MOV TMOD, #12H ; timer 0 chế độ 2 và timer 1 chế độ 1
MOV TH0,#(-13) ; sau 13 Ms thì xảy ra ngắt timer 0 ( tần số 38Khz)
SETB TR0 ; cho phép timer 0 chạy
SETB EA ; cho phép ngắt toàn bộ
SETB ET0 ; cho phép ngắt timer 0
SETB EX0 ; cho phép ngắt ngoài
SETB IT0 ; ngắt cạnh xuống
CLR P1.4 ; xóa p1.4 về 0 (tắt led báo hiệu dừng băng truyền)
MOV R7,#0 ; nạp cho R7 giá trị ban đầu (R7 chứa số đếm)
MOV R5,#50 ; nạp cho R5 giá trị 50 (mục đích tạo khoảng thời gian để ngừng băng truyền)
LOOP: MOV A,R7 ; chuyển số đếm trong R7 vào A
MOV B,#10 ; nạp cho B giá trị 10
DIV AB ; chia A cho B
MOV DPTR,#LUT ; chỉ con trỏ DPTR vào bảng LUT
MOVC A,@A+DPTR ;chuyển giá trị đã chọn trong bảng LUT vào thanh ghi tích lũyA
MOV P0,A ; xuất A ra port 0
CLR P1.7 ; cho phép led chục sáng
SETB P1.6 ; tắt led đơn vị
ACALL DELAY ; gọi chương trình delay
MOV A,B ; chuyển B vào A
MOV DPTR,#LUT ; chỉ con trỏ DPTR vào bảng LUT
MOVC A,@A+DPTR ;chuyển giá trị đã chọn trong bảng LUT vào thanh ghi tích lũyA
MOV P0,A ; xuất A ra port 0
CLR P1.6 ; cho phép led đơn vị sáng
SETB P1.7 ; tắt led chục
ACALL DELAY ; gọi chương trình delay
SJMP LOOP ; quay lại chương trình chính
RET
T0_ISR: CPL P1.5 ; đảo trạng thái p1.5 ( mục đích tạo xung vuông )
RETI ; quay lại từ ngắt
E0_ISR: INC R7 ; tăng R7 lên 1
CJNE R7,#20,TIEP ; so sánh R7 với 20, nếu chưa bằng thì nhảy tới nhản TIEP còn nếu bằng rồi thì gọi chương trình TIEPTUC
ACALL TIEPTUC ; gọi chương trình TIEPTUC
TIEP: CJNE R7,#40,TIEP1 ; so sánh R7 với 40
ACALL TIEPTUC ; gọi chương trình tiếp tục
TIEP1: CJNE R7,#60,TIEP2 ; so sánh R7 với 60
ACALL TIEPTUC ; gọi chương trình TIEPTUC
TIEP2: CJNE R7,#80,TIEP3 ; so sánh R7 với 80
ACALL TIEPTUC ; gọi chương trình TIEPTUC
TIEP3: CJNE R7,#100,EXIT ; so sánh R7 với 100
MOV R7,#0 ; xóa R7 về 0
ACALL TIEPTUC ; gọi chương trình TIEPTUC
EXIT: RETI ; quay về từ ngắt
DELAY: MOV R6,#200
DJNZ R6,$
RET ; 3 dòng lệnh này là delay 400Ms
TIEPTUC: SETB P1.4 ; cho đèn sáng ( báo hiệu dừng băng truyền )
SETB ET1 ; cho phép ngắt timer 1
MOV TH0,#HIGH(-50000)
MOV TL0,#LOW(-50000) ; hai dòng lệnh này là nạp giá trị cho timer 1 ( sau 50000 Ms thì xảy ra ngắt timer 1)
SETB TR1 ; cho timer 1 chạy
RET ; kết thúc chương trình tiếp tục
T1_ISR: DJNZ R5,THOAT ; giảm R5 đi 1 và so sánh nó với 0 nếu chưa bằng 0 thì thoát còn nếu bằng 0 thì lằm tiếp
CLR P1.4 ; tắt đèn ( báo hiệu cho băng truyền hoạt động trở lại )
CLR ET1 ; cấm ngắt timer 1
CLR TR1 ; dừng timer 1
MOV R5,#50 ; nạp lại cho R5 giá trị 50
THOAT: RETI ; trở về từ ngắt
LUT: DB 03H,9FH,25H,0DH,99H,49H,41H,1FH,01H,09H
END