Tải bản đầy đủ (.pdf) (28 trang)

BÁO cáo điều KHIỂN tốc độ ĐỘNG cơ BẰNG VI điều KHIỂN PIC 16f877a

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.09 MB, 28 trang )

ỨNG DỤNG ĐO, ĐIỀU KHIỂN VÀ GIÁM SÁT TỐC ĐỘ ĐỘNG CƠ
ENCODER SỬ DỤNG VI ĐIỀU KHIỂN PIC 16F877A

I.

TÌM HIỂU THIẾT BỊ
1) Pic 16F877A

Đây là vi điều khiển thuộc họ PIC16Fxxx với tập lệnh gồm 35 lệnh có độ dài 14
bít.Mỗi lệnh đều được thực thi trong một chu kỳ xung clock.Tốc độ hoạt động
tối đa cho phép là 20MHz với một chu kỳ lệnh là 200ns.Bộ nhớ chương trình
8Kx14 bít, bộ nhớ dữ liệu 368x8 byte RAM và bộ nhớ dữ liệu EEPROM với


dung lượng 256x8 byte.Số PORT I/O là 5 với 33 pin I/O. - Các đặc tính ngoại vi
bao gồm các khối chức năng sau:

+ Timer0: bộ đếm 8 bít với bộ chia tần số 8 bít. + Timer1: bộ đếm 16
bít với bộ chia tần số, có thể thực hiện chức năng đếm dựa vào xung
clock ngoại vi ngay khi vi điều khiển hoạt động ở chế độ sleep. +
Timer2: bộ đếm 8 bít với bộ chia tần số, bộ postcaler. + Hai bộ
Capture/ so sánh/ điều chế độ rộng xung. + Các chuẩn giao tiếp nối
tiếp SSP, SPI và I2C. + Chuẩn giao tiếp nối tiếp USART với 9 bít địa
chỉ. + Cổng giao tiếp song song PSP với các chân điều khiển RD, WR,
CS ở bên ngoài. - Các kênh Analog: + 8 kênh chuyển đổi ADC 10
bít.Hai bộ so sánh. - Bên cạnh đó là một vài đặc tính khác của vi điều
khiển như: + Bộ nhớ flash với khả năng ghi xóa được 100.000 lần. +
Bộ nhớ EEPROM với khả năng ghi xóa được 1.000.000 lần. + Dữ liệu
bộ nhớ EEPROM có thể lưu trữ trên 40 năm. + Khả năng tự nạp
chương trình với sự điều khiển của phần mềm. + Watchdog Timer với
bộ dao động trong. + Chức năng bảo mật mã chương trình. + Chế độ


Sleep. + Có thể hoạt động với nhiều dạng Oscillator khác nhau.
2) IC L293D điều khiển động cơ


Nguồn cấp Vs (chân 10) : max là 36V , min bằng Vss
- Nguồn cấp logic Vss ( chân 20 ) : max là 36V, min là 4.5 V
- Dòng làm việc bình thường 600 mA
- Dòng đỉnh 1.2 A
-L293D là IC cầu H điều khiển động cơ. Gồm 4 kênh điều khiển có thể điều
khiển 2 động cơ DC hoặc 1 động cơ bước 4 pha (5 dây). Để điều khiển động cơ
DC, bạn sẽ sử dụng 2 kênh của L293D cho 1 động cơ.
-L293D đã được tích hợp sẵn đi ốt bảo vệ vi điều khiển chống lại dòng cảm ứng
khi động cơ khởi động hoặc tắt. Vì vậy, bạn chỉ cần gắn motor vào L293D và
các chân của vi điều khiển tương ứng, là có thể làm cho động cơ chạy ngay.
Dòng L293 có 2 loại: L293B/E và L293D, dòng L293B có khả năng chịu tải cao
hơn (1A so với 600mA của L293D) nhưng không có đi ốt bảo vệ vi điều khiển.
-Với mỗi motor, bạn cần 3 chân từ vi điều khiển kết nối với L293D, trong đó có
1 chân điều khiển tốc độ đông cơ dùng xung PWM, 2 chân còn lại là logic 0
hoặc 1 dùng điều chỉnh chiều quay của motor.
-Tín hiệu điều khiển được xử lý độc lập với nhau với từng đầu ra. Ví dụ: bạn có
thể điều khiển 2 động cơ DC chạy với tốc độ khác nhau, hướng khác nhau, 1
động cơ dừng còn 1 động cơ chạy...
-Mỗi kênh của L293D chịu được tải 600mA và dòng đỉnh là 1A.
-Để sử dụng các động cơ công suất cao hơn, bạn chỉ việc gắn song song 2 hoặc
nhiều L293 lại với nhau. Với 2 IC L293, bạn sẽ có tải chịu được là 1.2A và tải
đỉnh là 2A.
-L293D có chức năng tự động ngắt khi bị nóng quá mức nhằm bảo vệ IC.
3) Động cơ DC
a) Nguyên lí hoạt động
Giống như các loại động cơ điện khác, động cơ điện một chiều cũng gồm có

