Mục lục:

Hướng dẫn lắp ráp AVR 2: 4 bước
Hướng dẫn lắp ráp AVR 2: 4 bước

Video: Hướng dẫn lắp ráp AVR 2: 4 bước

Video: Hướng dẫn lắp ráp AVR 2: 4 bước
Video: AVR máy phát điện đuôi kích không chổi than điện hướng dẫn lắp đặt | Quang máy phát điện 2024, Tháng bảy
Anonim
Hướng dẫn lắp ráp AVR 2
Hướng dẫn lắp ráp AVR 2

Hướng dẫn này là phần tiếp theo của "Hướng dẫn lắp ráp AVR 1"

Nếu bạn chưa xem qua Hướng dẫn 1, bạn nên dừng lại ngay bây giờ và làm điều đó trước.

Trong hướng dẫn này, chúng ta sẽ tiếp tục nghiên cứu về lập trình hợp ngữ của atmega328p được sử dụng trong Arduino.

Bạn sẽ cần:

  1. Arduino breadboard hoặc chỉ là Arduino bình thường như trong Hướng dẫn 1
  2. một đèn LED
  3. một điện trở 220 ohm
  4. một nút nhấn
  5. kết nối dây để tạo mạch trên breadboard của bạn
  6. Hướng dẫn sử dụng bộ Instuction: www.atmel.com/images/atmel-0856-avr-instruction-s…
  7. Datasheet: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…

Bộ sưu tập đầy đủ các hướng dẫn của tôi có thể được tìm thấy tại đây:

Bước 1: Xây dựng mạch

Xây dựng mạch
Xây dựng mạch

Đầu tiên bạn cần xây dựng mạch mà chúng ta sẽ nghiên cứu trong hướng dẫn này.

Đây là cách nó được kết nối:

PB0 (chân kỹ thuật số 8) - LED - R (220 ohm) - 5V

PD0 (chân số 0) - nút bấm - GND

Bạn có thể kiểm tra xem đèn LED của mình có được định hướng đúng hay không bằng cách kết nối nó với GND thay vì PB0. Nếu không có gì xảy ra thì hãy đảo ngược hướng và đèn sẽ sáng. Sau đó kết nối lại với PB0 và tiếp tục. Hình ảnh cho thấy cách kết nối arduino breadboard của tôi.

Bước 2: Viết mã hội

Viết mã hội
Viết mã hội

Viết mã sau vào một tệp văn bản có tên pushbutton.asm và biên dịch nó với avra như bạn đã làm trong Hướng dẫn 1.

Lưu ý rằng trong đoạn mã này, chúng tôi có rất nhiều nhận xét. Mỗi khi trình hợp dịch nhìn thấy dấu chấm phẩy, nó sẽ bỏ qua phần còn lại của dòng và chuyển sang dòng tiếp theo. Thực hành lập trình tốt (đặc biệt là trong hợp ngữ!) Là bình luận nhiều về mã của bạn để khi bạn quay lại nó trong tương lai, bạn sẽ biết mình đang làm gì. Tôi sẽ nhận xét mọi thứ khá nhiều trong một vài hướng dẫn đầu tiên để chúng ta biết chính xác điều gì đang xảy ra và tại sao. Sau này, một khi chúng tôi trở nên tốt hơn một chút trong việc mã hóa lắp ráp, tôi sẽ nhận xét mọi thứ ít chi tiết hơn một chút.

;************************************

; được viết bởi: 1o_o7; ngày: 23 tháng 10 năm 2014; ************************************

.nolist

.include "m328Pdef.inc".list.def temp = r16; chỉ định thanh ghi làm việc r16 là Init tạm thời rjmp; dòng đầu tiên được thực hiện

Trong đó:

nhiệt độ ser; đặt tất cả các bit ở nhiệt độ thành 1. ra DDRB, tạm thời; thiết lập một chút là 1 trên I / O Hướng dữ liệu; đăng ký cho PortB, là DDRB, thiết lập điều đó; chân là đầu ra, một 0 sẽ đặt chân đó làm đầu vào; vì vậy ở đây, tất cả các chân PortB đều là đầu ra (đặt thành 1) ldi temp, 0b11111110; tải số `` ngay lập tức '' vào thanh ghi tạm thời; nếu nó chỉ là ld thì đối số thứ hai; sẽ phải là một vị trí bộ nhớ thay vì DDRD, tạm thời; mv temp vào DDRD, kết quả là PD0 là đầu vào; và phần còn lại là đầu ra clr temp; tất cả các bit trong tạm thời được đặt thành 0 của PortB, tạm thời; đặt tất cả các bit (tức là các chân) trong PortB thành 0V ldi temp, 0b00000001; tải số ngay lập tức để tạm thời ra PortD, tạm thời; chuyển nhiệt độ sang PortD. PD0 có một điện trở kéo lên; (tức là đặt thành 5V) vì nó có 1 trong bit đó; phần còn lại là 0V kể từ 0.

Chủ chốt:

ở nhiệt độ, PinD; PinD giữ trạng thái của PortD, sao chép nó vào tạm thời; nếu nút được kết nối với PD0, điều này sẽ là; 0 khi nút được nhấn, 1 nếu không kể từ khi; PD0 có một điện trở kéo lên, nó thường ở 5V ra PortB, nhiệt độ; gửi số 0 và số 1 đã đọc ở trên tới PortB; điều này có nghĩa là chúng tôi muốn đèn LED được kết nối với PB0,; khi PD0 là LOW, nó đặt PB0 thành LOW và quay đầu; trên đèn LED (vì phía bên kia của đèn LED; được kết nối với 5V và điều này sẽ đặt PB0 thành 0V vì vậy; dòng điện sẽ chạy) rjmp Main; lặp lại phần bắt đầu của Main

Lưu ý rằng lần này chúng ta không chỉ có thêm nhiều nhận xét trong mã của mình mà còn có phần tiêu đề cung cấp một số thông tin về ai đã viết nó và thời điểm nó được viết. Phần còn lại của mã cũng được tách thành các phần.

Sau khi bạn đã biên dịch mã trên, bạn nên tải nó vào bộ vi điều khiển và thấy rằng nó hoạt động. Đèn LED sẽ bật trong khi bạn nhấn nút và sau đó tắt lại khi bạn buông tay. Tôi đã cho thấy nó trông như thế nào trong hình.

Bước 3: Phân tích từng dòng của mã

Tôi sẽ bỏ qua những dòng chỉ đơn thuần là bình luận vì mục đích của chúng là hiển nhiên.

.nolist

.include "m328Pdef.inc".list

Ba dòng này bao gồm tệp chứa định nghĩa Đăng ký và Bit cho ATmega328P mà chúng tôi đang lập trình. Lệnh.nolist yêu cầu trình hợp dịch không bao gồm tệp này trong tệp pushbutton.lst mà nó tạo ra khi bạn lắp ráp nó. Nó tắt tùy chọn danh sách. Sau khi bao gồm tệp, chúng tôi bật lại tùy chọn liệt kê bằng lệnh.list. Lý do chúng tôi làm điều này là vì tệp m328Pdef.inc khá dài và chúng tôi không thực sự cần phải xem nó trong tệp danh sách. Trình hợp dịch của chúng tôi, avra, không tự động tạo tệp danh sách và nếu chúng tôi muốn một tệp, chúng tôi sẽ lắp ráp bằng cách sử dụng lệnh sau:

avra -l pushbutton.lst pushbutton.asm

Nếu bạn làm điều này, nó sẽ tạo ra một tệp có tên pushbutton.lst và nếu bạn kiểm tra tệp này, bạn sẽ thấy rằng nó hiển thị mã chương trình của bạn cùng với thông tin bổ sung. Nếu bạn nhìn vào thông tin bổ sung, bạn sẽ thấy rằng các dòng bắt đầu bằng C: theo sau là địa chỉ tương đối trong hệ thập lục phân của nơi mã được đặt trong bộ nhớ. Về cơ bản, nó bắt đầu từ 000000 với lệnh đầu tiên và tăng từ đó với mỗi lệnh tiếp theo. Cột thứ hai sau vị trí tương đối trong bộ nhớ là mã hex cho lệnh, theo sau là mã hex cho đối số của lệnh. Chúng tôi sẽ thảo luận thêm về các tệp danh sách trong các hướng dẫn trong tương lai.

.def temp = r16; chỉ định đăng ký làm việc r16 làm tạm thời

Trong dòng này, chúng tôi sử dụng chỉ thị trình hợp dịch ".def" để xác định biến "temp" bằng với "thanh ghi làm việc" r16. Chúng ta sẽ sử dụng thanh ghi r16 làm thanh ghi lưu trữ các số mà chúng ta muốn sao chép vào các cổng và thanh ghi khác nhau (không thể ghi trực tiếp vào).

Bài tập 1: Cố gắng sao chép trực tiếp một số nhị phân vào một cổng hoặc thanh ghi đặc biệt như DDRB và xem điều gì sẽ xảy ra khi bạn cố gắng lắp ráp mã.

Một thanh ghi chứa một byte (8 bit) thông tin. Về cơ bản, nó thường là một tập hợp các SR-Latch, mỗi cái là một "bit" và chứa 1 hoặc 0. Chúng ta có thể thảo luận về điều này (và thậm chí xây dựng một!) Ở phần sau của loạt bài này. Bạn có thể tự hỏi "sổ đăng ký làm việc" là gì và tại sao chúng tôi chọn r16. Chúng ta sẽ thảo luận điều đó trong một bài hướng dẫn trong tương lai khi chúng ta đi sâu vào vũng lầy của các bộ phận bên trong chip. Bây giờ tôi muốn bạn hiểu cách làm những việc như viết mã và lập trình phần cứng vật lý. Sau đó, bạn sẽ có một hệ quy chiếu từ kinh nghiệm đó sẽ làm cho các thuộc tính bộ nhớ và thanh ghi của vi điều khiển dễ hiểu hơn. Tôi nhận thấy rằng hầu hết các sách giáo khoa và cuộc thảo luận giới thiệu đều làm điều này theo cách khác nhưng tôi nhận thấy rằng chơi trò chơi điện tử một lúc để có cái nhìn toàn cầu trước khi đọc hướng dẫn sử dụng sẽ dễ dàng hơn nhiều so với việc đọc hướng dẫn trước.

rjmp Init; dòng đầu tiên được thực hiện

Dòng này là một "bước nhảy tương đối" đến nhãn "Init" và không thực sự cần thiết ở đây vì lệnh tiếp theo đã có trong Init nhưng chúng tôi đưa nó vào để sử dụng trong tương lai.

Trong đó:

nhiệt độ ser; đặt tất cả các bit ở nhiệt độ thành 1.

Sau nhãn Init, chúng ta thực hiện lệnh "set register". Điều này đặt tất cả 8 bit trong thanh ghi "temp" (mà bạn gọi là r16) thành 1's. Vì vậy, tạm thời bây giờ chứa 0b11111111.

ra DDRB, tạm thời; thiết lập một bit là 1 trên thanh ghi Data Direction I / O

; đối với PortB, là DDRB, đặt chân đó làm đầu ra; một 0 sẽ đặt chân đó làm đầu vào; vì vậy ở đây, tất cả các chân PortB đều là đầu ra (được đặt thành 1)

Thanh ghi DDRB (Thanh ghi hướng dữ liệu cho PortB) cho biết chân nào trên PortB (tức là từ PB0 đến PB7) được chỉ định làm đầu vào và chân nào được chỉ định làm đầu ra. Vì chúng tôi có chân PB0 được kết nối với đèn LED của chúng tôi và phần còn lại không được kết nối với bất kỳ thứ gì, chúng tôi sẽ đặt tất cả các bit thành 1 nghĩa là chúng đều là đầu ra.

ldi temp, 0b11111110; tải số `` ngay lập tức '' vào thanh ghi tạm thời

; nếu nó chỉ là ld thì đối số thứ hai sẽ; phải là một vị trí bộ nhớ

Dòng này tải số nhị phân 0b11111110 vào thanh ghi tạm thời.

ra DDRD, tạm thời; mv temp thành DDRD, kết quả là PD0 là đầu vào và

; phần còn lại là kết quả đầu ra

Bây giờ chúng ta đặt Thanh ghi hướng dữ liệu cho PortD từ tạm thời, vì tạm thời vẫn chứa 0b11111110, chúng ta thấy rằng PD0 sẽ được chỉ định làm chân đầu vào (vì có số 0 ở vị trí ngoài cùng bên phải) và phần còn lại được chỉ định làm đầu ra vì có 1 ở những điểm đó.

clr tạm thời; tất cả các bit trong nhiệt độ được đặt thành 0's

ra PortB, tạm thời; đặt tất cả các bit (tức là chân) trong PortB thành 0V

Đầu tiên, chúng ta "xóa" tạm thời thanh ghi có nghĩa là thiết lập tất cả các bit bằng không. Sau đó, chúng tôi sao chép nó vào thanh ghi PortB đặt 0V trên tất cả các chân đó. Một số không trên một bit PortB có nghĩa là bộ xử lý sẽ giữ chân đó ở 0V, một số trên một bit sẽ khiến chân đó được đặt thành 5V.

Bài tập 2: Sử dụng đồng hồ vạn năng để kiểm tra xem tất cả các chân trên PortB có thực sự bằng không. Có điều gì đó kỳ lạ đang xảy ra với PB1? Bất kỳ ý tưởng tại sao điều đó có thể là? (tương tự như bài tập 4 bên dưới sau đó làm theo mã…) Bài tập 3: Xóa hai dòng trên khỏi mã của bạn. Chương trình vẫn chạy chính xác? Tại sao?

ldi temp, 0b00000001; tải số ngay lập tức để tạm thời

