สารบัญ:

บทช่วยสอน AVR Assembler 1: 5 ขั้นตอน
บทช่วยสอน AVR Assembler 1: 5 ขั้นตอน

วีดีโอ: บทช่วยสอน AVR Assembler 1: 5 ขั้นตอน

วีดีโอ: บทช่วยสอน AVR Assembler 1: 5 ขั้นตอน
วีดีโอ: Learning AVR-C Episode 1: Introduction 2024, กรกฎาคม
Anonim
AVR Assembler บทช่วยสอน 1
AVR Assembler บทช่วยสอน 1

ฉันได้ตัดสินใจเขียนชุดบทเรียนเกี่ยวกับวิธีการเขียนโปรแกรมภาษาแอสเซมบลีสำหรับ Atmega328p ซึ่งเป็นไมโครคอนโทรลเลอร์ที่ใช้ใน Arduino หากยังมีคนสนใจอยู่ ฉันจะออกสัปดาห์ละหนึ่งสัปดาห์หรือมากกว่านั้นจนกว่าเวลาว่างฉันจะหมด มิฉะนั้นคนอื่นจะหยุดอ่าน

ฉันกำลังใช้งาน Arch linux และฉันกำลังทำงานกับ atmega328p-pu ที่ตั้งค่าไว้บนเขียงหั่นขนม คุณสามารถทำแบบเดียวกับฉันหรือเพียงแค่เสียบ Arduino เข้ากับคอมพิวเตอร์ของคุณและทำงานกับไมโครคอนโทรลเลอร์ด้วยวิธีนั้น

เราจะเขียนโปรแกรมสำหรับ 328p เช่นเดียวกับที่อยู่ใน Arduino ส่วนใหญ่ แต่คุณควรสังเกตว่าโปรแกรมและเทคนิคเดียวกันนี้จะใช้ได้กับไมโครคอนโทรลเลอร์ Atmel ใด ๆ และในภายหลัง (หากมีความสนใจ) เราจะทำงานร่วมกับบางส่วนของ คนอื่นเช่นกัน รายละเอียดของไมโครคอนโทรลเลอร์สามารถพบได้ในเอกสารข้อมูล Atmel และคู่มือชุดคำสั่ง ฉันกำลังแนบไปกับคำแนะนำนี้

นี่คือสิ่งที่คุณต้องการ:

1. เขียงหั่นขนม

2. Arduino หรือเพียงแค่ไมโครคอนโทรลเลอร์

3. คอมพิวเตอร์ที่ใช้ Linux

4. แอสเซมเบลอร์ avra โดยใช้ git: git clone https://github.com/Ro5bert/avra.git หรือหากคุณใช้อูบุนตูหรือระบบที่ใช้เดเบียน เพียงพิมพ์ "sudo apt install avra" แล้วคุณจะได้ทั้งแอสเซมเบลอร์ avr และความเกียจคร้าน อย่างไรก็ตาม หากคุณใช้เวอร์ชันล่าสุดโดยใช้ github คุณจะได้รับไฟล์รวมที่จำเป็นทั้งหมด กล่าวคือ มีไฟล์ m328Pdef.inc และ tn85def.inc อยู่แล้ว

5. สาระ

สามารถดูบทแนะนำ AVR assembler ทั้งชุดได้ที่นี่:

ขั้นตอนที่ 1: สร้างกระดานทดสอบ

สร้างคณะกรรมการทดสอบ
สร้างคณะกรรมการทดสอบ

คุณสามารถใช้ Arduino ของคุณและทำทุกอย่างในบทช่วยสอนเหล่านี้ได้หากต้องการ อย่างไรก็ตาม เนื่องจากเรากำลังพูดถึงการเข้ารหัสในภาษาแอสเซมบลี ปรัชญาของเราโดยเนื้อแท้คือเพื่อแยกอุปกรณ์ต่อพ่วงทั้งหมดออกและโต้ตอบกับไมโครคอนโทรลเลอร์โดยตรง คุณไม่คิดว่ามันจะสนุกกว่านี้ถ้าทำแบบนั้น?

สำหรับผู้ที่เห็นด้วย คุณสามารถดึงไมโครคอนโทรลเลอร์ออกจาก Arduino แล้วเริ่มต้นด้วยการสร้าง "Breadboard Arduino" โดยทำตามคำแนะนำที่นี่:

ในภาพฉันแสดงการตั้งค่าของฉันซึ่งประกอบด้วย Atmega328p แบบสแตนด์อโลนสองตัวบนเขียงหั่นขนมขนาดใหญ่ (ฉันต้องการใช้สายการสอนก่อนหน้าแบบมีสายและโหลดบนไมโครคอนโทรลเลอร์หนึ่งตัวในขณะที่ทำงานในครั้งต่อไป) ฉันได้ตั้งค่าแหล่งจ่ายไฟเพื่อให้รางด้านบนสุดคือ 9V และส่วนอื่น ๆ ทั้งหมดเป็น 5V จากตัวควบคุมแรงดันไฟฟ้า ฉันยังใช้บอร์ดฝ่าวงล้อม FT232R เพื่อตั้งโปรแกรมชิป ฉันซื้อมันมาและใส่ bootloaders ด้วยตัวเอง แต่ถ้าคุณเพิ่งดึง Arduino ตัวหนึ่งออกมาก็ไม่เป็นไร

โปรดทราบว่าหากคุณลองใช้ ATtiny85 คุณสามารถดาวน์โหลด Sparkfun Tiny Programmer ได้ที่นี่: https://www.sparkfun.com/products/11801# จากนั้นเพียงเสียบเข้ากับพอร์ต USB บนคอมพิวเตอร์ของคุณ คุณจะต้องติดตั้ง bootloader บน Attiny85 ก่อน และวิธีที่ง่ายที่สุดคือใช้ Arduino IDE อย่างไรก็ตาม คุณจะต้องคลิกที่ไฟล์และค่ากำหนด จากนั้นเพิ่ม URL บอร์ดใหม่นี้: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json ซึ่งจะ ให้คุณติดตั้ง bootloader ได้ (หาก ATtiny85 ของคุณไม่มีมาให้)

ขั้นตอนที่ 2: ติดตั้ง Assembler และ Avrdude

ตอนนี้คุณสามารถดาวน์โหลดและติดตั้งแอสเซมเบลอร์และ avrdude ได้จากลิงก์ที่ให้ไว้ในขั้นตอนแรกของบทช่วยสอนนี้ เป็นไปได้ว่าถ้าคุณได้ทำงานกับ Arduino อยู่แล้ว แสดงว่าคุณได้ติดตั้ง avrdude แล้ว

หลังจากที่คุณได้ติดตั้ง avra แล้ว คุณจะสังเกตเห็นว่ามีไดเร็กทอรีย่อยที่มาพร้อมกับไดเร็กทอรีที่เรียกว่า "แหล่งที่มา" และภายในไดเร็กทอรีนั้นมีไฟล์รวมอยู่มากมาย นี่คือไมโครคอนโทรลเลอร์ทั้งหมดที่คุณสามารถตั้งโปรแกรมด้วย avra คุณจะสังเกตเห็นได้ทันทีว่าไม่มีไฟล์สำหรับ 328p ที่เราใช้อยู่ที่นี่ ฉันได้แนบหนึ่ง ไฟล์ควรเรียกว่า m328Pdef.inc และคุณควรใส่ไว้ในไดเร็กทอรี include หรือที่อื่น ๆ ที่คุณต้องการ เราจะรวมไว้ในโปรแกรมภาษาแอสเซมบลีของเรา ทั้งหมดนี้คือให้แต่ละรีจิสเตอร์ในชื่อไมโครคอนโทรลเลอร์จากแผ่นข้อมูล เพื่อที่เราจะไม่ต้องใช้ชื่อเลขฐานสิบหกของพวกมัน ไฟล์ด้านบนมี "คำสั่ง Pragma" เนื่องจากได้รับการออกแบบมาสำหรับการเขียนโปรแกรม C และ C ++ หากคุณเบื่อที่จะเห็นแอสเซมเบลอร์ถ่มน้ำลายว่า "ละเลยคำสั่ง Pragma" ให้เข้าไปในไฟล์แล้วลบหรือแสดงความคิดเห็นออกทุกบรรทัดที่ขึ้นต้นด้วย #pragma

เอาล่ะ เมื่อคุณมีไมโครคอนโทรลเลอร์พร้อม แอสเซมเบลอร์พร้อม และโปรแกรมเมอร์ของคุณพร้อมแล้ว เราก็สามารถเขียนโปรแกรมแรกของเราได้

หมายเหตุ: หากคุณใช้ ATtiny85 แทน ATmega328P คุณต้องมีไฟล์รวมอื่นที่เรียกว่า tn85def.inc ฉันจะแนบมันด้วย (โปรดทราบว่าฉันต้องเรียกมันว่า tn85def.inc.txt เพื่อให้ Instructables อนุญาตให้ฉันอัปโหลดได้) อย่างไรก็ตามหากคุณได้รับ avra assembler จาก github แสดงว่าคุณมีไฟล์ทั้งสองนี้อยู่แล้ว ดังนั้นผมขอแนะนำให้รับมันและรวบรวมมันเอง:git clone

ขั้นตอนที่ 3: สวัสดีชาวโลก

เป้าหมายของบทช่วยสอนแรกนี้คือการสร้างโปรแกรมมาตรฐานตัวแรกที่เขียนเมื่อเรียนรู้ภาษาใหม่หรือสำรวจแพลตฟอร์มอิเล็กทรอนิกส์ใหม่ "สวัสดีชาวโลก!." ในกรณีของเรา เราเพียงแค่ต้องการเขียนโปรแกรมภาษาแอสเซมบลี ประกอบ และอัปโหลดไปยังไมโครคอนโทรลเลอร์ของเรา โปรแกรมจะทำให้ไฟ LED เปิดขึ้น การทำให้ LED "กะพริบ" เหมือนกับที่ทำกับโปรแกรม Arduino Hello World ทั่วไป แท้จริงแล้วเป็นโปรแกรมที่ซับซ้อนกว่ามากในภาษาแอสเซมบลี ดังนั้นเราจะไม่ทำอย่างนั้นในตอนนี้ เราจะเขียนโค้ด "กระดูกเปล่า" ที่ง่ายที่สุดโดยมีขนปุยที่ไม่จำเป็นน้อยที่สุด

ขั้นแรกให้เชื่อมต่อ LED จาก PB5 (ดูแผนภาพ pinout) ซึ่งเรียกอีกอย่างว่า Digital Out 13 บน Arduino กับตัวต้านทาน 220 โอห์ม จากนั้นไปที่ GND เช่น.

PB5 -- LED -- R(220 โอห์ม) -- GND

ตอนนี้มาเขียนโปรแกรม เปิดโปรแกรมแก้ไขข้อความที่คุณชื่นชอบและสร้างไฟล์ชื่อ "hello.asm"

;สวัสดี.asm

; เปิด LED ซึ่งเชื่อมต่อกับ PB5 (ดิจิตอลออก 13).include "./m328Pdef.inc" ldi r16, 0b00100000 ออก DDRB, r16 ออก PortB, r16 เริ่ม: rjmp เริ่ม

ด้านบนเป็นรหัส เราจะดำเนินการทีละบรรทัดในไม่กี่นาที แต่ก่อนอื่นให้ตรวจสอบให้แน่ใจว่าเราสามารถทำงานได้บนอุปกรณ์ของคุณ

หลังจากที่คุณสร้างไฟล์แล้ว ในเทอร์มินัล คุณจะต้องประกอบมันดังนี้:

avra สวัสดี.asm

สิ่งนี้จะรวบรวมรหัสของคุณและสร้างไฟล์ชื่อ hello.hex ซึ่งเราสามารถอัปโหลดได้ดังนี้:

avrdude -p m328p -c stk500v1 -b 57600 -P /dev/ttyUSB0 -U แฟลช:w:hello.hex

หากคุณกำลังใช้ breadboard arduino คุณจะต้องกดปุ่มรีเซ็ตบน breadboard arduino ก่อนที่คุณจะรันคำสั่งด้านบน โปรดทราบว่าคุณอาจต้องเพิ่ม sudo ข้างหน้าหรือดำเนินการเป็นรูท โปรดทราบว่าใน Arduino บางตัว (เช่น Arduino UNO) คุณอาจต้องเปลี่ยนบิตเรตเป็น -b 115200 และพอร์ต -P /dev/ttyACM0 (หากคุณได้รับข้อผิดพลาดจาก avrdude เกี่ยวกับลายเซ็นอุปกรณ์ที่ไม่ถูกต้อง ให้เพิ่ม - F ถึงคำสั่ง)

หากทุกอย่างทำงานได้ตามปกติ ตอนนี้คุณจะมีไฟ LED ติดสว่าง….. "สวัสดีชาวโลก!"