stator và rotor….Động cơ điện một chiều gồm có stator, rotor, cổ góp và chổi
điện.


- Stator: còn gọi là phần cảm, gồm dây quấn kích thích được quấn tập trung
trên các cực từ stator. Các cực từ stator được ghép cách điện từ các lá
thép kỹ 7 thuật điện được dập định hình sẵn có bề dày 0,5-1mm, và được
gắn trên gông từ bằng thép đúc, cũng chính là vỏ máy.

- Rotor: còn được gọi là phần ứng, gồm lõi thép phần ứng và dây quấn phần
ứng. lõi thép phần ứng có hình trụ, được ghép từ các lá thép kỹ thuật điện
ghép cách điện với nhau. Dây quấn phần ứng gồm nhiều phần tử, được
đặt vào các rãnh trên lõi thép rotor. Các phần tử dây quấn rotor được nối
tiếp nhau thông qua các lá góp trên cổ góp. Lõi thép phần ứng và cổ góp
ñược cố định trên trục rotor. Cổ góp và chổi điện: làm nhiệm vụ đảo chiều
dòng điện trong dây quấn phần ứng.

b) Phân loại động cơ DC
Dựa vào hình thức kích từ, người ta chia động cơ điện một chiều thành các loại
sau:
Động cơ điện một chiều kích từ độc lập: Dòng điện kích từ được lấy từ nguồn
riêng biệt so với phần ứng. Trường hợp đặc biệt, khi từ thông kích từ được tạo ra
bằng nam châm vĩnh cữu, người ta gọi là động cơ điện một chiều kích thích vĩnh
cửu.


Động cơ điện một chiều kích từ song song: Dây quấn kích từ được nối song
song với mạch phần ứng.
Động cơ điện một chiều kích từ nối tiếp: Dây quấn kích từ được mắc nối tiếp
với mạch phần ứng.

Động cơ điện một chiều kích từ hỗn hợp: Dây quấn kích từ có hai cuộn, dây
quấn kích từ song song và dây quấn kích từ nối tiếp. Trong đó, cuộn kích từ
song song thường là cuộn chủ đạo

4) ENCODER
Để điều khiển số vòng quay hay vận tốc động cơ thì chúng ta nhất thiết phải đọc
được góc quay của motor. Một số phương pháp có thể được dùng để xác định
góc quay của motor bao gồm tachometer (thật ra tachometer đo vận tốc quay),
dùng biến trở xoay, hoặc dùng encoder. Trong đó 2 phương pháp đầu tiên là
phương pháp analog và dùng optiacal encoder (encoder quang) thuộc nhóm
phương pháp digital


- CẤU TẠO , NGUYÊN LÍ HOẠT ĐỘNG