ra PortD, tạm thời; chuyển nhiệt độ sang PortD. PD0 ở mức 5V (có một điện trở pullup); vì nó có 1 trong bit đó, phần còn lại là 0V. Bài tập 4: Xóa hai dòng trên khỏi mã của bạn. Chương trình vẫn chạy chính xác? Tại sao? (Điều này khác với Bài tập 3 ở trên. Hãy xem sơ đồ chân cắm. Cài đặt DDRD mặc định cho PD0 là gì? (Xem trang 90 của bảng dữ liệu

Đầu tiên, chúng tôi "tải ngay lập tức" số 0b00000001 để tạm thời. Phần "ngay lập tức" nằm ở đó vì chúng ta đang tải một số thẳng lên tạm thời chứ không phải là một con trỏ đến vị trí bộ nhớ chứa số cần tải. Trong trường hợp đó, chúng ta chỉ cần sử dụng "ld" thay vì "ldi". Sau đó, chúng tôi gửi số này đến PortD đặt PD0 thành 5V và phần còn lại là 0V.

Bây giờ chúng tôi đã đặt các chân làm đầu vào hoặc đầu ra và chúng tôi đã thiết lập trạng thái ban đầu của chúng là 0V hoặc 5V (THẤP hoặc CAO) và vì vậy bây giờ chúng tôi nhập "vòng lặp" chương trình của chúng tôi.

Chính: ở nhiệt độ, PinD; PinD giữ trạng thái của PortD, sao chép nó vào tạm thời

; nếu nút được kết nối với PD0 thì đây sẽ là; a 0 khi nút được nhấn, 1 nếu không kể từ khi; PD0 có một điện trở kéo lên, nó thường ở 5V

Thanh ghi PinD chứa trạng thái hiện tại của các chân PortD. Ví dụ: nếu bạn gắn dây 5V vào PD3, thì ở chu kỳ xung nhịp tiếp theo (xảy ra 16 triệu lần mỗi giây kể từ khi chúng tôi kết nối bộ vi điều khiển với tín hiệu xung nhịp 16MHz) bit PinD3 (từ trạng thái hiện tại của PD3) sẽ trở thành 1 thay vì 0. Vì vậy, trong dòng này, chúng tôi sao chép trạng thái hiện tại của các chân thành tạm thời.

ra PortB, tạm thời; gửi số 0 và số 1 đã đọc ở trên tới PortB

; điều này có nghĩa là chúng tôi muốn đèn LED được kết nối với PB0, vì vậy; khi PD0 là THẤP, nó sẽ đặt PB0 thành THẤP và quay đầu; trên đèn LED (phía bên kia của đèn LED được kết nối; đến 5V và điều này sẽ đặt PB0 thành 0V để dòng điện chạy qua)

Bây giờ chúng ta gửi trạng thái của các chân trong PinD đến đầu ra PortB. Một cách hiệu quả, điều này có nghĩa là PD0 sẽ gửi 1 tới PortD0 trừ khi nút được nhấn. Trong trường hợp đó vì nút được kết nối với đất nên chân đó sẽ ở 0V và nó sẽ gửi 0 đến PortB0. Bây giờ, nếu bạn nhìn vào sơ đồ mạch, 0V trên PB0 có nghĩa là đèn LED sẽ phát sáng vì phía bên kia của nó là 5V. Nếu chúng ta không nhấn nút, để một 1 được gửi đến PB0, điều đó có nghĩa là chúng ta có 5V trên PB0 và cũng có 5V ở phía bên kia của đèn LED và do đó, không có sự khác biệt tiềm năng và không có dòng điện nào chạy và do đó Đèn LED sẽ không phát sáng (trong trường hợp này là đèn LED là một diode và do đó dòng điện chỉ chạy một hướng bất kể nhưng bất kể điều gì).

rjmp Chính; lặp lại để bắt đầu

Bước nhảy tương đối này đưa chúng ta trở lại nhãn Main: và chúng ta kiểm tra lại PinD, v.v. Kiểm tra 16 phần triệu giây một lần xem nút có đang được nhấn hay không và thiết lập PB0 cho phù hợp.

Bài tập 5: Sửa đổi mã của bạn để đèn LED của bạn được kết nối với PB3 thay vì PB0 và thấy rằng nó hoạt động. Bài tập 6: Cắm đèn LED của bạn vào GND thay vì 5V và sửa đổi mã của bạn cho phù hợp.

Bước 4: Kết luận

Trong hướng dẫn này, chúng tôi đã nghiên cứu sâu hơn về ngôn ngữ hợp ngữ cho ATmega328p và học cách điều khiển đèn LED bằng nút nhấn. Đặc biệt, chúng tôi đã học các lệnh sau:

thanh ghi ser đặt tất cả các bit của thanh ghi thành 1's

thanh ghi clr đặt tất cả các bit của thanh ghi thành 0

trong sổ đăng ký, i / o đăng ký sao chép số từ một sổ đăng ký i / o vào một sổ đăng ký hoạt động

Trong hướng dẫn tiếp theo, chúng ta sẽ xem xét cấu trúc của ATmega328p và các thanh ghi, hoạt động và tài nguyên khác nhau có trong đó.

Trước khi tiếp tục với những hướng dẫn này, tôi sẽ đợi và xem mức độ quan tâm. Nếu có một số người thực sự thích học cách viết mã các chương trình cho bộ vi xử lý này bằng hợp ngữ thì tôi sẽ tiếp tục và xây dựng các mạch phức tạp hơn và sử dụng mã mạnh hơn.

Đề xuất: