Tải bản đầy đủ (.docx) (46 trang)

Thiết kế mạch hiển thị LCD

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 (1.21 MB, 46 trang )

LỜI CẢM ƠN

Lời đầu tiên em xin gửi lời cảm ơn chân thành và sự tri ân sâu sắc đối với
các thầy cô của trường cao đẳng Công Nghệ Viettronics, đặc biệt là các thầy cô
khoa Điện – Điện Tử của trường đã truyền đạt kiến thức bổ ích trong suốt thời
gian em học tập và rèn luyện tại trường. Và em cũng xin chân thành cám ơn thầy
chủ nhiệm Th.S Phạm Công Huân đã nhiệt tình hướng dẫn hướng dẫn em hoàn
thành tốt khóa luận này
Trong quá trình học tập, cũng như là trong quá trình làm bài báo cáo khó
tránh khỏi sai sót, rất mong các Thầy, Cô bỏ qua. Đồng thời do trình độ lý luận
cũng như kinh nghiệm thực tiễn còn hạn chế nên bài báo cáo không thể tránh
khỏi những thiếu sót, em rất mong nhận được ý kiến đóng góp Thầy, Cô để em
học thêm được nhiều kinh nghiệm, những ý kiến đó sẽ là hành trang quý báu
giúp em hoàn thiện kiến thức của mình trong tương lai.
Em xin chân thành cảm ơn!

Hải Phòng, tháng 6 năm 2015
Sinh viên thực hiện

Đỗ Văn Tuất

1


MỤC LỤC

2


DANH MỤC HÌNH VẼ
Hình 1.1: Sơ đồ các chân của chip ATmega8................................................................


Hình 1.2: Sơ đồ các chân của chip Atmega16...............................................................
Hình 2.1. Sơ đồ cấu trúc CPU của ATmega16..............................................................
Hình 2.2. Thanh ghi trạng thái SREG...........................................................................
Hình 1.4: Cách tổ chức ngắt thông thường...................................................................
Hình 1.5: Các vector ngắt trên chip Atmega8..............................................................
Hình 1.10: Tạo nguồn AVCC từ VCC...........................................................................
Hình 2.1. Hình ảnh KIT LEKTENIK............................................................................
Hình 2.2. Module Vi điều khiển 8051 và AVR...............................................................
Hình 2.3. Module Vi điều khiển PIC..............................................................................
Hình 2.4.Sơ đồ nguyên lý của module LED 7 thanh....................................................
Hình 2.5.Sơ đồ nguyên lý của module ADC..................................................................
Hình 2.6.Sơ đồ nguyên lý của module LED ma trận...................................................
Hình 2.7.Sơ đồ nguyên lý của module ma trận phím nhấn.........................................
Hình 2.8. Sơ đồ nguyên lý của module LED đơn.........................................................
Hình 2.9.Sơ đồ nguyên lý của module LCD..................................................................
Hình 2.10.Sơ đồ nguyên lý của module LED hồng ngoại............................................
Hình 2.11.Sơ đồ nguyên lý của module EEPROM và DS1307....................................
Hình 2.12.Sơ đồ nguyên lý của module RS232.............................................................
Hình 2.13.Sơ đồ nguyên lý của module Rơle và Loa....................................................
Hình 2.14.Sơ đồ nguyên lý của module cảm biến nhiệt DS18B20..............................
Hình 2.15.Sơ đồ nguyên lý của module nguồn và module điều khiển động cơ

Trang
10
10
11
12
13
14
22

24
24
25
25
26
27
27
28
28
29
29
30
31
31
32

bước..................................................................................................................................
Hình 2.16. Text LCD 16x2..............................................................................................
Hình 2.17.Bảng sơ đồ chân.............................................................................................
Hình 2.18. Kết nối Text LCD..........................................................................................
Hình 3.1.Sơ đồ nguyên lý mạch hiển thị LCD..............................................................
Hình 3.2.Sơ đồ mô phỏng trên chương trình Proteus..................................................

33
34
35
37
45

3



MỞ ĐẦU
1. Tính cấp thiết của đề tài
Ngày nay khi khoa học công nghệ phát triển, chúng ta sẽ cần đến những
thiết bị có thể thay thế con người trong những công việc mà con người cần có sự
hỗ trợ (trong môi trương độc hại, cần có độ chính xác cao...). Để có thể làm việc
thay thế con người thì máy móc thiết bị cần phải được trang bị một “Bộ não
nhân tạo” để có thể xử lí các tình huống như một người bình thường. Đó chính
là các bộ vi điều khiển. Việc ứng dụng rộng rãi vi điều khiển trong thực tế đòi
hỏi sinh viên phải có kiến thức cơ bản về chúng, chính vì vậy việc nghiên cứu
và tìm hiểu về họ vi điều khiển AVR mang tính cần thiết cao
2. Mục đích nghiên cứu
Với mục đính nghiên cứu và tìm hiểu về cấu tạo, hoạt động của KIT thực
hành Vi điều khiển LEKTENIK để hiển thị LCD sử dụng vi điều khiển AVR
Atmega16nhằm nắm vững được bản chất của nó để sau này có thể ứng dụng
được trong các mạch điện trong thực tế
3. Nhiệm vụ nghiên cứu
- Tìm hiểu vềVi điều khiển AVR Atmega16
- Tìm hiểu về KIT LEKTENIK
- Nghiên cứu về phuơng pháp hiển thị trên LCD
4. Đối tượng nghiên cứu
Đối tượng nghiên cứu là vi điều khiển AVR Atmega16 và KIT
LEKTENIK.Phương pháp nghiên cứu là nghiên cứu lý thuyết và xây dựng các
chương trình điều khiển và kiểm nghiệm trên mạch thực tế.
5. Phương pháp nghiên cứu
Đề tài kết hợp giữa nghiên cứu lý thuyết và nghiên cứu thực nghiệm
+ Nghiên cứu lý thuyết:
- Nghiên cứu tổng hợp việc thiết kế, gia công, lắp ráp các chi tiết để cho ra
mạch

- Nghiên cứu thiết kế các chương trình.
- Chế tạo mạch hoàn chỉnh để kiểm chứng kết quả nghiên cứu lý thuyết.

4


6. Những đóng góp thực tiễn
Đề tài cung cấp một cách hệ thống lại những kiến thức cơ bản vi điều
khiển AVR Atmega16 từ đó giúp cho sinh viên có thể ứng dụng được các mạch
điều khiển trong thực tế
7. Kết cấu đề tài
Đề tài “Thiết kế mạch hiển thị LCD”được trình bày gồm ba chương:
Chương 1: Vi điều khiển AVR
Chương 2: Giới thiệu về KITLEKTENIK
Chương 3: Thiết kế mạch hiển thị LCD
DANH MỤC CHỮ VIẾT TẮT
ADC: Analog Digital Converter (Bộ biến đổi từ tương tự sang số)
ALU: Arithmetic Logic Unit (Bộ logic và số học)
ASCII: American Standard Code for Information Interchange (Bảng mã
chuẩn phục vụ việc trao đổi thông tin của Mỹ)
ASM: Ngôn ngữ lập trình Assembly
AVR: Tên một họ vi điều khiển
CPU: Central Processing Unit (Đơn vị xử lí trung tâm)
EEPROM: Electrically Ereasable Programmable ROM (Bộ nhớ xoá bằng
điện)
HLL: Hight Level Language (Ngôn ngữ lập trình bậc cao)
LCD: Liquid Crystal Display (Màn hình tinh thể lỏng)
LED: Light Emitting Diode (Điốt phát quang)
LSB: Least Significant Bit (Bit có trọng số nhỏ nhất)
MSB: Most Significant Bit (Bit có trọng số lớn nhất)