Hệ thống optical encoder bao gồm một nguồn phát quang (thường là hồng ngoại
– infrared), một cảm biến quang và một đĩa có chia rãnh. Optical encoder lại
được chia thành 2 loại: encoder tuyệt đối (absolute optical encoder) và encoder
tương đối (incremental optical encoder). Trong đa số các DC Motor, incremental
optical encoder được dùng và mô hình động cơ servo trong bài này cũng không
ngoại lệ.
Encoder thường có 2 kênh bao gồm kênh A, kênh B. Bên ngoài đĩa quay được
chia thành các rãnh nhỏ và một cặp thu-phát dành cho các rãnh này. Đây là kênh
A của encoder, hoạt động của kênh A như sau : khi tia hồng ngoại từ nguồn phát
xuyên qua rãnh của encoder đến cảm biến quang ,1 tính hiệu xuất hiện trên cảm
biến,kênh A xuất hiện 1 xung.Như vậy trong 1 vòng quay của motor, có N
“xung” xuất hiện trên kênh A. N là số rãnh trên đĩa và được gọi là độ phân giải
(resolution) của encoder. Mỗi loại encoder có độ phân giải khác nhau, có khi
trên mỗi đĩa chĩ có vài rãnh nhưng cũng có trường hợp đến hàng nghìn rãnh
được chia. Để điều khiển động cơ, ta phải biết độ phân giải của encoder đang

dùng. Độ phân giải ảnh hưởng đến độ chính xác điều khiển và cả phương pháp
điều khiển. Trên các encoder còn có một cặp thu phát khác được đặt trên cùng
đường tròn với kênh A nhưng lệch một chút (lệch M+0,5 rãnh), đây là kênh B
của encoder. Tín hiệu xung từ kênh B có cùng tần số với kênh A nhưng lệch pha
90o. Bằng cách phối hợp kênh A và B người đọc sẽ biết chiều quay của động cơ.
Hãy quan sát hình.


Hình trên thể hiện sự bộ trí của 2 cảm biến kênh A và B lệch pha nhau. Khi cảm
biến A bắt đầu bị che thì cảm biến B hoàn toàn nhận được hồng ngoại xuyên
qua, và ngược lại. Hình thấp là dạng xung ngõ ra trên 2 kênh. Xét trường hợp
motor quay cùng chiều kim đồng hồ, tín hiệu “đi” từ trái sang phải. Bạn hãy
quan sát lúc tín hiệu A chuyển từ mức cao xuống thấp (cạnh xuống) thì kênh B
đang ở mức thấp. Ngược lại, nếu động cơ quay ngược chiều kim đồng hồ, tín
hiệu “đi” từ phải qua trái. Lúc này, tại cạnh xuống của kênh A thì kênh B đang ở
mức cao. Như vậy, bằng cách phối hợp 2 kênh A và B chúng ta không những
xác định được góc quay (thông qua số xung) mà còn biết được chiều quay của
động cơ (thông qua mức của kênh B ở cạnh xuống của kênh A).

5) LCD
- LCD pinout - Sơ đồ nối chân của LCD


VSS: tương đương với GND - cực âm
VDD: tương đương với VCC - cực dương (5V)
Constrast Voltage (Vo): điều khiển độ sáng màn hình
Register Select (RS): điều khiển địa chỉ nào sẽ được ghi dữ liệu
Read/Write (RW): Bạn sẽ đọc (read mode) hay ghi (write mode) dữ liệu?
Nó sẽ phụ thuộc vào bạn gửi giá trị gì vào.
6. Enable pin: Cho phép ghi vào LCD

7. D0 - D7: 8 chân dư liệu, mỗi chân sẽ có giá trị HIGH hoặc LOW nếu bạn
đang ở chế độ đọc (read mode) và nó sẽ nhận giá trị HIGH hoặc LOW
nếu đang ở chế độ ghi (write mode)
8. Backlight (Backlight Anode (+) và Backlight Cathode (-)): Tắt bật đèn
màn hình LCD.
1.
2.
3.
4.
5.

6) Truyền thông bằng RS232
a/ Cổng COM:
- Giao tiếp giữa PIC và PC thông qua cổng nối tiếp hay còn gọi là cổng COM
theo chuẩn giao tiếp RS232. - Cổng COM có 2 dạng: đầu nối DB25 ( 25 chân )
và DB9 ( 9 chân ) được mô tả như bảng sau: - Cổng nối tiếp được sử dụng để
truyền dữ liệu hai chiều giữa máy tính và ngoại vi, nó có các ưu điểm sau:
+ Khoảng cách truyền xa hơn so với truyền song song.
+ Số dây kết nối ít.
+ Có thể truyền không dây dùng hồng ngoại.


+ Có thể ghép nối với VĐK hay PLC.
+ Cho phép nối mạng.
+ Có thể tháo lắp thiết bị trong lúc máy tính đang làm việc.
+ Có thể cung cấp nguồn cho các mạch điện đơn giản.
- Các thiết bị ghép nối chia làm 2 loại:
+ DCE: là các thiết bị trung gian như MODEM.
+ DTE: là các thiết bị tiếp nhận hay truyền dữ liệu như PC, PLC, VĐK.
+ Việc trao đổi tín hiệu thông thường qua 2 chân RDX (nhận) và RTX (gửi).

Tín hiệu truyền theo chuẩn RS232:
+ Chuẩn RS232 truyền tín hiệu với các tốc độ thông dụng là: 1200 bps, 4800
bps, 9600 bps, 19200 bps.
+ Định dạng khung truyền chuẩn RS232: Khi không truyền dữ liệu, đường
truyền sẽ ở trạng thái mark ( điện áp -• 10V). Khi bắt đầu truyền, DTE sẽ đưa ra
xung Start ( space :10V ) và sau đó• truyền lần lượt từ D0 -> D7 và Parity, cuối
cùng là xung Stop ( mark: - 10V ) để khôi phục lại trạng thái đường truyền.Ví
dụ truyền ký tự A:


Các đặc tính kỹ thuật của chuẩn RS232:

b/ IC MAX 232

IC MAX 232 là IC chuyên dùng trong giao tiếp nối tiếp với PC. Nó có 2 bộ đệm
và 2 bộ nhận.Đường dẫn điều khiển lối vào CTS, điều khiển việc xuất dữ liệu ở
cổng nối tiếp khi cần thiết, được nối với chân 9.Chân RTS (chân 10) được nối
với đường dẫn bắt tay để điều khiển với quá trình nhận.Thường thì các đường
dẫn bắt tay được nối với cổng nối tiếp qua các cầu nối, để khi không dùng đến


nữa có thể để hở mạch các cầu này.Cách truyền dữ liệu đơn giản nhất là chỉ
dùng 3 chân RTX, RDX và GND.

Tuy nhiên hiện nay để giao tiếp máy tính với vi điều khiển người ta đã tích hợp
sẵn trong 1 modul đảm nhận tất cả các công việc trên đó là modul USB to TTL
PL2303

Cách kết nối
Chân 5V nối với VCC của vi điều khiển

GND nối với GND của vi điều khiển
TXD nối với RX (chân 26) của vi điều khiển
RXD nối với TX (chân 25) của vi điều khiển


7) Một số linh kiện khác


II.

LẬP TRÌNH CCS, SƠ ĐỒ NGUYÊN LÝ, TRUYỀN THÔNG
MÁY TÍNH BẰNG C#

