Tải bản đầy đủ (.doc) (26 trang)

BÁO cáo THỰC HÀNH lập TRÌNH CHO họ VI điều KHIỂN 8051

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 (429.28 KB, 26 trang )

BÁO CÁO THỰC HÀNH LẬP TRÌNH CHO HỌ VI ĐIỀU KHIỂN 8051

1.- Nêu cấu trúc của một chương trình viết bằng ngôn ngữ C.
- Nêu các cấu trúc với if else, while, do while, for, switch.
- Phân biệt sự khác nhau giữa while và do while.
2. - Mảng dữ liệu là gì? Cách thực hiện trong C.
- Con trỏ là gì? Cách thực hiện trong C.
- Phương pháp thực hiện với mảng, con trỏ, chuỗi kí tự.
3. - Ngắt là gì? Nêu các loại ngắt trong vi điều khiển 8051.
- Cấu trúc một chương trình có sử dụng ngắt trong KeilC và MikroC.
4. - Nêu các bước thực hiện một chương trình trong MikroC hình ảnh.
- Viết chương trình điều khiển led đơn để hiện thị chữ cái đầu của tên
sinh viên thực hiện? Vẽ lưu đồ thuật toán.
5. - Phương pháp quét ma trận bàn phím?
- Phương pháp chống nhiễu, chống đè cho nút bấm bằng phần cứng và
phần mềm.
6. - Phương pháp quét led 7 thanh?
- Viết chương trình điều khiển đếm từ 0->10---------500 và thực hiện
lại? Vẽ lưu đồ thuật tốn?
7. Viết chương trình cảnh báo q nhiệt nếu t > 40 0 C? vẽ lưu đồ thuật
tốn?
8. Viết chương trình đếm số bấm nút sử dụng ngắt và hiện thị trên led 7
thanh?. Lưu đồ thuật tốn
Câu 1. Cấu trúc của một chương trình viết bằng bằng ngữ C
Một hàm C phải bao gồm một kiểu trả về (kiểu đó trả về void nếu khơng
có giá trị trả về), một tên xác định, một danh sách các tham số để trong ngoặc
đơn (nếu danh sách này khơng có tham số nào thì ghi là void bên trong dấu
ngoặc), sau đó là khối các câu lệnh (hay khối mã) và/hay các câu lệnh return.
(Nếu kiểu trả về là void thì mệnh đề này khơng bắt buộc phải có. Ngược lại,
cũng khơng bắt buộc chỉ có một câu lệnh return mà tùy theo kỹ thuật, người lập
1




trình có thể dẫn dịng mã sao cho mọi hướng chẻ nhánh đều được trả về đúng
kiểu.)
< kiểu_trả_về> tên_hàm<danh sách tham số>
{
<các_câu_lệnh>
Return<biến hay gái trị có kiểu là kiểu_trả_về>;
}
Trong đó, <danh sách tham số> của N biến thì được khai báo như là kiểu
dữ liệu và tách rời nhau bởi dấu phẩy ,:
<kiểu_dữ_liêuh> var1, var2,…,varN;
Toàn bộ danh sách này được đặt trong ngoặc đơn ngay sau tên_hàm.
- Cấu trúc điều kiện if … else
Dạng khuyết
If (biểu thức điều kiện)
{
Khối lệnh;
}
Cách hoạt động: Đầu tiên, chương trình kiểm tra biểu thức điều kiện sau
if. Nếu biểu thức điều kiện đúng thì các câu lệnh trong khối lệnh trong cấu trúc
if được thực hiện. Ngược lại, chương trình sẽ thốt ra khỏi cấu trúc if và thực
hiện các lệnh tiếp theo sau cấu trúc if.
Biểu diễn dưới dạng lưu đồ cách hoạt động của cấu trúc if:

2


Dạng đầy đủ
if (biểu thức điều kiện)

{
Khối lệnh 1;
}
else
{
Khối lệnh 2;
}
Cách hoạt động: Đầu tiên, chương trình kiểm tra biểu thức điều kiện
sau if, nếu biểu thức điều kiện đúng thì thực hiện các câu lệnh trong khối lệnh 1.
Ngược lại, nếu biểu thức điều kiện sai sẽ thực hiện các câu lệnh trong khối lệnh
2.
Biểu diễn dưới dạng lưu đồ:

- Cấu trúc while
- Cú pháp:
while(biểu thức)
Khối lệnh;
- Sự hoạt động của vịng lặp while:
Bước 1: tính giá trị của (biểu thức) sau while

3


Bước 2: nếu giá trị tính được của (biểu thức) là ‘sai’ (==0) thì kết thúc
vịng lặp while.
Bước 3: nếu giá trị của (biểu thức) là ‘đúng’ (!=0) thì thực hiện khối lệnh
sau while.
Bước 4: quay lại bước 1
Chú ý: Thân while có thể được thực hiện một lần hoặc nhiều lần và cũng
có thể khơng được thực hiện lần nào nếu ngay từ đầu biểu thức sau while đã sai.

- Biểu diễn bằng lưu đồ:

- Cấu trúc lặp for
Cú pháp:
for (biểu thức 1; biểu thức 2; biểu thức 3)
Khối lệnh;
Trong đó:
Biểu thức 1: biểu thức khởi đầu.
Biểu thức 2: biểu thức điều kiện - điều kiện lặp.
Biểu thức 3: bước nhảy - thường dùng với ý nghĩa là thay đổi bước nhảy.
Cả 3 biểu thức này đều là tuỳ chọn, chúng có thể vắng mặt trong câu lệnh
cụ thể nhưng các dấu chấm phẩy vẫn phải có.
Sự hoạt động của vòng lặp for:
Bước 1: Thực hiện biểu thức khởi đầu – Biểu thức 1.
Bước 2: Tính giá trị biểu thức 2 để xác định điều kiện lặp.
Nếu biểu thức 2 có giá trị ‘sai’ (==0) thì ra khỏi vịng lặp.

4


Ngược lại, nếu biểu thức có giá trị ‘đúng’ ( khác 0) thì chuyển tới bước 3.
Bước 3: Thực hiện khối lệnh sau for ( thân của for ), chuyển tới bước 4.
Bước 4: Thực hiện biểu thức 3, rồi quay về bước 2.
Biểu diễn bằng lưu đồ:

- Cấu trúc lặp “do while”
Cú pháp:
do
Khối lệnh;
while (biểu thức);

Giải thích cú pháp:
Bước 1: thực hiện khối lệnh sau do.
Bước 2: kiểm tra giá trị biểu thức <biểu thức> sau while, nếu có giá trị
‘đúng’ ( khác 0) thì lặp lại bước 1, nếu ‘sai’ (=0) thì kết thúc vịng lặp.
Biểu diễn bằng lưu đồ:

5


- Cấu trúc lựa chọn: switch
Cú pháp của lệnh switch là kiểm tra một vài giá trị hằng cho một biểu
thức, tương tự với những gì chúng ta làm ở đầu bài này khi liên kết một
vài lệnh if và else if với nhau. Dạng thức của nó như sau:
switch (expression)
{
case constant1:
block of instructions 1
break;
case constant2:
block of instructions 2
break;
default:
default block of instructions
}
Nó hoạt động theo cách sau: switch tính biểu thức và kiểm tra xem nó có
bằng constant1 hay khơng, nếu đúng thì nó thực hiện block of instructions 1 cho
đến khi tìm thấy từ khố break, sau đó nhảy đến phần cuối của cấu trúc lựa chọn
switch. Còn nếu khơng, switch sẽ kiểm tra xem biểu thức có bằng constant2 hay
khơng. Nếu đúng nó sẽ thực hiện block of instructions 2 cho đến khi tìm thấy từ
khố break.

Cuối cùng, nếu giá trị biểu thức không bằng bất kỳ hằng nào được chỉ
định ở trên (bạn có thể chỉ định bao nhiêu câu lệnh case tuỳ thích), chương trình
sẽ thực hiện các lệnh trong phần default: Nếu nó tồn tại vì phần này khơng bắt
buộc phải có.

6


- Sự khác nhau giữa while và do while
While được dùng để kiểm tra điều kiện trước; nếu điều kiện trả về true thì
thực thi những câu lệnh bên trong.
Do-While được dùng để thực thi những câu lệnh bên trong ít nhất một
lầntrước khi kiểm tra điều kiện; nếu điều kiện trả về true thì tiếp tục thực thi;
nếu điều kiện là false thì thốt khỏi vịng lặp.
2. Mảng dữ liệu là gì
Mảng là một tập hợp các phần tử cố định có cùng một kiểu, gọi là kiểu
phần tử. Kiểu phần tử có thể là có các kiểu bất kỳ: ký tự, số, chuỗi ký tự…; cũng
có khi ta sửdụng kiểu mảng để làm kiểu phần tử cho một mảng (trong trường
hợp này ta gọi là mảng của mảng hay mảng nhiều chiều).
Ta có thể chia mảng làm 2 loại: mảng 1 chiều và mảng nhiều chiều.
Mảng là kiểu dữ liệu được sử dụng rất thường xuyên. Chẳng hạn người ta
cần quản lý một danh sách họ và tên của khoảng 100 sinh viên trong một lớp.
Nhận thấy rằng mỗi họ và tên để lưu trữ ta cần 1 biến kiểu chuỗi, như vậy 100
họ và tên thì cần khai báo 100 biến kiểu chuỗi. Nếu khai báo như thế này
thì đoạn khai báo cũng như các thao tác trên các họ tên sẽ rất dài dòng và rắc rối.
Vì thế, kiểu dữ liệu mảng giúp ích ta trong trường hợp này; chỉ cần khai báo 1
biến, biến này có thể coi như là tương đương với 100 biến chuỗi ký tự; đó là 1
mảng mà các phần tử của nó là chuỗi ký tự. Hay như đểlưu trữ các từ khóa của
ngơn ngữ lập trình C, ta cũng dùng đến một mảng để lưu trữchúng.
- Cách thực hiện

Mảng 1 chiều
Cú pháp: <Kiểu> <Tên mảng ><[số phần tử]>
Ý nghĩa:
+ Tên mảng: đây là một cái tên đặt đúng theo quy tắc đặt tên của danh
biểu. Tên này cũng mang ý nghĩa là tên biến mảng.
+Số phần tử: là một hằng số nguyên, cho biết số lượng phần tử tối đa
trong mảng là bao nhiêu (hay nói khác đi kích thước của mảng là gì).
7


+Kiểu: mỗi phần tử của mảng có dữ liệu thuộc kiểu gì.
Ở đây, ta khai báo một biến mảng gồm có số phần tử phần tử, phần
tử thứ nhất là tên mảng [0], phần tử cuối cùng là tên mảng[số phần tử -1]
Mảng nhiều chiều
Mảng nhiều chiều là mảng có từ 2 chiều trở lên. Điều đó có nghĩa là mỗi
phần tử của mảng là một mảng khác.
Người ta thường sử dụng mảng nhiều chiều để lưu các ma trận, các
tọa độ 2 chiều, 3 chiều…
Phần dưới đây là các vấn đề liên quan đến mảng 2 chiều; các mảng 3, 4,
… chiều thì tương tự (chỉ cần tổng quát hóa lên).
Khai báo mảng 2 chiều tường minh Cú pháp:
<Kiểu> <Tên mảng><[Số phần tử chiều 1]><[Số phần tử
- Con trỏ là gì
Con trỏ (pointer) đơn giản là địa chỉ của một đối tượng trong bộ nhớ.
Thng thường, các đối tượng có thể được truy xuất trong hai cách: trực tiếp bởi
tên đại diện hoặc gián tiếp thông qua con trỏ. Các biến con trỏ được định nghĩa
trỏ tới các đối tượng của một kiểu cụ thể sao cho khi con trỏ hủy thì vùng
nhớ mà đối tượng chiếm giữ được thu hồi.
Các con trỏ thường được dùng cho việc tạo ra các đối tượng động trong
thời gian thực thi chương trình. Khơng giống như các đối tượng bình thường

(tồn cục và cục bộ) được cấp phát lưu trữ trên runtime stack, một đối
tượngđộng được cấp phát vùng nhớ từ vùng lưu trữ khác được gọi là heap.
Các đối tượng không tuân theo các luật phạm vi thông thường. Phạm vi của
chúng đượcđiều khiển rõ ràng bởi lập trình viên
- Cách thực hiện trong C.
Con trỏ đơn giản chỉ là địa chỉ của một vị trí bộ nhớ và cung cấp cách
gián tiếpđể truy xuất dữ liệu trong bộ nhớ. Biến con trỏ được định
nghĩa để “trỏ tới” dữ liệu thuộc kiểu dữ liệu cụ thể. Ví dụ,
int

*ptr1;

//trỏtớimộtint
8


char
*ptr2;
//trỏtớimộtchar
Giá trị của một biến con trỏ là địa chỉ mà nó trỏ tới. Ví dụ, với các định
nghĩa đã có và
int num;
chúng ta có thể viết:
ptr1=#
Ký hiệu & là tốn tử lấy địa chỉ; nó nhận một biến như là một đối số và
trả về địa chỉ bộ nhớ của biến đó. Tác động của việc gán trên là địa chỉ của
num được khởi tạo tới ptr1. Vì thế, chúng ta nói rằng ptr1 trỏ tới num.
Minh họa một con trỏ số nguyên đơn giản.
ptr1


num

Với ptr1 trỏ tới num thì biểu thức *ptr1 nhận giá trị của biến ptr1 trỏ tới
và vì thế nó tương đương với num. Ký hiệu * là tốn tử lấy giá trị; nó nhận con
trỏ như một đối số và trả về nội dung của vị trí mà con trỏ trỏ tới.
Thơng thường thì kiểu con trỏ phải khớp với kiểu dữ liệu mà được trỏ tới.
Tuy nhiên, một con trỏ kiểu void* sẽ hợp với tất cả các kiểu. Điều này thật thuận
tiện để định nghĩa các con trỏ có thể trỏ đến dữ liệu của những kiểu khác nhau
hay là các kiểu dữ liệu gốc khơng được biết.
Con trỏ có thể được ép (chuyển kiểu) thành một kiểu khác. Ví dụ,
ptr2=(char*)ptr1; chuyển con trỏ ptr1 thành con trỏ char trước khi gán nó
tới con trỏ ptr2.
Khơng quan tâm đến kiểu của nó thì con trỏ có thể được gán tới giá
trị null (gọi là con trỏ null). Con trỏ null được sử dụng để khởi tạo cho các con
trỏ và tạo ra điểm kết thúc cho các cấu trúc dựa trên con trỏ (ví dụ, danh sách
liên kết).
- Phương pháp thực hiện con trỏ, mảng, chuỗi kí tự
- Khai báo theo mảng
Cú pháp: char <Biến> [Chiều dài tối đa]
Ví dụ: Trong chương trình, ta có khai báo:
9


char Ten[12];
Trong khai báo này, bộ nhớ sẽ cung cấp 12+1 bytes để lưu trữ nội dung
của chuỗi ký tựTen; byte cuối cùng lưu trữ ký tự‘\0’ để chấm dứt chuỗi.
Ghi chú:
- Chiều dài tối đa của biến chuỗi là một hằng nguyên nằmtrong khoảng
từ1 đến 255 bytes.
- Chiều dài tối đa không nên khai báo thừa để tránh lãng phí bộ nhớ,

nhưng cũng khơng nên khai báo thiếu.
- Khai báo theo con trỏ
Cú pháp: char *<Biến>
Ví dụ: Trong chương trình, ta có khai báo:
char *Ten;
Trong khai báo này, bộnhớsẽdành 2 byte đểlưu trữ địa chỉcủa biến con
trỏTen đang chỉ đến, chưa cung cấp nơi để lưu trữ dữ liệu. Muốn có chỗ để lưu
trữ dữ liệu, ta phải gọi đến hàm malloc() hoặc calloc()có trong “alloc.h”, sau đó
mới gán dữ liệu cho biến.
- Các thao tác trên chic kí tự
- Nhập xuất chuỗi
- Nhập chuỗi từbàn phím
Để nhập một chuỗi ký tựtừbàn phím, ta sửdụng hàmgets()
Cú pháp: gets(<Biến chuỗi>)
Ví dụ: char Ten[20];
gets(Ten);
Ta cũng có thểsửdụng hàm scanf() đểnhập dữliệu cho biến chuỗi, tuy
nhiên lúc này ta chỉcó thểnhập được một chuỗi khơng có dấu khoảng trắng.
Ngồi ra, hàm cgets() (trong conio.h) cũng được sửdụng đểnhập chuỗi.
- Xuất chuỗi lên màn hình
Đểxuất một chuỗi (biểu thức chuỗi) lên màn hình, ta sửdụng hàm puts().
Cú pháp: puts(<Biểu thức chuỗi>)
10


3. Ngắt là gì
Ngắt (interrupt) là quá trình dừng chương trình chính đang chạy để ưu
tiên thực hiện một chương trình khác, chương trình này được gọi là chương trình
phục vụ ngắt (ISR –Interrupt Service Routine). ISR hoàn toàn giống với một
chương trình bình thường trên máy tính, nghĩa là nó có khả năng truy xuất đến

tất cả các lệnh ngôn ngữ máy của μP. Tuy nhiên cuối ISR sẽ kết thúc bằng lệnh
IRET (Interrupt Return) để μP tiếp tục thực hiện lệnh đã kếtthúc trước đây.
Trong các quá trình ngắt, ta phân biệt thành 2 loại: ngắt cứng và ngắt
mềm.
Ngắt mềm : là ngắt được gọi bằng một lệnh trong chương trình ngơn ngữ
máy. Ngắt mềm được thục hiện trên hợp ngữ thông qua lệnh INT. Đối với các
ngôn ngữ bậc cao hơn, vẫn cho phép thực hiện gọi ngắt nhưng phải được biên
dịch thành lệnh INT trong hợp ngữ rồi mời thực hiện.
Ngắt cứng :khác với ngắt mềm, ngắt cứng khơng được khởi động bên
trong máy tính mà do các linh kiện điện tử tác đông lên hệ thống. Ngắt cứng
cũng được chia thành 2 loại: ngắt che được và ngắt không che được. Ngắt che
được là ngắt có thể cho phép hay khơng cho phép thực thi bằng phần mềm thông
qua cờ ngắt IF (Interrupt Flag): lệnh CLI (Clear InterruptFlag) sẽ cấm ngắt và
lệnh STI (Set Interrupt Flag) sẽ cho phép các ngắt này hoạt động.
Khi thực hiện lệnh gọi một ngắt nào đó, chương trình con phục vụ cho
ngắt sẽ được gọi. Để thực hiện các ngắt tương ứng, địa chỉ thực hiện các chương
trình con phục vụ ngắt được đặt trong một bảng, gọi là bảng vector ngắt.
- Sáu ngắt của 8051 được phân bố như sau:
1. RESET: Khi chân RESET được kích hoạt từ 8051, bộ đếm chương
trình nhảy về địa chỉ 0000H. Đây là địa chỉ bật lại nguồn.
2. 2 ngắt dành cho các bộ định thời: 1 cho Timer0 và 1 cho Timer1. Địa
chỉ tương ứng của các ngắt này là 000BH và 001BH.

11


3. 2 ngắt dành cho các ngắt phần cứng bên ngoài: chân 12 (P3.2) và 13
(P3.3) của cổng P3 là các ngắt phần cứng bên ngoài INT0 và INT1 tương ứng.
Địa chỉ tương ứng của các ngắt ngoài này là 0003H và 0013H.
4. Truyền thơng nối tiếp: có 1 ngắt chung cho cả nhận và truyền dữ liệu

nối tiếp. Địa chỉ của ngắt này trong bảng vector ngắt là 0023H.
- Cấu trúc một chương trình có sử dụng ngắt trong Keil C.
- Cấu trúc:
void Tên hàm(void) interrupt nguồn ngắt using băng thanh ghi
{
}
Hàm ngắt không được phép trả lại giá tri hay truyền tham biến vào hàm
- Tên hàm : tùy chọn
- Interrupt : từ khóa chỉ hàm ngắt
- Nguồn ngắt : từ 0 đến 5 theo bảng vecter ngắt
- Ngắt do Cờ Địa chỉ vector Nguồn ngắt
- Reset hệ thống RST 0000H –
- Ngắt ngoài 0 IE0 0003H 0
- Timer 0 TF0 000BH 1
- Ngắt ngoài 1 IE1 001 3H 2
- Timer 1 TF1 001BH 3
- Port nối tiếp RI hoặc TI 0023H 4
- Timer 2 TF2 hoặc EXF2 002BH 5
- Băng thanh ghi trên RAM chon từ 0 đến 3.
Câu 4.. - Nêu các bước thực hiện một chương trình trong MikroC
hình ảnh
Bắt đầu!- Khởi động phần mềm MikroC PRO for Pic: Vào Start >>
Programs >> Mikroelektronika >> MikroC PRO for PIC hoặc double click vào
shortcut trên màn hình Desktop.
- Sau khi khởi động phần mềm, giao diện sẽ xuất hiện như sau:
12


Ban đầu phần mềm sẽ load một ví dụ có sẵn trong thư mục cài đặt, ta có
thể tắt project này bằng cách click vào Tab menu Project >> Close Project.

- Tạo một project mới cho việc lập trình: Vào lại Tab menu Project >>
New Project.

Sau khi nhấp chọn để tạo project mới cửa sổ sau sẽ xuất hiện:

Đây là cửa sổ thiết lập các thông số project
+ Ở ô đầu tiên Project Name: các bạn đặt tên cho project của mình (tùy ý),
chẳng hạn đặt tên là " Vi du 1"

13


+ Ở ô Project Folder: chọn đường dẫn để lưu project, để kiểm sốt dữ liệu
cho cơng việc các bạn nên tạo một folder mới cho mỗi project.
+ Ô Device Name: chọn dòng vi điều khiển, nếu bạn sử dụng pic16F877A
để lập trình thì tìm đúng tên của nó là "P16F877A" trong hộp combo box khi ấn
nút xổ xuống.
+ Device clock: chọn tần số hoạt động cho vi điều khiển, tần số này chính
là tần số thạch anh sử dụng cho vi điều khiển.
Cuối cùng nhấn Next để chuyển qua bước tiếp theo. Khi đó cửa sổ sau
xuất hiện:

Trong bước này, các bạn để trong và tiếp tục nhấn Next sẽ đến bước sau:

Trong cửa sổ này, bạn stick vào nút có dịng chữ " Include None
(Advaned)" rồi nhấn nút Next. Trong bước cuối cùng bạn cứ để mặc định và
nhấn nút Finish khi đó cửa sổ lập trình sẽ xuất hiện, sẵn sàng cho bạn viết code.

14



Bạn có thể viết code của mình vào giữa hai dấu ngoặc { .......... }
- Đoạn code đầu tiên, giả sử ta muốn tất cả các chân của port B đều lên
mức 1 (5V). Ta viết như sau:
TRISB=0x00; PORTB=0xFF;
Sau đó bạn nhấp vào nút Build hoặc nhấn tổ hợp phím Ctrl + F9 để tạo
file hex.

Mỗi port, mỗi chân của vi điều khiển này đều có chức năng riêng, tuy
nhiên tất cả chúng (trừ chân cấp nguồn , reset..) đều có khả năng làm chân
digital input/output (ngõ vào - ngõ ra với mức logic 0 hoặc 1). Do đó nếu muốn
1 chân trên vi điều khiển làm ngõ vào hay ngõ ra phải sử dụng lệnh TRIS, và sử
dụng cho port nào thì đi kèm với tên của port đó. Ví dụ đề thiết lập ngõ vào-ra
cho các chân của portB sử dụng lệnh TRISB.
Lệnh này có thể nhận giá trị là số thập phân Dec, số nhị phân Bin hay số
hex 0x. Bạn có thể thiết lập ngõ vào - ra cho từng chân của port hay cả port. Ví
dụ bạn muốn Chân RB0 của portB là ngõ ra bạn viết như sau:
15


Cách 1: TRISB.F0=0; // Điều này có nghĩa là bit 0 của portB nhận giá trị
là 0 nên nó là ngõ ra, nếu nó nhận giá trị 1 thì nó sẽ là ngõ vào. Cách này chỉ tác
động đến bit 0 khơng ảnh hưởng các bit khác.
- Viết chương trình điều khiển led đơn để hiện thị tên của sinh viên
Void maid() {
Do{
P0.b0=0;
P3.b0=0;
Delay_ms(100);
P0.b1=0;

P3.b1=0;
Delay_ms(100);
P1.b0=0;
P2.b0=0;
Delay_ms(100);
P1.b1=0;
P2.b1=0;
Delay_ms(100);
P1.b2=0;
P2.b2=0;
Delay_ms(100);
P1.b3=0;
P2.b3=0;
Delay_ms(100);
P1.b4=0;
P2.b4=0;
Delay_ms(100);
P1.b5=0;
P2.b5=0;
Delay_ms(100);
P1.b6=0;
P2.b6=0;
Delay_ms(100);
P1.b7=0;
P2.b7=0;
// Sáng dần chữ T
Delay_ms(100);
P0=0xff;
P1=0xff;
P2=0xff;

P3=0xff;
// Tắt các Port
Delay_ms(100);
16


P1=0;
P2=0;
P0.b0=0;
P0.b1=0;
P3.b0=0;
P3.b1=0;
Delay_ms(100);
} while(1);
}

// Sáng chữ T

17


Câu 5: Phương pháp quét ma trận bàn phím?
Ma trận phím 4x4 gồm có 16 nút bấm được sắp xếp theo ma trận 4 hàng, 4 cột. Các
nút bấm trong cùng một hàng và một cột được nối với nhau, vì vậy ma trận phím 4x4 sẽ có
tổng cộng 8 ngõ ra.
Sơ đồ nguyên lý:

Mô phỏng:

18



Ma trận phím 4x4 cho phép các bạn nhập các chữ số, chữ cái, ký hiệu vào
bộ điều khiển qua đó dùng để điều khiển một thiết bị ngoại vi nào đó.
Các bạn có thể mắc thêm trở treo (thơng thường là 10K) cho các nút bấm để nút
bấm hoạt động ổn định hơn.
- Nguyên lý hoạt động của ma trận phím
Để giao tiếp được với ma trận phím 4x4, chúng ta dùng phương pháp
"quét" để kiểm tra xem nút nào được bấm, cụ thể cách quét như sau (quét theo
cột):
Các chân P1.0, P1.1, P1.2, P1.3 (các hàng) được thiết lập là các chân INPUT,
còn lại các chân P1.4, P1.5, P1.6, P1.7 (các cột) là các chân OUTPUT (ở mức
logic ‘0’).
Câu 6:- Phương pháp quét cho led 7 đoạn
Dựa theo ngun tắc qt ảnh vì mắt chúng ta có hiện tượng lưu ảnh trên
võng mạc nên khi ta quét với tần số nhanh thì mắt chúng ta khơng có cảm giác
là nó sáng lần lượt các Led mà có cảm giác là nó sáng tắt. Đầu tiên ta phải gửi
dữ liệu muốn hiển thị cho Led1 và bật chân điều khiển của Led1 lên để hiển thị.
Sau đó ta gửi tiếp dữ liệu muốn hiển thị Led2 và cũng bật chân điều khiển của
Led2 để cho số tiếp theo hiển thị. Tiếp tục với Led3 và Led4. Quá trình này diễn
ra nhanh với tần số cao nên ta không hề có cảm giác là các Led sáng lần lượt
- Viết chương trình điều khiển đếm từ 0->10---------500 và thực
hiện lại? Vẽ lưu đồ thuật toán?
#include "Display_utils.h"
unsigned short shifter,digits_array_index;
unsigned int digit, number;
unsigned short digits_array[4];
void main(){
int n = 0;
digit = 0;

digits_array_index = 0;
19


shifter = 1;
P0 = 0;
number = 0;
//===========================================
======================
do {
for(n=0;n<500;n++)
{ digit = (number/1000u)%100u;
digits_array[3] = mask(digit);
digit = (number/100u)%10u;
digits_array[2] = mask(digit);
digit = (number/10u)%10u;
digits_array[1] = mask(digit);
digit = number % 10u;
digits_array[0] = mask(digit);
P0 = digits_array[digits_array_index];
P1 = shifter;
shifter <<= 1;
if(shifter > 8u)
shifter = 1;
delay_ms(1);
digits_array_index++;
if(digits_array_index >3u)
digits_array_index = 0;
}
if(number == 500)

{
number = 0;
}
20


else
number = number + 10;
}
while(1);
}
Lưu đồ thuật toán

21


Câu 7.Viết chương trình cảnh báo quá nhiệt nếu t > 40 0 C? vẽ lưu đồ
thuật toán?
sbit LCD_RS at P2_0_bit;
sbit LCD_EN at P2_1_bit;
sbit LCD_D4 at P2_2_bit;
sbit LCD_D5 at P2_3_bit;
sbit LCD_D6 at P2_4_bit;
sbit LCD_D7 at P2_5_bit;
sbit OW_Bit at P1_2_bit;
const unsigned short TEMP_RESOLUTION = 9;
char *text = "000.0000";
unsigned temp;
void Display_Temperature(unsigned int temp2write) {
const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;

char temp_whole;
unsigned int temp_fraction;
if (temp2write & 0x8000) {
text[0] = '-';
temp2write = ~temp2write + 1;
}
temp_whole = temp2write >> RES_SHIFT;
if(temp_whole < 40){
P0.B1 = 0xFF;
}
else
P0.B1 = 0x00;
if (temp_whole/100)
22


text[0] = temp_whole/100 + 48;
else
text[0] = '0';
text[1] = (temp_whole/10)%10 + 48;
text[2] = temp_whole%10

+ 48;

//===========================================
=============
temp_fraction = temp2write << (4-RES_SHIFT);
temp_fraction &= 0x000F;
temp_fraction *= 625;
text[4] = temp_fraction/1000


+ 48;

text[5] = (temp_fraction/100)%10 + 48;
text[6] = (temp_fraction/10)%10 + 48;
text[7] = temp_fraction%10

+ 48;

Lcd_Out(2, 5, text);
}
void main() {
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
Lcd_Out(1, 1, " nhietdo: ");
Lcd_Chr(2,13,176);
Lcd_Chr(2,14,'C');
do {
Ow_Reset();
Ow_Write(0xCC);
Ow_Write(0x44);
Delay_us(120);
Ow_Reset();
23


Ow_Write(0xCC);
Ow_Write(0xBE);
temp = Ow_Read();

temp = (Ow_Read() << 8) + temp;
Display_Temperature(temp);
Delay_ms(500);;
} while (1);
}
-

Lưu đồ thuật tốn

Begin

Qt tín hiệu từ
ADC

Xử lý đưa ra 7 sec

sai

>40

Báoquá nhiệt

End
đúng

Câu 8 . Viết chương trình đếm số bấm nút sử dụng ngắt và hiện thị
trên led 7 thanh?. Lưu đồ thuật toán
#include "Display_utils.h"
unsigned short shifter,digits_array_index;
24



unsigned int digit, number;
unsigned short digits_array[4];
unsigned int cnt=0;
bit tmp;
int n = 0;
void external_ISR()org 0x0003 ilevel 0{
EA_bit =0;
tmp = 1;
EA_bit =1;
}
void main(){
unsigned int j=0;
tmp=0;
P0= 0xFF;
P3 =0xFF;
IE= 0x81;
digit = 0;
digits_array_index = 0;
shifter = 1;
while(1){
if(tmp){
cnt= cnt + 1;
tmp = 0;
}
for(n=0;n<500;n++)
{
digit = (cnt/1000u)%100u;
digits_array[3] = mask(digit);

digit = (cnt/100u)%10u;
25


×