PC: Program counter (Bộ đếm chương trình)
PID: Propotional Integral Derivative (Bộ điều khiển tỷ lệ, tích phân, vi
phân).
PWM: Pulse Width Modulation (Điều chế độ rộng xung)
5


RISC: Reduced Instruction Set Computer (Cấu trúc với hệ lệnh giảm thiểu)
SPI: Serial Peripheral Interface (Giao diện ngoại vi nối tiếp)
SRAM: Static Random Access Memory (Bộ nhớ truy nhập ngẫu nhiên
tĩnh)
TWI: Two-Wire Serial Intereafce (Chuẩn truyền thông nối tiếp hai dây)
USART: Universal Synchronous & Asynchronous serial Reveiver and
Transmitter, (Bộ truyền nhận nối tiếp đồng bộ và không đồng bộ)

CHƯƠNG 1: VI ĐIỀU KHIỂN AVR
1.1. Giới thiệu chung về vi điều khiển AVR
AVR là một họ vi điều khiển do hãng Atmel sản xuất (Atmel cũng là nhà
sản xuất dòng vi điều khiển 8051). AVR là chip vi điều khiển 8 bits với cấu trúc
tập lệnh đơn giản hóa-RISC(Reduced Instruction Set Computer), một kiểu cấu
trúc đang thể hiện ưu thế trong các bộ xử lí, vi điều khiển.
So với các chip vi điều khiển 8 bits khác, AVR có nhiều đặc tính hơn hẳn
trong việc ứng dụng (dễ sử dụng) và đặc biệt là về chức năng:
Gần như không cần mắc thêm bất kỳ linh kiện phụ nào khi sử dụng AVR,
thậm chí không cần nguồn tạo xung clock cho chip (thường là các khối thạch
anh).
Thiết bị lập trình (mạch nạp) cho AVR rất đơn giản, có loại mạch nạp chỉ
cần vài điện trở là có thể làm được. Một số AVR còn hỗ trợ lập trình on – chip
bằng bootloader không cần mạch nạp…
Bên cạnh lập trình bằng ASM, cấu trúc AVR được thiết kế tương thích C.

Nguồn tài nguyên về source code, tài liệu, application note…rất lớn trên
internet.
Hầu hết các chip AVR có những tính năng sau:
- Có thể sử dụng xung clock lên đến 16MHz, hoặc sử dụng xung clock nội
lên đến 8MHz(sai số 3%)
6


- Bộ nhớ chương trình Flash có thể lập trình lại rất nhiều lần và có dung
lượng lớn. Có SRAM (Ram tĩnh) lớn và đặc biệt có bộ nhớ lưu trữ lập trình
được EEPROM.
- Nhiều ngõ vào ra (I/O port) 2 hướng (bidirectional).
- 8 bits, 16bits timer/counter tích hợp PWM
- Các bộ chuyển đổi Analog-Digital phân giải 10 bits, nhiều kênh
- Chức năng Analog comparator
- Giao diện nối tiếp USART (tương thích chuẩn nối tiếp RS-232)
- Giao tiếp nối tiếp Two – Wire – Serial (tương thích chuẩn I 2C)Master và
Slaver
- Giao diện nối tiếp Serial Peripheral Interface (SPI)
Đây cũng là ưu điểm vượt trội của AVR so với 8051, nó chỉ thua kém 8051
ở một điểm duy nhất là giá thành.
Một số chip AVR thông dụng:
AT90S1200
AT90S2313
ATtiny15
ATtiny22
ATtiny26
ATtiny28
ATmega8/8515/8535
Atmega32

ATmega161
ATmega162
ATmega163
ATmega169
ATmega32
7