1) Lập trình bằng CCS
a) Giới thiệu về Bộ định thời Timer
Định thời là tạo một khoảng thời gian giữa 2 sự kiện
Trong các ứng dụng của vi điều khiển trong thực tế, việc định thời là việc
thường xuyên xảy ra. Để thực hiện việc này, ta có 2 cách:
- Dùng các lệnh thực hiện các vòng lặp để tạo ra khoảng thời gian. Nguyên tắc
tạo ra khoảng thời gian này đơn giản như sau: nếu vi điều khiển mất một khoảng
thời gian x để thực hiện một lệnh, việc lặp lại một lệnh n lần sẽ mất n*x thời
gian.
- Dùng các bộ định thời Timer để tạo ra khoảng thời gian trễ.
Trong bài này, ta sẽ đi vào nguyên cứu các bộ timer.
Một chế độ quan trọng nữa của Timer là khi ta cài đặt cho nó hoạt động như bộ
đếm. Trong ứng dụng này, timer hoạt động như một bộ đếm, có nhiệm vụ đếm
số các xung đi vào một chân cụ thể trên vi điều khiển (Đối với timer0 chân đầu
vào của tín hiệu xung là RA4, với timer1 là RC0
Chế độ bộ đếm này có nhiều ứng dụng trong thực tế như đếm số vòng quay của
động cơ (phản hồi từ bộ đo tốc độ động cơ- encoder), đếm số sản phẩm trên một

dây chuyền v.v.
Vi điều khiển PIC16F877A có 3 bộ Timer:
- Timer0: 8 bit (số đếm tối đa của nó là 255), hoạt động ở 2 chế độ định thời và
bộ đếm.
- Timer1: 16 bit (số đếm tối đa của nó là 65535), hoạt động ở 2 chế độ định thời
và bộ đếm.
- Timer2: 8 bit, hoạt động phục vụ chức năng PWM (Pulse Width Modulation Điều chế độ rộng xung)
Trong bài này ta sử dụng Timer1 hoạt động ở chế độ định thời
Nguyên lí hoạt động:


Chế độ định thời:
Mỗi bộ timer có một hoặc nhiều thanh ghi chứa giá trị đếm của nó (tùy thuộc
vào độ dài của timer), ta giả sử tên thanh ghi là TMR có độ dài là n byte (n=1
với timer0, n=2 với timer1), hay giá trị đếm tối đa là 0 (Chuyển từ 2^8n-1 về 0).
Khi giá trị của TMR đạt đến giá trị này, vi điều khiển sẽ set bit cờ của bộ timer
đó lên mức 1. Người dùng sẽ biết được thời điểm này bằng cách kiểm tra bit cờ.
Khi được cài đặt hoạt động trong chế độ định thời:
- Giá trị của thanh ghi TMR sẽ tự động tăng lên 1 đơn vị sau mỗi chu kì lệnh
của vi điều khiển: TMR=TMR+1
- Khi giá trị của TMR đạt đến giá trị tối đa (Đối với timer0: từ 255 cộng thêm 1
chuyển về 0, đối với timer1: từ 65535 cộng 1 chuyển về 0) , bit cờ của Timer
(Đối với Timer0, tên bit cờ là TMR0IF, vị trí là bit số 2 của thanh ghi INTCON;
Đối với Timer1, tên bit cờ là TMR1IF, vị trí là bit số 0 của thanh ghi PIR1) sẽ
được set lên mức 1
* Trong bài này cứ 25ms ta lại tính toán tốc độ động cơ 1 lần dựa vào số xung
encoder đo được. Vậy cần dùng timer1 để định 1 khoảng thời gian là 25 ms
Sử dụng tần số thạch anh 20MHz, dùng bộ chia 8
 1 chu kì xung Tx= 1/20(us)
1 chu kì lệnh = 4 chu kì xung

 1 chu kì lệnh Tl = 4Tx*8 = 4*1/20*8 = 1.6 (us)
 Để có 25 ms = 25 000 us ta cần
 25 000/1.6 = 15 635 (lần đếm)
 Cần set_timer1 ở giá trị 2^16 – 15 635 = 65 536 – 15 635 = 49 911
Khi tràn Timer1 (TMR1IF set lên mức 1) chương trình sẽ nhảy vào đoạn
chương trình con ngắt timer1


b) Bộ tạo xung PWM
Nguyên lí hoạt động

setup_timer_2 (mode, period, postscale)
Ta có công thức tính chu kì xung PWM:

f = fosc / [ 4*mode*(period+1) ]
 Tpwm = Tosc * 4 * mode * (period + 1)
Trong đó :
mode: T2_DIV_BY_1, T2_DIV_BY_4, T2_DIV_BY_16
period: 0-255
postscale: 1
Tosc = 1/fosc = 1/(20*10^6)
Chọn fpwm = 10 kHz = 10^4 Hz => Tpwm = 10^-4
Tần số điều xung PWM:
10^-4 = (period + 1)* 4 * 1/(20*10^6) * mode
500 = (period + 1) * mode
Chọn cặp period = 124
Mode = 4
 setup_timer_2(T2_DIV_BY_4, 124, 1);






Ta có công thức tính duty (duty cycle) là:


duty = giatriphantram * (4 * (period +1) )
 duty = giatriphantram * 4 * (124+1)
 duty = giatri/100 * 500
 duty = giatri * 5
lưu ý : giatriphantram (%),
giatri là một số thực
c) Giới thiệu ngắt
Ngắt hiểu theo nghĩa đơn giản là các sự kiện ngẫu nhiên làm gián đoạn quá trình
đang xảy ra. Ngắt được thực hiện khi và chỉ khi cho phép nó. Cụ thể hoạt động
của vi điều khiển khi có sự kiện ngắt xảy ra và ngắt đó đã được cho phép:
- Thực hiện nốt lệnh đang thực hiện
- Dừng chương trình đang thực hiện
- Lưu lại địa chỉ của lệnh kế tiếp trong chương trình đang thực hiện vào bộ nhớ
stack
- Nhảy tới địa chỉ 0x04 trong bộ nhớ chương trình
- Tại đây,vi điều khiển sẽ thực hiện chương trình con phục vụ ngắt do người lập
trình đã lập trình từ trước.
- Sau khi thực hiện xong chương trình con phục vụ ngắt, vi điều khiển lấy lại
địa chỉ của lệnh kế tiếp đã được lưu và thực hiện tiếp chương trình đang thực
hiện dở lúc chưa có ngắt
Tới đây ta tổng hợp lại các thuật ngữ dùng cho xử lý ngắt trong vi điều khiển:
- Nguồn ngắt: nguồn ngắt là nguyên nhân gây ra ngắt. Như trong ví dụ trên,
nguồn ngắt có thể là điện thoại gọi hoặc bạn gọi
- Sự kiện ngắt: khi nguồn ngắt xảy ra

- Chương trình con phục vụ ngắt: là chương trình vi điều khiển xử lý khi có sự
kiện ngắt xảy ra do người lập trình lập trình ra Ví dụ như ta trả lời hoặc chạy ra
khỏi phòng gặp bạn
- Vecto ngắt: tức địa chỉ 0x04 nơi vi điều khiển chạy tới sau khi lưu địa chỉ trả
về
- Bit cho phép ngắt: tức việc cho phép vi điều khiển chạy chương trình con
phục vụ ngắt khi có sự kiện ngắt xảy ra. Trong vi điều khiển PIC, mỗi ngắt có


bit cho phép của nó. Bit này tận cùng bằng chữ E (enable), nằm trong các thanh
ghi chuyên dụng. Muốn cho phép ngắt đó, ta phải đưa bit cho phép ngắt tương
ứng lên giá trị 1. Ngắt chỉ thực sự được cho phép ngắt khi ta cho bit cho phép
ngắt toàn cục GIE (Global Interrupt Enable) lên mức 1. Ta hình dùng như sau:
khi có sự kiện ngắt- điện thoại gọi, nếu ta cho phép mình nghe điên thoại (tức bit
cho phép ngắt của ngắt đó được set lên 1) đồng thời thầy giáo cho phép (bit cho
phép ngắt toàn cục GIE được lên mức 1) thì ta mới nghe điện thoại (cho chương
trình con phục vụ ngắt hoạt động).
- Một số các ngắt khác, như các ngắt ngoại vi bao gồm ADC, PWM v.v Muốn
cho phép nó còn phải đưa bit cho phép ngắt ngoại vi lên mức 1.
Cờ ngắt: là bit phản ánh trạng thái của sự kiện ngắt. Mỗi ngắt có một bit cờ. Khi
bit cờ này bằng 1 nghĩa là sự kiện ngắt tương ứng với cờ đó xảy ra. Ta hình
dung như tiếng chuông của điện thoại là cờ ngắt, chuông rung báo có sự kiện
ngắt- có điện thoại xảy ra. Các bit này tận cùng bằng từ F (Flag- cờ). Lưu ý là dù
một ngắt có được cho phép hay không thì cờ ngắt vẫn được set lên 1 khi có sự
kiện ngắt xảy ra. (Dù ta có được phép nghe điện thoại hay không thì chuông
điện thoại vẫn cứ reo).
Các ngắt trong vi điều khiển PIC16F877A:
Vi điều khiển PIC16F877A có 15 nguồn ngắt. Được chia làm 2 lớp ngắt:
- Lớp ngắt cơ bản: bao gồm các ngắt cơ bản như ngắt tràn timer 0, ngắt ngoài,
ngắt thay đổi trạng thái của các chân PortB (RB4-RB7). Bit cho phép ngắt và bit

cờ tương ứng là TMR0IE,TMR0IF; INTE, INTF; RBIE và RBIF. Để ý là để cho
phép ngắt thực sự xảy ra phải có bit cho phép ngắt toàn cục GIE.
- Lớp ngắt ngoại vi: bao gồm các ngắt ngoại vi như ngắt tràn timer 1
(TMR1IE, TMR1IF), ngắt tràn Time2(TMR2IE, TMR2IF), ngắt hoàn thành việc
chuyển đổi ADC (ADCIE, ADCIF), ngắt hoàn thành việc nhận kí tự trong
truyền thông RS232 (RCIE, RCIF), ngắt hoàn thành việc truyền kí tự trong
truyền thông RS232 (TXIE, TXIF) v.v Để ý là muốn thực sự cho phép các ngắt
này ngoài bit cho phép ngắt toàn cục được set phải set cả bỉt cho phép ngắt
ngoại vi PEIE.

Trong bài này ta sử dụng ngắt ngoài để đếm xung encoder
Hoạt động của ngắt ngoài
Nguồn ngắt: là xung đi vào chân RB0 của vi điều khiển PIC


Sự kiện ngắt: sự kiện ngắt xảy ra khi có xung đi vào chân RB0 của vi điều
khiển. Xung là xung sườn dương hay sườn âm phụ thuộc bit cài đặt chọn dạng
xung, bit INTEDG ( bit 6 của thanh ghi OPTION_REG) là 1 hay 0. Bit cho phép
ngắt: Để cho phép ngắt ngoài, bit cho phép ngắt ngoài INTIE (bit 4 của thanh
ghi INTCON) phải được set lên 1. Ngoài ra, bit cho phép ngắt toàn cục GIE (bit
7 của thanh ghi INTCON) cũng phải được set lên 1.
Cờ ngắt: bit cờ ngắt ngoài là bit INTIF (bit 1 của thanh ghi INTCON) được tự
động set lên 1 khi có sự kiện ngắt ngoài xảy ra. Cờ này phải được xóa bằng
chương trình (cụ thể là
trong chương trình con phục vụ ngắt) để vi điều khiển quản lý chính xác các lần
ngắt kế tiếp.
code CCS
///////////////////////////////////////////////////////////////////////////////////////
#include <16F877A.h>
#device ADC=16

#FUSES NOWDT
//No Watch Dog Timer
#FUSES NOBROWNOUT
//No brownout reset
#FUSES NOLVP
//No low voltage prgming,
B3(PIC16) or B5(PIC18) used for I/O
#use delay(crystal=20000000)
#use RS232 (Baud = 9600, parity = n ,xmit = pin_C6, rcv =
pin_C7)
#include <lcd.h>
//khai bao ket noi cac nut nhan
#define TANG input(PIN_B1)
#define GIAM input(PIN_B2)
//khai bao ket noi chan voi L293D
#define EN1 PIN_C3
unsigned int16 counter = 0;
unsigned int16 SoXungDangDem = 0;
unsigned int16 SoXungDoDuoc = 0;


void _KhoiTaoTIMER1(void);
void _KhoiTaoNgatNgoai(void);
void _KhoiTaoTIMER1(void)
{
setup_timer_1(T1_internal|T1_DIV_BY_8);
set_timer1(49911);
enable_interrupts(int_timer1); //cho phep ngat timer1
}
//-------------------void _KhoiTaoNgatNgoai(void)

