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

bài giảng vi xử lí lập trình pic16f887

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.66 MB, 25 trang )

6/16/2018

CHƯƠNG 3
NGÔN NGỮ LẬP TRÌNH
VI ðIỀU KHIỂN

GV: Vũ Thị Hồng Nga

Khoa Công Nghệ Điện Tử

1. TỔNG QUAN LẬP TRÌNH CHO VI ĐIỀU KHIỂN
• Vi điều khiển truyền thông với con người thông qua ngôn ngữ lập trình
• Ngôn ngữ lập trình: cấp thấp hoặc cấp cao
• Ngôn ngữ lập trình được sử dụng trong bài học này là ngôn ngữ C.

2

1


6/16/2018

1. TỔNG QUAN LẬP TRÌNH CHO VI ĐIỀU KHIỂN
• Hợp ngữ là một tập các qui luật (lệnh) được dùng để viết
chương trình cho vi điều khiển
• Để vi điều khiển có thể hiểu một chương trình được viết bằng
hợp ngữ thì nó cần phải được biên dịch thành ngôn ngữ máy.
• Assembly: là một tập các qui luật (lệnh) được dùng để viết
chương trình cho vi điều khiển
• Assembler: là một chương trình trên máy tính dùng để dịch các
phát biểu hợp ngữ sang ngôn ngữ của các con số 0 hoặc 1.



3

• Chương trình (Program) / Mã nguồn (Source Code):
• Là tập tin dữ liệu được lưu trên máy tính
• Được thể hiện bằng hợp ngữ (hoặc các ngôn ngữ khác: ngôn ngữ C)
• Định dạng tập tin là .ASM và .C( ngôn ngữ C).

4

2


6/16/2018

• Thực thi (Executive) / Mã máy (Machine Code):
• Là tập tin dữ liệu được lưu trên máy tính hoặc nạp PIC
• Được thể hiện bằng các con số 0 hoặc 1
• Định dạng tập tin là .HEX (Ví dụ: Program.hex).

5

• Chương trình sau khi biên dịch sẽ được nạp vào vi điều khiển
bằng các bộ lập trình (Programmer) chuyên dụng dành cho PIC.

6

3



6/16/2018

• Vi điều khiển sau khi được lập trình sẽ được gắn vào bo mạch
chủ để điều khiển toàn hệ thống hoạt động theo chương trình
mà không cần sự can thiệp của con người.

7

2. Nhắc lại kiến thức ngôn ngữ lập trình C
Các thành phần chính của chương trình

- Khai báo thư viện
- Chương trình chính có tên là main, chương trình sẽ bắt
đầu chạy tại chỗ này.
- Chương trình bắt đầu bằng dấu { và kết thúc bằng dấu }

4


6/16/2018

Kiểu số nguyên có dấu
• Miền giá trị (số n-bit): -2n-1 .. +2n-1 – 1
Kiểu
(Type)

ðộ lớn
(Byte)

Miền giá trị

(Range)

char

1

–128 … +127

int

2
4

–32.768 … +32.767
–2.147.483.648 … +2.147.483.647

short

2

–32.768 … +32.767

long

4

–2.147.483.648 … +2.147.483.647

long long


8

–9,223,372,036,854,775,808
… 9,223,372,036,854,775,807

Một số môi trường lập trình ñồng nhất kiểu long long với kiểu long
cho nên kiểu này ít ñược sử dụng trong lập trình ứng dụng.
9

Kiểu số nguyên không dấu
• Miền giá trị (số n-bit): 0 .. 2n – 1
Kiểu
(Type)

ðộ lớn
(Byte)

Miền giá trị
(Range)

unsigned char

1

0 … 255

unsigned int

2
4


0 … 65535
0 … 4.294.967.295

unsigned short

2

0 … 65535

unsigned long

4

0 … 4.294.967.295

unsigned long long

8

0…
18,446,744,073,709,551,615

Một số môi trường lập trình ñồng nhất kiểu unsigned long long với kiểu
unsigned long cho nên kiểu này ít ñược sử dụng trong lập trình ứng dụng.
10

5



6/16/2018

• Hằng số nguyên có thể biểu diễn ở 4 dạng
• Bát phân: viết bắt đầu bằng số 0
• Nhị phân: viết bắt đầu bằng số 0B
• Thập phân: viết bắt đầu bằng số từ 1 đến 9
• Thập lục phân: viết đầu bằng 0x
VD: PORTA = 0X4A = 0B01001010

• Các phép toán số học
• Phép cộng: +, phép trừ: –, phép nhân: *
• Phép chia lấy phần nguyên: /
• Phép chia lấy phần dư: %

11

Toán tử trên bit

12

6


6/16/2018

VD: phép toán trên bit cho số nguyên không dấu
#include <stdio.h>
void main()
{
unsigned char a = 45;

00101101

//

unsigned char b = 58;
00111010

//

int c1, c2, c3, c4, c5, c6;
c1 = a & b;

// 00101000

c2 = a | b;

// 00111111

c3 = a ^ b;

// 00010111

c4 = ~a;

// 11010010

c5 = a >> 4;

// 11010000


c6 = a << 4;

// 00000010

}

13

Toán tử quan hệ

7


6/16/2018

Phép toán luận lý
Có 3 kiểu phép toán luận lý trong ngôn ngữ C, ñó là AND, OR và
NOT. Phép toán logic trả về kết quả true (1) nếu kết quả của biểu thức
khác 0, trả về kết quả false (0) nếu kết quả của biểu thức bằng 0.

Phép gán
• Việc tính toán trong chương trình được thực hiện bằng cách
tính toán và chép kết quả tính toán vào một biến nằm bên
trái của phép gán.
• Ví dụ:

sum = A + B;
sum = A + 2;
sum = A + n;


// chép tổng A + B vào biến sum
// chép tổng A + 2 vào biến sum
// chép tổng A + n vào biến sum

16

8


6/16/2018

Định dạng dữ liệu nhập xuất
•Đối với NNLT C
•Nhập xuất số nguyên (kiểu char, int)
• Có dấu dạng thập phân: %d hay %i
• Không dấu:
• Dạng thập phân: %u
• Dạng thập lục phân: %x hay %X
• Dạng bát phân: %o

•Trường hợp nhập xuất số nguyên kiểu
khác:
• short (16-bit): %hd, %hi, %ho, %hu, %hx, %hX
• long: %ld, %li, %lo, %lu, %lx, %lX
17

ðịnh dạng dữ liệu nhập xuất
• ðối với NNLT C
• Ký tự ñặc biệt: \\ (dấu \) và %% (dấu %)
• Ký tự tab và ký tự xuống dòng: \t, \n, \r

• Nhập xuất ký tự: %c
• Nhập xuất chuỗi ký tự: %s
• Về việc quy ñịnh ñộng rộng và ñộ chính xác (nếu là
số thực) cho dữ liệu xuất ñược ghi ngay sau dấu %
với dạng wid.pre, ví dụ %9.2f nghĩa là ñộ rộng ít nhất
9 ký tự (thêm khoảng trống vào nếu thiếu) và nhiều
nhất là 2 ký tự cho phần lẻ sau dấu chấm thập phân.

18

9


6/16/2018

Biến toàn cục & biến cục bộ
• Biến toàn cục (Global variables): vị trí biến đặt bên ngoài tất
cả các hàm, cấu trúc...Các biến này có ảnh hưởng đến toàn
bộ chương trình. Chu trình sống của nó là bắt đầu chạy
chương trình đến lúc kết thúc chương trình.
• Biến cục bộ (Local variables): Vị trí biến đặt bên trong hàm,
cấu trúc…. Chỉ ảnh hưởng nội bộ bên trong hàm, cấu trúc
đó…. Chu trình sống của nó bắt đầu từ lúc hàm, cấu trúc
được gọi thực hiện đến lúc thực hiện xong.

19

Cấu trúc điều khiển có 2 loại:
Cấu trúc điều khiển rẽ nhánh:
if else

switch

Cấu trúc điều khiển vòng lặp:
for
while
do while

10


6/16/2018

Cấu trúc điều khiển rẽ nhánh if:
if
(biểu_thức_ñiều_kiện)
{
Lệnh 1;
Lệnh 2;

Lệnh n;
}
else
{
Lệnh 1;
Lệnh 2;

Lệnh n;
}

Cấu trúc điều khiển

rẽ nhánh switch:

if
(biểu_thức_ñiều_kiện)
{
Lệnh 1;
Lệnh 2;

Lệnh n;
}

switch (biểu_thức_chọn)
{
case Giá_Trị_1:
Lệnh 1;
..
Lệnh n;
break;
case Giá_Trị_2:
Lệnh 1;
..
Lệnh n;
break;
default:
Lệnh 1;
..
Lệnh n;
break;
}


11


6/16/2018

Cấu trúc điều khiển vòng lặp:
while (điều_kiện_lặp)
{
Lệnh 1;
Lệnh 2;

Lệnh n;
}

for (biểu_thức_1;biểu_thức_2;biểu_thức_3)
{
Lệnh 1;
Lệnh 2;

Lệnh n;
}

Câu lệnh return
• Trả về dòng điều khiển mà nơi nó gọi, khi lệnh return được
theo sau bởi một biểu thức thì biểu thức đó sẽ được đánh
giá và giá trị này sẽ được trả về cho nơi đã gọi hàm. Khi
return được gọi mà không có biểu thức đi kèm thì giá trị trả
về là không xác định.
• Câu lệnh return không chỉ thoát khỏi vòng lặp mà nó còn
thoát luôn khỏi hàm mà đang chứa nó.


