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ố để
Trang 1BÁ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ênsinh 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ệnlại? Vẽ lưu đồ thuật toán?
7 Viết chương trình cảnh báo quá nhiệt nếu t > 400C? vẽ lưu đồ thuậttoá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 7thanh? Lưu đồ thuật toá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ấungoặ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
Trang 2trình có thể dẫn dòng mã sao cho mọi hướng chẻ nhánh đều được trả về đúngkiể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
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ẽ thoát ra khỏi cấu trúc if và thựchiệ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:
Trang 3Cá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
- 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
Trang 4Bướ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 đồ:
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
Trang 5Ngượ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”
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 đồ:
Trang 6- 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ểuthứ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ộtvài lệnh if và else if với nhau Dạng thức của nó như sau:switch (expression)
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ắtbuộc phải có
Trang 7- 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ì thoát khỏi vòng lặp
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 tacầ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àythì đ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 1biến, biến này có thể coi như là tương đương với 100 biến chuỗi ký tự; đó là 1mả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ủangô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ì)
Trang 8+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]
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ởitên đại diện hoặc gián tiếp thông qua con trỏ Các biến con trỏ được định nghĩatrỏ tới các đối tượng của một kiểu cụ thể sao cho khi con trỏ hủy thì vùngnhớ 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 trongthời gian thực thi chương trình Không giống như các đối tượng bình thường(toàn cục và cục bộ) được cấp phát lưu trữ trên runtime stack, một đốitượ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ủachú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 địnhnghĩa để “trỏ tới” dữ liệu thuộc kiểu dữ liệu cụ thể Ví dụ,
int *ptr1; //trỏtớimộtint
Trang 9Ký hiệu & là toá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ủanum đượ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.
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à toá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ậntiện để định nghĩa các con trỏ có thể trỏ đến dữ liệu của những kiểu khác nhauhay 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áchliê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:
Trang 10- Các thao tác trên chuôic kí tự
Ngoà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>)
Trang 113 Ngắt là gì
Ngắt (interrupt) là quá trình dừng chương trình chính đang chạy để ưutiê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ìnhphục vụ ngắt (ISR –Interrupt Service Routine) ISR hoàn toàn giống với mộtchương trình bình thường trên máy tính, nghĩa là nó có khả năng truy xuất đếntấ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ệnhIRET (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ắtmề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ácngô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êndị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êntrong 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ứngcũ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ôngqua 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ụ chongắ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ươngtrì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.
Trang 123 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.
- 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
- 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àoshortcut 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:
Trang 13Ban đầ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"
Trang 14+ Ở ô Project Folder: chọn đường dẫn để lưu project, để kiểm soát dữ liệucho 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 ấnnú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ổ sauxuấ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
Trang 15Bạ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ênmức 1 (5V) Ta viết như sau:
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-racho 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:
Trang 16Cá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
Trang 18Câ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:
Trang 19Ma 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útbấ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 theocộ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 nguyên tắc quét ảnh vì mắt chúng ta có hiện tượng lưu ảnh trênvõ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ủaLed2 để 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;