Professional Documents
Culture Documents
ORG
I. Giới thiệu
Ở chương này chúng ta sẽ tìm hiểu 1 cách khái quát về cấu trúc của vi
điều khiển AVR.
Vi điều khiển AVR là bộ xử lý RISC (viết tắt của Reduced Instructions
Set Computer - Máy tính với tập lệnh đơn giản hóa) là một phương pháp thiết
kế các bộ vi xử lý (VXL) theo hướng đơn giản hóa tập lệnh, trong đó thời gian
thực thi tất cả các lênh đều như nhau.
AVR có cấu trúc Harvard, cụm từ kiến trúc Harvard được dùng để chỉ
những kiến trúc máy tính mà trong đó phân biệt rõ ràng bộ nhớ dữ liệu và bộ
nhớ chương trình, chúng có những đường truyền (bus) riêng để truy cập vào bộ
nhớ dữ liệu và bộ nhớ chương trình.
Tất cả các instruction sử dụng Register File làm toán hạng đều có thể truy nhập
tất cả các RF một cách trực tiếp trong 1 chu kỳ xung clock, ngoại trừ SBCI,
SUBI, CPI, ANDI và LDI, các instruction này chỉ có thể truy nhập các thanh
ghi từ R16 đến R31.
Thanh ghi R0 là thanh ghi duy nhất được sử dụng trong instruction LPM
(Load Program Memory). Các thanh ghi R26, R27, R28, R29, R30 và R31
ngoài chức năng thông thường còn được sử dụng như các con trỏ (Pointer
register) trong một số instruction truy xuất gián tiếp
+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.
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 (64 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. Việc điều khiển các PORT của AVR liên quan đến 3 thanh ghi
DDRx, PORTx và PINx (x là tên PORT), 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.
Vì các thanh ghi trong vùng I/O không được hiểu theo tên gọi như các
Register file, khi lập trình cho các thanh ghi này, người lập trình cần nhớ địa
chỉ của từng thanh ghi, đây là việc tương đối khó khăn. Tuy nhiên, trong hầu
hết các phần mềm lập trình cho AVR, địa chỉ của tất cả các thanh ghi trong
vùng I/O đều được định nghĩa trước trong 1 file định nghĩa, bạn chỉ cần đính
kèm file này vào chương trình của bạn là có thể truy xuất các thanh ghi với tên
gọi của chúng. Giả sử dùng phần mềm MikroC for AVR thanh ghi PORTB
được định nghĩa sẵn, bạn chỉ cần gọi tên thanh ghi này để truy xuất.
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 thực chất 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. Như trong hình 2, phần bộ nhớ EEPROM được tách riêng
và có địa chỉ tính từ 0x0000.
Hình 4. Stack.
Stack được truy xuất thông qua thanh ghi Stack Pointer(con trỏ ngăn
xếp). Thanh ghi này được dùng để chỉ đến vùng trong bộ nhớ SRAM ở đỉnh
của ngăn xếp.
Do cách truy xuất đặc biệt của stack, nên stack được dùng để lưu trữ địa
chỉ trở về của bộ đếm chương trình trong khi thực hiện các ngắt.
+Khi có ngắt xảy ra, vi điều khiển tự động lưu địa chỉ lệnh kế tiếp vào
stack và PC lúc này sẽ hướng đến vector ngắt tương ứng
+Khi AVR thoát khỏi 1 ngắt, địa chỉ của lệnh kế tiếp của chương trình
chính sẽ trả lại cho PC để tiếp tục thực hiện chương trình.
Bit 0 – C (Carry Flag: Cờ nhớ): là bit nhớ trong các phép đại số hoặc logic, ví
dụ thanh ghi R1 chứa giá trị 200, R2 chứa 70, chúng ta thực hiện phép cộng có
nhớ: R1, R2, sau phép cộng, kết quả sẽ được lưu lại trong thanh ghi R1, trong
khi kết quả thực là 270 mà thanh ghi R1 lại chỉ có khả năng chứa tối đa giá trị
255 (vì có 8 bit) nên trong trường hợp này, giá trị lưu lại trong R1 thực chất chỉ
là 14, đồng thời cờ C được set lên 1 (vì 270=100001110, trong đó 8 bit sau
00001110 =14 sẽ được lưu lại trong R1).
Bit 1 – Z (Zero Flag: Cờ 0): cờ này được set lên 1 nếu kết quả phép toán đại số
hay phép Logic bằng 0.
Bit 2 – N (Negative Flag: Cờ âm): cờ này được set lên 1 nếu kết quả phép toán
đại số hay phép Logic là số âm.
Bit 3 – V (Two’s complement Overflow Flag: Cờ tràn của bù 2): hoạt động của
cờ này liên quan đến kiến thức số nhị phân (phần bù), chúng ta sẽ đề cập đến
khi nào thấy cần thiết.
Bit 4 – S (Sign Bit: Bit dấu): Bit S là kết quả phép XOR giữa 1 cờ N và V,
S=N xor V.
Bit 5 – H (Half Carry Flag: Cờ nhớ nữa): cờ H là cờ nhớ trong 1 vài phép toán
đại số và phép Logic, cờ này hiệu quả đối với các phép toán với số BCD.
Bit 6 – T (Bit Copy Storage): được sử dụng trong 2 lệnh BLD (Bit LoaD) và
BST (Bit STorage).
Bit 7 – I (Global Interrupt Enable) : Cho phép ngắt toàn cục): Bit này phải được
set lên 1 nếu trong chương trình có sử dụng ngắt. Sau khi set bit này, bạn muốn
kích hoạt loại ngắt nào cần set các bit ngắt riêng của ngắt đó.
Phần này chỉ giải thích ngắn gọn chức năng của các bit trong thanh ghi
SREG, đối với ngôn ngữ ASEMBLY thì việc theo dõi cờ trạng thái giúp ta
kiểm soát các phép toán số học, tuy nhiên trong ngôn ngữ C ta chỉ dùng 1 số bit
cần thiết như bit 7 sử dụng trong các ứng dụng của ngắt. Trong trình biên dịch
MikroC, ta có thể truy xuất thanh ghi này như bằng tên gọi của nó.
Trên đây là các thành phần cơ bản trong cấu trúc AVR. Để hiểu sâu hơn
về các chức năng của AVR, các bạn cần tìm hiểu thêm về các thanh ghi
chức năng đặc biệt để phục vụ việc lập trình cho AVR sau này.
U1
1 3
GND
+5 Volt In Out +5 Volt
C1 LM7805 C2
2
470uF 100uF
Ground Ground
Lưu ý: tùy vào dạng đóng gói và loại vi điều khiển mà có thể có nhiều hơn 1
cặp chân nguồn-mass. Cần cung cấp đầy đủ để AVR vi điều khiển hoạt động
ổn định.
b/. Các chân phục vụ chức năng ADC.
AVCC: là chân cấp nguồn cho bộ chuyển đổi ADC, chân này được nối lên
nội bộ lên VCC ngay cả khi bộ chuyển đổi ADC không hoạt động. iá trị
điện áp cấp cho AVCC không được khác nguồn nuôi chip (VCC) quá +/-
0.3V. Nhiễu 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 3, đây là cách
được gợi ý bởi nhà sản xuất AVR.
Aref: chân cung cấp điện thế tham chiếu cho bộ ADC, nếu cấu hình cho
AVR dùng điện áp tham chiếu nội thì chân này phải nối mass thông qua 1
tụ điện để chống nhiễu.
c/. Các chân cấp xung đồng hồ.
Như đã nói, AVR có 2 nguồn cấp dao động chính là dao động nội có
xung nhịp tối đa 8MHz và dao động ngoại lên đến 16MHz.
Khi dùng mạch dao động ngoại, ta có 2 cách:
+Dùng mạch RC: Khi đó chân XTAL2 bỏ trống, cách này cũng dùng
khi ta có 1 nguồn dao động bất kỳ được cấp vào chân XTAL1
+Dùng dao động thạch anh: Trong đó, giá trị tụ C1=C2 từ 12pF đến
22pF. Mạch dao động thạch anh rất thông dụng do có độ chính xác cao.
Các chân của mỗi PORT đều có 2 hướng dữ liệu, hướng dữ liệu được
cấu hình bởi thanh ghi DDRx (x là tên PORT). Nếu bit nào được set lên 1
thì chân tương ứng sẽ là ngõ ra và ngược lại nếu bit nào bị xóa thì chân
tương ứng sẽ là ngõ vào.
Vd: DDRA=0b00001111 (“0b” trong ngôn ngữ C cho biết đang dùng
số ở hệ nhị phân)
Có nghĩa là PORT A có 4 bit thấp là ngõ ra và 4 bit cao là ngõ vào.
+Khi các chân được cấu hình là ngõ ra, chúng được ánh xạ trực tiếp tới
thanh ghi PORTx, khi đó trạng thái của mỗi chân sẽ tương ứng với từng bit
dữ liệu mà thanh ghi đang chứa. Hay nói cách khác, đây là thanh ghi xuất
dữ liệu.
Vd : PORTD=0b11110000
Có nghĩa là PORTD có các chân từ D0 đến D3 ở mức điện thế thấp và
các chân D4 đến D7 có mức điện thế cao.
+Khi các chân được cấu hình là ngõ vào, chúng được ánh xạ trực
tiếp đến thanh ghi PINx, khi đó tùy mức logic ở mỗi chân mà bit tương ứng
của thanh ghi PINx có giá trị 0 hay 1. Hay nói cách khác, đây là thanh ghi
nhận dữ liệu.
Vd : Khi các chân từ D0 đến D3 nối lên mức điện thế cao, các chân còn
lại nối với mức điện thế thấp thì thanh ghi PIND sẽ có giá trị 0b00001111.
Các chân vào-ra số đều được bảo vệ bởi diode và có khả năng cấp dòng lên đến
20mA nên có thể dễ dàng điều khiển các led mà không cần mắc thêm tầng công
suất.
Ngoài chức năng là ngõ vào-ra số, các chân của AVR còn có thể mang thêm 1
hoặc vài chức năng như ngắt ngoài, ADC…Ta có thể nhận ra chức năng khác
bằng tên trên sơ đồ chân của vi điều khiển.
Ví dụ : trong hình 5 chân số 23 có 2 chức năng là chân I/O thứ nhất của
PORTC (PC0) và là kênh ADC thứ nhất (ADC0).
R1
10k
RESET PIN
SW1
RESET BUTTON
AVR910USB : là phiên bản cải tiến của mạch nạp AVR910 của
ATMEL, nó cho phép giao tiếp qua cổng USB của máy tính. Vì vậy trên mạch
cần có 1 chip giao tiếp, đó là chip Atmega8. Tuy nhiên, ta lại gặp vấn đề « con
gà và quả trứng » : muốn thi công mạch này thì phải có 1 mạch nạp khác nạp
firmware cho chip giao tiếp Atmega8. Ta có thể thi công trước 1 mạch
STK200/300 rồi nạp cho chip Atmega8. Sơ đồ mạch và file chương trình-
firmware (*.hex) các bạn có thể tham khảo trên website www.eeelabs.org
USB AVR-Lab : là mạch nạp do website www.ullihome.de phát
triển, đây cũng là mạch nạp giao tiếp qua USB và chip giao tiếp vẫn là
Atmega8. Điểm đặc biệt là mạch này giả lập các loại mạch nạp khác như
STK500, MkII... Firmware nạp cho chip được ghi vào phần boot flash, khi cần
thay đổi, ta chỉ cần dùng phần mềm trên máy tính để thay đổi loại mạch nạp mà
mạch này giả lập, không cần phải nạp lại firmware mới. Sơ đồ mạch, layout
mạch in, driver, firmware và chương trình các bạn có thể tham khảo trên
website www.eeelabs.org
3. Chương trình nạp.
Là phần mềm chạy trên máy tính để lấy file hex nạp vào vi điều khiển,
ngoài ra nó còn có thể kiêm luôn chức năng lập trình fuse bit (sẽ đề cập ở
phần sau).
Như đã nói ở trên, chương trình nạp thông dụng được tích hợp sẵn trong
1 số trình biên dịch như AVR Studio hay Codevision.
Tôi sẽ giới thiệu cách nạp chương trình bằng AVR Studio 4 như sau :
+Khởi động chương trình, ở gaio diện chính chọn nút (display
the ‘Connect’ dialog).
+Cửa sổ mới hiện ra:
Chọn loại mạch nạp đang dùng ở mục Platform, sau đó ở phần Port chọn
Auto nếu mạch nạp sử dụng cổng COM hoặc COM ảo(USB giả lập COM – ví
dụ như AVR910USB). Nếu mạch nạp chuẩn USB thì chọn USB. Chọn xong
bấm Connect…
+Nếu máy nhận ra mạch nạp thì có cửa sổ sau hiện ra:
Ở thẻ main, ta chọn loại chip sử dụng trong list mà mạch nạp đang dùng
hỗ trợ ở mục Device anh Signature Bytes, sau đó bấm Read Signature để kiểm
tra. Sẽ có thông báo cho biết có đúng loại chip bạn chọn đang được kết nối hay
không.
+Chọn tiếp chuẩn nạp: ở mục Programming Mode anh Target Settings.
Nếu chuẩn nạp là ISP thì chọn setting chọn tần số ISP Freq sao cho tần số này
nhỏ hơn ¼ xung nhịp của chip đích(chip cần nạp) đang dùng. Sau đó bấm
write, bấm read để kiểm tra lại. Bấm close để thoát.
+Thẻ Program: Check vào các mục Erase device before flash
programming và mục Verify device after programming. Mục đích là đảm bảo
quá trình nạp diễn ra suôn sẻ.
Mục Flash chọn Input HEX file, sau đó chỉ đường dẫn đến file chương
trình cần nạp. Sau đó bấm Program. Nếu muốn đọc dữ liệu trong chip và ghi
thành file hex trên máy thì bấm Read và chọn nơi lưu file hex.
Các chức năng còn lại sẽ đề cập ở các chương sau.
4. Trình mô phỏng ISIS Proteus.
Đây là trình mô phỏng mạch điện tử rất thông dụng nhờ tính trực quan,
giao diện thân thiện, thư viện linh kiện khá lớn, và hỗ trợ hầu hết các loại vi
điều khiển thông dụng như AVR, PIC,8051.
Khi mô phỏng vi điều khiển AVR với ISIS Proteus các công đoạn như
fuse bit(cấu hình cứng), được thực hiện bằng cách cấu hình linh kiện.
Sau đây là vài bước thực hiện việc mô phỏng mạch vi điều khiển AVR
với ISIS Proteus.
Bước 1: Chọn linh kiện. Bấm vào nút để chọn chế độ lấy linh kiện.
Sau đó, bấm vào nút để lấy linh kiện trong thư viện, cửa sổ mới hiện ra, gõ
tên linh kiện cần lấy (hoặc cần tìm) vào ô keyword. Bấm vào linh kiện hiện ra ở
kết quả, sau đó bấm ok. Lấy các linh kiện cần thiết với các bước như trên.
Bước 2: Lấy nguồn và mass. Bấm vào nút để lấy các thành phần đầu
cuối(terminal) như POWER(nguồn) hoặc Ground(mass).
Bước 3: Vẽ đường liên kết. Bấm vào nút , sau đó bấm vào chân linh
kiện bất kỳ rồi kéo đường dây đến chân linh kiện khác. Trong quá trình kéo,
bấm chuột vào không gian để định hướng đường dây.
Trường hợp có quá nhiều đường dây có đặt tính gần giống nhau, ta dùng
công cụ tuyến (BUS) để vẽ , bấm vào để vẽ tuyến, sau đó vẽ các đường liên
kết ngắn nhất đến tuyến. Tiếp theo là đặt tên các đường tín hiệu, các đường dây
trong 1 tuyến chỉ nối với nhau khi chúng có cùng tên nhãn(label). Ta bấm
sau đó bấm vào đường dây để đặt tên.
Bước 4: Sau khi đã vẽ xong mạch, bấm bào linh kiện để điều chỉnh các
trị số thích hợp như giá trịn điện trở, tụ điện. Đối với vi điều khiển AVR thì các
thông số khá nhiều và có thể khác nhau ở mỗi loại:
Các thông số cần quan tâm:
+Program File: đường dẫn đến file hex đã biên dịch, chính là file dùng
để nạp xuống chip trong thực tế.
+Clock Frequency: tần số thạch anh mà vi điều khiển đang dùng trong
mạch thực tế ( cấu hình trong trình biên dịch).
+Các thông số còn lại chính là các fuse bit, sẽ được giới thiệu ở phần
sau.
Bước 5: Sau khi hoàn tất vẽ mạch, ta tiến hành dùng các nút
1
2
3
4
5
6
VCC IC1 L1
10uH
10
1 1 40 1
2 2 PB0/(XCK/T0) PA0/(ADC0) 39 2
VC C
PB1/(T1) PA1/(ADC1) J6
3 3 38 3
PB2/(INT2/AIN0) PA2/(ADC2) EXTERNAL Vref
4 4 37 4
PB3/(OC0/AIN1) PA3/(ADC3)
5 5 36 5
PB4/(SS) PA4/(ADC4)
6 6 35 6
PB5/(MOSI) PA5/(ADC5)
VCC 7 7 34 7
1
2
PB6/(MISO) PA6/(ADC6)
8 8 33 8
PB7/(SCK) PA7/(ADC7)
9 9
10 9 10 J5
C1 RESET
R1 22p 32
AREF
10K J1 12 J4 1
Lập trình vi điều khiển AVR với ngôn ngữ C
XTAL2
2
RESET 30 3
Y1 AVCC
SW1 VCC 16Mhz C4
C5 C2 104 VCC C3 Vref SELECTOR
10uF PORTD 22p 13 PORTC 104
XTAL1
10 14 29 1
PD0/(RXD) PC7/(TOSC2)
9 15 28 2
PD1/(TXD) PC6/(TOSC1)
8 16 27 3
PD2/(INT0) PC5/(TDI)
7 17 26 4
6 18 PD3/(INT1) PC4/(TDO) 25 5
PD4/(OC1B) PC3/(TMS)
5 19 24 6
PD5/(OC1A) PC2/(TCK)
4 20 23 7
PD6/(ICP) PC1/(SDA)
3 21 22 8
GN D
GN D
PD7/(OC2) PC0/(SCL)
2 9
1 10
11
31
J2 J3
WWW.EEELABS.ORG
21