CÙNG HỌC AVR AVR3– LẬP TRÌNH C CHO AVR: NGẮT VÀ TIMER/COUNTER

Chia sẻ: caothunhamay

Đây là thứ 3 trong loạt bài cùng học AVR. Nếu bài 1 và bài 2 giới thiệu một cách chung nhất về AVR thì kể từ bài 3 tôi sẽ giới thiệu lập trình điều khiển peripheral (thiết bị ngoại vi hay các chức năng mở rộng tích hợp sẵn trên các chip AVR).

Bạn đang xem 10 trang mẫu tài liệu này, vui lòng download file gốc để xem toàn bộ.

Nội dung Text: CÙNG HỌC AVR AVR3– LẬP TRÌNH C CHO AVR: NGẮT VÀ TIMER/COUNTER

AUTO.NLU

CÙNG HỌC AVR
AVR3– LẬP TRÌNH C CHO AVR: NGẮT VÀ TIMER/COUNTER

Thoả thuận: tài liệu này thuộc quyền sở hữu của tác giả, bạn có thể tự do tham khảo
tài liệu nhưng không được phép sử dụng để in thành sách báo, đăng lên các diễn đàn
hay website, nhưng bạn có thể dùng đường link http://www.dieukhientudong.net để
hướng tới tài liệu. Liên hệ tác giả qua email: thanhtam.h@gmail.com.

I. Bạn sẽ đi đến đâu.
Đây là thứ 3 trong loạt bài cùng học AVR. Nếu bài 1 và bài 2 giới thiệu một cách chung nhất
về AVR thì kể từ bài 3 tôi sẽ giới thiệu lập trình điều khiển peripheral (thiết bị ngoại vi hay các
chức năng mở rộng tích hợp sẵn trên các chip AVR). Do là các thiết bị ngoại vi mở rộng nên
không phải tất cả các chip AVR đều có tất cả các thiết bị này, ví dụ chip AVR AT90S2313,
AT90S8515 không có bộ chuyển đổi Analog-Digital (ADC) và giao tiếp TWI (I2C)…Tuy nhiên,
các chip thuộc dòng Mega có khá nhiều thiết bị ngoại vi phục vụ cho các ứng dụng đo lường, điều
khiển…Chúng ta sẽ tiếp tục sử dụng chip Atmega8 để khảo sát, trong quá trình khảo sát, nếu có
sự khác biệt giữa Atmega8 và các chip mới hơn (như Atmega16, Atmega32, Atmega64,
Atmega128…) tôi sẽ nói rõ để bạn rõ.
Một sự khác biệt lớn giữa AVR3 so với các bài viết trước là tôi sẽ hướng dẫn lập trình bằng
C mà cụ thể là bằng AVR-GCC (được tích hợp trong WinAVR). Các bạn xem phần II để biết rõ
hơn.
Sau bài này, tôi hy vọng bạn sẽ:
- Cài đặt và sử dụng WinAVR, Programmer Notepad.
- Hiểu được một số hàm cơ bản trong thư viện avr-libc.
- Hiểu về INTERRUPT (ngắt), cách sử dụng ngắt bằng C và cả ASM.
- Cải tiến ví dụ trong bài 2 bằng Interrupt.
II. WinAVR.
Tại sao C: như tôi đã trình bày ở các bài học trước, khi bạn đã hiểu về AVR, để thực hiện
các ứng dụng, bạn có thể không nhất thiết phải luôn lập trình bằng ASM. Ngôn ngữ cấp cao như C
sẽ giúp cho bạn xây dựng các ứng dụng nhanh chóng và dễ dàng hơn, tuy nhiên không vì thế mà
bạn “quên” ASM, lập trình bằng C kết hợp ASM là giải pháp hay nhất. Một chú ý là chúng ta chỉ
sử dụng C để đơn giản hóa lập trình tính toán, cấu trúc điều khiển…lập trình C cho AVR không
có nghĩa là bạn không cần biết cấu trúc và cách thức hoạt động của chip!!!
Tại sao WinAVR: WinAVR (đọc là Whenever: theo tác giả của WinAVR) là một bộ phần
mềm mã nguồn mở bao gồm các công cụ cho dòng vi điều khiển AVR . WinAVR chạy trên nền
hệ điều hành Windows, nó bao gồm các công cụ sau:
- Trình biên dịch avr-gcc, GNU GCC là trình biên dịch C, C++ phát triển bởi cộng
đồng mã nguồn mở GNU, avr-gcc phát triển riêng cho AVR.
- Chương trình nạp chip avrdude.
- Chương trình debugger avr-gdb.


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

- Programmer Notepad: trình biên tập code hỗ trợ nhiều ngôn ngữ như C, C++,
CSS, HTML, Java,…
- MFile: tiện ích tạo các file Makefile dùng trong quá trình biên dịch code…
Cốt lõi của WinAVR là trình biên dịch GNU GCC và thư viện avr-libc, đây là bộ công cụ
lập trình C miễn phí hoàn chỉnh duy nhất cho AVR. Có thể nói bộ công cụ này góp phần không
nhỏ giúp cho chip AVR ngày càng trở nên phổ biến. WinAVR liên tục được cập nhật và hoàn
thiện bởi rất nhiều người, nguồn tài liệu và chương trình mẫu viết bằng công cụ này là rất
lớn…Đây là những lí do chính khiến tôi chọn WinAVR để giới thiệu với bạn.
Download và cài đặt: có 2 cách để bạn cài đặt bộ công cụ C cho AVR, cách thứ nhất, bạn
download từng phần gồm binutils, gnu-gcc, avr-libc, và avrdude…rồi cài đặt (cách này thường
được sử dụng trên hệ điều hành Linux…tôi sẽ giới thiệu trong 1 tài liệu khác) và cách thứ 2 là
dùng WinAVR (dành cho windows). Bạn có thể download trực tiếp phiên bản mới nhất tại
website chính thức của WinAVR: http://winavr.sourceforge.net/index.html. Quá trình cài đặt
tương đối dễ dàng vì bạn có thể chỉ cần làm theo các lựa chọn mặc định. Sau khi cài đặt WinAVR
vào máy (tôi giả sử thư mục cài đặt của bạn là C:\WinAVR) bạn sẽ có đầy đủ bộ công cụ từ IDE
(Integrated Development Environment) để biên tập code, trình biên dịch, linker, chương trình nạp
chip, tiện ích tạo Makefile…
Programmer Notepad (pn): Programmer Notpad là phần mềm môi trường phát triển tích
hợp (IDE) miễn phí cho việc lập trình các ngôn ngữ như C, C++, CSS, HTML, Java,…Tuy giao
diện của pn khá đơn giản nhưng đây là công cụ rất hoàn hảo và được tích hợp sẵn trong WinAVR,
avr-gcc lugin được tích hợp sẵn trong pn cho WinAVR nên chúng ta có thể biên dịch code,
download chương trình vào chip trực tiếp với pn. (có thể tham khảo thêm về pn tại website
http://www.pnotepad.org/ ) (hey, bạn có thể viết code cho avr-gcc bằng AVRStudio, Eclipse IDE
hay ngay cả với Windows Notepad…makes sense).
MFile: để biên dịch 1 chương trình bằng trình biên dịch gnu gcc, bạn cần 1 file tên là
Makefile không có phần mở rộng, file này chứa thông tin cần thiết như thông tin về trình biên
dịch, target (là các chip AVR trong trường hợp của chúng ta), trình nạp chip…MFile là tiện ích
giúp chúng ta tạo các Makefile nhanh chóng và chinh xác. MFile được tích hợp sẵn trong
WinAVR.
III. Khởi động cùng Programmer Notepad (pn).
Sau khi cài đặt WinAVR, trên desktop của bạn có thể sẽ xuất hiện 2 icon của pn và MFile
như trong hình 1.




Hình 1
Phần này chúng ta tìm hiểu cách viết một chương trình C trong pn thông qua 1 ví dụ đơn
giản. Từ Desktop, hãy khởi động pn, lần đầu chạy pn bạn sẽ thấy giao diện của chương trình như
trong hình 2.


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU




File Editor
Vùng Project




Kết quả biên dịch




Hình 2: giao diện pn.
Trước hết chúng ta hãy cài đặt thêm một số tính năng vào pn bao gồm chức năng tạo ra file
coff (dùng mô phỏng với AVR Studio Simulator) và chức năng vừa biên dịch vừa nạp chip. Từ
menu chính của pn, chọn menu “Tool > Option”, bạn sẽ thấy hộp thoại Option xuất hiện, hãy
chọn mục Tool trong hộp thoại Option rồi nhấn button “Add” như trong hình 3.




For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU




Hình 3: Option cho pn.
Trong hộp thoại “New Tool Properties” hãy đặt các thông số như trong hình 4:




Hình 4: Add chức năng tạo file COFF cho pn.


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

Lặp lại các bước trên để add thêm chức năng vừa biên dịch vừa đổ chương trình vào pn (xem
hình 5).




Hình 5: Add chức năng Make và Program cho pn.
Nhấn “OK” để kết thúc cài đặt, click vào menu Tools bạn sẽ thấy có 2 lệnh mới được add
vào, chúng ta sẽ sử dụng chúng sau này.




Hình 6: Tools menu.
Khi add các chức năng mới vào pn, bạn chú ý 2 mục là command và parameters, command
thì luôn là “make” vì đây chính là lệnh “đa năng” khi làm việc với trình biên dịch gnu-gcc.


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

Parameters là các thông số gởi kèm với lệnh make, như vậy khi bạn click vào 1 dòng lệnh mới tạo
ra, pn sẽ yêu cầu trình dịch gcc thực hiện lệnh make với thông số mà bạn đã tạo.
Chúng ta đã sẵn sàng để viết ví dụ đầu tiên bằng WinAVR. Từ pn, chọn menu
“File>New>Project” , bạn chọn nơi lưu Project của bạn (ví dụ C:\WinAVR\My Project) và hãy
đặt tên cho Project của bạn là AVR1-gcc vì chúng ta sẽ viết lại ví dụ cho bài AVR1 bằng C.
Hãy type đoạn code sau vào của sổ “new” (phần bên phải trong pn)

//code 1
//file: main.c
//Description: AVR1 by GCC, "Cung hoc AVR" Series
#include
#include
unsigned char val=1;
int main(void){
DDRB=0xFF; //set PORTB as output lines
while(1){
PORTB=val;
_delay_loop_2(65000);
val*=2;
if (!val) val=1;
}
return 0;
}

Chọn “File>save” để lưu đoạn code trên thành 1 file có tên là main.c
Trong vùng “Project” (phần bên trái), click phải vào Project “AVR1-gcc” rồi chọn “Add
Files”, hãy add file “main.c” vào Project của bạn.
Hãy thử biên dịch Project của bạn bằng cách chọn menu “Tools>[WinAVR] Make All”,
quan sát vùng thông báo biên dịch (nằm ở phía dưới) bạn sẽ thấy thông báo như sau:




Nghĩa là có lỗi trong quá trình biên dịch, quá trình biên dịch thất bại vì “No rule to make
target ‘all’.” Lỗi này do Project của chúng ta không có file Makefile. Hãy tạo 1 file Makefile bằng
tiện ích MFile.
Từ Desktop, chạy chương trình MFile, giao diện của MFile rất đơn giản như trong hình 7
(chú ý: chúng ta có thể thêm bớt các cài đặt cho MFile bằng cách chỉnh sửa file mfile.tcl trong thư
mục cài đặt của WinAVR).


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU




Hình 7: chương trình tiện ích MFile
Hãy chọn menu “Makefile>Main file name”, một hộp thoại nhỏ xuất hiện, điền tên file chính
trong Project của bạn (trong trường hợp của chúng ta ở đây là “main”), nhấn “OK”. Tiếp tục chọn
“Makefile > MCU type > ATmega > atmega8”. Đối với Project ví dụ này, chỉ cần set 2 tham số
tên file và loại chip như trên là đủ, bạn chọn “File>save as” và lưu Makefile vào chung thư mục
chứa Project (C:\WinAVR\My Project trong trường hợp của tôi). Bạn đã có thể tắt chương trình
MFile.
Trở lại pn, chọn menu “Tools>[WinAVR] Make All” lần nữa để biên dịch, lần này bạn sẽ
thấy thông báo cuối cùng là “>Process Exit code: 0”, biên dịch thành công. Vào thư mục chứa
Project bạn sẽ thấy 1 file “main.hex” được tạo ra. Để thử nghiệm chức năng tạo file COFF mà bạn
đã add vào pn, chọn “Tools > [WinAVR] Make COFF”, quay lại thư mục chứa Project bạn sẽ
thấy 1 file mới “main.cof” được tạo.
Hãy tìm và copy file “AVR1.DSN” (file của phần mềm Proteus) trong bài học AVR1 vào
thư mục Project của bạn, chạy AVR1.DSN với Proteus, đổi file program cho chip atmega8 thành
main.hex (xem lại bài AVR1 nếu bạn quên cách thực hiện). Chạy mô phỏng để kiểm tra kết quả,
nếu kết quả tương tự như trong AVR1, bạn đã thành công ((b)? (a): (b)) : định nghĩa một macro tìm số lớn nhất trong 2 số a và b,
trong chương trình nếu bạn gọi x=max(2,3) thì kết quả thu được x=3.
Biểu thức (Expressions): là 1 phần của các câu lệnh, biểu thức có thể bao gồm biến, toán
tử, gọi hàm…, biểu thức trả về 1 giá trị đơn. Biểu thức không phải là 1 câu lệnh hoàn chỉnh. Ví
dụ: PORTB=val.
Câu lệnh (Statement): thường là 1 dòng lệnh hoàn chỉnh, có thể bao gồm các keywords,
biểu thức và các câu lệnh khác và được kết thúc bằng dấu “;”. Ví dụ: unsigned char val=1; val*=2;
…là các câu lệnh.
Khối (Blocks): là sự kết hợp của nhiều câu lệnh để thực hiện chung 1 nhiệm vụ nào đó,
khối được bao bởi 2 dấu mở khối “{“ và đóng khối “}”: ví dụ 1 khối:
while(1){
PORTB=val;
_delay_loop_2(65000);
val*=2;
if (!val) val=1;
}


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

Toán tử (Operators): là những ký hiệu báo cho trình biên dịch các nhiệm vụ cần thực hiện,
các bảng bên dưới tóm tắt các toán tử C dùng cho lập trình AVR:
Bảng 1 các toán tử đại số: dùng thực hiện các phép toán đại số quen thuộc, trong đó đáng chú ý là
các toán tử “++” (tăng thêm 1) và “--“ (bớt đi 1), chú ý phân biệt y=x++ và y=++x, ví dụ ta có x=3 trong
khi y=x++ nghĩa là gán x cho y rồi sau đó tăng x thêm 1, điều này không ảnh hưởng đến y (cuối cùng y=3,
x=4) trong khi y=++x nghĩa là tăng x trước rồi mới gán cho y (cuối cùng y=x=4), tương tự cho các trường
hợp của toán tử “--“ .




Bảng 2 Toán tử truy cập và kích thức : toán tử [] thường được sử dụng khi bạn dùng mảng trong
lúc lập trình, phần tử thứ của mảng sẽ được truy xuất thông qua [i], chú ý mảng trong C bắt đầu từ 0.




For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU
Bảng 3 Toán tử Logic và quan hệ: thực hiện các phép so sánh và logic, thường được dùng làm
điều kiện trong các cấu trúc điều khiển, chú ý toán tử so sánh bằng “==”, toán tử này khác với toán tử gán
“=”, trong khi y = x nghĩa là lấy giá trị của x gán cho y thì (y== x) nghĩa là “nếu y bằng x”.




Bảng 4 Toán tử thao tác Bit (Bitwise operator): là các toán tử thực hiện trên từng bit nhị phân của
các con số, các toán tử dịch trái “” rất thường được sử dụng khi sử lí số.




Bảng 5 các toán tử khác :là 1 số toán tử đặc biệt rất hay sử dụng nhưng chúng ta thường không để
ý vì vai trò của chúng rất dễ nhận thấy. Đặc biệt chú ý toán tử “?:” là 1 toán tử rất đặc biệt của C so với
các ngôn ngữ lập trình khác, “?:” là toán tử 3 ngôi duy nhất có thể dùng thay thế cho cấu trúc “if” đơn giản.




For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

Cấu trúc điều khiển (Flow Controls): các cấu trúc điều khiển biến ý tưởng của bạn thành
hiện thực. Một số cấu trúc điều khiển cơ bản trong C như sau:
- “If (điều kiện) statement;” : nếu điều kiện là đúng thì thực hiện statement theo sau,
statement có thể được trình bày cùng dòng hoặc dòng sau điều khiển If. Điều kiện có thể là một
biểu thức bất kỳ, có thể là sự kết hợp của nhiều điều kiện bằng các toán tử quan hệ AND (&&),
OR (||)…Điều kiện được cho là đúng khi nó khác 0, ví dụ if (1) thì điều kiện hiển nhiên là đúng.
Xét một vài ví dụ dùng cấu trúc if như sau:
If (!val) val=1; nghĩa là nếu val bằng 0 thì chương trình sẽ gán cho val giá trị là 1, “!” là
toán tử NOT, NOT của một số khác 0 thì bằng 0, ngược lại, NOT của 0 thì thu được kết quả
là 1. Trong ví dụ này, nếu val bằng 0 thì !val sẽ bằng 1, như thế điều kiện sẽ trở thành đúng
và câu lệnh “val=1” được thực thi.
If (x==1 && y==2) result=’A’; nghĩa là nếu x bằng 1 và y bằng 2 thì gán ký tự ‘A’ cho biến
result. Trong ví dụ này, toán tử logic “&&” được sử dụng để “nối” 2 điều kiện lại, bạn hoàn
toàn có thể sử dụng nhiều toán tử logic khác nếu cần thiết.
Trong trường hợp bạn muốn thực thi nhiều câu lệnh cùng lúc nếu một điều kiện nào đó thỏa
thì bạn cần đặt tất cả các câu lệnh đó trong 1 khối như bên dưới:
If (điều kiện) {
Statement1;
Statement2;

}
- “If (điều kiện ) statement1; else statement2; ”: nếu điều kiện đúng thì thực hiện
statement1, ngược lại thực thi statement2. Việc đặt các statement và else..trên cùng 1 dòng hay
trên những dòng khác nhau đều không ảnh hưởng đến kết quả.
Tương tự trường hợp trên, nếu có nhiều statements thì cần đặt chúng trong 1 khối.
If (điều kiện) {
Statement1;
Statement2;

}else {
Statement1;
Statement2;

}
Ngoài ra, bạn cũng có thể đặt nhiều cấu trúc if…else… lồng vào nhau.


For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

- Trong trường hợp có nhiều khả năng có thể xảy ra cho 1 biểu thức (hay 1 biến), ứng với
mỗi khả năng bạn cần chương trình thực hiện một việc nào đó, khi này bạn nên sử dụng cấu trúc
switch. Cấu trúc này được trình bày như bên dưới.
switch (biểu thức) {
case hằng_số_1:
các statement1;
break;
case hằng_số_2:
các statement2;
break;

Default:
các statement khác;
}
Hãy xét 1 ví dụ bạn kết nối 2 chip AVR với nhau, 1 chip làm Master sẽ ra các lệnh điều
khiển chip Slaver, chip Slaver nhận mã lệnh từ Master và thực hiện các công việc được thảo
hiệp trước. Giả sử mã lệnh được lưu trong biến Command, dưới đây là chương trình ví dụ
cách xử lí của chip Slaver ứng với từng mã lệnh.

switch (Command){ 1
case 1: 2
PWM=255; 3
ON_Motor(); 4
break; 5
case 2: 6
PWM=0; 7
OFF_Motor(); 8
break; 9
default: 10
Get_Cmd(); 11
break; 12
} 13

Nếu Command=1, gán giá trị 255 cho biến PWM và gọi chương trình con ON_Motor().
Trong trường hợp này, break được sử dụng, break nghĩa là thoát khỏi cấu trúc điều khiển
hiện tại ngay lập tức, như vậy sau khi thực hiện 2 lệnh, switch kết thúc mà không cần xét đến
các trường hợp khác. Bây giờ, nếu Command=2, gán giá trị 0 cho biến PWM và gọi chương
trình con OFF_Motor(), trong tất cả các trường hợp còn lại (default), thực hiện chương trình
con Get_Cmd().



For more details and questions, contact me: thanhtam.h@gmail.com
AUTO.NLU

- “while (điều kiện ) statement1;”: là một cấu trúc lặp (Loop), ý nghĩa của cấu trúc while là
khi điều kiện còn đúng thì sẽ thực hiện statement1 (hoặc các statements nếu chúng được đặt trong
1 khối {} như trong trường hợp của if được giới thiệu ở trên). Cẩn thận, bạn rất dễ rơi vào một
vòng lặp “không lối thoát” với while nếu điều kiện luôn luôn đúng.
- “for (biểu_thức_1; biểu_thức_2; biểu_thức_3) statement;”: là một cấu trúc lặp khác, trong
cấu trúc for, biểu_thức_1 thường được hiểu là khởi tạo, biểu_thức_2 là điều kiện và biểu_thức_3
là biểu thức được thực hiện sau. Cấu trúc for này tương đương với cấu trúc while sau:
biểu_thức_1;
while (biểu_thức_2){
statement;
biểu_thức_3;
}
Các biểu thức trong cấu trúc for có thể vắng mặt trong cấu trúc nhung các dấu “;” thì không
được bỏ. Nếu bạn viết for( ; ; ) tương đương với vòng lặp vô tận while (1).
Cấu trúc for thường được dùng để thực hiện 1 hay những công việc nào đó trong số lần nào
đó, ví dụ bên dưới thực hiện xuất các giá trị từ 0 đến 200 ra PORTB, sau mỗi lần xuất sẽ gọi
lệnh delay trong 65000 chu kỳ máy.
for (uint8_t i=0; i
Đề thi vào lớp 10 môn Toán |  Đáp án đề thi tốt nghiệp |  Đề thi Đại học |  Đề thi thử đại học môn Hóa |  Mẫu đơn xin việc |  Bài tiểu luận mẫu |  Ôn thi cao học 2014 |  Nghiên cứu khoa học |  Lập kế hoạch kinh doanh |  Bảng cân đối kế toán |  Đề thi chứng chỉ Tin học |  Tư tưởng Hồ Chí Minh |  Đề thi chứng chỉ Tiếng anh
Theo dõi chúng tôi
Đồng bộ tài khoản