หากคุณกำลังใช้ ATtiny85 คำสั่ง avrdude จะเป็น:

avrdude -p attiny85 -c usbtiny -U flash:w:hello.hex

ขั้นตอนที่ 4: Hello.asm ทีละบรรทัด

เพื่อจบการกวดวิชาเบื้องต้นนี้ เราจะดำเนินการผ่านโปรแกรม hello.asm ทีละบรรทัดเพื่อดูว่ามันทำงานอย่างไร

;สวัสดี.asm

; เปิดไฟ LED ที่เชื่อมต่อกับ PB5 (ดิจิตอลออก 13)

ทุกอย่างหลังจากเครื่องหมายอัฒภาคถูกละเว้นโดยแอสเซมเบลอร์และด้วยเหตุนี้สองบรรทัดแรกจึงเป็นเพียง "ความคิดเห็น" ที่อธิบายว่าโปรแกรมทำอะไร

.include "./m328Pdef.inc"

บรรทัดนี้บอกให้แอสเซมเบลอร์รวมไฟล์ m328Pdef.inc ที่คุณดาวน์โหลด คุณอาจต้องการใส่สิ่งนี้ในไดเร็กทอรีของไฟล์ include ที่คล้ายกันแล้วเปลี่ยนบรรทัดด้านบนให้ชี้ไปที่ไฟล์นั้น

ldi r16, 0b00100000

ldi ย่อมาจาก "loadทันที" และบอกให้แอสเซมเบลอร์ทำการรีจิสเตอร์ที่ใช้งานได้ r16 ในกรณีนี้และโหลดเลขฐานสองเข้าไป 0b00100000 ในกรณีนี้ 0b ข้างหน้าบอกว่าเลขของเราเป็นเลขฐานสอง ถ้าเราต้องการ เราสามารถเลือกฐานอื่นได้ เช่น เลขฐานสิบหก ในกรณีนั้นจำนวนของเราจะเป็น 0x20 ซึ่งเป็นเลขฐานสิบหกสำหรับ 0b00100000 หรือเราอาจใช้ 32 ซึ่งเป็นทศนิยมฐาน 10 สำหรับจำนวนเดียวกัน

แบบฝึกหัดที่ 1: ลองเปลี่ยนตัวเลขในบรรทัดด้านบนเป็นเลขฐานสิบหกแล้วเปลี่ยนเป็นทศนิยมในโค้ดของคุณและตรวจสอบว่ายังคงใช้ได้ในแต่ละกรณี

