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

THIẾT kế MẠCH HIỂN THỊ LED MA TRẬN

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.85 MB, 49 trang )

BỘ CÔNG THƯƠNG
TỔNG CÔNG TY CP ĐIỆN TỬ VÀ TIN HỌC VIỆT NAM
TRƯỜNG CAO ĐẲNG CÔNG NGHỆ VIETTRONICS

KHOÁ LUẬN TỐT NGHIỆP
TÊN ĐỀ TÀI: THIẾT KẾ MẠCH HIỂN THỊ LED
MA TRẬN

Người hướng dẫn
Đơn vị

: Th.S Phạm Công Huân
: Khoa Điện – Điện tử

Sinh viên thực hiện

: Vũ Thị Thủy

Lớp

: 2ĐT10

Nghành

: Công nghệ kỹ thuật điện tử truyền thông

Hải Phòng, tháng 7 năm 2015

LỜI CẢM ƠN

1




Lời đầu tiên em xin gửi lời cảm ơn tới các thầy cô trường cao đẳng Công
nghệ Viettronics, các thầy cô khoa Điện – Điện tử đã dạy dỗ và truyền đạt cho
em những 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. Em xin cảm ơn thầy chủ nhiệm Phạm Công Huân đã tận tình chỉ bảo
giúp em hoàn thành bản khóa luận này.
Được nhận nghiên cứu đề tài này và được trình bày trước hội đồng là
niềm vinh hạnh rất lớn đối với em.Tuy có gặp khó khăn trong quá trình nghiên
cứu và thực hiện song kinh nghiệm và bài học mà em có được sau đó là vô cùng
quý giá.
Với vốn kiến thức hạn hẹp nên em không tránh khỏi những thiếu xót, em
rất mong nhận được những ý kiến đóng góp của thầy cô, 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.
Chúc sức khỏe và thành công đến tất cả mọi người!

Hải Phòng, tháng 7 năm 2015

Sinh viên thực hiện
Vũ Thị Thủy

MỤC LỤC
2


3


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
RISC


Pulse Width Modulation (Điều chế độ rộng xung)
Reduced Instruction Set Computer (Cấu trúc với hệ lệnh
giảm thiểu)

SPI
SRAM

Serial Peripheral Interface (Giao diện ngoại vi nối tiếp)
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ộ)

4


DANH MỤC HÌNH VẼ
Hình1.1

Sơ đồ các chân của chip ATmega8………………………….........13


Hình1.2

Sơ đồ các chân của chip Atmega16………………………….........13

Hình1.3

Thanh ghi 8 bits………………………………………………..........14

Hình 1.4

Cách tổ chức ngắt thông thường……………………………..........16

Hình 1.5

Các vector
…………..17

Hình 1.6

Cấu trúc thanh ghi TCCR0………………………………………..19

Hình 1.7

Chức năng các bit CS0X………………………………………….19

Hình 1.8

Cấu trúc thanh ghi TMISK…………………………………..........19


Hình 1.9

Các chế độ hoạt động của T/C1……………………………….......21

Hình1.10

Tạo nguồn AVCC từ VCC…………………………………………..28

Hình 2.1

Hình ảnh KIT LEKTENIK…………………………………….........30

ngắt

trên

5

chip

Atmega8……………………...


Hình 2.2

Module Vi điều khiển 8051 và AVR………………………….......30

Hình 2.3

Module Vi điều khiển PIC…………………………………………..31


Hình 2.4

Sơ đồ nguyên lý của module LED 7 thanh………………………..31

Hình 2.5

Sơ đồ nguyên lý của module ADC………………………………..32

Hình 2.6

Sơ đồ nguyên lý của module LED ma trận………………………..33

Hình 2.7

Sơ đồ nguyên lý của module ma trận phím nhấn………………….33

Hình 2.8

Sơ đồ nguyên lý của module LED đơn……………………………34

Hình 2.9

Sơ đồ nguyên lý của module LCD………………………………...34

Hình 2.10

Sơ đồ nguyên lý của module LED hồng ngoại……………………35

Hình 2.11


Sơ đồ nguyên lý của module EEPROM và DS1307…………..........35

Hình 2.12

Sơ đồ nguyên lý của module RS232…………………………........36

Hình 2.13

Sơ đồ nguyên lý của module Rơle và Loa………………………...37

Hình 2.14

Sơ đồ nguyên lý của module cảm biến nhiệt DS18B20…………...37

Hình 2.15

Sơ đồ nguyên lý của module nguồn và module điều khiển động cơ
bước………………………………………………........................38

Hình 3.1

Sơ đồ nguyên lý của mạch LED ma trận…………………………..39

Hình 3.2

Cấu trúc của LED ma trận 8x8 hai mầu……………………………40

Hình 3.3


Hình ảnh sản phẩm………………………………………………..47

DANH MỤC CÁC BẢNG BIỂU
Bảng 1.1

Các toán tử đại số………………………………...23

Bảng 1.2

Các toán tử truy cập và kích thước………………..23

Bảng 1.3

Các toán tử Logic và quan hệ……………………..24

6


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
7



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ị thời gian thực sử dụng vi điều khiển
AVR Atmega16 nhằ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 LED ma trận
4. Đối tượng, phương pháp 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. 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ế

6. Kết cấu đề tài
Đề tài “Thiết kế mạch hiển thị LED ma trận”đượ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ề KIT LEKTENIK
Chương 3: Thiết kế mạch hiển thị LED ma trận

8


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).
9


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%)
- 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
10


ATtiny28
ATmega8/8515/8535
Atmega32
ATmega161
ATmega162
ATmega163
ATmega169
ATmega32
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.

11


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.

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 Tổ chức bộ nhớ của AVR
1.2.1 Bộ nhớ chương trình (Program memory)
Là bộ nhớ Flash lập trình được, trong các chip AVR cũ (như AT90S1200
hay AT90S2313…) bộ nhớ chương trình chỉ gồm một phần là Application Flash
Section nhưng trong các chip AVR mới thì có thêm phần Boot Flash setion. Khi
12


nói về bộ nhớ chương trình, đó chính là Application section. Thực chất,
application section bao gồm 2 phần: phần chứa các instruction (mã lệnh cho hoạt
động của chip) và phần chứa các vector ngắt (interrupt vectors). Các vector ngắt
nằm ở phần đầu của application section (từ địa chỉ 0x0000) và dài đến bao nhiêu
tùy thuộc vào loại chip. Phần chứa instruction nằm liền sau đó, chương trình viết
cho chip phải được load vào phần này.
1.2.2 Bộ nhớ dữ liệu (data memory)
Đây là phần chứa các thanh ghi quan trọng nhất của chip, việc lập trình
cho chip phần lớn là truy cập bộ nhớ này. Bộ nhớ dữ liệu trên các chip AVR có
độ lớn khác nhau tùy theo mỗi chip, về cơ bản phần bộ nhớ này được chia thành
5 phần:
Phần 1: là phần đầu tiên trong bộ nhớ dữ liệu, phần này bao gồm 32 thanh
ghi có tên gọi là register file (RF), hay General Purpose Rgegister – GPR, hoặc
đơn giản là các Thanh ghi. Tất cả các thanh ghi này đều là các thanh ghi 8 bits
như trong hình.

Hình 1.3: Thanh ghi 8 bits.

Tất cả các chip trong họ AVR đều bao gồm 32 thanh ghi Register File có
địa chỉ tuyệt đối từ 0x0000 đến 0x001F. Mỗi thanh ghi có thể chứa giá trị dương
từ 0 đến 255 hoặc các giá trị có dấu từ -128 đến 127 hoặc mã ASCII của một ký
tự nào đó…Các thanh ghi này được đặt tên theo thứ tự là R0 đến R31. Các thanh

ghi này có các đặc điểm sau:
Được truy cập trực tiếp trong các instruction.
Các toán tử, phép toán thực hiện trên các thanh ghi này chỉ cần 1 chu kỳ
xung clock.
Register File được kết nối trực tiếp với bộ xử lí trung tâm – CPU của chip.
Chúng là nguồn chứa các số hạng trong các phép toán và cũng là đích
chứa kết quả trả lại của phép toán.

13


Tóm lại 32 RF của AVR được xem là 1 phần của CPU, vì thế chúng được
CPU sử dụng trực tiếp và nhanh chóng, để gọi các thanh ghi này, chúng ta
không cần gọi địa chỉ mà chỉ cần gọi trực tiếp tên của chúng. RF thường được sử
dụng như các toán hạng (operand) của các phép toán trong lúc lập trình.
Phần 2: là phần nằm ngay sau register file, phần này bao gồm 64 thanh
ghi được gọi là 64 thanh ghi nhập/xuất (I/O register) hay còn gọi là vùng nhớ
I/O (I/O Memory). Vùng nhớ I/O là cửa ngõ giao tiếp giữa CPU và thiết bị
ngoại vi. Tất cả các thanh ghi điều khiển, trạng thái…của thiết bị ngoại vi đều
nằm ở đây. Ví dụ như việc điều khiển các PORT của AVR, mỗi PORT liên quan
đến 3 thanh ghi DDRx, PORTx và PINx, tất cả 3 thanh ghi này đều nằm trong
vùng nhớ I/O. Xa hơn, nếu muốn truy xuất các thiết bị ngoại vi khác như Timer,
chuyển đổi Analog/Digital, giao tiếp USART…đều thực hiện thông qua việc
điều khiển các thanh ghi trong vùng nhớ này.
Phần 3: RAM tĩnh, nội (internal SRAM), là vùng không gian cho chứa
các biến (tạm thời hoặc toàn cục) trong lúc thực thi chương trình, vùng này
tương tự các thanh RAM trong máy tính nhưng có dung lượng khá nhỏ (khoảng
vài KB, tùy thuộc vào loại chip).
Phần 4: RAM ngoại (external SRAM), các chip AVR cho phép người sử
dụng gắn thêm các bộ nhớ ngoài để chứa biến, vùng này chỉ tồn tại khi nào

người sử dụng gắn thêm bộ nhớ ngoài vào chip.
Phần 5: EEPROM (Electrically Ereasable Programmable ROM) là một
phần quan trọng của các chip AVR mới, vì là ROM nên bộ nhớ này không bị xóa
ngay cả khi không cung cấp nguồn nuôi cho chip, rất thích hợp cho các ứng
dụng lưu trữ dữ liệu.
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
14


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.4: 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
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.

15


Hình 1.5: 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ộ 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 dòng mega sau này như
16


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ộ…
1.4.1 Timer/Counter0:
Các thanh ghi: có 4 thanh ghi được thiết kế riêng cho hoạt động và điều
khiển T/C0, đó là:
TCNT0 (Timer/Counter Register): là 1 thanh ghi 8 bit chứa giá trị vận
hành của T/C0. Thanh ghi này cho phép bạn đọc và ghi giá trị một cách trực
tiếp.
TCCR0 (Timer/Counter Control Register): là thanh ghi điều khiển hoạt
động của T/C0. Tuy là thanh ghi 8 bit nhưng thực chất chỉ có 3 bit có tác dụng
đó là CS00, CS01 và CS02.

Hình 1.6: Cấu trúc thanh ghi TCCR0
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.

17



Hình 1.7: Chức năng các bit CS0X

TIMSK (Timer/Counter Interrupt Mask Register): là thanh ghi mặt nạ cho
ngắt của tất cả các T/C trong Atmega8, trong đó chỉ có bit TOIE0 tức bit số 0
(bit đầu tiên) trong thanh ghi này là liên quan đến T/C0, bit này có tên là bit cho
phép ngắt khi có tràn ở T/C0. Tràn (Overflow) là hiện tượng xảy ra khi bộ giá trị
trong thanh ghi TCNT0 đã đạt đến MAX (255) và lại đếm thêm 1 lần nữa.

Hình 1.8: Cấu trúc thanh ghi TMISK

Khi bit TOIE0=1, và bit I trong thanh ghi trạng thái được set nếu một
“tràn” xảy ra sẽ dẫn đến ngắt tràn.
TIFR (Timer/Counter Interrupt Flag Register): là thanh ghi cờ nhớ cho tất
cả các bộ T/C. Trong thanh ghi này bit số 0, TOV0 là cờ chỉ thị ngắt tràn của
T/C0. Khi có ngắt tràn xảy ra, bit này tự động được set lên 1. Thông thường
trong điều khiển các T/C vai trò của thanh ghi TIFR không quá quan trọng.
Hoạt động: T/C0 hoạt động rất đơn giản, hoạt động của T/C được “kích”
bởi một tín hiệu (signal), cứ mỗi lần xuất hiện tín hiệu “kích” giá trị của thanh
ghi TCNT0 lại tăng thêm 1 đơn vị, thanh ghi này tăng cho đến khi nó đạt mức
MAX là 255, tín hiệu kích tiếp theo sẽ làm thanh ghi TCNT0 trở về 0 (tràn), lúc
này bit cờ tràn TOV0 sẽ tự động được set bằng 1. Với cách thức hoạt động như
thế có vẻ T/C0 vô dụng vì cứ tăng từ 0 đến 255 rồi lại quay về 0, và quá trình lặp
lại. Tuy nhiên, yếu tố tạo sự khác biệt chính là tín hiệu kích và ngắt tràn, kết hợp
2 yếu tố này chúng ta có thể tạo ra 1 bộ định thời gian hoặc 1 bộ đếm sự kiện.
Trước hết bạn hãy nhìn lại bảng 1 về các bit chọn xung nhịp cho T/C0. Xung
nhịp cho T/C0 chính là tín hiệu kích cho T/C0. Xung nhịp này có thể tạo bằng
nguồn tạo dao động của chip (thạch anh, dao động nội trong chip…). Bằng cách
18



đặt giá trị cho các bit CS00, CS01 và CS02 của thanh ghi điều khiển TCCR0,
chúng ta sẽ quyết định bao lâu thì sẽ kích T/C0 một lần. Ví dụ mạch ứng dụng
của bạn có nguồn dao động clk = 1MHz tức chu kỳ 1 nhịp là 1us (1 micro giây),
bạn đặt thanh ghi TCCR0=5 (tức SC02=1, CS01=0, CS00=1). Căn cứ theo hình
1.7, tín hiệu kích cho T/C0 sẽ bằng clk/1024 nghĩa là sau 1024us thì T/C0 mới
được kích 1 lần, nói cách khác giá trị của TCNT0 tăng thêm 1 sau 1024us (chú ý
là tần số được chia cho 1024 thì chu kỳ sẽ tăng 1024 lần). Quan sát 2 dòng cuối
cùng trong hình 1.7 bạn sẽ thấy rằng tín hiệu kích cho T/C0 có thể lấy từ bên
ngoài (External clock source), đây chính là ý tưởng cho hoạt động của chức
năng đếm sự kiện trên T/C0. Bằng cách thay đổi trạng thái chân T0 (chân 6 trên
chip Atmega8) chúng ta sẽ làm tăng giá trị thanh ghi TCNT0 hay nói cách khác
T/C0 có thể dùng để đếm sự kiện xảy ra trên chân T0.
1.4.2 Timer/Counter1:
Timer/Counter1 là bộ T/C 16 bits, đa chức năng. Đây là bộ T/C rất lý
tưởng cho lập trình đo lường và điều khiển vì có độ phân giải cao (16 bits) và có
khả năng tạo xung điều rộng PWM (Pulse Width Modulation – thường dùng để
điều khiển động cơ).
Các thanh ghi: có khá nhiều thanh ghi liên quan đến T/C1. Vì là T/C 16
bits trong khi độ rộng bộ nhớ dữ liệu của AVR là 8 bit nên đôi khi cần dùng
những cặp thanh ghi 8 bits tạo thành 1 thanh ghi 16 bit, 2 thanh ghi 8 bits sẽ có
tên kết thúc bằng các ký tự L và H trong đó L là thanh ghi chứa 8 bits thấp
(LOW) và H là thanh ghi chứa 8 bits cao (High) của giá trị 16 bits mà chúng tạo
thành.
Các chế độ hoạt động của T/C1 được tóm tắt trong hình 1.9

19


Hình 1.9: Các chế độ hoạt động của T/C1.


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
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.*/
20


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;
}
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.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 1.1: Các toán tử đại số

21


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

Bảng 1.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 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
22


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 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;
23



}
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;
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;
24



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
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.
25



×