ATmega323
Ngôn ngữ lập trình: có thể lập trình cho AVR bằng các phần mềm hỗ trợ
ngôn ngữ cấp cao như BascomAVR (Basic) hay CodevisionAVR (C). Để hiểu
thấu đáo về AVR cần phải lập trình bằng chính ngôn ngữ của nó, ASM. Như vậy
lập trình bằng ASM giúp hiểu tường tận về AVR, và tất nhiên để lập trình được
bằng ASM cần phải hiểu về cấu trúc AVR….Một lý do khác nên lập trình bằng
ASM là các trình dịch (compiler) ASM cho AVR là hoàn toàn miễn phí, và
nguồn source code cho AVR viết bằng ASM là rất lớn. Tuy nhiên một khi đã
thành thạo AVR và ASM thì có thể sử dụng các ngôn ngữ cấp cao như C để viết
ứng dụng vì ưu điểm của ngôn ngữ cấp cao là giúp bạn dễ dàng thực hiện các
phép toán đại số 16 hay 32 bit (vốn là vấn đề khó khăn khi lập trình bằng ASM).
Trong họ VĐK AVR thì chip ATmega8 và Atmega32 là hai loại chip thuộc
dòng AVR mới và được sử dụng phổ biến. Chip ATmega8 nó có đầy đủ các tính
năng của AVR nhưng lại nhỏ gọn (gói PDIP có 28 chân) và có giá thành rẻ hơn.

Hình 1.1. Sơ đồ các chân của chip ATmega8

Chip này gồm 28 chân, trong đó có các chân được ghi là PB0(chân 14),
PB1(chân 15),…,PB7(chân 10), đó là các chân của PORTB. PORT là khái niệm
chỉ các ngõ xuất nhập. Trong AVR, PORT có thể giao tiếp theo 2 hướng (bi –
directional), có thể dùng để xuất hoặc nhận thông tin, mỗi PORT có 8 chân.
Chip Atmega8 có 3 PORT có tên tương ứng là PORTB, PORTC và PORTD

(một số chip AVR khác có 4 hoặc 6 PORT). PORT được coi là “cửa ngõ” then
chốt của vi điều khiển.

8


Hình 1.2. Sơ đồ các chân của chip Atmega16

Trong AVR, mỗi PORT liên quan đến 3 thanh ghi (8 bits) có tên tương ứng
là DDRx, PINx, và PORTx với “x” là tên của PORT, mỗi bit trong thanh ghi
tương ứng với mỗi chân của PORT. Trong trường hợp của Atmega8 “x” là B, C
hoặc D, còn Atmega16 thì “x” là A, B, C hoặc D. Ví dụ khi viết giá trị 1 vào một
bit trong thanh ghi DDRB thì chân tương ứng của PORTB sẽ là chân xuất
(Output), ngược lại giá trị 0 xác lập chân tương ứng là ngõ nhập. Sau khi viết
giá trị điều khiển vào DDRB, việc truy xuất PORTB được thực hiện thông qua 2
thanh ghi PINB và PORTB
1.2. Cấu trúc nhân AVR.
CPU của AVR có chức năng bảo đảm sự hoạt động chính xác của các chương
trình. Do đó nó phải có khả năng truy cập bộ nhớ, thực hiện các quá trình tính
toán, điều khiển các thiết bị ngoại vi và quản lý ngắt.
1.2.1 Cấu trúc tổng quát.

9


Hình 1.3. Sơ đồ cấu trúc CPU của ATmega16

AVR sử dụng cấu trúc Harvard, tách riêng bộ nhớ và các bus cho chương
trình và dữ liệu. Các lệnh được thực hiện chỉ trong một chu kỳ xung clock. Bộ
nhớ chương trình được lưu trong bộ nhớ Flash.

1.2.2. ALU
ALU làm việc trực tiếp với các thanh ghi chức năng chung. Các phép toán
được thực hiện trong một chu kỳ xung clock. Hoạt động của ALU được chia làm
3 loại: đại số, logic và theo bit.
1.2.3. Thanh ghi trạng thái
Đây là thanh ghi trạng thái có 8 bit lưu trữ trạng thái của ALU sau các phép
tính số học và logic.

Hình 1.4. Thanh ghi trạng thái SREG
10