การใช้ไบนารีนั้นง่ายที่สุดเนื่องจากวิธีการทำงานของพอร์ตและการลงทะเบียน เราจะพูดถึงพอร์ตและการลงทะเบียนของ atmega328p ในรายละเอียดเพิ่มเติมในบทช่วยสอนในอนาคต แต่ตอนนี้ฉันจะระบุว่าเราใช้ r16 เป็น "รีจิสเตอร์ที่ใช้งานได้" ซึ่งหมายความว่าเราจะใช้เป็นตัวแปรที่เราจัดเก็บ ตัวเลขค่ะ "รีจิสเตอร์" คือชุด 8 บิต ความหมาย 8 จุดที่อาจเป็น 0 หรือ 1 (`ปิด' หรือ `เปิด') เมื่อเราโหลดเลขฐานสอง 0b00100000 ลงในรีจิสเตอร์โดยใช้บรรทัดด้านบน เราได้เก็บตัวเลขนั้นไว้ในรีจิสเตอร์ r16

ออก DDRB, r16

บรรทัดนี้บอกให้คอมไพเลอร์คัดลอกเนื้อหาของรีจิสเตอร์ r16 ลงในรีจิสเตอร์ DDRB DDRB ย่อมาจาก "Data Direction Register B" และตั้งค่า "หมุด" บน PortB บนแผนที่ pinout สำหรับ 328p คุณจะเห็นว่ามี 8 พินที่ระบุว่า PB0, PB1, …, PB7 หมุดเหล่านี้เป็นตัวแทนของ "บิต" ของ "PortB" และเมื่อเราโหลดเลขฐานสอง 00100000 ลงในการลงทะเบียน DDRB เรากำลังบอกว่าเราต้องการตั้ง PB0, PB1, PB2, PB3, PB4, PB6 และ PB7 เป็นพิน INPUT เนื่องจากมี มี 0 อยู่ในนั้น และ PB5 ถูกตั้งค่าเป็นพิน OUTPUT เนื่องจากเราใส่ 1 ลงในจุดนั้น

ออก PortB, r16

ตอนนี้เราได้กำหนดทิศทางของหมุดแล้ว เราสามารถตั้งค่าแรงดันไฟฟ้าบนหมุดได้ บรรทัดด้านบนคัดลอกเลขฐานสองเดียวกันจากที่เก็บข้อมูลของเราลงทะเบียน r16 ไปยัง PortB ซึ่งจะตั้งค่าพินทั้งหมดเป็น 0 โวลต์ ยกเว้นพิน PB5 ถึง HIGH ซึ่งเป็น 5 โวลต์

แบบฝึกหัดที่ 2: ใช้มัลติมิเตอร์แบบดิจิตอล เสียบตะกั่วสีดำเข้ากับกราวด์ (GND) จากนั้นทดสอบพิน PB0 แต่ละตัวผ่าน PB7 ด้วยตะกั่วสีแดง แรงดันไฟฟ้าบนพินแต่ละอันตรงกับการวาง 0b00100000 ใน PortB หรือไม่ ถ้าไม่ใช่เพราะอะไรถึงคิดว่าใช่? (ดูแผนที่พิน)

เริ่ม:

rjmp เริ่ม

สุดท้าย บรรทัดแรกด้านบนคือ "ป้ายกำกับ" ซึ่งระบุจุดในโค้ด ในกรณีนี้ให้ติดป้ายจุดนั้นว่า "เริ่ม" บรรทัดที่สองระบุว่า "ข้ามไปที่ป้ายกำกับเริ่ม" ผลลัพธ์ที่ได้คือคอมพิวเตอร์ถูกวางลงในลูปที่ไม่มีที่สิ้นสุดซึ่งเพียงแค่วนกลับไปเริ่มต้น เราต้องการสิ่งนี้เพราะเราไม่สามารถให้โปรแกรมสิ้นสุดหรือตกหน้าผา โปรแกรมต้องวิ่งต่อไปเพื่อให้แสงติดสว่าง

แบบฝึกหัดที่ 3: ลบสองบรรทัดข้างต้นออกจากโค้ดของคุณเพื่อให้โปรแกรมตกจากหน้าผา เกิดอะไรขึ้น? คุณควรเห็นสิ่งที่ดูเหมือนโปรแกรม "กะพริบตา" แบบเดิมๆ ที่ Arduino ใช้ว่าเป็น "สวัสดีชาวโลก!" ทำไมคุณถึงคิดว่ามันทำแบบนี้? (ลองคิดดูว่าจะต้องเกิดอะไรขึ้นเมื่อรายการตกหน้าผา…)

ขั้นตอนที่ 5: บทสรุป

ถ้ามาไกลขนาดนี้ก็ยินดีด้วย! ตอนนี้คุณสามารถเขียนโค้ดแอสเซมบลี ประกอบ และโหลดลงในไมโครคอนโทรลเลอร์ของคุณ

ในบทช่วยสอนนี้ คุณได้เรียนรู้วิธีใช้คำสั่งต่อไปนี้:

ldi hregister หมายเลขโหลดตัวเลข (0-255) ลงในทะเบียนครึ่งบน (16-31)

ออก ioregister, register คัดลอกหมายเลขจากทะเบียนทำงานไปยังเครื่องบันทึก I/O

ฉลาก rjmp ข้ามไปที่บรรทัดของโปรแกรมที่ติดป้ายกำกับว่า "ป้ายกำกับ" (ซึ่งอยู่ห่างออกไปไม่เกิน 204 คำสั่ง - นั่นคือการกระโดดแบบสัมพัทธ์)

ตอนนี้พื้นฐานเหล่านี้กำลังจะหมดหนทางแล้ว เราสามารถเขียนโค้ดที่น่าสนใจและวงจรและอุปกรณ์ที่น่าสนใจมากขึ้นต่อไปโดยไม่ต้องพูดถึงกลไกของการคอมไพล์และการอัปโหลด

ฉันหวังว่าคุณจะสนุกกับการกวดวิชาเบื้องต้นนี้ ในบทช่วยสอนถัดไป เราจะเพิ่มส่วนประกอบวงจรอื่น (ปุ่ม) และขยายโค้ดของเราเพื่อรวมพอร์ตอินพุตและการตัดสินใจ

แนะนำ: