Phone

(8)3896.8699-0972924961

Giỏ hàng 0 item(s)

Giỏ hàng trống

No-avatar-100

Học vi điều khiển PIC trong 1 ngày (Phần 1)

le_hieu_29 - 19/03/2012

Bài 1 : Điều khiển Led đơn

Phần này giúp chúng ta viết những chương trỉnh phần mềm đơn giản nhất cho PIC, trên quan điểm chúng ta đã có một hệ phần cứng phát triển PIC trong phần đầu .

Bài viết chú trọng vào kiến trúc của Vi Điều khiển PIC, do đó tác giả sử dụng ngôn ngữ Assembly để hướng dẫn chúng ta. Chúc các bạn thành công !

Nguồn : Picvietnam "

Bài tập 1: Bật tắt đèn LED

Cực dương của LED được nối với điện trở, điện trở được nối với các chân vi điều khiển. Cực âm của
LED được nối với GND của vi điều khiển. Như vậy, khi chân vi điều khiển ở mức cao, tức là 5V, đèn
LED sẽ sáng. Khi chân vi điều khiển ở mức thấp (0V) đèn LED sẽ tắt.
Lưu ý trong hình: Giá trị của điện trở được xác định dựa vào dòng tối đa của vi điều khiển, điện áp
và dòng điện tối đa của đèn LED. Như vậy, giá trị nhỏ nhất của điện trở được dùng được tính toán
như trong hình. R = 125 Ohm.
Tuy nhiên, để đảm bảo hoạt động của đèn LED, chúng ta nâng giá trị điện trở lên thành 200 Ohm.
Đèn LED khi sáng quá, chỉ cần sờ tay vào nó, hoặc các va chạm mạnh, hoặc trường hợp bị tĩnh
điện, đèn LED có thể bị hư ngay. Hiện tượng này dễ thấy nhất là ở các LED cực sáng dùng trong
các bảng hiệu hoặc biển báo giao thông, các đèn LED cực sáng chỉ cần chạm tay vào, sẽ có hiện
tượng tĩnh điện và nổ ngay. Với các LED thường và dùng trong thí nghiệm, khó xảy ra hiện tượng
này, tuy nhiên chất lượng sản xuất của các đèn LED cũng không đảm bảo, do vậy chúng ta chọn
giải pháp an toàn là trên hết. Hơn nữa, chúng ta cũng không cần đèn LED quá sáng.
Để bắt đầu bài tập 1, chúng ta tìm hiểu sơ qua về cấu trúc một chương trình viết bằng MPASM
như sau:
Bất cứ một chương trình ASM nào, cũng được bắt đầu bằng việc giới thiệu về chương trình, tên
chương trình, người thực hiện chương trình, ngày thực hiện chương trình, ngày hoàn tất, người
kiểm tra lại chương trình, ngày kiểm tra chương trình, phiên bản của chương trình, mô tả phần
cứng của mạch giao tiếp và một số chú thích. Vì vậy, tôi đưa ra đây một form mà tôi cho rằng hợp
lý, từ đây về sau, các bạn chỉ cần cắt dán form này, thay đổi nội dung từng mục để làm phần mở
đầu.
Chúng ta quy định một số quy ước sau:
;========== dùng để phân cách các phần chính của chương trình
;---------------- dùng để phân cách các chương trình con của chương trình

Code:

;================================================= =======
; Ten chuong trinh : Mach test den LED_1
; Nguoi thuc hien : Falleaf
; Ngay thuc hien : 23/05/2005
; Phien ban : 1.0
; Mo ta phan cung : Dung PIC16F628A - thach anh 10MHz
; : LED giao tiep voi PORTB
; : Cuc am cua LED noi voi GND
; : RB0 - RB7 la cac chan output
;----------------------------------------------------------------
; Ngay hoan thanh : 23/05/2005
; Ngay kiem tra : 23/05/2005
; Nguoi kiem tra : Doan Hiep
;----------------------------------------------------------------
; Chu thich : Mo ta cac diem khac nhau cua cac phien ban khac nhau
; : hoac cac chu thich khac
; : vd, dung che do Power On Reset, PORTB = 00000000
; : hoac, chuong trinh viet cho PIC Tutorial
; : hoac, chuong trinh nay hoan toan mien phi va co the dung cho
; : moi muc dich khac nhau
;================================================= =======