C: Carry Flag ;cờ nhớ (Nếu phép toán có nhớ cờ sẽ được thiết lập)
Z: Zero Flag ;Cờ zero (Nếu kết quả phép toán bằng 0)
N: Negative Flag (Nếu kết quả của phép toán là âm)
V: Two’s complement overflow indicator (Cờ này được thiết lập khi tràn số
bù 2)
V, For signed tests (S=N XOR V) S: N
H: Half Carry Flag (Được sử dụng trong một số toán hạng sẽ được chỉ rõ
sau)
T: Transfer bit used by BLD and BST instructions(Được sử dụng làm nơi
chung gian trong các lệnh BLD,BST).
I: Global Interrupt Enable/Disable Flag (Đây là bit cho phép toàn cục ngắt.
Nếu bit này ở trạng thái logic 0 thì không có một ngắt nào được phục vụ.)

11


1.3. Ngắt trên AVR
Ngắt (Interrupt) là một tín hiệu khẩn cấp gửi đến bộ xử lí, yêu cầu bộ xử lí

tạm ngừng tức khắc các hoạt động hiện tại để “nhảy” đến một nơi khác thực
hiện một nhiệm vụ khẩn cấp nào đó, nhiệm vụ này gọi là trình phục vụ ngắt –
ISR (interrupt service routine ). Sau khi kết thúc nhiệm vụ trong ISR, bộ đếm
chương trình sẽ được trả về giá trị trước đó để bộ xử lí quay về thực hiện tiếp
các nhiệm vụ còn dang dở.Như vậy, ngắt có mức độ ưu tiên xử lí cao nhất, ngắt
thường được dùng để xử lí các sự kiện bất ngờ nhưng không tốn quá nhiều thời
gian. Các tín hiệu dẫn đến ngắt có thể xuất phát từ các thiết bị bên trong chip
(ngắt báo bộ đếm timer/counter tràn, ngắt báo quá trình gửi dữ liệu bằng RS232
kết thúc…) hay do các tác nhân bên ngoài (ngắt báo có 1 button được nhấn, ngắt
báo có 1 gói dữ liệu đã được nhận…).

Hình 1.5. Cách tổ chức ngắt thông thường

Ngắt là một trong 2 kỹ thuật “bắt” sự kiện cơ bản là hỏi vòng (Polling) và
ngắt. Khi cần thiết kế một mạch điều khiển hoàn chỉnh thực hiện rất nhiều
nhiệm vụ bao gồm nhận thông tin từ người dùng qua các button hay keypad,
nhận tín hiệu từ cảm biến, xử lí thông tin, xuất tín hiệu điều khiển, hiển thị thông
tin trạng thái lên các LCD…, trong các nhiệm vụ này việc nhận thông tin người
dùng (start, stop, setup, change,…) rất hiếm xảy ra (so với các nhiệm vụ khác)
nhưng lại rất “khẩn cấp”, được ưu tiên hàng đầu. Nếu dùng Polling nghĩa là cần
viết 1 đoạn chương trình chuyên thăm dò trạng thái của các button (tạm gọi đoạn
chương trình đó là Input) và phải chèn đoạn chương trình Input này vào rất
12


nhiều vị trí trong chương trình chính để tránh trường hợp bỏ sót lệnh từ người
dùng, điều này thật lãng phí thời gian thực thi. Giải pháp cho vấn đề này là sử
dụng ngắt, bằng cách kết nối các button với đường ngắt của chip và sử dụng
chương trình Input() làm trình phục vụ ngắt - ISR của ngắt đó, không cần phải
chèn Input() trong lúc đang thực thi và vì thế không tốn thời gian cho nó, Input()

chỉ được gọi khi người dùng nhấn các button. Đó là ý tưởng sử dụng ngắt.

Hình 1.6. Các vector ngắt trên chip Atmega8.