{
enable_interrupts(int_ext); //Cho phep ngat ngoai hoat dong
enable_interrupts(int_ext_H2L); //Khi tin hieu chuyen tu cao
xuong thap
clear_interrupt(int_ext);
}

#int_timer1
void _NgatTIMER1(void)
{
disable_interrupts(int_ext); //Tat timer
setup_timer_1(T1_disabled); //Stop dem timer
SoXungDoDuoc = SoXungDangDem;
SoXungDangDem = 0;
set_timer1(49911); //thoi gian lay mau = 25 ms
//25ms=25000us = (65536 - value)*1.6us =>value = 49911
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //Cho phep ngat
timer hoat dong lai
enable_interrupts(int_ext); //cho phep ngat ngoai hoat dong lai
Counter++;


}
//---------------#int_ext
void _NgatNgoai(void)
{
SoXungDangDem = SoXungDangDem + 1;
}
//------------------


void main()
{
int16 Duty=250;
int16 GiaTri=50; //50%
int16 TocDo;
float Tam;

_KhoiTaoTIMER1();
_KhoiTaoNgatNgoai();
enable_interrupts(GLOBAL); //Cho phep ngat toan cuc - la tien de
cho cac ngat hoat dong
lcd_init();
lcd_putc('\f');
setup_timer_2(T2_DIV_BY_4,124,1);// fpwm = 10KHz
setup_ccp1(CCP_PWM);
set_pwm1_duty(0);
output_bit(EN1,0);
output_bit(EN1,1);
set_pwm1_duty(Duty);


while(TRUE)
{

lcd_gotoxy(1,1);
printf(lcd_putc,"VALUE DUTY:%02ld",GiaTri);
lcd_putc('%');
if(TANG==0)
{
while(TANG==0);

GiaTri=GiaTri+5;
if(GiaTri>90)
{
GiaTri=30;
}
Duty =GiaTri * 5;
output_bit(EN1,1);
set_pwm1_duty(Duty);
}

else if(GIAM==0)
{
while(GIAM==0);
GiaTri=GiaTri-5;
if(GiaTri<20)
{
GiaTri=50;
}
Duty =GiaTri * 5;
output_bit(EN1,1);
set_pwm1_duty(Duty);
}
if (Counter >=10)
{


Counter = 0;
//Tocdo= (so xung moi phut)/So xung encoder
//25 ms <-> SoXungDoDuoc => so Xung moi phut =
(SoXungDoDuoc / 0.025) * 60s

Tam = ((float)SoXungDoDuoc * (1000f/25f) *60f)/334f;
TocDo = (int16)Tam;
lcd_gotoxy(1,2);
printf(lcd_putc, "TOC DO:%04ld",TocDo);
printf("%4ld\r",TocDo);
delay_ms(50);
}
}

}

2) Mô phỏng bằng proteus


3) Mạch in


4) Kết nối với máy tính
Giao diện được viết bằng phần mềm c# để vẽ và hiển thị tốc độ động


Code C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO.Ports;

namespace Giaodien
{
public partial class frmMain : Form
{
#region Quan ly bien
SerialPort UART = new SerialPort();
#endregion
#region Quan ly ham
private void _KhoiDong()


{
try
{
cbxCom.DataSource = SerialPort.GetPortNames();
if (cbxCom.Items.Count > 0)
{
cbxCom.SelectedIndex = 0;
}
}
catch (Exception)
{
}
}
#endregion
#region Quan ly form
public frmMain()
{

InitializeComponent();
}

private void frmMain_Load(object sender, EventArgs e)
{
try
{
Control.CheckForIllegalCrossThreadCalls = false;
_KhoiDong();
this.UART.DataReceived += new
System.IO.Ports.SerialDataReceivedEventHandler(this.UART_DataReceived);
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Interval = 1;
chart1.ChartAreas[0].AxisX.Maximum = 10;
chart1.ChartAreas[0].AxisY.Maximum = 4000;
// btnConnect_Click(null, null);
}
catch (Exception)
{


×