24

12


6/16/2018

Định nghĩa hàm
return-type function_name(param-type param_name,
…, param-type param_name)
{
// statements here…
}
• Trong đó:
• return-type: kiểu của giá trị hàm sẽ trả về, nếu không trả về gì
cả thì kiểu trả về sẽ là void.
• function_name: tên của hàm, thể hiện công việc hàm sẽ làm,
nên bắt đầu bằng một động từ.
• param-name, param-type: tên và kiểu tương ứng của tham số
hình thức (formal parameter).
• Tiếp theo là thân hàm (đặt trong {}) chứa các câu lệnh hàm sẽ
thực hiện (phải có ít nhất một lệnh return nếu kiểu trả về
không phải là void)
25

3. Lưu đồ giải thuật

13



6/16/2018

VD: Giải và biện luận phương trình bậc nhất: ax + b = 0

SV chuẩn bị các phần mềm và tài liệu sau
- phần mềm viết code: MPLAB
- phần mềm mô phỏng : PROTEUS
- Sách Thực hành vi xử lý

14


6/16/2018

Phần mềm viết code MPLAB

Phần mềm mô phỏng proteus

15


6/16/2018

KIT RP hoặc mô hình thí nghiệm vi xử lý

Bộ nạp chip PICKIT 2

VD1: lập trình điều khiển led đơn D4 và D5 chớp tắt với
Ton = Toff = 500ms

C7

Y1
4MHz

OSC2

22p

U2
MCLR

1

OSC2
OSC1

2
3
4
5
6
7
14
13

OSC1
+5V

C6

22p

R2
10K

R49

MCLR

100R

SW1

C10
0.1uF

33
34
35
36
37
38
39
40

BAI TAP UNG DUNG DIEU KHIEN XUAT/NHAP CO BAN

RE3/MCLR/VPP

RC0/T1OSO/T1CKI

RC1/T1OSI/CCP2
RA0/AN0/ULPW U/C12IN0RC2/P1A/CCP1
RA1/AN1/C12IN1RC3/SCK/SCL
RA2/AN2/VREF-/CVREF/C2IN+ RC4/SDI/SDA
RA3/AN3/VREF+/C1IN+
RC5/SDO
RA4/T0CKI/C1OUT
RC6/TX/CK
RA5/AN4/SS/C2OUT
RC7/RX/DT
RA6/OSC2/CLKOUT
RA7/OSC1/CLKIN
RD0
RD1
RB0/AN12/INT
RD2
RB1/AN10/C12IN3RD3
RB2/AN8
RD4
RB3/AN9/PGM/C12IN2RD5/P1B
RB4/AN11
RD6/P1C
RB5/AN13/T1G
RD7/P1D
RB6/ICSPCLK
RB7/ICSPDAT
RE0/AN5
RE1/AN6
RE2/AN7


15
16
17
18
23
24
25
26
19
20
21
22
27
28
29
30
8
9 RE1
10 RE2

RE2

R12

D5

470
LED

RE1


R13

D4

470
LED

PIC16F887

16


6/16/2018

Lưa đồ giải thuật:

Begin
Start
Cấu hình tất cả
Analog Input → Digital I/O
Cấu hình Port E
Output
Loop
ðiều khiển LED
D4, D5 = OFF
Delay 500ms
ðiều khiển LED
D4, D5 = ON
Delay 500ms


