Professional Documents
Culture Documents
Chương 12
Chương 12
mục tiêu
Mục tiêu của chương này là sau khi nghiên cứu nó, người đọc có thể: •Hiểu được các tính năng
chính của chương trình C. •Sử dụng C để viết các
chương trình đơn giản dành cho vi điều khiển.
Sau đây là các tính năng chính của chương trình được viết bằng ngôn ngữ C. Lưu ý rằng trong các chương
trình C, các dấu cách và dấu xuống dòng bị trình biên dịch bỏ qua và hoàn toàn được sử dụng để tạo sự
thuận tiện cho người lập trình, giúp họ đọc chương trình dễ dàng hơn.
1 Từ khóa
Trong C một số từ nhất định được dành làm từ khóa có ý nghĩa cụ thể. Ví dụ, int được sử dụng để chỉ
ra rằng các giá trị số nguyên có liên quan; if được sử dụng khi chương trình có thể thay đổi hướng
dựa trên việc quyết định là đúng hay sai. C yêu cầu tất cả các từ khóa phải viết thường. Những từ
như vậy không nên được sử dụng cho bất kỳ mục đích nào khác trong chương trình C. Sau đây là các từ
Đây là các mục tạo nên một chương trình, mọi câu lệnh đều được kết thúc bằng dấu chấm phẩy. Các câu
lệnh có thể được nhóm lại với nhau thành các khối bằng cách đặt chúng giữa các dấu ngoặc nhọn, tức
{
tuyên bố 1;
tuyên bố 2;
}
3 chức năng
Thuật ngữ hàm được sử dụng cho một khối mã chương trình độc lập, thực hiện một tập hợp hành động cụ
thể và có tên để tham chiếu (nó giống như một chương trình con trong chương trình hợp ngữ).
Một hàm được viết dưới dạng tên theo sau là dấu ngoặc, tức là tên( ). Các dấu ngoặc bao quanh các
đối số; đối số của hàm là một giá trị được truyền cho hàm khi hàm được gọi. Một hàm được thực thi
bằng cách gọi nó bằng tên của nó trong câu lệnh chương trình. Ví dụ: chúng ta có thể có tuyên bố:
Điều này có nghĩa là từ Cơ điện tử được chuyển tới hàm printf( ), một hàm được viết sẵn được gọi
bằng lệnh tiền xử lý và kết quả là từ này được hiển thị trên màn hình. Để chỉ ra rằng các ký tự tạo
thành một chuỗi, ví dụ như các ký tự tạo nên từ Cơ điện tử, chúng được đặt trong dấu ngoặc kép.
Machine Translated by Google
4 Trở về
Một hàm có thể trả về một giá trị cho thủ tục gọi. Kiểu trả về
xuất hiện ở phía trước tên hàm, điều này chỉ định loại giá trị được trả về cho hàm
gọi khi quá trình thực thi hàm hoàn tất. Ví dụ: int main( ) được sử dụng để trả
về số nguyên từ hàm main. Kiểu trả về có thể được chỉ định là void nếu hàm không
trả về giá trị, ví dụ: void main(void). Thông thường, tệp tiêu đề sẽ chứa thông
tin trả về này và do đó, nó sẽ không cần phải được chỉ định cho các chức năng được
xác định bởi tệp tiêu đề.
Để trả về một giá trị từ một hàm về điểm gọi, từ khóa return được sử dụng, ví
dụ: để trả về kết quả:
Ví dụ, hàm printf( ) là một hàm có thể được gọi từ thư viện stdio.h và là hàm để
in ra màn hình của màn hình. Một hàm khác là scanf( ) có thể được sử dụng để đọc
dữ liệu từ bàn phím.
6 Bộ tiền xử lý
Bộ tiền xử lý là một chương trình được xác định bằng các lệnh tiền xử lý để nó
được thực thi trước khi biên dịch. Tất cả các lệnh như vậy được xác định bằng dấu
# ở đầu dòng. Như vậy chúng ta có thể có:
để bao gồm tệp có tên giữa dấu ngoặc nhọn < >. Khi đạt được lệnh này, tệp được
chỉ định sẽ được chèn vào chương trình.
Nó thường được sử dụng để thêm nội dung của các tệp tiêu đề tiêu chuẩn, chúng đưa
ra một số khai báo và định nghĩa để cho phép sử dụng các hàm thư viện tiêu chuẩn.
Mục nhập sau đó sẽ là:
chủ yếu( )
}
Machine Translated by Google
Trước khi bắt đầu chương trình chính, tệp stdio.h sẽ được thêm vào. Vì vậy,
khi chương trình chính bắt đầu, chúng ta có thể truy cập vào hàm printf( )
và kết quả là từ Mechatronics được hiển thị trên màn hình.
Một loại lệnh tiền xử lý khác là:
và điều này có thể được sử dụng để xác định các giá trị sẽ được chèn bất cứ
khi nào gặp một ký hiệu cụ thể trong chương trình. Do đó, bất cứ khi nào gặp
số pi thì giá trị 3,14 sẽ được sử dụng.
sẽ thay thế số hạng bình phương trong chương trình bằng (x)*(x).
chỉ ra rằng không có kết quả nào được trả về chương trình chính và không có
đối số. Theo quy ước, giá trị trả về 0 từ main() được sử dụng để biểu thị
việc kết thúc chương trình thông thường, tức là mục nhập:
trả về 0;
8 bình luận
/* và */ được dùng để đính kèm chú thích. Vì vậy, chúng tôi có thể có một
mục như:
Các chú thích bị trình biên dịch bỏ qua và chỉ được sử dụng để giúp lập
trình viên hiểu chương trình dễ dàng hơn. Nhận xét có thể kéo dài nhiều hơn
một dòng, ví dụ:
9 biến
Biến là một vị trí bộ nhớ được đặt tên có thể chứa nhiều giá trị khác nhau.
Các biến có thể chứa một ký tự được chỉ định bằng từ khóa char, biến đó dài
8 bit và thường được sử dụng để lưu trữ một ký tự. Các số nguyên có dấu, tức
là các số không có phần phân số và được ký để biểu thị số dương hoặc số âm,
được chỉ định bằng từ khóa int. Từ khóa float được sử dụng cho các số có dấu
phẩy động, đây là những số có phần phân số. Từ khóa double cũng là
Machine Translated by Google
được sử dụng cho các số có dấu phẩy động nhưng cung cấp số chữ số có
nghĩa gấp đôi số float. Để khai báo một biến, kiểu được chèn trước tên
biến, ví dụ:
bộ đếm int;
Điều này khai báo biến 'bộ đếm' có kiểu số nguyên. Một ví dụ khác
chúng ta có thể có:
nổi x, y;
Điều này chỉ ra rằng các biến x và y đều là số có dấu phẩy động.
10 bài tập
Câu lệnh gán gán giá trị của biểu thức ở bên phải dấu 5 cho biến ở bên
trái của nó. Ví dụ: a 5 2 gán giá trị 2 cho biến a.
11 toán tử số học
Các toán tử số học được sử dụng là: cộng 1, trừ 2, nhân *, mô đun chia
%, tăng 1 ,1 và giảm22. Toán tử tăng tăng giá trị của một biến lên 1,
toán tử giảm giảm giá trị của một biến đi 1. Các quy tắc số học thông
thường giữ nguyên độ ưu tiên của các phép toán.
Ví dụ: 2*4 + 62 cho kết quả là 11. Một ví dụ về chương trình bao gồm
các toán tử số học là:
int bán kính, diện tích /*bán kính biến và diện tích là số nguyên*/
int main(void) /*bắt đầu chương trình chính, int chỉ định
rằng một giá trị số nguyên được trả về, khoảng trống biểu thị
printf("\nDiện tích = %d", diện tích); /*Trên dòng mới in Khu vực
12 Toán tử quan hệ
Các toán tử quan hệ được sử dụng để so sánh các biểu thức, đặt các câu
hỏi như ' X có bằng y không?' hoặc ' X có lớn hơn 10 không?' Các toán
tử quan hệ là: bằng 55, không bằng !5, nhỏ hơn , nhỏ ,hơn hoặc bằng ,
5, lớn hơn . , lớn hơn hoặc bằng . 5. Lưu ý rằng 5 5 phải được dùng
khi hỏi hai biến có giống nhau không, 5 được dùng cho
Machine Translated by Google
bài tập khi bạn nói rằng chúng giống nhau. Ví dụ: chúng ta có thể đặt câu
hỏi 'Có x bằng 2 không?' và biểu diễn điều này bằng (a 55 2).
13 Toán tử logic
Các toán tử logic là:
VÀ &&
HOẶC ||
KHÔNG !
Lưu ý rằng trong C kết quả bằng 1 nếu đúng và 0 nếu sai.
VÀ &
HOẶC |
ĐỘC QUYỀN-HOẶC
^
KHÔNG ~
Tiền tố 0x được sử dụng để chỉ ra rằng 0c là giá trị hex, là 0000 1100 ở
dạng nhị phân. Do đó, giá trị ORed với cổng A là một số nhị phân buộc các
bit 2 và 3 bật, tất cả các bit khác không thay đổi.
^
cổngA = cổngA 1;
Câu lệnh này làm cho tất cả các bit ngoại trừ bit 1 của cổng A không thay
đổi. Nếu bit 0 là 1 trong cổng A, XOR sẽ buộc nó về 0 và nếu là 0 thì nó sẽ
buộc nó về 1.
15 chuỗi
Một chuỗi các ký tự được đặt trong dấu ngoặc kép, tức là " ", được gọi là
chuỗi. Như thuật ngữ ngụ ý, các ký tự trong dấu ngoặc kép được coi là một
thực thể được liên kết. Ví dụ: chúng ta có thể có:
printf(“Tổng = %d”, x)
Machine Translated by Google
Đối số trong ( ) chỉ định nội dung được truyền cho hàm in.
Có hai đối số, hai đối số được phân tách bằng dấu phẩy. Đối số đầu tiên là
chuỗi giữa dấu ngoặc kép và chỉ định cách trình bày đầu ra, %d chỉ định rằng
biến sẽ được hiển thị dưới dạng số nguyên thập phân. Các công cụ xác định
định dạng khác là:
ký tự %c
%d số nguyên thập phân có dấu
%s chuỗi ký tự
%u số nguyên thập phân không dấu
%% in ra dấu %
scanf(“%d”, &x);
đọc một số nguyên thập phân từ bàn phím và gán nó cho biến số nguyên x. Ký
hiệu & phía trước x là toán tử 'địa chỉ của'. Khi đặt trước tên biến, nó sẽ
trả về địa chỉ của biến.
Do đó, lệnh sẽ quét dữ liệu và lưu trữ mục bằng địa chỉ đã cho.
printf(“\nSum = %d”, d)
với \n chỉ ra rằng một dòng mới sẽ được sử dụng khi nó được in trên màn
hình. Trình tự thoát thường được sử dụng là:
Một ví dụ về một chương trình đơn giản để minh họa việc sử dụng một số thuật
ngữ trên là:
{
int a, b, c, d; /*a, b, c và d là số nguyên*/
a = 4; /*a được gán giá trị 4*/
b = 3; /*b được gán giá trị 3*/
c = 5; /*c được gán giá trị 5*/
* * *
d = ab c; /*d được gán giá trị của b * c*/
*
printf("a * b c = %d\n", d);
}
Câu lệnh int a, b, c, d; khai báo các biến a, b, c và d là kiểu số nguyên. Các
câu lệnh a 5 4, b 5 3, c 5 5 gán giá trị ban đầu cho các biến, dấu 5 được dùng
để biểu thị phép gán. Câu lệnh d 5 * b * c chỉ ra rằng a sẽ được nhân với b
rồi nhân với c và được lưu dưới dạng d. printf trong câu lệnh printf("a * b *
Một
Ký tự \n ở cuối chuỗi dùng để chỉ ra rằng một dòng mới sẽ được chèn vào điểm
đó.
1 Nếu
Câu lệnh if cho phép phân nhánh (Hình 12.2(a)). Ví dụ: nếu một biểu thức
đúng thì câu lệnh sẽ được thực thi, nếu không đúng thì không, và chương
trình sẽ chuyển sang câu lệnh tiếp theo. Vì vậy chúng ta có thể có các phát
biểu có dạng:
Là Là
KHÔNG KHÔNG
sự biểu lộ sự biểu lộ
ĐÚNG VẬY? ĐÚNG VẬY?
ĐÚNG ĐÚNG
tuyên bố tuyên bố
#include <studio.h>
int x, y;
chủ yếu( )
scanf("%d", &x);
scanf(%d", &y);
nếu(x = = y)
nếu(x > y)
nếu(x < y)
trả về 0;
Màn hình hiển thị Nhập một giá trị nguyên cho x: rồi nhập một giá trị vào.
Sau đó, màn hình hiển thị Nhập một giá trị cho y: rồi nhập một giá trị vào.
Sau đó, chuỗi if sẽ xác định xem liệu nhập vào có hay không giá trị bằng nhau
hoặc lớn hơn giá trị kia và hiển thị kết quả trên
màn hình.
2 Nếu/khác
Câu lệnh if có thể được kết hợp với câu lệnh else . Điều này cho phép một câu
lệnh được thực thi nếu kết quả là có và câu lệnh khác nếu kết quả là không
(Hình 12.2(b)). Như vậy chúng ta có thể có:
#include <studio.h>
chủ yếu( )
printf("Cảnh báo");
khác
3 Vì
Vòng lặp thuật ngữ được sử dụng để thực hiện một chuỗi các câu lệnh cho đến
khi một điều kiện cụ thể đạt đến điều kiện bắt buộc là đúng hoặc sai.
Hình 12.3(a) minh họa điều này. Một cách viết câu lệnh cho vòng lặp là sử
dụng hàm for. Dạng tổng quát của phát biểu là:
for(khởi tạo biểu thức; biểu thức kiểm tra; biểu thức tăng dần)
#include <studio.h>
số int
Machine Translated by Google
Thực hiện
khởi tạo
Là Là
KHÔNG KHÔNG
biểu hiện có biểu hiện có
ĐÚNG ĐÚNG
tuyên bố
main( )
printf("\n%d", count); }
Ban đầu, số đếm là 0 và sẽ tăng thêm 1, sau đó lặp lại để lặp lại
câu lệnh for miễn là số đếm nhỏ hơn 7. Kết quả là màn hình hiển thị 0
1 2 3 4 5 6 với mỗi số nằm trên một số riêng biệt. đường kẻ.
4 Trong khi
Câu lệnh while cho phép một vòng lặp được lặp lại liên tục miễn là
biểu thức đó đúng (Hình 12.3(b)). Khi biểu thức trở thành sai thì
chương trình sẽ tiếp tục với câu lệnh sau vòng lặp.
Để minh họa, chúng ta có thể có chương trình sau trong đó câu lệnh
while được sử dụng để đếm miễn là số đó nhỏ hơn 7, hiển thị kết quả:
#include <studio.h>
số int;
int chính();
{
đếm = 1;
} trả về 0;
}
Machine Translated by Google
Màn hình hiển thị là 1 2 3 4 5 6 với mỗi số nằm trên một dòng riêng biệt.
5 Công tắc
Câu lệnh switch cho phép lựa chọn giữa một số lựa chọn thay thế, điều kiện kiểm tra
được đặt trong ngoặc. Các lựa chọn có thể được xác định bằng nhãn trường hợp, chúng
xác định các giá trị mong đợi của điều kiện thử nghiệm. Ví dụ: chúng ta có thể gặp
tình huống nếu trường hợp 1 xảy ra thì chúng tôi thực thi câu lệnh 1, nếu trường hợp
2 xảy ra, chúng tôi thực thi câu lệnh 2, v.v. Nếu biểu thức không bằng bất kỳ trường
hợp nào thì câu lệnh mặc định sẽ được thực thi. Sau mỗi câu lệnh case thường có một
câu lệnh break để chuyển việc thực thi sang câu lệnh sau switch và dừng switch tiếp
tục xuống danh sách các case. Trình tự như sau (Hình 12.4):
{
trường hợp 1;
tuyên bố 1;
phá vỡ
trường hợp 2;
tuyên bố 2;
phá vỡ;
trường hợp 3;
Là
ĐÚNG Hành hình
sự biểu lộ
1?
KHÔNG
Là
ĐÚNG Hành hình
sự biểu lộ
2?
KHÔNG
Là
ĐÚNG Hành hình
sự biểu lộ
3?
KHÔNG
tuyên bố
tuyên bố
Machine Translated by Google
tuyên bố 3;
phá vỡ;
mặc định;
}
tuyên bố tiếp theo
#include <stdio.h>
int chính ( );
int x;
scanf("%d", &x);
trường hợp 1:
printf("Một");
phá vỡ;
trường hợp 2:
printf("Hai");
phá vỡ;
trường hợp 3:
printf("Ba");
phá vỡ;
mặc định;
trả về 0;
12,4 Mảng
Giả sử chúng ta muốn ghi lại nhiệt độ giữa ngày của mỗi ngày trong một tuần
và sau đó có thể tìm thấy nhiệt độ tương ứng với một ngày cụ thể bất kỳ.
Điều này có thể được thực hiện bằng cách sử dụng một mảng. Mảng là tập hợp
các vị trí lưu trữ dữ liệu, mỗi vị trí có cùng kiểu dữ liệu và được tham
chiếu thông qua cùng một tên. Để khai báo một mảng có tên Nhiệt độ để lưu
trữ các giá trị kiểu float chúng ta sử dụng câu lệnh:
Kích thước của mảng được biểu thị giữa dấu ngoặc vuông [ ] ngay sau tên
mảng. Trong trường hợp này, số 7 đã được sử dụng cho dữ liệu của bảy ngày
trong tuần. Các phần tử riêng lẻ trong một mảng được tham chiếu bằng một
giá trị chỉ mục. Phần tử đầu tiên có số 0, phần tử thứ hai có số 1, v.v.
Machine Translated by Google
đến phần tử cuối cùng trong dãy n sẽ là n – 1. Hình 12.5(a) cho thấy dạng
của một mảng tuần tự. Để lưu trữ các giá trị trong mảng chúng ta có thể viết:
mảng[2][0] mảng[2][1]
(Một) (b)
Nếu bạn muốn sử dụng scanf( ) để nhập một giá trị vào một phần tử mảng, hãy
đặt & trước tên mảng, ví dụ:
Sau đây là ví dụ về chương trình đơn giản để lưu trữ và hiển thị bình
phương của các số 0, 1, 2, 3 và 4:
#include <stdio.h>
int chính(void) {
int sqrs[5];
int x;
printf(“%d”, sqrs[x]);
trả về 0;
Mảng có thể được cung cấp các giá trị ban đầu khi được khai báo lần đầu, ví dụ:
Nếu bạn bỏ qua kích thước mảng, trình biên dịch sẽ tạo một mảng vừa đủ lớn
để chứa các giá trị khởi tạo:
Mảng đa chiều có thể được sử dụng. Ví dụ, một bảng dữ liệu là một mảng
hai chiều (Hình 12.5(b)), trong đó x đại diện cho hàng và y đại diện cho cột
và được viết là:
mảng[x][y];
Machine Translated by Google
chứa địa chỉ của một biến khác có tên là x thì p được cho là trỏ đến x. Do đó, nếu
x ở địa chỉ 100 trong bộ nhớ thì p sẽ có giá trị 100. Con trỏ là một biến và cũng
như tất cả các biến khác, nó phải được khai báo trước khi sử dụng. Một khai báo con
trỏ có dạng:
tên loại;
Dấu * chỉ ra rằng tên đề cập đến một con trỏ. Thông thường tên dùng cho con trỏ
được viết bằng tiền tố p, tức là ở dạng pname. Như vậy chúng ta có thể có:
int *pnumber;
Để khởi tạo một con trỏ và gán cho nó một địa chỉ để trỏ tới, chúng ta có thể sử dụng &,
đó là địa chỉ của toán tử, trong một câu lệnh có dạng:
#include <stdio.h>
int chính(void)
int *p, x;
x =
12; p = &x; /*gán cho p địa chỉ của x*/
printf("%d", *p); /*hiển thị giá trị của x bằng con trỏ*/
return 0;
{
Do đó chương trình sẽ hiển thị số 12 trên màn hình. Truy cập nội dung của một biến
bằng cách sử dụng con trỏ, như trên, được gọi là truy cập gián tiếp.
Quá trình truy cập dữ liệu trong biến được trỏ đến bởi một con trỏ được gọi là
dereferencing con trỏ.
hoặc:
pa = pa + 1; /*thêm 1*/
Machine Translated by Google
Con trỏ có thể được sử dụng để truy cập các phần tử riêng lẻ trong một mảng, chương trình
sau đây hiển thị quyền truy cập đó:
#include <stdio.h>
int chính(void)
int *p;
trả về 0;
Câu lệnh printf("%d %d", x[0], x[2]); dẫn đến việc trỏ đến địa chỉ được cung
cấp bởi x và do đó các giá trị tại địa chỉ [0] và [2] được hiển thị, tức là 0
và 4, trên các dòng riêng biệt.
12.6 Phát
Khi phát triển các chương trình, mục đích là tạo ra một bộ hướng dẫn ngôn ngữ
triển chương trình
máy có thể được sử dụng để vận hành hệ thống bộ vi xử lý/vi điều khiển. Những
hướng dẫn này được gọi là tập tin thực thi. Để có được một tập tin như vậy,
chuỗi sự kiện sau đây sẽ xảy ra.
1 Tạo mã nguồn
Đây là cách viết chuỗi các câu lệnh trong C sẽ tạo nên chương trình. Nhiều
trình biên dịch đi kèm với một trình soạn thảo và do đó người lập trình có
thể chỉ cần nhập mã nguồn từ bàn phím. Nếu không, có thể sử dụng một chương
trình như Notepad với Microsoft Windows. Việc sử dụng trình xử lý văn bản
có thể gây ra sự cố ở chỗ thông tin định dạng bổ sung được đưa vào có thể
ngăn cản quá trình biên dịch trừ khi tệp được lưu mà không có thông tin
định dạng.
12.6.1Tệp tiêu đề
Các lệnh tiền xử lý được sử dụng khi bắt đầu chương trình để xác định các chức năng
được sử dụng trong chương trình đó; điều này là để chúng có thể được gọi bằng các nhãn
đơn giản. Tuy nhiên, để tiết kiệm việc phải viết danh sách dài các hàm tiêu chuẩn cho
mỗi chương trình, có thể sử dụng lệnh tiền xử lý để chỉ ra rằng nên sử dụng một tệp
bao gồm các hàm tiêu chuẩn liên quan. Tất cả những gì cần thiết là chỉ ra tập tin nào
của các hàm tiêu chuẩn sẽ được trình biên dịch sử dụng; tập tin này là một tiêu đề vì
nó nằm ở phần đầu của chương trình. Ví dụ: <stdio.h> chứa các hàm đầu vào và đầu ra
tiêu chuẩn như get (đầu vào, tức là đọc một dòng từ thiết bị), đặt (đầu ra, tức là ghi
một dòng vào thiết bị) và scanf (đọc dữ liệu); <math.h> chứa các hàm toán học như cos,
sin, tan, exp (số mũ) và sqrt (căn bậc hai).
Các tệp tiêu đề cũng có sẵn để xác định các thanh ghi và cổng của bộ vi
điều khiển, đồng thời giúp lập trình viên phải xác định từng thanh ghi và
cổng bằng cách viết các dòng tiền xử lý cho mỗi thanh ghi. Do đó, đối với bộ
vi điều khiển Intel 8051, chúng ta có thể có tiêu đề <reg.51.h>; điều này xác
định các thanh ghi, ví dụ như các cổng P0, P1, P2 và P3, và các bit riêng lẻ
trong các thanh ghi có thể định địa chỉ bit, ví dụ như các bit TF1, TR1, TF0,
TR0, IE1, IT1, IE0 và IT0 trong thanh ghi TCON. Vì vậy, chúng ta có thể viết
các lệnh tham chiếu đến đầu vào/đầu ra của cổng 0 bằng cách sử dụng nhãn P0
hoặc TF1 để tham chiếu đến bit TF1 trong thanh ghi TCON. Tương tự, đối với
Motorola M68HC11E9, tiêu đề <hc11e9.h.> xác định các thanh ghi, ví dụ: PORTA,
PORTB, PORTC và PORTD, và các bit riêng lẻ trong các thanh ghi có thể định
địa chỉ theo bit, ví dụ: các bit STAF, STAI, CWOM, HNDS, OIN, PLS, EGA và
INVB trong sổ đăng ký PIOC. Vì vậy, ví dụ, chúng ta có thể viết các hướng dẫn
tham chiếu đến đầu vào/đầu ra của cổng A bằng cách sử dụng nhãn PORTA. Thư
viện cũng có thể cung cấp các quy trình hỗ trợ việc sử dụng các thiết bị
ngoại vi phần cứng như bàn phím và màn hình tinh thể lỏng.
Chương trình chính được viết cho một bộ vi điều khiển cụ thể có thể dễ dàng được
điều chỉnh để chạy với một bộ vi điều khiển khác nhờ việc thay đổi tệp tiêu đề. Do đó,
các thư viện làm cho các chương trình C có tính di động cao.
12.7 Ví dụ về các
chương trình Sau đây là ví dụ về các chương trình được viết bằng C cho hệ thống vi điều khiển.
Hãy xem xét việc lập trình cho bộ vi điều khiển M68HC11 để khởi động và dừng động cơ
một chiều. Cổng C được sử dụng cho đầu vào và cổng B cho đầu ra cho động cơ thông qua
bộ điều khiển thích hợp (Hình 12.6). Nút khởi động được kết nối với PC0 để chuyển từ
đầu vào 1 sang đầu vào 0 khi khởi động động cơ. Nút dừng được kết nối với PC1 để chuyển
từ đầu vào 1 sang 0 khi động cơ dừng. Thanh ghi hướng dữ liệu cổng C DDRC phải được
đặt thành 0 để cổng C được đặt cho đầu vào.
Machine Translated by Google
PB0
PC1
M68HC11
{
PORTB.PB0 &=0; /*ban đầu đảm bảo tắt động cơ*/
DDRC = 0; /*đặt cổng C làm đầu vào*/
while (1) /*lặp lại khi điều kiện này được giữ nguyên*/
{
if (PORTC.PC0 = =0) /*có nhấn nút khởi động không?*/
PORTB.PB0 |=1; /*bắt đầu xuất nếu được nhấn*/
else if(PORTC.PC1 = =0) /*có nhấn nút dừng không?*/
PORTB.PB0 &=0; /*dừng xuất nếu được nhấn*/
}
}
Lưu ý rằng | là toán tử OR và chỉ đặt một bit trong kết quả thành 0 nếu các
bit tương ứng trong cả hai toán hạng là 0, nếu không thì nó đặt thành 1. Nó
được sử dụng để bật hoặc đặt một hoặc nhiều bit trong một giá trị. Do đó,
Cổng B.PB0 |51 có 1 ORed với giá trị trong PB0 và do đó bật động cơ. Đó là
một cách hữu ích để chuyển đổi đồng thời một số bit trong một cổng. & trong
PORTB.PB0 &50 được sử dụng để AND bit PB0 bằng 0 và do đó, vì PB0 đã là 1
nên gán cho PORTB.PB0 giá trị 0.
Hãy xem xét nhiệm vụ lập trình một bộ vi điều khiển (M68HC11) để có thể đọc
được một kênh của bộ chuyển đổi tương tự sang số (ADC) của nó.
M68HC11 chứa ADC gần đúng liên tiếp 8 kênh, ghép kênh 8 kênh với đầu vào
qua cổng E (Hình 12.7). Thanh ghi trạng thái/điều khiển ADC ADCTL chứa cờ
hoàn thành chuyển đổi CCF ở bit 7 và các bit khác để điều khiển bộ ghép
kênh và quét kênh.
Khi CCF 5 0 quá trình chuyển đổi chưa hoàn tất và khi 1 thì quá trình chuyển đổi hoàn tất.
Machine Translated by Google
PE1
PE7 sổ đăng ký
Điện tử
đầu ra
0 0 0 0 PE0
Kiểm soát quét liên tục
0 0 0 1 PE1
0 = một chu kỳ bốn chuyển đổi
mỗi lần ADCTL được viết
0 0 1 0 PE2
1 = chuyển đổi liên tục
0 0 1 1 PE3
Điều khiển nhiều kênh/đơn kênh
0 1 0 0 PE4
0 = thực hiện bốn chuyển đổi liên tiếp
trên một kênh duy nhất 0 1 0 1 PE5
1 = thực hiện bốn chuyển đổi trên bốn kênh
0 1 1 0 PE6
liên tiếp
0 1 1 1 PE7
Chọn đồng hồ
Việc chuyển đổi tương tự sang số được bắt đầu bằng cách ghi 1 vào bit cấp
nguồn từ tương tự sang số (ADPU) trong thanh ghi OPTION. Tuy nhiên, ADC
phải được bật ít nhất 100 μs trước khi đọc giá trị.
Để chuyển đổi đầu vào tương tự thành PE0, 4 bit đầu tiên trong thanh
ghi ADCTL, tức là CA, CB, CC và CD, phải được đặt thành 0. Khi hoạt động
để chuyển đổi chỉ một kênh, bit 5 SCAN có thể được đặt thành 0 và bit 4
MULT thành 0. Do đó, một chương trình đơn giản để đọc một kênh cụ thể có
thể bao gồm, sau khi cấp nguồn cho ADC, chuyển tất cả các bit trong thanh
ghi ADCTL về 0, nhập số kênh và sau đó đọc đầu vào trong khi CCF đang hoạt động. 0.
Do đó chương trình có thể như sau:
{
int không dấu k; /*cái này nhập số kênh*/
Lưu ý rằng ~ là toán tử bù và hành động của nó là đảo ngược mọi bit trong toán
hạng của nó, thay đổi tất cả các số 0 thành số 1 và ngược lại. Do đó bit 7 được thiết
lập. | là toán tử OR và chỉ đặt một bit trong kết quả thành 0 nếu các bit tương ứng
trong cả hai toán hạng là 0, nếu không thì nó đặt thành 1. Nó được sử dụng để bật
hoặc đặt một hoặc nhiều bit trong một giá trị. Trong trường hợp này với k 5 1, nó chỉ
đặt CA thành 1. Có thể đưa vào một chương trình con trì hoãn để đảm bảo rằng sau khi
bật nguồn, giá trị không được đọc quá nhanh.
12.8 chương
Thuật ngữ phác thảo được sử dụng cho các chương trình sử dụng với bo mạch Arduino.
trình Arduino
Arduino sử dụng ngôn ngữ C cho các chương trình của nó. Định dạng cơ bản của các
chương trình như vậy bao gồm hai chức năng, thiết lập và lặp lại. Hàm thiết lập
được thực thi khi bắt đầu chương trình và được sử dụng để cấu hình các chân cũng
như khai báo các biến, hằng, v.v. Hàm vòng lặp được thực thi từng bước và khi đến
cuối vòng lặp, nó sẽ tự động quay lại bước đầu tiên của hàm vòng lặp và tiếp tục
lặp lại vòng lặp cho đến khi chương trình dừng lại.
Lưu ý rằng trong các chương trình Arduino, { đầu tiên đôi khi được đặt trên dòng
sau lệnh và do đó chương trình trên sẽ xuất hiện như sau:
Bản thân hàm thiết lập gọi hai hàm tích hợp là pinMode và digitalWrite. Hàm
pinMode đặt một chân cụ thể làm đầu vào hoặc đầu ra, vì các chân kỹ thuật số
Arduino có thể hoạt động như đầu vào hoặc đầu ra. Hàm digitalWrite đặt mức Pin
Cao hoặc Thấp.
Hai hàm này không trả về giá trị nên chương trình phải nói chúng là void. Để minh
họa, hãy xem xét một chương trình tạo ra điốt phát sáng (LED) trên bo mạch, được
kết nối bên trong với chân 13,
Machine Translated by Google
để nhấp nháy và tắt. Chú thích về chương trình được bao quanh bởi /* và */
khi ở trên nhiều dòng hoặc chỉ đứng trước // khi ở trên một dòng. Các chú
thích không được biên dịch thành mã máy để tải vào vi điều khiển.
//Bật đèn LED bên trong trong 0,5 giây, sau đó tắt liên tục trong 0,5 giây.
độ trễ (500);
Chức năng trì hoãn là tạo ra độ trễ 0,500 giây giữa việc ghi mức cao ở chân
13 và sau đó ghi ở mức thấp.
Giả sử chúng ta muốn bật đèn LED bên ngoài trong 0,5 giây, sau đó tắt
liên tục trong 0,5 giây. Chúng ta cần chỉ định đèn LED được kết nối với chân
nào và chân đó được coi là đầu vào. Một điểm quan trọng khi kết nối đèn LED
là thông thường điện áp rơi trên đèn LED được giới hạn ở khoảng 2V với dòng
điện 20mA. Vì bo mạch cung cấp nguồn 5V nên cần phải mắc một điện trở nối
tiếp với đèn LED để điện áp rơi trên nó sẽ là 3V, chỉ để lại mức giảm 2V cho
đèn LED. Do đó điện trở tối thiểu cần thiết là V/I = 3/0,020 = 150 Ω. Nói
chung, giá trị cao hơn sẽ được sử dụng vì đèn LED vẫn có thể phát sáng khá
rực rỡ với ít dòng điện hơn.
// Tắt đèn LED bên ngoài trong 0,5 giây, sau đó bật lại trong 0,5 giây.
#define ext_LED 12
độ trễ (500);
Bây giờ hãy xem xét vận hành với đèn LED bên ngoài và bên trong.
/*Bật đèn LED bên trong và tắt đèn LED bên ngoài trong 0,5 giây, sau đó tắt đèn LED bên
trong và đèn LED bên ngoài bật liên tục trong 0,5 giây.
*/
Machine Translated by Google
#define int_LED 13
#define ext_LED 12
trễ (500);
trễ (500); }
Do đó, chương trình trên có các đèn LED bên trong và bên ngoài liên tục
nhấp nháy luân phiên tắt và bật. Một cải tiến có thể có của chương trình
trên là việc này chỉ diễn ra khi một công tắc được đóng lại.
/*Nếu công tắc đóng, hãy bật đèn LED bên trong và tắt đèn LED bên ngoài để
0,5 giây, sau đó đèn LED bên trong tắt và đèn LED bên ngoài bật liên tục trong 0,5 giây.
*/
#define int_LED 13
#define ext_LED 12
#define ext_sw 11
Int switch_value;
INPUT);
( ) { switch_value = digitalRead(ext_sw);
trễ (500);
trễ (500); }
khác
{ digitalWrite(int_LED, THẤP);
Machine Translated by Google
digitalWrite(ext_LED, THẤP)
}
}
Phần trên chỉ giới thiệu đơn giản về cách viết chương trình cho Arduino.
Các quy trình cần thiết về cơ bản chỉ là những quy trình được nêu trước đó
trong chương này với C. Nhiều chương trình đã được viết sẵn và có sẵn miễn
phí trên trang web Arduino.
Để sử dụng chương trình ngôn ngữ C với Arduino, chương trình có tên Môi
trường phát triển Arduino trước tiên được tải xuống từ trang web Arduino
vào máy tính chủ. Chương trình này cho phép nhập mã ngôn ngữ C vào máy tính
và sau đó biên dịch chương trình, kiểm tra xem nó có tuân thủ các quy tắc
của ngôn ngữ C hay không và dịch nó sang hợp ngữ rồi sang mã máy vì đây là
ngôn ngữ mà bo mạch Arduino hiểu được . Khi bạn khởi động bo mạch Arduino
lần đầu tiên, nó sẽ vào bộ nạp khởi động, đây là một đoạn mã đã được tải
xuống bộ nhớ của nó tại nhà máy và cho phép các chương trình được tải lên
thông qua đầu nối USB. Sau đó, nếu nó nhận được lệnh từ máy chủ để tải
chương trình lên, chương trình mã máy sẽ được tải vào bộ nhớ Arduino để bộ
vi điều khiển Arduino sử dụng.
C là ngôn ngữ cấp cao có ưu điểm khi so sánh với ngôn ngữ hợp ngữ là dễ sử
dụng hơn và có thể sử dụng cùng một chương trình với các bộ vi xử lý khác
nhau; tất cả những gì cần thiết cho việc này là sử dụng trình biên dịch
thích hợp để dịch chương trình C sang ngôn ngữ máy phù hợp cho bộ vi xử lý
liên quan. Ngôn ngữ hội là khác nhau đối với các bộ vi xử lý khác nhau
trong khi ngôn ngữ C được chuẩn hóa.
Các gói C được cung cấp các thư viện chứa một số lượng lớn các hàm được
xác định trước chứa mã C đã được viết sẵn.
Để sử dụng nội dung của bất kỳ thư viện cụ thể nào, thư viện đó phải được chỉ định
trong tệp tiêu đề. Mọi chương trình C đều phải có một hàm gọi là main(); bài tập
này kiểm soát thời điểm chương trình được thực thi và là hàm đầu tiên được gọi. Một
chương trình được tạo thành từ các câu lệnh, mỗi câu lệnh đều được kết thúc bằng
dấu chấm phẩy. Các câu lệnh có thể được nhóm lại với nhau thành các khối bằng cách
đặt chúng giữa các dấu ngoặc nhọn, tức là { }.
Machine Translated by Google
Các vấn đề
12.1 Các câu hỏi sau đây đều liên quan đến các thành phần của chương trình.
(a) Nêu rõ những gì được chỉ định bởi int trong câu lệnh:
bộ đếm int;
số = 10
printf("Tên");
#include <stdio.h>
12.2 Đối với chương trình sau, lý do đưa dòng (a) #include <stdio.h>, (b) the
{ và }, (c) the /d, và (d) những gì sẽ xuất hiện trên màn hình là gì khi
chương trình được thực thi?
#include <stdio.h>
chủ yếu( )
{
printf(/d“vấn đề 3”);
}
12.3 Trong chương trình sau, màn hình sẽ hiển thị những gì?
#include <stdio.h>
int chính(void);
{
int số;
số = 20;
0; }
12.4 Viết chương trình tính diện tích hình chữ nhật biết chiều dài và chiều rộng
của nó tại dấu nhắc trên màn hình về chiều dài và chiều rộng, sau đó hiển
thị câu trả lời trước từ 'Diện tích bằng'.
Machine Translated by Google
12.5 Viết chương trình hiển thị các số từ 1 đến 15, mỗi số trên một dòng riêng.
12.6 Giải thích nguyên nhân của các phát biểu trong chương trình chia hai số sau:
#include <stdio.h>
int chính(void);
nếu(num2 = = 0)
print f("Không thể chia cho 0")
khác