1.4. Timer/Counter
Timer/Counter là các module độc lập với CPU.Chức năng chính của các bộ
Timer/Counter, như tên gọi của chúng, là định thì (tạo ra một khoảng thời gian,
đếm thời gian…) và đếm sự kiện. Trên các chip AVR, các bộ Timer/Counter
còn có thêm chức năng tạo ra các xung điều rộng PWM (Pulse Width
Modulation), ở một số dòng AVR, một số Timer/Counter còn được dùng như các
bộ canh chỉnh thời gian (calibration) trong các ứng dụng thời gian thực. Các bộ
13


Timer/Counter được chia theo độ rộng thanh ghi chứa giá trị định thời hay giá trị
đếm của chúng, cụ thể trên chip Atmega8 có 2 bộ Timer 8 bit (Timer/Counter0
và Timer/Counter2) và 1 bộ 16 bit (Timer/Counter1). Chế độ hoạt động và
phương pháp điều khiển của từng Timer/Counter cũng không hoàn toàn giống
nhau, ví dụ ở chip Atmega8:
Timer/Counter0: là một bộ định thời, đếm đơn giản với 8 bit. Gọi là đơn
giản vì bộ này chỉ có 1 chế độ hoạt động (mode) so với 5 chế độ của bộ
Timer/Counter1. Chế độ hoat động của Timer/Counter0 thực chất có thể coi như
2 chế độ nhỏ (và cũng là 2 chức năng cơ bản) đó là tạo ra một khoảng thời gian
và đếm sự kiện. Chú ư là trên các chip AVR ḍng mega sau này như
Atmega16,32,64…chức năng của Timer/Counter0 được nâng lên như các bộ
Timer/Counter1…
Timer/Counter1: là bộ định thời, đếm đa năng 16 bit. Bộ Timer/Counter
này có 5 chế độ hoạt động chính.Ngoài các chức năng thông thường,
Timer/Counter1 còn được dùng để tạo ra xung điều rộng PWM dùng cho các
mục đích điều khiển. Có thể tạo 2 tín hiệu PWM độc lập trên các chân OC1A

(chân 15) và OC1B (chân 16) bằng Timer/Counter1. Các bộ Timer/Counter kiểu
này được tích hợp thêm khá nhiều trong các chip AVR sau này, ví dụ Atmega128
có 2 bộ, Atmega2561 có 4 bộ…
Các bit CS00, CS01 và CS02 gọi là các bit chọn nguồn xung nhịp cho T/C0
(Clock Select). Chức năng các bit này được mô tả trong hình 1.7.
1.5. Lập trình C cho AVR.
Một chương trình C cho AVR thường bao gồm các thành phần như: chú
thích (comments), biểu thức (expressions), câu lệnh (statements), khối (blocks),
toán tử, cấu trúc điều khiển (Flow controls), hàm (functions)…
Chú thích (comments): có 2 cách để tạo phần chú thích trong C là chú thích
từng dòng bằng 2 dấu “//” như trong dòng đầu của đoạn ví dụ “//day la chu
thich, khong duoc bien dich” hoặc chú thích block bằng cách kẹp block cần chú
thích vào giữa /* ….*/ ví dụ:
/*
Ban co the type bat ky chu thich nao trong block nay
14


Ngay ca khi ban xuong dong
Phan chu thich thuong co mau chu la green
*/
Tiền xử lí (preprocessor): là một tiện ích của ngôn ngữ C, các preprocessor
được trình biên dịch xử lí trước tất cả các phần khác, các preprocessor có chức
năng tương tự các Directive trong ASM cho AVR.Các preprocessor được bắt đầu
bằng dấu “#”, trong số các preprocessors trong ngôn ngữ C có hai preprocessors
được sử dụng phổ biến nhất là #include và #define. Preprocessor #include chỉ
định 1 file được đính kèm trong quá trình biên dịch (tương đương .INCLUDE
trong ASM) và #define để định nghĩa 1 chuổi thay thế hoặc 1 macro. Xem các ví
dụ sau:
#include "avr/io.h" *đính kèm nội dung file io.h trong lúc biên dịch (file

io.h nằm trong thư mục con avr của thư mục include trong thư mục cài đặt của
WinAVR).*/
#define max (a,b) ((a)>(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;

15


if (!val) val=1;
}
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 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 1.1. Các toán tử đại số

Bảng 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.
Bảng 1.2. Các toán tử truy cập và kích thước

16


Bảng 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 1.3. Các toán tử Logic và quan hệ

1.5.1 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 để

17


“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 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.
Cấu trúc switch: 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;
18


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 Slave, chip Slave nhận mã lệnh từ Master và thực hiện
các công việc được thoả 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 Slave ứng với
từng mã lệnh.
switch (Command) {
case 1:
PWM=255;
ON_Motor();
break;

case 2:
PWM=0;
OFF_Motor();;
break;

default:
Get_Cmd();
break;
}
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
19


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().
“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 nhưng 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<=200; i++){
PORTB=i;
_delay_loop_2(65000);
}
Chú ý, bạn có thể thực hiện việc khai báo 1 biến (xem phần khai báo biến
bên dưới) ngay trong cấu trúc for nếu biến lần đầu được sử dụng. Ví dụ trên
được hiểu như sau: khai báo 1 biến i kiểu byte không âm, gán giá trị khởi đầu
cho i=0 (chỉ thực hiện 1 lần duy nhất), kiểm tra điều kiện i<=200 (nhỏ hơn hoặc
bằng 200), nếu điều kiện còn đúng, thực hiện 2 statements trong block {}, sau
20


đó quay về để thực hiện i++ (tăng i thêm 1) rồi lại kiểm tra điều kiện i<=200 và
quá trình lặp lại. Như thế đoạn code trong {} được thực thi khoảng 201 lần trước
khi biến i bằng 201 và điều kiện i<=200 sai.
1.6. Chuyển đổi ADC
Chip AVR Atmega32của Atmel có tích hợp sẵn các bộ chuyển đổi ADC với
độ phân giải 10 bit. Có tất cả 8 kênh đơn (các chân ADC0 đến ADC7), 16 tổ hợp
chuyển đổi dạng so sánh, trong đó có 2 kênh so sánh có thể khuếch đại. Bộ
chuyển đổi ADC trên AVR không hoạt động theo nguyên lý flash ADC mà tôi đề
cập ở phần trên, ADC trong AVR là loại chuyển đổi xấp xỉ lần lượt (successive

approximation ADC).
ADC trên AVR cần được “nuôi” bằng nguồn điện áp riêng ở chân AVCC,
giá trị điện áp cấp cho AVCC không được khác nguồn nuôi chip (VCC) quá +/0.3V. Nhiễu (noise) là vấn đề rất quan trọng khi sử dụng các bộ ADC, để giảm
thiểu sai số chuyển đổi do nhiễu, nguồn cấp cho ADC cần phải được “lọc”
(filter) kỹ càng. Một cách đơn giản để tạo nguồn AVCC là dùng một mạch LC
kết nối từ nguồn VCC của chip như minh họa trong hình 1.11, đây là cách được
gợi ý bởi nhà sản xuất AVR.

Hình 1.7. Tạo nguồn AVCC từ VCC.

Điện áp tham chiếu cho ADC trên AVR có thể được tạo bởi 3 nguồn: dùng
điện áp tham chiếu nội 2.56V (cố định), dùng điện áp AVCC hoặc điện áp ngoài
21


đặt trên chân VREF. Một lần nữa, bạn cần chú ý đến noise khi đặt điện áp tham
chiếu, nếu dùng điện áp ngoài đặt trên chân VREF thì điện áp này phải được lọc
thật tốt, nếu dùng điện áp tham chiếu nội 2.56V hoặc AVCC thì chân VREF cần
được nối với một tụ điện. Việc chọn điện áp tham chiếu sẽ được đề cập chi tiết
trong phần sử dụng ADC.
Có 4 thanh trong bộ ADC trên AVR trong đó có 2 thanh ghi data chứa dữ
liệu sau khi chuyển đổi, 2 thanh ghi điều khiển và chứa trạng thái của ADC.
ADMUX (ADC Multiplexer Selection Register): là 1 thanh ghi 8 bit điều
khiển việc chọn điện áp tham chiếu, kênh và chế độ hoạt động của ADC.
ADCSRA (ADC Control and Status RegisterA): là thanh ghi chính điều
khiển hoạt động và chứa trạng thái của module ADC.
ADCL và ADCH (ADC Data Register): 2 thanh ghi chứa giá trị của quá
trình chuyển đổi. Do module ADC trên AVR có độ phân giải tối đa 10 bits nên
cần 2 thanh ghi để chứa giá trị chuyển đổi. Tuy nhiên tổng số bít của 2 thanh ghi
8 bit là 16, con số này nhiều hơn 10 bit của kết quả chuyển đổi, vì thế chúng ta

được phép chọn cách ghi 10 bit kết quả vào 2 thanh ghi này. Bit ADLAR trong
thanh ghi ADMUX quy định cách mà kết quả được ghi vào.
Thông thường, 2 thanh ghi data được sắp xếp theo định dạng ADLAR=0,
ADCL chứa 8 bit thấp và 2 bit thấp của ADCH chứa 2 bit cao nhất của giá trị
thu được. Chú ý thứ tự đọc giá trị từ 2 thanh ghi này, để tránh đọc sai kết quả,
bạn cần đọc thanh ghi ADCL trước và ADCH sau, vì sau khi ADCH được đọc,
các thanh ghi data có thể được cập nhật giá trị tiếp theo.
SFIOR(Special FunctionIO Register C): thanh ghi chức năng đặc biệt, 3 bit
cao trong thanh ghi này quy định nguồn kích ADC nếu chế độ Auto Trigger
được sử dụng. Đó là các bit ADTS2:0 (Auto Trigger Source 2:0).

22


CHƯƠNG 2: GIỚI THIỆU VỀ LEKTENIK
2.1. Tổng quan về KIT Vi điều khiển LEKTENIK

Hình 2.1. Hình ảnh KIT LEKTENIK

Bộ KIT được thiết kế cho 3 loại Vi điều khiển phổ biến hiện nay đó là:
8051, AVR và PIC với 3 module điều khiển:

Hình 2.2. Module Vi điều khiển 8051 và AVR
23


Hình 2.3. Module Vi điều khiển PIC

2.2. Module LED 7 thanh


Hình 2.4.Sơ đồ nguyên lý của module LED 7 thanh

Quan sát sơ đồ nguyên lý của module LED 7 thanh ta nhận thấy đây là
phương pháp hiển thị theo phương pháp quét LED. Tức là tại một thời điểm chỉ
có duy nhất một LED sang điều này rất có ý nghĩa trong việc tiết kiệm năng
lượng dùng trong mạch đồng thời tiết kiệm tối đa số chân của Vi điều khiển

24


dùng để điều khiển module. Tuy nhiên có theo cách thiết kế này có một nhược
điểm đó là kỹ thuật lập trình tương đối phức tạp.
Để điều khiển module LED 7 thanh từ Vi điều khiển ta cần có 2 Port 8 bit.
Trong đó một Port để điều khiển đường dữ liệu và một Port còn lại để điều
khiển các đèn LED sáng hay tắt
2.3. Module bộ biến đổi tín hiệu từ tương tự sang số ADC

Hình 2.5.Sơ đồ nguyên lý của module ADC

Ta nhận thấy IC ADC được sử dụng là ADC0809, đó là loại bộ biến đổi
tương tự-số với 8 kênh tương tự đầu vào. Có nghĩa là nó có thể đo được 8 tín
hiệu tương tự. Việc điều khiển hoạt động của ADC hoàn toàn do Vi điều khiển
đảm nhiệm thông qua một Port 8 bit, và một Port 8 bit còn lại cập nhật kết quả
của các phép biến đổi.

25


×