#include <htc.h>
#include <math.h>
__CONFIG (FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF &
BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
#define _XTAL_FREQ 4000000
void main()
{
ANSEL = 0X00;
ANSELH = 0X00;
TRISE = 0X00;
while(1)
{
PORTE = 0X00;
__delay_ms(500); //su dung 5 lan ham __delay_ms(100)
PORTE = 0X06;
__delay_ms(500);
}
}

17


6/16/2018

Bài tập 1: lập trình điều khiển 8 led đơn D1 và D7 nối với PORTD
chớp tắt với Ton = Toff = 300ms

Ví dụ 2: Dựa vào sơ đồ, viết chương trình điều khiển LED sáng dần
D1 → D8. Led nối với port C


18


6/16/2018

• Giải thuật:

Bảng dữ liệu Table
b'00000000
b'00000001
b'00000011
b'00000111
b'00001111
b'00011111
b'00111111
b'01111111
b'11111111

Begin
Start
Cấu hình tất cả
Analog Input → Digital I/O
Cấu hình Port C
Output
Loop
Xóa giá trị ñộ lệch (vị trí) của
dữ liệu trong bảng Table
Loop_1
Lấy giá trị ñộ lệch của

dữ liệu
ðọc dữ liệu nhận ñược từ
bảng Table (tùy thuộc vào
giá trị ñộ lệch)
Xuất dữ liệu nhận
ñược ra Port C
Delay 500ms
Tăng giá trị ñộ lệch
Kiểm tra
ñã lấy ñủ 9 byte từ bảng
Table ?
ð

S
37

Ví dụ 2: Dựa vào sơ đồ, viết chương trình điều khiển LED sáng dần
D1 → D8
• #include <htc.h>
• #include <math.h>
• __CONFIG (FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF &
CPD_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
• #define _XTAL_FREQ 4000000
void main (void)
{
unsigned char i,j,temp;
ANSEL = 0;
ANSELH = 0;
TRISC = 0x00;
while(1)

{
PORTC = 0x00;
__delay_ms(500);

temp = 0x01;
for(j=1;j<=8;j++)
{
PORTC = temp;
__delay_ms(500);
temp = temp | (temp << 1);
}
}
}

38

19


6/16/2018

• Ví dụ 4: Dựa vào sơ đồ, viết chương trình hiển thị số 3 chớp
tắt trên 1 led7SEG (LED4)

39

Hướng dẫn:
- Xác định led 7 đoạn dùng loại nào: anode hay cathode?
- Tìm mà led 7 đoạn cho số 3
- Chọn Ton = ? Toff =?

- Xác định led hien thị nối với port nào?
- Cấu hình port: digital, output
- Xuất dữ liệu ra port

20


6/16/2018

Giải:
- led 7 đoạn dùng loại anode chung 0 sang, 1 tắt
- mã led 7 đoạn cho số 3 là 10110000 = 0XB0
- Chọn Ton = Toff = 500ms
- led hien thị nối với PORTD
- Cấu hình PORTD: digital, output
- Xuất dữ liệu ra portD

Lưu đồ giải thuật

21


6/16/2018

#include <htc.h>
#include <math.h>
__CONFIG (FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF &
BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
#define _XTAL_FREQ 4000000
void main()

{
PORTD = 0XB0;
ANSEL = 0X00;
__delay_ms(100);
ANSELH = 0X00;
__delay_ms(100);
TRISD = 0X00;
__delay_ms(100);
PORTD = 0X00;
__delay_ms(100);
while(1)
__delay_ms(100);
{
}
}
PORTD = 0XFF;
__delay_ms(100);
__delay_ms(100);
__delay_ms(100);
__delay_ms(100);
__delay_ms(100);

VD 5: viết chương trình điều khiển nút nhấn
Nhấn nút 1 (RB0) : led7seg hiển thị số 12 trong 1s
Nhấn nút 2 (RB1) : led7seg hiển thị số 24 trong 1s

44

22



6/16/2018

Lưu đồ giải thuật

#include <htc.h>
#include <math.h>
__CONFIG (FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF &
BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
#define _XTAL_FREQ 4000000
#define sw0 RB0
#define sw1 RB1
void khai_bao_port(void)
{
ANSEL = 0X00;
ANSELH = 0X00;
TRISD = 0X00;
PORTD = 0X00;
PORTC = 0X00;
TRISC = 0X00;
TRISB = 0XFF;
PORTB = 0XFF;
nRBPU = 0;
WPUB0 = 1;
WPUB1 = 1;

void delay_1s (void)
{
unsigned char i;
for (i=0;i<10;i++)

{
__delay_ms(100);
}
}

void so_24 (void)
{
PORTD = 0X99;
PORTC = 0XA4;
delay_1s();
}

void so_12 (void)
{
PORTD = 0XA4;
PORTC = 0XF9;
delay_1s();
}

}

23


6/16/2018

void main (void)
{
khai_bao_port();
while (1)

{
if(!sw0)
{
__delay_ms(10);
while(!sw0);
so_12();
PORTC = 0xFF;
PORTD = 0xFF;
}
else if(!sw1)
{
__delay_ms(10);
while(!sw1);
so_24();
PORTC = 0xFF;
PORTD = 0xFF;
}
}
}

Ví dụ 5: viết chương trình hiển thị hình “trái tim” trên led
matrix

48

24


6/16/2018


#include <htc.h>
#include <math.h>
__CONFIG (FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & CPD_OFF &
BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_ON);
#define _XTAL_FREQ 4000000
const unsigned char a[]= {0xF3,0xE1,0xC1,0x83,0xC1,0xE1,0xF3,0xFF};
void main(void)
{
unsigned char vitri,i;
ANSEL = 0X00;
ANSELH = 0X00;

while(1)
{
vitri = 0x01;
for(i=0;i<=7;i++)
{
PORTC = a[i];
PORTD = vitri;
__delay_ms(3);
PORTD = 0x00;
vitri = vitri << 1;

TRISD = 0X00;
PORTD = 0X00;
TRISC = 0X00;
PORTC = 0X00;

}


}
}

25


×