Ngôn ngữ C cho vi điều khiển

0
976
ngôn ngữ C cho vi điều khiển

Khi bạn muốn lập trình cho một vi điều khiển nào đó thì điều đầu tiên bạn phải làm đó là học một ngôn ngữ lập trình. Hiện nay, có nhiều ngôn ngữ có thể sử dụng để lập trình cho vi điều khiển, đầu tiên phải nói đến ASM, rồi đến C, C++,… trong số này thì ngôn ngữ C được rất nhiều người dùng. Đây là một ngôn ngữ bậc cao khá thân thiện và được ưa chuộng nhất khi lập trình cho vi điều khiển. Trong bài viết này tôi sẽ giúp các bạn làm quen với ngôn ngữ C, từ đó các bạn có thể sử dụng ngôn ngữ này vào việc lập trình cho vi điều khiển.

Các kiểu dữ liệu của biến

Trong chương trình thường khai báo biến để lưu dữ liệu và xử lý dữ liệu, tùy thuộc vào loại dữ liệu mà ta chọn loại dữ liệu cho phù hợp. Các biến của vi điều khiển bao gồm bit, byte, word và long word tương ứng với dữ liệu 1bit, 8bit, 16bit và 32bit.

Kiểu dữ liệu Số bit Số byte Khoảng giá trị
Char 8 1 -128 to +127
Unsigned char 8 1 0 to 255
Enum 16 2 -32,768 to +32,767
Short 16 2 -32,768 to + 32,767
Unsigned short 16 2 0 to 65.535
Int 16 2 -32,768 to + 32,767
Unsigned int 16 2 0 to 65,535
Long 12 4 -2,147,483,648 to +2,147,483,648
Unsigned long 12 4 0 to 4,294,697,295
 

Khai báo biến:

Cú pháp: Kiểu_dữ_liệu Vùng_nhớ   Tên_biến _tại_ Đia_chỉ;

Ví dụ:        Unsigned char data x;

Khi khai báo biến có thể gán luôn cho biến giá trị ban đầu.

Ví dụ:       Thay vì:         unsigned char x;

                                                 x = 0;

                Ta chỉ cần:    unsigned char x = 0;

Có thể khai báo nhiều biến cùng một kiểu một lúc.

Ví dụ:   Unsigned int x,y,z,t;

Các toán tử 

Toán tử gán (=)

Cú pháp: Biến_1 = Biến_2;
Trong đó Biến_2 có thể là giá trị xác định cũng có thể là biến.

Ví dụ:

b  =  5;

a  =  2  +  b;

a  =  2  +  (b  =  5);

a  =  b  =  c  =  5;

Các toán tử số học 

Phép toán
Ý nghĩa
Ví dụ
+
Phép cộng 
X = a+b;
Phép trừ 
X = a-b;
*
Phép nhân 
X = a*b;
/
Phép chia lấy phần nguyên
X = a/b;
(a=9, b=2 → X=4)
%
Phép chia lấy phần dư 
X = a%b;
(a=9, b=2 → X=1)

Các toán tử gán phức hợp 

Phép toán
Ví dụ
+=
a+=5 tương đương với a=a+5
-=
a-=5 tương đương với a=a-5
*=
a*=5 tương đương với a=a*5
/=
a/=5 tương đương với a=a/5
%=
a%=5 tương đương với a=a%5

Toán tử tăng và giảm  (++, – -)

a++; tương đương với  a+=1; tương đương với  a=a+1;

Lưu ý: (++a) khác với (a++)

Ví dụ:

B=3; B=3;A=++B; // A là 4, B là 4

B=3;  A=B++; // A là 3, B là 4

Các toán tử so sánh

Phép toán
Ý nghĩa
Ví dụ
So sánh lớn hơn
a>b
4>5 sẽ trả ra giá trị false
>=
So sánh lớn hơn hoặc bằng
a>=b
6>=2 sẽ trả ra giá trị true
So sánh nhỏ hơn
a<b 
6<7 sẽ trả ra giá trị true
<=
So sánh nhỏ hơn hoặc bằng
a<=b
8<=5 sẽ trả ra giá trị false
==
So sánh bằng nhau
a==b
6==6 sẽ trả ra giá trị true
!=
So sánh khác nhau
a!=b
9!=9 sẽ trả ra giá trị false

Các toán tử logic

Chức năng
Phép toán
AND
&&
OR
||
NOT
!

Ví dụ:

!(5  ==  5) trả về false vì biểu thức bên phải (5  ==  5) có giá trị true. !(6  <=  4) trả về true vì (6  <=  4)có giá trị false. !true trả về false. !false trả  về  true. ( (5  ==  5) && (3  >  6) ) trả  về false (true  &&  false).   

Các toán tử thao tác bit

Phép toán
Ý nghĩa
Ví dụ
&
Phép VÀ (AND)
Bit_1 & Bit_2
|
Phép HOẶC (OR) 
Bit_1 | Bit_2
!
Phép ĐẢO (NOT) 
!Bit_1
^
Phép EX-OR
Bit_1 ^ Bit_2
<< 
Dịch bit sang trái 
a<<3
>> 
Dịch bit sang phải 
a>>4
~
Lấy bù theo bit
~a

Thứ tự ưu tiên của các toán tử

Thứ tự Toán tử Mô tả Thứ tự ưu tiên
1 :: scope trái
2 { } [ ] ->, sizeof   trái

3

++    — Tăng/ giảm

Phải

˜

Đảo ngược bit

! Not

& *

Toán tử con trỏ

(type) Chuyển đổi kiểu
+ – Dương hoặc âm
4 /  * Toán tử số học Trái
5 + – Toán tử số học Trái
6 <<   >> Dịch bit Trái
7 <   <=   >   >= Toán tử quan hệ Trái
8 ==    != Toán tử quan hệ Trái
9 & ^  | Toán tử thao tác bit Trái
10 &&  || Toán tử logic Trái
11 ? : Toán tử điều kiện Phải
12 =   +=     -=    *=    >>= <<=    &=    ^=     |= Toán tử gán Phải
13 , Dấu phảy Trái

Cấu trúc cơ bản của một chương trình C

Cấu trúc chương trình

Cấu trúc:

  1. Khai báo chỉ thị tiền xử lý
  2. Khai báo các biến toàn cục
  3. Khai báo nguyên mẫu các hàm
  4. Xây dựng các hàm và chương trình chính

Ví dụ:

// Khai báo chỉ thị tiền xử lý:

#include <AT89X52.H>  hoặc  #include “AT89X52.H”

#include<string.h>

#define Led1 P1_0

//*********************************

// Khai báo các biến toàn cục:

            Unsigned char code Led_arr[3];

            Unsigned char data dem;

            Unsigned int xdata X;

//*********************************

// Khai báo nguyên mẫu hàm

            Void delay(unsigned int n);

            bit kiemtra(unsigned int a);

//*********************************

// Xây dựng các hàm và chương trình chính:

             void delay(unsigned int n)

            {

                        Khai báo biến cục bộ;

Mã chương trình trễ;

            }

Void main()  // Chương trình chính

            {

                        Khai báo biến cụ bộ;

Mã chương trình chính;

            }

            Bit kiemtra(unsigned int a)

            {

                        Khai báo biến cục bô;

Mã chương trình kiểm tra biến a;

            }

Chỉ thị tiền xử lý

Các chỉ thị tiền sử lý không phải là các lệnh của ngôn ngữ C mà là các lệnh giúp cho việc soạn thảo chương trình nguồn C trước khi biên dịch. Khi dịch một chương trình C thì không phải chính bản chương trình nguồn mà ta soạn thảo được dịch. Trước khi dịch, các lệnh tiền xử lý sẽ chỉnh lý bản gốc, sau đó bản chỉnh lý này sẽ được dịch. Có ba cách chỉnh lý được dùng là:

  + Phép thay thế #Define

  + Phép chèn tệp #Include

  + Phép lựa chọn biên dịch #Ifdef

Các chỉ thị tiền xử lý giúp ta viết chương trình ngắn gọn hơn và tổ chức biên dịch, gỡ rối chương trình linh hoạt, hiệu quả hơn.

Chỉ thị #Define: Chỉ thị #define cho phép tạo các macro thay thế đơn giản.

 Cú pháp: #Define Tên_thay_thế dãy_kí_tự

Một Tên_thay_thế có thể được định nghĩa lại nhiều lần, nhưng trước khi định nghĩa lại phải giải phóng định nghĩa bằng chỉ thị:

            #Undef Tên_thay_thế

Ví dụ:         #define N 100

Chỉ thị #Include: Chỉ thị #include báo cho trình biên dịch nhận nội dung của tệp khác và chèn vào tệp chương trình nguồn mà ta soạn thảo.

Cú pháp:

Cách 1:          #include<tên_tệp>

Cách 2:          #include“tên_tệp”

Ví dụ:

            Cách 1: #include<regx51.h>

Ở cách này tệp regx51.h sẽ được tìm trong thư mục INC để chèn vào chương trình nguồn.

            Cách 2: #include“regx51.h”

Ở cách này tệp regx51.h sẽ được tìm trong thư mục chứa chương trình nguồn nếu không có mới tìm trong thư mục INC.

Khi muốn chèn tệp ngoài thư viện hoặc ngoài thư mục chứa chương trình nguồn thìtên_tệp sẽ bao gồm cả đường dẫn thư mục chứa tệp.

Chỉ thị #Ifdef: Chỉ thị #ifdef này thường dùng để biên dịch các tệp thư viện.

Cú pháp:

Cách 1:          #Ifdef ten_macro

                                                //Đoạn chương trình

                                    #endif

Cách 2:          #ifdef ten_macro

                                                //Đoạn chương trình 1

                                    #else

                                                //Đoạn chương trình 2

                                    #endif

Ở cách 1: nếu tên_macro đã  được định nghĩa thì “Đoạn chương trình” sẽ được dịch, ngược lại thì “Đoạn chương trình” sẽ bị bỏ qua.

Chỉ thị #Ifndef: Chỉ thị #ifndef này thường dùng để biên dịch các tệp thư viện.

Cú pháp:

Cách 1:          #ifndef ten_macro

//Đoạn chương trình

                                    #endif

Cách 2:          #ifndef ten_macro

                                                //Đoạn chương trình 1

                                    #else

                                                //Đoạn chương trình 2

                                    #endif

 

Ở cách 1: nếu  tên_macro chưa được định nghĩa thì “Đoạn chương trình” sẽ được dịch, ngược lại thì “Đoạn chương trình” sẽ bị bỏ qua.

Chú thích trong chương trình

Việc viết chú thích trong trình nhằm mục đích giải thích ý nghĩa của câu lệnh, đoạn chương trình hoặc hàm hoạt động như thế nào và làm gì. Viết chú thích sẽ giúp cho người đọc có thể hiểu được chương trình dễ dàng và nhanh chóng hơn, sửa lỗi đơn giản hơn hoặc giúp cho ta xem lại chương trình cũ mà ta đã viết trở lên nhanh hơn.

Chú thích trong chương trình sẽ không ảnh hưởng đến chương trình mà ta soạn thảo vì trình dịch sẽ bỏ qua tất cả lời chú thích khi biên dịch chương trình sang mã máy.

Lời giải thích được đặt sau dấu “//” nếu chú thích chỉ viết trên một dòng hoặc trong cặp dấu /*…*/ nếu chú thích được viết trên nhiều dòng.

Ví dụ:

// Khai báo PORT điều khiển LED

#define LED_PORT     PORTD

#define LED_PORT_Dir TRISD

/*Chương trình điều khiển LED đơn

Người viết: Nguyễn Hữu Phước

Version: 01

Ngày khởi tạo: 14/03/2019

*/

Các lệnh cơ bản trong C

Cấu trúc điều kiện: if và else

Cú pháp 1:     if(điều_kiện)

                                    {

                                                // Đoạn chương trình

                                    }

Giải thích: nếu điều_kiện đúng thì xử lí các câu lệnh bên trong còn sai thì bỏ qua.

Ví dụ: if  (x  ==  100)  x++;

nếu x=100 thì tăng x thêm 1

Cú pháp 2:           if(điều_kiện)

                                    {

                                    // Đoạn chương trình 1

                                    }

                                    else

                                    {

                                  // Đoạn chương trình 2

                                    }

Giải thích: nếu dieu_kien đúng thì xử lí “Đoạn chương trình 1” bên trong còn sai thì xử lý “Đoạn chương trình 2”.

Ví dụ: if  (x  ==  100)    x++; else    x- -;

nếu x=100 thì tăng x thêm 1 còn ngược lại giảm x đi 1

Cấu trúc vòng lặp

Vòng lặp while 

Cú pháp:           while(điều_kiện)

                                    {

                                                // các câu lệnh

                                    }

Giả thích: Trước tiên chương trình sẽ kiểm tra điều_kiện, nếu đúng thì thực hiện các câu lệnh, sau đó quay lại kiểm tra điều_kiện. Còn nếu điều_kiện sai thì thoát khỏi vòng lặp ngay.

Ví dụ: while(1) {};

Tạo vòng lặp mãi mãi, rất hay dùng trong lập trình vi xử lý. Chương trình chính sẽ được viết trong dấu ngoặc.

Vòng lặp do-while 

Cú pháp:          do

                                    {

                                    // các câu lệnh

                                    } while(điều_kiện);

Giải thích: Trước tiên đoạn chương trình thực hiện các câu lệnh sau đó kiểm tra điều_kiện nếu đúng thì lặp lại thực hiện các câu lệnh tiếp, nếu sai thì thoát khỏi vòng lặp.

Ví dụ: 

do

{

x++; 

} while(x>10)

Tăng giá trị của x cho đến khi x > 10

Vòng lặp for 

Cú pháp:           for( x=n ; điều_kiện ; phép_toán )

                                    {

                                                // các câu lệnh xử lí

                                    }

Giải thích:  x là biến, n là giá trị xác định. Trước tiên vòng lặp sẽ gán giá trị ban đầu cho biến: x=n, rồi kiểm tra nếu điều_kiện đúng thì thực hiện các câu lệnh xử lý, sau đó thực hiện Phép_toán nhằm tác động đến điều kiện. Sau đó lại kiểm tra lại điều_kiện, nếu còn đúng thì thực hiện tiếp, nếu sai sẽ thoát khỏi vòng lặp.

Các thành phần trong vòng for có thể không cần khai báo,for sẽ bỏ qua phần đó, nhưng vẫn phải có đủ 2 dấu “;”.

Ví dụ:

For (int n = 0; n<100; n++)

{

x=x+10;

}

Vòng lặp thực hiện với biến n = 0 cho đến khi n bằng 100 thì dừng lại.

Cấu trực lựa chọn – Switch

Cú pháp:            switch(biến)

                                    {

                                 case gia_tri_1:

                               //các câu lệnh 

                            break;

                                    case gia_tri_2:

                              //các câu lệnh 

                             break;

                                    ………………………………………

                                    case gia_tri_n:

                               //các câu lệnh 

                              break;

                              Default:

                             //các câu lệnh

                                    }

Giải thích: Tuỳ vào biến có giá trị bằng giá trị của Case nào thì thực hiện các câu lệnh tương ứng trong Case đó, sau đó thoát khỏi cấu trúc nhờ câu lệnh “break;”. Nếu không có Case nào phù hợp thì thực hiện các câu lệnh trong default.

Các lệnh rẽ nhánh và lệnh nhảy

Lệnh break

Sử dụng break chúng ta có thể thoát khỏi vòng lặp ngay cả khi điều kiện để nó kết thúc chưa được thoả mãn. Lệnh này có thể được dùng để kết thúc một vòng lặp không xác định hay buộc nó phải kết thúc giữa chừng thay vì kết thúc một cách bình thường. 

Lệnh continue

Lệnh continue làm cho chương trình bỏ qua phần còn lại của vòng lặp và nhảy sang lần lặp tiếp theo. 

Lệnh goto

Lệnh này cho phép nhảy vô điều kiện tới bất kì điểm nào trong chương trình. Nói chung bạn nên tránh dùng nó trong chương trình C++. Tuy nhiên chúng ta vẫn có một ví dụ dùng lệnh goto để đếm ngược.

Hàm exit

Mục đích của exit là kết thúc chương trình và trả về một mã xác định. Dạng thức của nó như sau void exit (int exit code); exit code được dùng bởi một số hệ điều hành hoặc có thể được dùng bởi các chương trình gọi. Theo quy ước, mã trả về 0 có nghĩa là chương trình kết thúc bình thường còn các giá trị khác 0 có nghĩa là có lỗi.

Các lệnh trên mình chủ yếu chỉ dùng lệnh break để thoát khỏi vòng lặp. Các lệnh khác thường rất ít dược sử dụng.

BÌNH LUẬN

Please enter your comment!
Please enter your name here