Mặc dù chưa chắc rằng đoạn chú thích này có thể ngắn hơn chương trình các bạn viết, và như vậy
việc viết chú thích dài hơn việc viết chương trình? Không, thực sự các chú thích này rất quan
trọng, vì sau 1, 2, 3 năm, các bạn nhìn lại, các bạn sẽ vẫn còn hiểu được mình đã làm gì. Có thể
khi mới bắt đầu, các bạn thấy công việc ghi chú này là nhàm chán, chính vì vậy, tôi đã cung cấp
form của ghi chú này, các bạn sau đó chỉ cần cắt và dán. Tôi hy vọng rằng các bạn nên tạo thói
quen đưa đoạn chú thích này vào chương trình để các bạn trở nên chuyên nghiệp hơn khi làm việc
với vi điều khiển, cụ thể ở đây là PIC.
Tất nhiên, đây là bài học đầu tiên, do vậy các chú thích sẽ được ghi rất chi tiết, nhất là khi mô tả
phần cứng. Sau này, với các mạch phức tạp hơn, các bạn không thể ghi chú quá chi tiết như thế
này được, các bạn chỉ ghi chú những điểm chính thôi. Cũng tất nhiên, khi lập trình với CCS C hay
HT PIC, các bạn cũng nên ghi chú như vậy trong chương trình chính, nhưng chúng ta chưa bàn
đến CCS C và HT PIC ở đây.
Phần thứ hai các bạn cần học, đó là khởi tạo PIC. Phần này là phần bắt buộc theo sau phần ghi
chú, bởi vì chương trình dịch cần phải hiểu bạn đang làm việc với con PIC nào, làm việc với nó như
thế nào?
Code:

;================================================= ======
TITLE "Mach test LED_1"
PROCESSOR P16F628A
INCLUDE <P16F628A.inc>
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF &_HS_OSC
;================================================= ======

Các bạn sẽ thấy rằng có một số từ khoá như sau:
TITLE: dùng để các bạn ghi chú thích tên chương trình. TITLE là ten chương trình chính. Cú pháp
ghi TITLE như trên. Nhớ phải có dấu nháy kép khi viết tên chương trình.
PROCESSOR: dùng để khai báo dòng vi điều khiển mà các bạn sử dụng. Các bạn lưu ý, trong
MPLAB quy định, không viết đầy đủ tên PIC16F628A mà chỉ viết P16F628A, vì trong chương trình
dịch đã quy định như vậy.
INCLUDE: dùng để đưa thêm vào các file mà bạn viết trong chương trình. Mặc định, trong MPLAB
đường dẫn đến thư mục chứa file P16F628A.inc đã có sẵn. Nếu bạn đặt file ở nơi khác không phải

