View Single Post
Old 24-05-2005, 04:16 AM   #4
falleaf
PIC Bang chủ
 
falleaf's Avatar
 
Tham gia ngày: May 2005
Bài gửi: 2,631
:
Send a message via Yahoo to falleaf
Thế là các bạn biết lập trình cho PIC

Một điểm lưu ý cuối cùng là các bạn phải sử dụng phím TAB để phân cách các cột của một chương trình viết bằng MPASM. Các dòng khởi tạo này được viết ở cột thứ 3. Các directive __CONFIG, TITLE, PROCESSOR, INCLUDE được viết vào cột thứ 3. Còn chi tiết khởi tạo được viết vào cột thứ tư.

Cột thứ nhất dùng để viết các [NHÃN], cột thứ hai để viết mã lệnh, cột thứ ba lại dùng để viết chi tiết các tham số của lệnh, và cột thứ tư bỏ trống để tạo khoảng cách với cột thứ năm. Cột thứ năm dùng để viết các chú thích.

Các chú thích bắt đầu bằng dấu chấm phẩy (. Trên một dòng, tất cả các ký tự viết sau dấu chấm phẩy đều vô nghĩa. Chính vì vậy, khi viết phần chú thích ban đầu, các bạn thấy rằng tất cả nội dung đó đều bắt đầu bằng dấu chấm phẩy. Như vậy, một dòng lệnh được cụ thể như sau:
Code:
NHÃN		LỆNH	thamso1,	thamso2		; chú thích dòng lệnh
Bây giờ chúng ta dành chút thời gian cho lý thuyết, các bạn mở datasheet PIC16F628A trang 15, Section 4. Memory Organization

Chúng ta sẽ thấy rằng tổ chức bộ nhớ chương trình của PIC được chia ra làm mấy phần như sau:

- Pointer
- Stack
- Interrupt vector
- Program memory

Chúng ta tạm thời chưa bàn đến pointer và stack.

Interrupt vector được đặt ở địa chỉ 0x0004
Program memory được đặt ở địa chỉ 0x0005

Vậy từ địa chỉ 0x0000 đến địa chỉ 0x0003 chúng ta làm được gì?

Khi PIC được reset, nó lập tức nhảy về địa chỉ 0x0000. Rồi cứ sau một chu kỳ máy, nó nhảy đến địa chỉ tiếp theo, xem xem trong địa chỉ đó yêu cầu nó làm gì, nó thực hiện việc đó, xong rồi lại nhảy tiếp. Cứ làm như thế cho đến khi hết chương trình. Tất nhiên, khi chúng ta thực hiện một số lệnh điều khiển vị trí nhảy, thì nó sẽ nhảy không theo thứ tự nữa, nhưng việc này chưa bàn vội. Chúng ta trước mắt chỉ cần biết rằng nó cứ nhảy như vậy cho đến hết chương trình.

Như vậy, nếu không sử dụng ngắt, thì chúng ta viết chương trình từ địa chỉ 0x0000 luôn, vì nó cứ thế là nhảy từ 0x0000 khi khởi động, cho đến hết chương trình. Tuy nhiên, nếu làm như vậy, sau này chúng ta sử dụng chương trình ngắt, thì chúng ta sẽ gặp trục trặc vì thói quen viết từ địa chỉ 0x0000.

Chính vì vậy, chúng ta nên đặt chương trình trong phần Program Memory như ý đồ thiết kế PIC.

Vậy, chương trình của chúng ta sẽ viết như sau:
Code:
;====================================================================
		ORG	0x0000
		GOTO	MAIN


		ORG	0x0005
MAIN
.....

		END.
;====================================================================
Đây sẽ là cấu trúc một chương trình mà chúng ta sẽ thực hiện
Directive ORG dùng để xác định địa chỉ mà chúng ta sẽ làm việc.

Bây giờ chúng ta xem tiếp đến trang 16 của datasheet.

Chúng ta thấy rằng, bộ nhớ dữ liệu của PIC16F628A được chia ra thành 4 BANK, hay chúng ta gọi tiếng Việt là 4 BĂNG.

Trong 4 băng này, chúng ta thấy rõ nó được chia làm 3 phần. Phần thứ nhất là phần các thanh ghi có địa chỉ xác định (được ghi chú ở bên cạnh) và có tên tuổi rõ ràng. Những thanh ghi này được gọi là những thanh ghi đặc biệt của PIC. Tên của chúng, thực ra không có, một thanh ghi chỉ được xác định bằng địa chỉ của thanh ghi mà thôi.

Tuy nhiên, chúng ta đã làm động tác include file P16F628A.inc, file này đã định nghĩa sẵn tên các thanh ghi này, và là quy ước của MPLAB, đồng thời cũng là quy ước chung cho tất cả người dùng PIC. Chúng ta có thể thay đổi, sửa chữa những định nghĩa này, tuy nhiên việc làm đó vừa không cần thiết, lại vừa gây ra rất nhiều khó khăn khi làm việc nhóm.

Vậy các bạn phải hiểu, những tên thanh ghi này xem như là không thay đổi trong PIC, và chúng ta sử dụng nó như nó đã tồn tại vài chục năm nay.

Phần thứ hai, đó là phần General Purpose Register. Chúng ta gọi nó là các Thanh Ghi Dùng Chung. Những thanh ghi này chưa được định nghĩa, và vì thế nó cũng không có tên. Những thanh ghi này có giá trị như các biến trong chương trình mà chúng ta sẽ sử dụng.

Phần thứ ba, đó là các thanh ghi nằm ở địa chỉ 70h đến 7Fh, và vị trí tương ứng của nó ở băng 1, 2, 3. Các thanh ghi tương ứng đó ở bank1, 2, 3 sẽ tương thích với các thanh ghi từ 70h đến 7Fh ở băng 0. Tuy nhiên, chúng ta tạm thời chưa quan tâm đến phần này.

Bây giờ chúng ta học viết chương trình
Code:
;===============================================================================
		ORG	0x0000
		GOTO	MAIN


		ORG	0x0005

MAIN		
		BANKSEL	TRISB		; bank select
		CLRF		TRISB		; trisb = 00000000
						; portb = output
		BANKSEL	PORTB
		BSF		PORTB,	0	; rb0 = 1
						; RB0 = 5V
		GOTO		$		; dung chuong trinh tai day
						; vong lap tai cho^~
						; khong bao gio ket thuc
		END.				; lenh bat buoc de ket thuc
;================================================================================
Rồi, như vậy, chúng ta đã thực hiện xong một chương trình viết bằng MPASM cho PIC16F628A.

Phân tích chương trình, chúng ta sẽ thấy, mới khởi động, chương trình gặp lệnh goto main, nó sẽ nhảy đến nhãn MAIN. Ở nhãn MAIN, nó gặp lệnh banksel, tức là lệnh bank select. Có nghĩa là nó sẽ chuyển sang hoạt động ở băng có chứa thanh ghi TRISB.

Vì sao? Bởi vì ban đầu khởi động, PIC luôn nằm ở băng 0. Nhưng thanh ghi TRISB lại nằm ở băng 1, vì thế cần phải chuyển sang băng 1 để làm việc. Thực ra chúng ta cũng có cách để yêu cầu PIC chuyển sang băng 1 một cách đích danh, chứ không phải là chuyển sang băng có thanh ghi trisb như chúng ta vừa làm. Nhưng việc này là không cần thiết, cả hai việc làm đều giống nhau. Chính vì vậy, chúng ta chọn cách viết nào cho dễ nhớ là được.

Sau khi chuyển sang băng 1. Chúng ta dùng lệnh CLRF để xoá thanh ghi TRISB.

Tức là TRISB = 00000000

Chúng ta lưu ý một điều rằng, thanh ghi TRISB có công dụng quy định PORTB sẽ có những chân nào là chân xuất, chân nào là chân nhập. Chúng ta nhớ thêm một điều nữa, số 0 giống chứ O, và số 1 giống chữ I. Như vậy, khi TRISB = 00000000 tức là PORTB sẽ là OOOOOOOO, tức có nghĩa là tất cả các chân của portB đều là Output. Nếu TRISB = 01010101 thì PORTB sẽ là OIOIOIOI. Có nghĩa là RB0 sẽ là Input, RB1 là Output, RB2 là Input, RB3 là Output.. cứ như thế cho đến RB7 là Output. Lưu ý rằng RB0 đến RB7 được tính từ phải sang trái.

Sau đó, chúng ta lại thực hiện lệnh Banksel portb, tức là chúng ta lại nhảy về băng 0 (băng chứa thanh ghi portb).

Tất cả các lệnh làm thay đổi giá trị của thanh ghi portb, sẽ làm thay đổi tín hiệu điện ở bên ngoài chân của PORT B.

Sau khi chuyển sang băng 0, chúng ta thực hiện lệnh BSF PORTB,0. Có nghĩa là chúng ta set bit ở vị trí 0 của portb, tức là chúng ta cho RB0 = 1.

Có nghĩa là ở ngoài chân RB0 sẽ mang giá trị điện áp 5V. Khi đó, đèn LED nối với RB0 sẽ sáng.
falleaf vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn