0968140191Miền Nam
0975897066Miền Bắc

Điều khiển động cơ bước dùng PIC16F877A: sơ đồ mạch, tạo xung bằng Timer, biến trở chỉnh tốc, LCD và Proteus

Viết bởi: Vũ Hồng Phúc
Vũ Hồng Phúc
Vũ Hồng Phúc, sinh năm 1985, sau khi tốt nghiệp cử nhân tại Đại Học Bách Khoa Hà Nội, Vũ Hồng Phúc đã tự mình khám phá thế giới qua việc du học tại EF Language School London và nhiều trường đại học khác. Tích lũy kinh nghiệm trong nhiều năm, anh quyết định trở về đất nước. Vũ Hồng Phúc đã hướng đến mục tiêu phát triển Dongco3pha.com là thương hiệu "Động cơ điện" hàng đầu Việt Nam. Trong nhiều năm liền danh liên tục mang lại nhiều thành tựu cho doanh nghiệp và đóng góp nhiều giải pháp tối ưu về chế tạo máy, chế tạo động cơ giảm tốc, động cơ điện.
14 thg 10 2026 15:19

Điều khiển động cơ bước dùng PIC16F877A là cách dùng vi điều khiển 8 bit PIC16F877A của Microchip để phát trình tự cấp điện cho các cuộn dây (qua ULN2003, L298) hoặc phát xung STEP/DIR cho driver (A4988, DRV8825, TB6600), kèm đọc phím nhấn, biến trở chỉnh tốc độ và hiển thị trạng thái lên LCD 16x2. Chip có 40 chân, 33 chân I/O, ADC 10 bit 8 kênh, ba bộ định thời và chạy tối đa 20 MHz, đủ dư cho một đến bốn động cơ bước ở tốc độ của mô hình và máy nhỏ.

Phần khó thường không nằm ở trình tự xung mà ở những chi tiết làm mạch thật không chạy: cấu hình config bits, chân MCLR, chế độ LVP, PORTA mặc định là analog, nguồn motor làm reset chip, và cách tạo xung đều khi vừa phải quét phím vừa cập nhật LCD.

Phần nguyên lý chung về họ PIC với động cơ bước có ở bài điều khiển động cơ bước dùng PIC; nội dung dưới đây đi thẳng vào PIC16F877A: sơ đồ chân, mạch ghép, đoạn code mẫu, mô phỏng và nạp chip.

Mạch điều khiển động cơ bước dùng PIC16F877A với LCD 16x2, nút nhấn và biến trở chỉnh tốc độ

1. PIC16F877A có những gì để điều khiển động cơ bước

PIC16F877A là vi điều khiển lõi 14 bit (mid-range), bộ nhớ chương trình 8K word Flash, 368 byte RAM, 256 byte EEPROM. Với bài toán động cơ bước, các khối đáng quan tâm là cổng I/O, Timer, CCP, ADC và ngắt ngoài.

Khối chức năngThông sốDùng vào việc gì
Xung nhịpTối đa 20 MHz (chu kỳ lệnh 200 ns)Tính chính xác thời gian giữa các bước
Cổng I/OPORTA 6, PORTB 8, PORTC 8, PORTD 8, PORTE 3 chânXuất trình tự pha, STEP/DIR, đọc phím, LCD
Dòng mỗi chân25 mA (hút hoặc cấp)Chỉ đủ kéo LED, ngõ vào driver; không kéo trực tiếp cuộn dây
Timer0 / Timer1 / Timer28 bit / 16 bit / 8 bitTimer1 tạo chu kỳ bước, Timer0 quét phím
CCP1, CCP2Capture, Compare, PWMCompare + Timer1 tạo chu kỳ bước tự nạp lại
ADC10 bit, 8 kênh AN0–AN7Đọc biến trở chỉnh tốc độ
Ngắt ngoàiRB0/INT, ngắt đổi trạng thái RB4–RB7Công tắc hành trình, nút dừng khẩn
Nguồn2,0–5,5 V (ở 20 MHz cần 4,5–5,5 V)Thực tế cấp 5 V từ 7805

Mỗi chân tối đa 25 mA, tổng cả cổng khoảng 200 mA, trong khi cuộn dây motor bước nhỏ nhất cũng ăn vài chục đến vài trăm mA, nên luôn phải có tầng công suất ở giữa.

2. Sơ đồ chân và phân bổ cổng cho mạch điều khiển động cơ bước PIC16F877A

Phân bổ chân hợp lý giúp viết code gọn (xuất cả nibble một lần) và tránh đụng các chân đặc biệt. Cách chia dưới đây là cách phổ biến cho đồ án một hoặc hai động cơ.

Chân (DIP40)TênGán chức năngGhi chú
1MCLR/VPPĐiện trở 10 kΩ lên 5 V, nút Reset xuống massBắt buộc kéo lên, không được để hở
2RA0/AN0Biến trở chỉnh tốc độCấu hình analog qua ADCON1
11, 32VDD5 VMỗi chân một tụ 100 nF sát chân
12, 31VSSMassNối cả hai chân
13, 14OSC1, OSC2Thạch anh 20 MHz + 2 tụ 15–22 pFConfig HS
33RB0/INTCông tắc gốc (home) hoặc dừng khẩnDùng ngắt ngoài
34, 35, 37, 38RB1, RB2, RB4, RB5Phím: chạy/dừng, đổi chiều, chế độ, cài đặtBật trở kéo lên nội của PORTB
36RB3/PGMTránh dùng nếu chưa tắt LVPXem mục 7
39, 40RB6/PGC, RB7/PGDĐể trống cho mạch nạp ICSPKhông treo tải nặng
19–22RD0–RD3IN1–IN4 của ULN2003/L298 hoặc STEP, DIR, ENXuất nibble thấp PORTD
27–30RD4–RD7Động cơ thứ hai hoặc LCD 4 bitTùy thư viện LCD

3. Mạch dao động 20 MHz, nguồn và chân MCLR

Ba phần "phụ" này quyết định chip có chạy hay không, nhiều hơn cả code.

Thạch anh 20 MHz

  • Đấu thạch anh giữa chân 13 và 14, mỗi chân một tụ 15–22 pF xuống mass, đặt sát chip.
  • Config dao động phải là HS. Để XT với thạch anh 20 MHz, mạch thường không dao động hoặc dao động chập chờn.
  • Ở 20 MHz, một chu kỳ lệnh là 200 ns; mọi phép tính Timer bên dưới đều dựa trên Fosc/4 = 5 MHz.

Nguồn cho mạch

Mạch thông dụng lấy 12 V cho motor, hạ 5 V bằng 7805 cho PIC; tụ 100 nF ở từng cặp VDD/VSS, tụ hóa 100–470 µF ở đầu vào 7805 và nguồn motor. Mass motor đi riêng về cực âm nguồn, gặp mass logic tại một điểm, để xung dòng cuộn dây không làm dao động chân VSS của PIC.

Chân MCLR

PIC16F877A không có bit cấu hình tắt chân MCLR, nên chân 1 luôn là chân reset tích cực mức thấp. Điện trở 10 kΩ lên 5 V là bắt buộc; nút reset nối từ chân này xuống mass, có thể thêm điện trở 100–470 Ω nối tiếp nút. Tránh đặt tụ lớn trực tiếp lên MCLR nếu nạp chip tại mạch (ICSP), vì tụ làm chậm sườn điện áp lập trình.

4. Ghép PIC16F877A với tầng công suất: ULN2003, L298 và driver STEP/DIR

Chọn tầng công suất theo loại motor đang có. Motor 5 dây hoặc 6 dây đơn cực dùng ULN2003; motor 4 dây lưỡng cực dòng nhỏ dùng L298; motor NEMA 17, NEMA 23 dòng từ 1 A trở lên nên dùng driver STEP/DIR có hạn dòng.

Tầng công suấtMotor phù hợpChân PIC dùngCode phải làm
ULN2003Đơn cực 5 dây/6 dây, dòng ≤ 0,5 A/phaRD0–RD3 → IN1–IN4Xuất trình tự 4 hoặc 8 trạng thái
L298NLưỡng cực 4 dây, điện trở cuộn caoRD0–RD3 → IN1–IN4, ENA/ENB lên 5 VXuất trình tự cầu H
A4988 / DRV8825NEMA 17 đến khoảng 1,5–2 ARD0 → STEP, RD1 → DIR, RD2 → ENPhát xung, PIC không lo trình tự pha
TB6600 / DM542NEMA 17–34RD0 → PUL+, RD1 → DIR+, PUL−/DIR− về massPhát xung, cần độ rộng xung đủ dài

a. PIC16F877A với ULN2003 cho motor đơn cực

Bốn chân RD0–RD3 nối IN1–IN4, bốn ngõ ra OUT1–OUT4 nối bốn đầu pha, dây chung của motor nối cực dương nguồn motor (5 V hoặc 12 V tùy motor), chân COM (chân 9) của ULN2003 cũng nối cực dương này để diode dập bên trong làm việc. Mass ULN2003 nối chung mass PIC. Motor đảo gió, motor máy in cũ loại 5 dây như trong ảnh trên chạy tốt với cách đấu này. Chi tiết dòng, sụt áp và nhiệt của IC xem bài điều khiển động cơ bước bằng ULN2003; thứ tự dây và chế độ kích từ của motor 4 pha 5 dây có ở bài động cơ bước 4 pha 5 dây.

b. PIC16F877A với L298 cho motor lưỡng cực

RD0, RD1 điều khiển cuộn A (IN1, IN2), RD2, RD3 điều khiển cuộn B (IN3, IN4); ENA, ENB nối 5 V hoặc nối thêm hai chân PIC nếu muốn ngắt điện cuộn khi đứng. L298 không hạn dòng, sụt áp 2–4 V, nên chỉ hợp motor điện trở cuộn cao; giới hạn này và cách chọn nguồn đã phân tích ở bài điều khiển động cơ bước dùng L298. Cùng một mảng trình tự cho ULN2003 dùng được cho L298 ở chế độ full step hai pha, chỉ khác ý nghĩa vật lý: ở L298 mỗi cặp bit là hai đầu của cùng một cuộn.

c. PIC16F877A với driver STEP/DIR (A4988, DRV8825, TB6600)

Khi dùng driver, PIC chỉ cần hai chân: STEP (mỗi sườn lên là một bước hoặc vi bước) và DIR (chiều quay). Ngõ ra 5 V của PIC khớp trực tiếp mức logic của A4988, DRV8825; với TB6600, DM542 ngõ vào là opto, đấu chung cathode: PUL+, DIR+ nối chân PIC, PUL−, DIR− nối mass.

Sơ đồ đấu driver A4988 với vi điều khiển: STEP, DIR, nguồn logic và nguồn motor 8–35 V, áp dụng cho PIC16F877A

Sơ đồ trên áp dụng nguyên cho PIC16F877A: VDD của A4988 lấy 5 V từ 7805, STEP và DIR nối RD0, RD1, chân RESET và SLEEP nối với nhau, tụ 100 µF đặt sát chân VMOT. Độ rộng xung STEP tối thiểu của A4988 là 1 µs, DRV8825 khoảng 1,9 µs; với TB6600 nên giữ mức cao ít nhất khoảng 5 µs cho opto kịp đóng. Khi viết code, giữ chân STEP ở mức cao vài micro giây rồi mới kéo xuống là an toàn cho mọi loại. Đặt dòng, vi bước của TB6600 xem bài mạch điều khiển động cơ bước TB6600.

5. Trình tự xung và code điều khiển động cơ bước bằng PIC16F877A

Với ULN2003 và L298, PIC phải tự xuất trình tự pha. Gom bốn chân pha vào nibble thấp PORTD giúp mỗi bước chỉ là một lệnh ghi cổng.

Bảng trình tự xuất ra PORTD (RD3…RD0)

Chế độSố trạng tháiGiá trị lần lượt (hex)Đặc điểm
Wave (1 pha)40x01, 0x02, 0x04, 0x08Ít dòng, mô-men thấp nhất
Full step (2 pha)40x03, 0x06, 0x0C, 0x09Mô-men lớn nhất ở bước đủ
Half step (1-2 pha)80x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09Gấp đôi độ phân giải, êm hơn

Đổi chiều quay chỉ là duyệt mảng theo chiều ngược lại. Khi ghi PORTD mà nibble cao đang dùng cho việc khác (LCD), phải giữ nguyên 4 bit cao: PORTD = (PORTD & 0xF0) | seq[i];.

Khung chương trình CCS C (delay đơn giản)

  • #include <16F877A.h>
  • #fuses HS, NOWDT, PUT, BROWNOUT, NOLVP, NOPROTECT
  • #use delay(clock=20M)
  • Mảng: const int8 seq[8] = {0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09};
  • Trong main(): set_tris_d(0xF0); rồi vòng lặp output_d(seq[i]); delay_ms(t); i = (i + 1) & 7;
  • Đổi chiều: i = (i - 1) & 7;

delay_ms(t) của CCS nhận biến.

Cùng logic viết bằng MikroC PRO for PIC

  • Config chọn trong Edit Project: HS, WDT Off, LVP Off; Oscillator 20 MHz.
  • TRISD = 0xF0; PORTD = 0;
  • PORTD = (PORTD & 0xF0) | seq[i];
  • Delay_ms() của MikroC chỉ nhận hằng số; muốn trễ theo biến dùng Vdelay_ms(t);.

Cùng logic viết bằng XC8 (MPLAB X)

  • #pragma config FOSC = HS, WDTE = OFF, PWRTE = ON, BOREN = ON, LVP = OFF, CPD = OFF, WRT = OFF, CP = OFF
  • #define _XTAL_FREQ 20000000
  • __delay_ms() và __delay_us() chỉ nhận hằng số. Trễ theo biến: viết vòng lặp for (k = 0; k < t; k++) __delay_us(100);.

Phát xung STEP/DIR cho A4988, TB6600

  • RD1 = dir; (đặt chiều trước, chờ vài micro giây)
  • RD0 = 1; __delay_us(5); RD0 = 0;
  • Chờ phần còn lại của chu kỳ bước rồi lặp lại.

Bảng quy đổi số bước ra góc quay

Motor / chế độBước mỗi vòng90° cần bao nhiêu bước
Hybrid 1,8°, full step (A4988 để 1/1)20050
Hybrid 1,8°, vi bước 1/81.600400
Hybrid 1,8°, vi bước 1/163.200800
PM 7,5° tháo máy in, full step4812
PM 7,5°, half step9624

Muốn quay đúng một góc, đếm số bước trong vòng lặp hoặc trong ngắt rồi dừng khi đủ. Với motor có hộp số như 28BYJ-48, số bước mỗi vòng khác hẳn; con số thật có ở bài động cơ bước 5 dây.

6. Tạo xung bằng delay hay bằng Timer và ngắt

Code dùng delay dễ hiểu và đủ cho bài thực hành đầu tiên, nhưng đến khi thêm LCD, phím và biến trở thì tốc độ motor bắt đầu dao động. Lý do: mỗi lần ghi LCD mất vài trăm micro giây đến vài mili giây, mỗi lần đọc ADC mất khoảng 20 µs, và tất cả các khoảng đó cộng vào khoảng cách giữa hai bước.

Cách tính Timer1 ở 20 MHz

Timer1 đếm xung Fosc/4 = 5 MHz. Đặt bộ chia trước (prescaler) 1:8, mỗi lần đếm là 1,6 µs, Timer1 16 bit tràn sau tối đa 65.536 × 1,6 µs ≈ 104,9 ms. Như vậy một ngắt Timer1 phủ được chu kỳ bước từ vài chục micro giây đến khoảng 105 ms, tức 10 bước/giây đến hàng nghìn bước/giây, đủ cho hầu hết motor.

  • Số đếm cần: N = chu kỳ bước / 1,6 µs. Ví dụ bước 5 ms → N = 3.125.
  • Kiểu nạp lại thủ công: trong ngắt ghi TMR1 = 65.536 − N (ở ví dụ là 62.411), rồi xuất bước tiếp theo.
  • Kiểu dùng CCP1 Compare: đặt CCPR1 = N, chế độ CCP1M = 1011 (special event trigger). Khi Timer1 bằng CCPR1, phần cứng tự xóa Timer1 về 0 và bật cờ ngắt CCP1IF. Không phải nạp lại TMR1 bằng phần mềm nên chu kỳ chính xác tuyệt đối, chỉ còn trễ vào ngắt vài micro giây.

Trong hàm ngắt nên làm gì

  • Xóa cờ ngắt (TMR1IF hoặc CCP1IF).
  • Xuất trạng thái pha tiếp theo, hoặc tạo một xung STEP ngắn.
  • Tăng/giảm biến đếm vị trí, so với vị trí đích, dừng khi đủ.
  • Không ghi LCD, không đọc ADC, không gọi delay dài trong ngắt.

Vì sao không dùng module PWM của CCP để phát xung STEP ở tốc độ thấp

Với thạch anh 20 MHz, tần số PWM thấp nhất của PIC16F877A là Fosc / (4 × 16 × 256) ≈ 1.220 Hz (Timer2 prescaler tối đa 1:16, PR2 = 255). Motor 1,8° full step ở 1.220 bước/giây đã là hơn 360 vòng/phút, không thể khởi động thẳng ở tốc độ này. PWM phần cứng chỉ hợp khi dùng vi bước cao (1/16 trở lên) và có cách đếm xung riêng. Với đồ án thông thường, Timer1 + Compare là lựa chọn đúng.

Tăng tốc và giảm tốc mềm

Tải quán tính sẽ làm motor mất bước nếu khởi động ngay ở tốc độ cao. Cách làm trên PIC: bắt đầu với chu kỳ bước dài (ví dụ 10 ms), mỗi bước giảm chu kỳ một lượng nhỏ cho tới chu kỳ đích; gần tới vị trí dừng thì làm ngược lại. Có thể tính trước một bảng 32–64 giá trị chu kỳ, lưu trong ROM bằng mảng const, để trong ngắt chỉ cần tra bảng thay vì tính phép chia. Phần lý thuyết gia tốc hình thang, S-curve và chọn driver có ở bài điều khiển động cơ bước lưỡng cực.

7. Đọc biến trở bằng ADC để chỉnh tốc độ

Biến trở 10 kΩ đấu kiểu chia áp: hai đầu ngoài lên 5 V và mass, chân giữa vào RA0/AN0, thêm tụ 100 nF từ AN0 xuống mass để lọc nhiễu motor.

Cấu hình ADC cho PIC16F877A ở 20 MHz

Thanh ghi / tham sốGiá trịÝ nghĩa
ADCON10x8EChỉ AN0 là analog, các chân PORTA/PORTE còn lại số; kết quả căn phải
Xung ADCFosc/32TAD = 1,6 µs, đúng mức tối thiểu cho phép
Thời gian thu mẫu≥ khoảng 20 µsChờ sau khi chọn kênh, trước khi bắt đầu chuyển đổi
Kết quả0–1023Ghép ADRESH:ADRESL

Trong CCS C dùng setup_adc(ADC_CLOCK_DIV_32); setup_adc_ports(AN0); set_adc_channel(0); delay_us(20); v = read_adc(); (khai báo #device ADC=10 để lấy đủ 10 bit). Trong MikroC dùng ADC_Read(0).

Quy đổi giá trị ADC thành chu kỳ bước

  • Ánh xạ tuyến tính: chu kỳ = Tmin + (1023 − v) × (Tmax − Tmin) / 1023. Vặn biến trở lên, chu kỳ ngắn lại, motor quay nhanh.
  • Giới hạn Tmin theo khả năng motor (ví dụ motor PM 7,5° với ULN2003 khoảng 2–3 ms mỗi bước; motor hybrid qua A4988 tùy vi bước).
  • Đọc ADC trong vòng lặp chính, khoảng 20–50 lần mỗi giây là đủ; ghi giá trị mới vào biến chu kỳ, hàm ngắt lấy giá trị này ở bước tiếp theo.
  • Lọc trung bình 4–8 lần đọc để tốc độ không rung theo nhiễu.

Nếu ứng dụng chỉ cần quay liên tục với tốc độ chỉnh bằng núm vặn, không cần định vị (băng tải nhỏ, máy khuấy, quay rang), động cơ giảm tốc mini kèm bộ điều tốc thường gọn và khỏe hơn một mạch PIC + động cơ bước.

8. Phím nhấn và LCD 16x2 trong đồ án

Phím nhấn trên PORTB

PORTB có trở kéo lên nội, bật bằng cách xóa bit RBPU của thanh ghi OPTION_REG (trong CCS: port_b_pullups(TRUE);). Phím nối từ chân RB xuống mass, không cần điện trở ngoài; nhấn là mức 0.

  • Chống dội: khi thấy mức 0, chờ 20–30 ms rồi đọc lại, xác nhận mới xử lý, sau đó chờ nhả phím.
  • Nếu tạo xung bằng Timer1, quét phím trong vòng lặp chính hoặc dùng Timer0 tràn mỗi khoảng 10 ms để đếm thời gian chống dội, không dùng delay dài.
  • Công tắc hành trình hoặc nút dừng khẩn nên đưa vào RB0/INT để phản ứng ngay trong ngắt, không chờ vòng lặp.

Phân công điển hình: RB1 chạy/dừng (bật, tắt TMR1ON), RB2 đảo chiều, RB4 đổi chế độ full/half step, RB5 nhập số vòng hoặc số độ, RB0/INT công tắc gốc.

LCD 16x2 (HD44780) chế độ 4 bit

LCD cần 6 chân: RS, E và D4–D7; chân RW nối mass (chỉ ghi). Chân V0 nối con trượt biến trở 10 kΩ để chỉnh tương phản, chân A/K là đèn nền (thường cần điện trở hạn dòng nếu module không có sẵn). Thư viện lcd.c của CCS mặc định dùng PORTD; nếu nibble thấp PORTD đã dành cho motor, phải sửa định nghĩa chân của thư viện để LCD sang PORTB/PORTC, hoặc chuyển motor sang PORTC. Trong MikroC, chân LCD khai báo bằng các biến sbit LCD_RS at ..., đổi cổng tùy ý.

  • Chỉ ghi lại LCD khi nội dung thay đổi (tốc độ, chiều, số bước), không xóa màn hình mỗi vòng lặp; lệnh xóa màn hình (clear) mất khoảng 1,5 ms và làm chữ nhấp nháy.
  • Hiển thị tốc độ theo vòng/phút: rpm = 60 / (chu kỳ bước × số bước mỗi vòng). Ví dụ 200 bước/vòng, 5 ms mỗi bước → 60 vòng/phút.

9. Mô phỏng Proteus mạch PIC16F877A điều khiển động cơ bước

Proteus có sẵn model PIC16F877A, ULN2003A, L298 và MOTOR-STEPPER (chọn được đơn cực hoặc lưỡng cực, góc bước, điện trở cuộn), đủ để chạy thử toàn bộ đồ án trước khi làm mạch.

Các bước mô phỏng

  • Biên dịch ra file .hex (CCS, MikroC, XC8 đều xuất được).
  • Nhấp đúp PIC16F877A, mục Program File chọn file .hex, mục Processor Clock Frequency gõ 20MHz. Proteus lấy xung nhịp từ ô này, linh kiện thạch anh vẽ trên sơ đồ không quyết định tốc độ mô phỏng.
  • Chân VDD, VSS của PIC bị ẩn và tự nối nguồn; chân MCLR thì không, vẫn phải kéo lên 5 V qua điện trở.
  • Đặt điện áp và điện trở cuộn của MOTOR-STEPPER sát motor thật; model sẽ hiển thị góc quay trên thân motor.

Proteus không đòi tụ thạch anh, tụ lọc nguồn, không mô phỏng quán tính tải và sụt áp nguồn, nên mạch chạy được trong mô phỏng chưa chắc chạy ngoài thực tế. Cảnh báo "simulation not running in real time" chỉ là máy tính không theo kịp khi xung quá dày, không phải lỗi code.

Các tình huống motor lắc qua lại trong Proteus do sai thứ tự cuộn đã có hướng xử lý ở bài điều khiển động cơ bước bằng L293; với PIC16F877A, cần kiểm tra thêm ADCON1 nếu dùng chân PORTA/PORTE làm ngõ ra và giá trị TRISD.

10. Nạp chip bằng PICkit qua cổng ICSP

PIC16F877A nạp được tại mạch qua 5 dây ICSP. Đặt sẵn một hàng rào 5–6 chân trên PCB giúp sửa code nhiều lần mà không phải nhổ chip.

Chân PICkitNối tới PIC16F877ALưu ý
1 – VPP/MCLRChân 1Vẫn giữ trở 10 kΩ lên 5 V, không gắn tụ lớn
2 – VDDChân 11/32 (5 V)Mạch có nguồn riêng thì không cho PICkit cấp nguồn
3 – VSSChân 12/31Mass chung
4 – PGDRB7 (chân 40)Không treo tải nặng
5 – PGCRB6 (chân 39)Không treo tải nặng
6 – PGM (LVP)RB3 (chân 36)Chỉ dùng khi nạp điện áp thấp; nạp thường không cần

Phần mềm

  • PICkit 3, PICkit 4, PICkit 5: dùng MPLAB X IPE, chọn thiết bị PIC16F877A, nạp file .hex.
  • PICkit 2 (và các bản tương thích): dùng phần mềm PICkit 2 Programmer độc lập, PIC16F877A nằm trong danh sách hỗ trợ.
  • PICkit chỉ cấp được dòng nhỏ (vài chục mA); nếu mạch có LCD đèn nền, driver, relay thì cấp nguồn ngoài cho mạch và tắt chức năng cấp nguồn của PICkit.

Bit LVP và chân RB3

Chip mới xuất xưởng có thể bật LVP (lập trình điện áp thấp). Khi LVP bật, RB3 là chân PGM: nếu chân này để hở hoặc nhận nhiễu lên mức cao, chip có thể vào chế độ lập trình và ngừng chạy chương trình. Luôn tắt LVP trong config (NOLVP / LVP = OFF) và nạp bằng điện áp cao thông thường; sau đó RB3 mới dùng làm I/O bình thường.

11. Lỗi thường gặp khi điều khiển động cơ bước dùng PIC16F877A

Hiện tượngNguyên nhân hay gặpCách xử lý
Nạp xong mạch không làm gì, LED không sángConfig XT/RC với thạch anh 20 MHz, thiếu tụ thạch anh, MCLR để hởConfig HS, tụ 15–22 pF, trở 10 kΩ ở MCLR
Chạy được một lúc rồi đứngWDT đang bật mà code không xóaTắt WDT hoặc gọi lệnh xóa WDT định kỳ
Chạy chập chờn, chạm tay vào chip thì chạyRB3 nổi khi LVP bật, MCLR không kéo lênTắt LVP, kiểm tra trở MCLR
Ngõ ra PORTA, PORTE không đổi mứcChân còn ở chế độ analogGhi ADCON1 (0x06 cho toàn bộ số, 0x8E nếu chỉ dùng AN0)
RA4 không lên mức caoRA4 là cực máng hởThêm trở kéo lên hoặc đổi chân
PIC reset mỗi khi motor bắt đầu quaySụt áp, nhiễu mass từ motor, thiếu tụTụ 100 nF tại VDD, tụ lớn ở nguồn motor, mass hình sao, BOR bật
Motor rung tại chỗ, không quaySai thứ tự pha, chu kỳ bước quá ngắnĐổi thứ tự trong mảng, tăng chu kỳ bước, thêm tăng tốc mềm
Tốc độ thay đổi khi LCD cập nhậtTạo xung bằng delay trong vòng lặpChuyển sang Timer1 + ngắt
Motor và ULN2003/L298 rất nóng khi đứng yênVẫn cấp điện cuộn dây khi dừngXuất 0x00 ra các pha khi không cần giữ lực

Không cắm, rút dây motor khi mạch đang có điện, nhất là với A4988, DRV8825.

12. Gợi ý đề tài và giới hạn của PIC16F877A với động cơ bước

PIC16F877A đủ dùng cho các đề tài: bàn xoay chụp ảnh sản phẩm 360°, rèm/cửa trượt mô hình, cơ cấu cấp phôi theo số bước, bơm định lượng bằng động cơ bước, máy quấn dây đếm vòng, đồng hồ kim dùng motor nhỏ. Với hai motor, mỗi motor dùng một nibble PORTD (ULN2003/L298) hoặc hai cặp STEP/DIR; một ngắt Timer1 có thể phục vụ cả hai bằng cách đếm chu kỳ riêng cho từng motor.

Giới hạn cần biết trước khi chọn PIC16F877A

  • Không có dao động nội: luôn cần thạch anh.
  • Tạo xung bằng phần mềm nên chạy nội suy nhiều trục đồng thời (như máy CNC 3 trục) rất vất vả; việc đó hợp với firmware GRBL trên vi điều khiển khác hoặc bo điều khiển chuyên dụng.
  • Xung STEP tối đa thực tế trong ngắt khoảng vài kHz đến khoảng 10 kHz mỗi kênh, tùy độ dài hàm ngắt; đủ cho NEMA 17 vi bước thấp, không đủ cho vi bước 1/32 ở tốc độ cao.
  • Nếu ứng dụng cần lực lớn, tốc độ cao và phản hồi vị trí (máy công nghiệp), PIC chỉ nên làm phần giao diện; phần chuyển động giao cho driver chuyên dụng hoặc motor servo có driver riêng nhận xung.

Cách chọn loại motor cho đề tài (PM nhỏ, hybrid NEMA 17, có hộp số) xem trang tổng quan động cơ bước; với motor 4 dây lưỡng cực cầm trên tay, quy trình tìm cặp cuộn và chạy lần đầu có ở bài điều khiển động cơ bước 4 dây.

13. Câu hỏi thường gặp về điều khiển động cơ bước dùng PIC16F877A

  • Dùng thạch anh 4 MHz hoặc 8 MHz thay cho 20 MHz được không? Được. Với 4 MHz chọn config XT, với 8–20 MHz chọn HS. Phải sửa khai báo tần số trong code (#use delay(clock=4M) hoặc _XTAL_FREQ) và tính lại giá trị Timer1, vì chu kỳ lệnh lúc này là 1 µs thay vì 200 ns. Ở 4 MHz, ADC nên dùng xung Fosc/8 trở lên để TAD không dưới 1,6 µs.
  • Vì sao code chạy đúng trong Proteus nhưng nạp vào mạch thật thì không chạy? Proteus bỏ qua nhiều điều kiện mà chip thật bắt buộc: tụ thạch anh, tụ lọc nguồn, config dao động đúng loại, LVP tắt, WDT tắt. Hãy kiểm tra lần lượt nguồn 5 V tại chân 11/32, điện áp chân MCLR (phải gần 5 V), config bits trong file .hex, rồi nạp thử chương trình nháy LED để chắc chip đã chạy trước khi gắn motor.
  • PIC16F877A có điều khiển được driver TB6600 hay DM542 không? Có. Ngõ ra 5 V của PIC kéo được opto của driver: nối PUL+, DIR+ vào chân PIC, PUL−, DIR− về mass, không cần điện trở thêm vì 5 V là mức chuẩn của các driver này. Chỉ cần giữ xung STEP ở mức cao khoảng 5 µs trở lên và đặt DIR trước xung đầu tiên vài micro giây.
  • Một PIC16F877A điều khiển được mấy động cơ bước? Về chân, PORTD và PORTC đủ cho bốn motor qua ULN2003/L298, hoặc nhiều hơn nếu dùng driver STEP/DIR. Giới hạn thật là thời gian xử lý trong ngắt: chạy đồng thời hai đến bốn motor ở tốc độ vừa phải là hợp lý; nhiều hơn nên chuyển sang vi điều khiển mạnh hơn hoặc dùng bo chuyên dụng.
  • Nên viết code bằng CCS C, MikroC hay XC8? CCS C có nhiều hàm dựng sẵn (output_d, read_adc, lcd.c) nên viết nhanh, hợp đồ án ngắn ngày. MikroC có thư viện LCD, ADC, phím rất gọn và trình cấu hình config trực quan. XC8 là trình biên dịch chính thức của Microchip trong MPLAB X, bản miễn phí đủ dùng, viết theo thanh ghi nên dễ chuyển sang PIC đời mới.
  • Có dùng module PWM của PIC16F877A để phát xung STEP được không? Chỉ khi cần tần số cao. Ở 20 MHz, PWM phần cứng không xuống được dưới khoảng 1.220 Hz và không tự đếm số xung, nên không khởi động motor từ tốc độ thấp và không định vị được. Dùng Timer1 với CCP Compare để tạo chu kỳ bước, mỗi ngắt phát một xung, vừa kiểm soát tốc độ vừa đếm được vị trí.
  • Làm sao để động cơ quay đúng 90° hoặc đúng một số vòng rồi dừng? Tính số bước cần: số bước = góc / góc mỗi bước (đã tính vi bước). Motor 1,8° full step cần 50 bước cho 90°, vi bước 1/16 cần 800 bước. Trong hàm ngắt đếm từng bước, khi đủ thì tắt Timer1; nên có công tắc gốc để xác định vị trí 0 mỗi lần bật máy vì motor vòng hở không biết vị trí ban đầu.
  • PICkit báo không tìm thấy chip hoặc đọc sai Device ID, xử lý thế nào? Kiểm tra thứ tự 5 dây ICSP (chân 1 PICkit có dấu tam giác là VPP), mạch đã có nguồn hoặc đã bật cấp nguồn từ PICkit, chân MCLR không có tụ lớn, RB6/RB7 không treo LED hay IC khác.
  • Có thay PIC16F877A bằng PIC16F887 mà giữ nguyên mạch được không? Gần như được vì cùng sơ đồ chân 40 chân và cùng các cổng. Cần sửa code: PIC16F887 cấu hình analog bằng ANSEL/ANSELH thay cho ADCON1, có dao động nội 8 MHz (có thể bỏ thạch anh), config bits có tên khác.
  • Vì sao vặn biến trở mà tốc độ motor đổi giật cục hoặc chỉ có vài nấc? Thường do chỉ đọc ADC 8 bit, ánh xạ thẳng giá trị vào hàm delay tính bằng mili giây (mỗi nấc 1 ms là quá thô ở tốc độ cao), hoặc ADC bị nhiễu. Đọc đủ 10 bit, tính chu kỳ theo micro giây qua Timer1, thêm tụ 100 nF tại chân AN0 và lấy trung bình vài lần đọc.
  • LCD 16x2 chỉ hiện một hàng ô vuông đen, không ra chữ là do đâu? Hàng ô đen nghĩa là LCD có nguồn nhưng chưa được khởi tạo. Kiểm tra định nghĩa chân RS, E, D4–D7 trong thư viện có trùng với mạch không, chân RW đã nối mass chưa, độ trễ khởi tạo sau khi cấp nguồn, và chỉnh biến trở tương phản V0.
  • Có dùng chân RB6, RB7 để điều khiển motor được không? Được sau khi nạp xong, nhưng không nên. Hai chân này là PGC, PGD của ICSP; treo ULN2003 hay driver lên đó dễ làm PICkit nạp lỗi, và mỗi lần nạp motor có thể giật. Nên để RB6, RB7 cho phím nhấn có trở kéo lên hoặc bỏ trống, dùng PORTD/PORTC cho motor.
3.120 reviews

Tin tức liên quan

Hộp giảm tốc harmonic: thông số, model CSF, SHF và cách chọn

Hộp giảm tốc harmonic: thông số, model CSF, SHF và cách chọn

14 thg 10 2026 15:12

Hộp giảm tốc harmonic (strain wave) size 14 – 32, tỉ số 1/50 – 1/120, mô men 5,4 – 137 Nm. Cách đọc tem, phân loại CSF, CSG, SHF-2UH, SHF-2UJ, SHF-2SO, SHD-2SH và cách chọn theo servo.
Đọc tiếp
Khám phá Bí Quyết Điều Khiển Động Cơ RC Servo Chính Xác Bằng STM32F4

Khám phá Bí Quyết Điều Khiển Động Cơ RC Servo Chính Xác Bằng STM32F4

15 thg 4 2025 20:44

Điều khiển động cơ RC Servo bằng STM32F4 mang đến độ chính xác cao và khả năng tùy chỉnh tín hiệu PWM tối ưu. Bài viết này hướng dẫn từ cấu hình bộ định thời, lập trình tín hiệu PWM, đến tối ưu hóa hiệu suất động cơ. Đây là giải pháp lý tưởng cho kỹ sư điện, kỹ sư cơ khí và các doanh nghiệp công nghiệp.
Đọc tiếp
Điều khiển động cơ RC servo bằng PWM: chu kỳ, độ rộng xung và cách tạo xung bằng timer

Điều khiển động cơ RC servo bằng PWM: chu kỳ, độ rộng xung và cách tạo xung bằng timer

10 thg 10 2026 17:36

Điều khiển động cơ RC servo bằng PWM: chu kỳ 20 ms, độ rộng xung 500–2500 µs, tính prescaler cho AVR, STM32, ESP32, PCA9685, mạch 555 và cách đo kiểm.
Đọc tiếp
Cách Điều Khiển Động Cơ DC Servo Chính Xác Bằng Giải Thuật PID

Cách Điều Khiển Động Cơ DC Servo Chính Xác Bằng Giải Thuật PID

12 thg 10 2026 08:32

Điều khiển động cơ DC Servo bằng giải thuật PID mang lại sự ổn định và hiệu suất cao cho hệ thống công nghiệp. Tìm hiểu cách áp dụng Proportional-Integral-Derivative, vi điều khiển và encoder để tối ưu hóa tốc độ và vị trí của động cơ. Phương pháp này được sử dụng rộng rãi trong robot, dây chuyền sản xuất và các hệ thống tự động hóa.
Đọc tiếp
Điều khiển động cơ DC servo: vòng dòng – tốc độ – vị trí, PID, encoder và cầu H

Điều khiển động cơ DC servo: vòng dòng – tốc độ – vị trí, PID, encoder và cầu H

12 thg 10 2026 08:32

Hướng dẫn điều khiển động cơ DC servo: 3 vòng dòng – tốc độ – vị trí, đọc encoder x4, cầu H BTS7960/VNH5019, PWM 20 kHz, chỉnh PID và code Arduino mẫu.
Đọc tiếp