trong thư mục bạn đang làm việc, hoặc các file include khong phải là file .inc có sẵn của MPLAB,
thì các bạn phải chỉ đường dẫn rõ ràng. Lưu ý rằng, để MPASM dịch được, các bạn phải đặt đường
dẫn từ thư mục gốc đến hết tên file (kể cả phần mở rộng của file) không được quá 60 ký tự.
__CONFIG: dùng để thiết lập các chế độ hoạt động của PIC. Các bạn có thể xem để hiểu thêm về
các chế độ hoạt động này trong tài liệu
PICmicro
Mid Range MCU Family
Reference Manual
Section 27. Device Configuration Bits
Table 27-1 page 27-7
Tài liệu này có thể download trên trang web của microchip http://www.microchip.com/, keyword:
MidRange Manual.
Mỗi directive để đặt chế độ, cách nhau một ký tự &.
Nếu ghi chế độ hoạt động vào đây, các chế độ hoạt động sẽ ở trạng thái mặc định khi khởi động.
Các bạn cũng có cách khác để đặt chế độ hoạt động bằng cách tác động trực tiếp vào các thanh
ghi khởi tạo. Tuy nhiên, việc này là việc làm không cần thiết, khi chúng ta đã có các directive để
viết tắt.
Như vậy, chúng ta đặt ở đây chế độ _CP_OFF, tức là khôngđặt chế độ bảo vệ source code khi
nạp vào PIC, sau khi nạp vào sẽ có thể đọc ngược lại từ PIC ra. Chúng ta không cần bảo vệ
chương trình này, để bạn có thể đọc ngược bằng IC-PROG và kiểm tra lại.
Chế độ _PWRITE_ON, tức là cho timer 0 chạy khi Power On Reset. Thực ra timer0 có chạy hay
không cũng không quan trọng, vì nó chẳng liên quan gì đến công việc của chúng ta. Nếu sau này
muốn dùng timer0, thì các bạn vẫn phải khởi tạo lại giá trị cho nó, chứ đâu thể sử dụng giá trị
ngẫu nhiên của nó được, thành ra cứ để cho nó chạy, sau này cần dùng khỏi phải khởi tạo.
_WDT_OFF, tại thời điểm này, tôi tắt Watch Dog Timer vì lý do các bạn chưa nên tìm hiểu phần
này vội.
_HS_OSC, chúng ta dùng thạch anh 10MHz, tức là chạy chế độ dao động HS. Tham khảo tại:
datasheet PIC16F628A
Section 14. Special Features of the CPU
14.2. Oscillator Configuration
Page 95

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.
Các bạn sẽ thấy mach ngoài hoạt động như thế này:
Khi bật điện lên, PIC được reset. Nó lập tức bật sáng đèn LED ở RB0, rồi sau đó giữ nguyên như
vậy, không làm gì cả.
Bây giờ các bạn lưu chương trình vừa viết thành LED_1.asm vào một thư mục nào đó.
Nhấn Alt - F10, chương trình sẽ dịch LED_1.asm thành LED_1.hex
Các bạn dùng mạch nạp PG2C và chương trình nạp IC-PROG để nạp vào PIC (tham khảo Hướng
dẫn mạch nạp Falleaf PG2C - PIC Tutorial).
Công việc của các bạn như sau:
0) Chạy thử chương trình ban đầu
1) Thay đổi lệnh BSF PORTB, 0 bằng lệnh BSF PORTB, 1. Nạp lại chương trình mới vào PIC. Bạn
sẽ thấy bây giờ đèn LED không sáng ở vị trí RB0 nữa mà sáng ở vị trí RB1.
2) Thay lệnh BSF PORTB,0 bằng đoạn lệnh
MOVLW b'11110000'
MOVWF PORTB
Bạn sẽ thấy các các chân từ RB0 đến RB3 sẽ tắt đèn, và các chân từ RB4 đến RB7 đèn sẽ sáng.
3) Bạn thay lệnh CLRF TRISB bằng đoạn lệnh
CLRF TRISB
BSF TRISB, 0
và giữ nguyên lệnh
BSF PORTB, 0
Các bạn sẽ thấy rằng đèn LED trong trường hợp này sẽ không sáng nữa.
Bởi vì các bạn đã làm cho TRISB = 00000001. Như vậy, RB0 trở thành chân Input. Khi RB0 trở
thành chân Input, thì lệnh BSF PORTB, 0 sẽ không còn tác dụng nữa. RB0 lúc này không thể thay
đổi giá trị bằng chương trình, nó chỉ có thể nhận giá trị điện áp từ bên ngoài vào.

 

4) Trong trường hợp mạch này, các bạn sẽ làm thế nào?

 

 

Kết luận: Qua bài học này, các bạn đã học được các nội dung sau:
- Làm một mạch chạy PIC
- Cấu trúc một chương trình PIC
- Lập trình từ máy tính, nạp vào PIC, và cho PIC hoạt động
- Hiểu được hoạt động xuất nhập của PIC, chức năng của thanh ghi TRISA, TRISB, PORTA, PORTB,
hiểu được các lệnh CLRF (xoá thanh ghi bất kỳ), MOVLW (ghi một giá trị bất kỳ vào thanh ghi W),
MOVWF (ghi giá trị của thanh ghi W vào một thanh ghi khác), BSF (bật một bit trong một thanh
ghi bất kỳ), GOTO (nhảy đến một nhãn bất kỳ), GOTO $ (nhảy tại chỗ), BANKSEL (chon băng
trong bộ nhớ chương trình, chứa một thanh ghi bất kỳ), ORG định địa chỉ trong bộ nhớ chương
trình. Hiện nay các bạn chưa học đến làm thế nào để Input, nhưng có thể các bạn sẽ thực hiện dễ
dàng bằng việc thay LED bằng một nút bấm. Hoặc giả, các bạn muốn đèn LED nhấp nháy, về
nguyên tắc các bạn có thể thực hiện bật tắt liên tục đèn LED bằng lệnh BSF và BCF. Nhưng làm
như thế nó nháy quá nhanh, không thể thấy được.
Bài học sau, chúng ta sẽ học cách viết hàm Delay, và các bạn có thể thực hiện việc làm cho đèn
LED nhấp nháy, làm cho dãy đèn từ RB0 đến RB7 chạy qua chạy lại...
Chúc các bạn may mắn trong bài học đầu tiên, và chúc các bạn thành công với PIC!

Nguồn : Picvietnam "


Bình luận(0)
Vui lòng Đăng Nhập hoặc đăng ký thành viên để chia sẻ,bình luận và tích lũy điểm.
Trả lời mới
    Đang tải...
Thegioiic-live-support