Სარჩევი:

AVR Assembler Tutorial 3: 9 ნაბიჯი
AVR Assembler Tutorial 3: 9 ნაბიჯი

ვიდეო: AVR Assembler Tutorial 3: 9 ნაბიჯი

ვიდეო: AVR Assembler Tutorial 3: 9 ნაბიჯი
ვიდეო: AVR Ассемблер. Урок 3. Таймер. Мигалка на таймере. AVR Assembler. Lesson 3. Timer. 2024, ივლისი
Anonim
AVR Assembler Tutorial 3
AVR Assembler Tutorial 3

მოგესალმებით სამეურვეო ნომერი 3!

სანამ დავიწყებდეთ მინდა ფილოსოფიური აზრი გავაკეთო. ნუ შეგეშინდებათ ექსპერიმენტების ჩატარება იმ სქემებთან და კოდთან, რომელსაც ჩვენ ვაშენებთ ამ გაკვეთილებში. შეცვალეთ მავთულები გარშემო, დაამატეთ ახალი კომპონენტები, ამოიღეთ კომპონენტები, შეცვალეთ კოდის ხაზები, დაამატეთ ახალი ხაზები, წაშალეთ ხაზები და ნახეთ რა მოხდება! ძალიან ძნელია რამის გატეხვა და თუ აკეთებ, ვის აინტერესებს? არაფერი, რასაც ჩვენ ვიყენებთ, მიკროკონტროლერის ჩათვლით, არ არის ძალიან ძვირი და ყოველთვის საგანმანათლებლო არის იმის დანახვა, თუ როგორ შეიძლება ყველაფერი ჩავარდეს. თქვენ არა მხოლოდ გაარკვევთ, რა არ უნდა გააკეთოთ შემდეგ ჯერზე, არამედ, რაც მთავარია, თქვენ გეცოდინებათ, რატომ არ უნდა გააკეთოთ ეს. თუ თქვენ ჩემნაირი ხართ, როდესაც ბავშვობაში იყავით და ახალი სათამაშო აიღეთ, დიდი დრო არ იყო გასული, რაც ნაჭრებად დაინახავდით, რა იყო ეს სწორი? ზოგჯერ სათამაშო გამოუსწორებლად დაზიანდა, მაგრამ დიდი არაფერი. ნება მიეცით ბავშვს შეისწავლოს თავისი ცნობისმოყვარეობა გატეხილი სათამაშოების ჩათვლით, რაც მას ჭურჭლის სარეცხის მაგივრად მეცნიერად ან ინჟინრად აქცევს.

დღეს ჩვენ ვაპირებთ ძალიან მარტივი წრის გაყვანილობას და შემდეგ ცოტათი შევეხებით თეორიას. ბოდიში ამის გამო, მაგრამ ჩვენ გვჭირდება ინსტრუმენტები! მე გპირდებით, რომ ჩვენ ამას გამოვასწორებთ მე –4 სამეურვეოში, სადაც ჩვენ გავაკეთებთ უფრო სერიოზულ წრიულ შენობას და შედეგი იქნება საკმაოდ მაგარი. თუმცა, ის, რაც თქვენ გჭირდებათ ყველა ამ გაკვეთილის გასაკეთებლად, არის ძალიან ნელი, ჭვრეტადი გზით. თუ თქვენ უბრალოდ ხვდებით, ააშენებთ წრეს, დააკოპირეთ და ჩასვით კოდი და გაუშვით მაშინ, რა თქმა უნდა, ის იმუშავებს, მაგრამ თქვენ ვერაფერს ისწავლით. თქვენ უნდა იფიქროთ თითოეულ ხაზზე. პაუზა. Ექსპერიმენტი. გამოგონება. თუ ასე მოიქეცით, მე –5 სამეურვეოს ბოლოს თქვენ არ შექმნით მაგარ ნივთებს და აღარ გჭირდებათ სწავლება. წინააღმდეგ შემთხვევაში თქვენ უბრალოდ უყურებთ ვიდრე სწავლობთ და ქმნით.

ნებისმიერ შემთხვევაში, საკმარისი ფილოსოფია, დავიწყოთ!

ამ გაკვეთილში დაგჭირდებათ:

  1. თქვენი პროტოტიპის დაფა
  2. LED
  3. დამაკავშირებელი მავთულები
  4. რეზისტორი 220 -დან 330 Ohms– მდე
  5. ინსტრუქციის ნაკრები სახელმძღვანელო: www.atmel.com/images/atmel-0856-avr-instruction-se…
  6. მონაცემთა ცხრილი: www.atmel.com/images/Atmel-8271-8-bit-AVR-Microco…
  7. განსხვავებული ბროლის ოსცილატორი (სურვილისამებრ)

აქ არის ბმული გაკვეთილების სრული კოლექციისთვის:

ნაბიჯი 1: წრის აგება

სქემის აგება
სქემის აგება

ამ გაკვეთილის წრე ძალიან მარტივია. ჩვენ არსებითად ვაპირებთ დავწეროთ "დახუჭვის" პროგრამა, ასე რომ ყველაფერი რაც ჩვენ გვჭირდება არის შემდეგი.

შეაერთეთ LED PD4– ზე, შემდეგ 330 ohm რეზისტორზე, შემდეგ კი ადგილზე. ე.ი.

PD4 - LED - R (330) - GND

და ეს არის ის!

თეორია იქნება რთული დამამცირებელი, თუმცა…

ნაბიჯი 2: რატომ გვჭირდება კომენტარები და M328Pdef.inc ფაილი?

მე ვფიქრობ, რომ ჩვენ უნდა დავიწყოთ იმის ჩვენებით, თუ რატომ არის გამოსაყენებელი ფაილი და კომენტარები სასარგებლო. არცერთი მათგანი არ არის საჭირო და თქვენ შეგიძლიათ ჩაწეროთ, ააწყოთ და ატვირთოთ კოდი მათ გარეშე და ის მშვენივრად იმუშავებს (თუმცა ჩართული ფაილის გარეშე შეიძლება მიიღოთ საჩივარი ასამბლეისგან - მაგრამ შეცდომები არ არის)

აქ არის კოდი, რომლის დაწერასაც ჩვენ ვაპირებთ დღეს, გარდა იმისა, რომ მე ამოვიღე კომენტარები და ჩართული ფაილი:

. მოწყობილობა ATmega328P

.org 0x0000 jmp a.org 0x0020 jmp ea: ldi r16, 0x05 out 0x25, r16 ldi r16, 0x01 sts 0x6e, r16 sei clr r16 out 0x26, r16 sbi 0x0a, 0x04 sbi 0x0b, 0x04 b: sbi 0x0b cbi 0x0b, 0x04 rcall c rjmp bc: clr r17 d: cpi r17, 0x1e brne d ret e: inc r17 cpi r17, 0x3d brne PC+2 clr r17 reti

საკმაოდ მარტივია არა? Ჰაჰა. თუ თქვენ ააწყობთ და ატვირთავთ ამ ფაილს, თქვენ გამოიწვევთ LED- ის მოციმციმე სიჩქარეს 1 მოციმციმე წამში, ხოლო მოციმციმე გრძელდება 1/2 წამს და პაუზას დახუჭვას შორის 1/2 წამი.

თუმცა, ამ კოდის ყურება ძნელად გასაგებია. თუ თქვენ დაწერდით ასე კოდს თქვენ გინდოდათ შეცვალოთ იგი ან გამოიყენოთ იგი მომავალში, გაგიჭირდებათ.

მოდით, ჩავდოთ კომენტარები და ჩავრთოთ ფაილი ისევ ისე, რომ ჩვენ გვექნება აზრი.

ნაბიჯი 3: დახუჭე.აზმი

აქ არის კოდი, რომელზეც დღეს ვისაუბრებთ:

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

; დაწერილი: 1o_o7; თარიღი: ვერსია: 1.0; ფაილი შენახულია როგორც: blink.asm; AVR– ისთვის: atmega328p; საათის სიხშირე: 16 MHz (სურვილისამებრ); ***********************************; პროგრამის ფუნქცია: ---------------------; ითვლის წამებს LED მოციმციმედ;; PD4 - LED - R (330 ohm) - GND;; --------------------------------------.. სია; ===============; დეკლარაციები:.def temp = r16.def overflows = r17.org 0x0000; მეხსიერების (კომპიუტერის) მდებარეობა გადატვირთვის დამმუშავებლის rjmp გადატვირთვა; jmp ღირს 2 cpu ციკლი და rjmp ღირს მხოლოდ 1; ასე რომ, თუ თქვენ არ გჭირდებათ 8k ბაიტზე მეტის გადახტომა; თქვენ მხოლოდ rjmp გჭირდებათ. ამიტომ ზოგიერთი მიკროკონტროლი მხოლოდ; აქვს rjmp და არა jmp.org 0x0020; მეხსიერების მდებარეობა Timer0 overflow handler rjmp overflow_handler; წადი აქ, თუ მოხდა ტაიმერის 0 გადავსების შეწყვეტა; ============ გადატვირთვა: ldi temp, 0b00000101 out TCCR0B, temp; დააყენეთ საათის ამომრჩევი ბიტი CS00, CS01, CS02 101; ეს აყენებს ტაიმერს Counter0, TCNT0 FCPU/1024 რეჟიმში; ასე რომ ის იწვის CPU freq/1024 ldi temp, 0b00000001 sts TIMSK0, temp; დააყენეთ Timer Overflow Interrupt Enable (TOIE0) ბიტი; ტაიმერის შეწყვეტის ნიღბის რეგისტრაციის (TIMSK0) sei; გლობალური შეფერხებების ჩართვა - ექვივალენტი "sbi SREG, I" clr temp out TCNT0, temp; ტაიმერის/მრიცხველის ინიციალიზაცია 0 sbi DDRD, 4; დააყენეთ PD4 გამომავალზე; ====================== პროგრამის ძირითადი ნაწილი: მოციმციმე: sbi PORTD, 4; ჩართეთ LED PD4 rcall დაგვიანებით; შეფერხება იქნება 1/2 წამი cbi PORTD, 4; გამორთეთ LED PD4 rcall დაგვიანებით; შეფერხება იქნება 1/2 წამის rjmp მოციმციმე; მარყუჟი უკან დაწყების დაგვიანებით: clr overflows; დააყენეთ overflows 0 sec_count: cpi overflows, 30; შეადარეთ გადინების რაოდენობა და 30 brne sec_count; ფილიალი რომ დაბრუნდეს sec_count– ზე, თუ არა თანაბარი ret; თუ 30 გადინება მოხდა დაბრუნების მოციმციმე overflow_handler: inc overflows; დაამატეთ 1 overflows ცვლადი cpi overflows, 61; შეადარეთ 61 brne PC+2; პროგრამის მრიცხველი +2 (გამოტოვეთ შემდეგი სტრიქონი) თუ არ არის თანაბარი clr overflows; თუ მოხდა 61 გადინება მრიცხველი გადააყენეთ ნულოვან რეტიზე; შეფერხებიდან დაბრუნება

როგორც ხედავთ, ჩემი კომენტარები ახლა უფრო მოკლეა. მას შემდეგ რაც ჩვენ ვიცით რა ბრძანებები ინსტრუქციის ნაკრებში არ გვჭირდება ამის ახსნა კომენტარებში. ჩვენ მხოლოდ უნდა ავუხსნათ რა ხდება პროგრამის თვალსაზრისით.

ჩვენ განვიხილავთ რას აკეთებს ეს ყველაფერი ნაწილებად, მაგრამ ჯერ შევეცადოთ გლობალური პერსპექტივის მიღებას. პროგრამის ძირითადი ნაწილი შემდეგნაირად მუშაობს.

პირველი ჩვენ დავაყენეთ PORTD- ის ბიტი 4 "sbi PORTD, 4" ეს აგზავნის 1 -ს PD4- ზე, რომელიც ამძიმებს ძაბვას 5V- მდე. ეს ჩართავს LED- ს. შემდეგ ჩვენ გადავდივართ "დაგვიანების" ქვეპროგრამზე, რომელიც ითვლის 1/2 წამს (ჩვენ ავუხსნით, როგორ აკეთებს ამას მოგვიანებით). შემდეგ ჩვენ ვუბრუნდებით მოციმციმე და გასუფთავებულ 4 -ს PORTD– ზე, რომელიც PD4– ს აყენებს 0V– მდე და, შესაბამისად, გამორთავს LED- ს. შემდეგ ჩვენ ვაყოვნებთ კიდევ 1/2 წამს, შემდეგ კი ისევ ხტუნვის დასაწყისს ვუბრუნდებით "rjmp blink".

თქვენ უნდა გაუშვათ ეს კოდი და ნახოთ რომ ის აკეთებს იმას რაც უნდა.

და აი თქვენ გაქვთ! ეს არის ის, რასაც ეს კოდი აკეთებს ფიზიკურად. შიდა მექანიკა, რასაც მიკროკონტროლერი აკეთებს, უფრო მეტად არის ჩართული და ამიტომაც ვაკეთებთ ამ გაკვეთილს. მოდით განვიხილოთ თითოეული ნაწილი თავის მხრივ.

ნაბიჯი 4:.org Assembler დირექტივები

ჩვენ უკვე ვიცით რას აკეთებს.nolist,.list,.include და.def ასამბლეის დირექტივები ჩვენი წინა გაკვეთილებიდან, ასე რომ, მოდით, ჯერ გადავხედოთ კოდის 4 სტრიქონს, რომელიც მოდის ამის შემდეგ:

.org 0x0000

jmp გადატვირთვა.org 0x0020 jmp overflow_handler

. Org განცხადება ეუბნება შემკრებელს, თუ სად არის "პროგრამის მეხსიერებაში" მოთავსებული შემდეგი განცხადება. თქვენი პროგრამის შესრულებისას, "პროგრამის მრიცხველი" (შეწყვეტილია როგორც კომპიუტერი) შეიცავს მიმდინარე ხაზის მისამართს. ამ შემთხვევაში, როდესაც კომპიუტერი არის 0x0000, ის დაინახავს ბრძანებას "jmp Reset", რომელიც მდებარეობს ამ მეხსიერების ადგილას. მიზეზი, რის გამოც ჩვენ გვსურს jmp Reset- ის დაყენება ამ ადგილას არის ის, რომ როდესაც პროგრამა იწყება, ან ჩიპი გადატვირთულია, კომპიუტერი იწყებს კოდის შესრულებას ამ ადგილას. ასე რომ, როგორც ვხედავთ, ჩვენ უბრალოდ ვუთხარით, რომ დაუყოვნებლივ "გადახტომა" იმ განყოფილებაში, სახელწოდებით "გადატვირთვა". რატომ გავაკეთეთ ეს? ეს ნიშნავს, რომ ზემოთ ბოლო ორი სტრიქონი უბრალოდ გამოტოვებულია! რატომ?

კარგი, სწორედ აქ ხდება ყველაფერი საინტერესო. ახლა თქვენ უნდა გახსნათ pdf მნახველი სრული ATmega328p მონაცემთა ცხრილით, რომელზეც მე აღვნიშნე ამ გაკვეთილის პირველ გვერდზე (სწორედ ამიტომ არის პუნქტი 4 "თქვენ დაგჭირდებათ" განყოფილებაში). თუ თქვენი ეკრანი ძალიან პატარაა, ან უკვე ძალიან ბევრი ფანჯარა გაქვთ გახსნილი (როგორც ეს ჩემთანაა), თქვენ შეგიძლიათ გააკეთოთ ის, რასაც მე ვაკეთებ და განათავსოთ იგი Ereader– ზე, ან თქვენს Android ტელეფონზე. თქვენ მას ყოველთვის გამოიყენებთ, თუ აპირებთ ასამბლეის კოდის წერას. ყველაზე მაგარი ის არის, რომ ყველა მიკროკონტროლი ორგანიზებულია ძალიან მსგავსი გზით და ასე რომ, როდესაც შეეგუებით მონაცემთა ფურცლების კითხვას და მათგან კოდირებას, თითქმის უმნიშვნელო იქნება იგივე გააკეთოთ სხვადასხვა მიკროკონტროლერისთვის. ჩვენ ვსწავლობთ როგორ გამოვიყენოთ ყველა მიკროკონტროლერი გარკვეული გაგებით და არა მხოლოდ atmega328p.

კარგი, გადადით მონაცემთა ცხრილში მე -18 გვერდზე და გადახედეთ ფიგურას 8-2.

ასე ხდება მიკროკონტროლერის პროგრამის მეხსიერების დაყენება. თქვენ ხედავთ, რომ ის იწყება 0x0000 მისამართით და იყოფა ორ ნაწილად; პროგრამის ფლეშ განყოფილება და ჩატვირთვის ფლეშ განყოფილება. თუ მოკლედ მიმართავთ 277 – ე ცხრილს 27-14, ნახავთ, რომ პროგრამის ფლეშ განყოფილება იკავებს ადგილებს 0x0000– დან 0x37FF– მდე და ჩამტვირთავი ფლეშ განყოფილება იკავებს დანარჩენ ადგილებს 0x3800– დან 0x3FFF– მდე.

სავარჯიშო 1: რამდენი ლოკაციაა პროგრამის მეხსიერებაში? ანუ გადააკეთეთ 3FFF ათწილადში და დაამატეთ 1 მას შემდეგ, რაც ჩვენ ვიწყებთ ათვლას 0 – ზე. ვინაიდან მეხსიერების თითოეული მდებარეობა 16 ბიტის (ან 2 ბაიტის) სიგანისაა, რა არის მეხსიერების ბაიტების საერთო რაოდენობა? ახლა გადააკეთეთ ეს კილობაიტად, გახსოვდეთ, რომ კილოიბაიტში არის 2^10 = 1024 ბაიტი. ჩატვირთვის ფლეშ განყოფილება მიდის 0x3800– დან 0x37FF– მდე, რამდენი კილობაიტია ეს? რამდენი კილობაიტი მეხსიერება რჩება ჩვენთვის, რომ გამოვიყენოთ ჩვენი პროგრამის შესანახად? სხვა სიტყვებით რომ ვთქვათ, რამდენად დიდი შეიძლება იყოს ჩვენი პროგრამა? დაბოლოს, რამდენი სტრიქონი შეგვიძლია გვქონდეს?

კარგი, ახლა, როდესაც ჩვენ ყველაფერი ვიცით ფლეშ პროგრამის მეხსიერების ორგანიზაციის შესახებ, გავაგრძელოთ.org განცხადებების განხილვა. ჩვენ ვხედავთ, რომ მეხსიერების პირველი ადგილმდებარეობა 0x0000 შეიცავს ჩვენს ინსტრუქციას გადავიდეთ ჩვენს განყოფილებაში, რომელსაც აღნიშვნა აქვს გადატვირთვა. ახლა ჩვენ ვხედავთ რას აკეთებს ".org 0x0020" განცხადება. მასში ნათქვამია, რომ ჩვენ გვსურს, რომ ინსტრუქცია მომდევნო ხაზზე განთავსდეს მეხსიერების ადგილას 0x0020. ჩვენ მიერ განთავსებული ინსტრუქცია არის გადახტომა ჩვენს კოდის იმ მონაკვეთზე, რომელსაც ჩვენ ვუწოდებთ "overflow_handler" … ახლა რატომ ვითხოვთ, რომ ეს ნახტომი განთავსდეს მეხსიერების ადგილას 0x0020? ამის გასარკვევად, ჩვენ გადავდივართ 65 – ე გვერდზე მონაცემთა ცხრილში და გადავხედავთ ცხრილს 12–6.

ცხრილი 12-6 არის "გადატვირთვისა და შეწყვეტის ვექტორების" ცხრილი და ის ზუსტად აჩვენებს სად წავა კომპიუტერი როდესაც მიიღებს "შეწყვეტას". მაგალითად, თუ გადახედავთ ვექტორ ნომერს 1. შეწყვეტის "წყარო" არის "RESET", რომელიც განმარტებულია როგორც "External Pin, Power-on Reset, Brown-out Reset and Watchdog system reset" მნიშვნელობა, თუ რომელიმე ეს ხდება ჩვენს მიკროკონტროლერთან, კომპიუტერი დაიწყებს ჩვენი პროგრამის შესრულებას პროგრამის მეხსიერების ადგილას 0x0000. რაც შეეხება ჩვენს.org დირექტივას მაშინ? კარგად, ჩვენ განათავსეთ ბრძანება მეხსიერების ადგილას 0x0020 და თუ დააკვირდებით ცხრილს დაინახავთ, რომ თუ მოხდება ტაიმერის/მრიცხველის გადატვირთვა (მოდის TIMER0 OVF– დან) ის შეასრულებს რასაც არის 0x0020 ადგილას. ასე რომ, როდესაც ეს მოხდება, კომპიუტერი გადავა იმ ადგილას, სადაც ჩვენ შეაფასეთ "overflow_handler". მაგარია არა? ერთ წუთში ნახავთ, რატომ გავაკეთეთ ეს, მაგრამ ჯერ დავასრულოთ სამეურვეო პროგრამის ეს ნაბიჯი განზე.

თუ გვინდა, რომ ჩვენი კოდი უფრო მოწესრიგებული და მოწესრიგებული იყოს, ჩვენ ნამდვილად უნდა შევცვალოთ 4 სტრიქონი, რომელსაც ამჟამად განვიხილავთ შემდეგში (იხ. გვერდი 66):

.org 0x0000

rjmp გადატვირთვა; PC = 0x0000 reti; PC = 0x0002 reti; PC = 0x0004 reti; PC = 0x0006 reti; PC = 0x0008 reti; PC = 0x000A… reti; PC = 0x001E jmp overflow_handler: PC = 0x0020 reti: PC = 0x0022… reti; PC = 0x0030 reti; კომპიუტერი = 0x0032

ასე რომ, თუ მოცემული შეფერხება მოხდება, ის უბრალოდ "reti" იქნება, რაც ნიშნავს "შეწყვეტიდან დაბრუნებას" და სხვა არაფერი ხდება. მაგრამ თუ ჩვენ არასოდეს "გავააქტიურებთ" ამ სხვადასხვა შეფერხებებს, მაშინ ისინი არ იქნება გამოყენებული და ჩვენ შეგვიძლია პროგრამის კოდი ამ წერტილებში ჩავდოთ. ჩვენს ამჟამინდელ "blink.asm" პროგრამაში ჩვენ ვაპირებთ მხოლოდ ტაიმერის 0 გადატვირთვის შეწყვეტის ჩართვას (და რა თქმა უნდა გადატვირთვის შეწყვეტა, რომელიც ყოველთვის ჩართულია) და ამიტომაც არ შევაწუხებთ სხვებს.

შემდეგ როგორ "გავააქტიუროთ" ტაიმერის 0 გადავსების შეწყვეტა? … ეს არის ჩვენი გაკვეთილის შემდეგი ნაბიჯის საგანი.

ნაბიჯი 5: ტაიმერი/მრიცხველი 0

ტაიმერი/მრიცხველი 0
ტაიმერი/მრიცხველი 0

შეხედეთ ზემოთ მოცემულ სურათს. ეს არის "კომპიუტერის" გადაწყვეტილების მიღების პროცესი, როდესაც გარეგანი გავლენა "წყვეტს" ჩვენი პროგრამის ნაკადს. პირველი რასაც აკეთებს, როდესაც იღებს სიგნალს გარედან, რომ შეფერხება მოხდა არის ის, რომ ამოწმებს, გვაქვს თუ არა მითითებული "შეწყვეტის ჩართვის" ბიტი ამ ტიპის შეწყვეტისთვის. თუ ჩვენ არ გვაქვს, მაშინ ის უბრალოდ აგრძელებს ჩვენი შემდეგი კოდის ხაზის შესრულებას. თუ ჩვენ დავაყენებთ ამ კონკრეტული შეწყვეტის ჩართვის ბიტს (ისე, რომ ამ ბიტის ადგილას არის 1 ნაცვლად 0), ის შეამოწმებს ჩართული გვაქვს თუ არა "გლობალური შეფერხებები", თუ არა, ის კვლავ გადავა შემდეგ სტრიქონზე კოდი და გააგრძელე. თუ ჩვენ გლობალური შეფერხებებიც გვაქვს ჩართული, მაშინ ის გადავა ამ ტიპის შეფერხების პროგრამის მეხსიერებაში (როგორც ეს მოცემულია ცხრილში 12-6) და შეასრულებს ნებისმიერ ბრძანებას, რომელიც ჩვენ იქ ჩავსვით. მოდით ვნახოთ, როგორ განვახორციელეთ ეს ყველაფერი ჩვენს კოდში.

ჩვენი კოდის ეტიკეტირებული გადატვირთვა იწყება შემდეგი ორი ხაზით:

გადატვირთვა:

ldi ტემპერატურა, 0b00000101 out TCCR0B, ტემპერატურა

როგორც უკვე ვიცით, ეს იტვირთება დროებითი (ანუ R16) რიცხვი, რომელიც მომდევნოა, რომელიც არის 0b00000101. შემდეგ ის წერს ამ ნომერს რეესტრში სახელწოდებით TCCR0B "out" ბრძანების გამოყენებით. რა არის ეს რეგისტრი? მოდით გადავიდეთ მონაცემთა ცხრილის 614 გვერდზე. ეს არის ცხრილის შუაში, რომელიც აჯამებს ყველა რეგისტრს. მისამართზე 0x25 თქვენ ნახავთ TCCR0B. (ახლა თქვენ იცით საიდან გაჩნდა ხაზი "0x25, r16" კოდის ჩემს დაუკომენტარებელ ვერსიაში). ჩვენ ვხედავთ ზემოთ კოდის სეგმენტს, რომ ჩვენ დავაყენეთ მე -0 ბიტი და მე -2 ბიტი და გავწმინდეთ ყველა დანარჩენი. ცხრილის დათვალიერებისას ხედავთ, რომ ეს ნიშნავს, რომ ჩვენ დავაყენეთ CS00 და CS02. ახლა მოდით გადავიდეთ მონაცემთა ცხრილის თავში, სახელწოდებით "8 ბიტიანი ქრონომეტრი/მრიცხველი 0 PWM- ით". კერძოდ, გადადით იმ თავის 107 გვერდზე. თქვენ იხილავთ "ქრონომეტრის/მრიცხველის კონტროლის რეესტრის B" (TCCR0B) რეგისტრის ერთსა და იმავე აღწერას, რაც ჩვენ ვნახეთ რეესტრის შემაჯამებელ ცხრილში (ასე რომ ჩვენ შეგვეძლო პირდაპირ აქ მოსვლა, მაგრამ მე მინდოდა თქვენ გენახათ, თუ როგორ გამოვიყენოთ შემაჯამებელი ცხრილები მომავალი მითითებისთვის). მონაცემთა ცხრილი აგრძელებს ამ რეგისტრის თითოეული ბიტის აღწერას და რას აკეთებს ისინი. ჩვენ ახლა გამოვტოვებთ ამ ყველაფერს და გვერდზე გადავიყვანთ ცხრილში 15-9. ეს ცხრილი აჩვენებს "საათის არჩევის ბიტის აღწერა". ახლა გადახედეთ ქვემოთ ცხრილს, სანამ არ იპოვით იმ ხაზს, რომელიც შეესაბამება ბიტებს, რომლებიც ჩვენ უბრალოდ დავადგინეთ ამ რეესტრში. ხაზში ნათქვამია "clk/1024 (წინასწარი გამყიდველიდან)". ეს ნიშნავს იმას, რომ ჩვენ გვსურს ტაიმერი/მრიცხველი 0 (TCNT0) მონიშნოს იმ სიჩქარით, რაც არის პროცესორის სიხშირე გაყოფილი 1024 -ზე. ვინაიდან ჩვენ გვაქვს ჩვენი მიკროკონტროლერი, რომელიც იკვებება 16 მჰც ბროლის ოსცილატორით, ეს ნიშნავს, რომ ჩვენი CPU ასრულებს მითითებებს წამში 16 მილიონი ინსტრუქცია. ასე რომ, ჩვენი TCNT0 მრიცხველის მაჩვენებელი არის 16 მილიონი/1024 = 15625 ჯერ წამში (სცადეთ სხვადასხვა საათის შერჩევით ბიტებით და ნახეთ რა მოხდება - გახსოვთ ჩვენი ფილოსოფია?). მოდით შევინარჩუნოთ რიცხვი 15625 გონების უკანა ნაწილში და გადავიდეთ კოდის შემდეგ ორ სტრიქონზე:

ldi ტემპერატურა, 0b00000001

ქ. TIMSK0, ტემპ

ეს ადგენს რეგისტრის მე -0 ბიტს, სახელწოდებით TIMSK0 და ასუფთავებს ყველა დანარჩენს. თუ გადახედავთ მონაცემთა 109 გვერდზე, ნახავთ, რომ TIMSK0 ნიშნავს "ტაიმერს/მრიცხველის შეწყვეტის ნიღბის რეგისტრაციას 0" და ჩვენს კოდს აქვს მითითებული მე -0 ბიტი, სახელწოდებით TOIE0, რაც ნიშნავს "ტაიმერს/Counter0 Overflow Interrupt Enable" … იქ! ახლა თქვენ ხედავთ, რა არის ეს ყველაფერი. ჩვენ ახლა გვაქვს "შეწყვეტის ჩართვის ბიტის ნაკრები", როგორც გვინდოდა ჩვენი სურათის პირველი გადაწყვეტილებიდან ზედა. ასე რომ, ახლა ჩვენ მხოლოდ უნდა გავაკეთოთ "გლობალური შეფერხებების" ჩართვა და ჩვენი პროგრამა შეძლებს რეაგირება მოახდინოს ამ ტიპის შეფერხებებზე. ჩვენ მალე შევძლებთ გლობალური შეფერხებების გააქტიურებას, მაგრამ სანამ ჩვენ ამას გავაკეთებთ, თქვენ შეიძლება რაღაცამ შეგაწუხოთ.. რატომ გამოვიყენე ბრძანება "sts" TIMSK0 რეგისტრში ჩვეულებრივი "out" - ის ნაცვლად?

როდესაც დამინახავთ, ვიყენებ ინსტრუქციას, რომელიც აქამდე არ გინახავთ, პირველი რაც უნდა გააკეთოთ არის გადახვიდეთ 616 გვერდზე, მონაცემთა ცხრილში. ეს არის "ინსტრუქციის ნაკრების შეჯამება". ახლა იპოვნეთ ინსტრუქცია "STS", რომელიც მე გამოვიყენე. ნათქვამია, რომ ის იღებს ნომერს R რეგისტრიდან (ჩვენ გამოვიყენეთ R16) და "პირდაპირ მაღაზიაში SRAM" მდებარეობა k (ჩვენს შემთხვევაში მოცემულია TIMSK0). მაშ, რატომ უნდა გამოვიყენოთ "sts", რომელსაც სჭირდება 2 საათის ციკლი (იხ. ცხრილის ბოლო სვეტი) შესანახად TIMSK0- ში და ჩვენ გვჭირდებოდა მხოლოდ "out", რომელსაც მხოლოდ ერთი საათის ციკლი სჭირდება, TCCR0B- ში შესანახად? ამ კითხვაზე პასუხის გასაცემად ჩვენ უნდა დავუბრუნდეთ ჩვენს რეგისტრატორთა შემაჯამებელ ცხრილს 614 გვერდზე. ხედავთ, რომ TCCR0B რეგისტრი მდებარეობს 0x25 მისამართზე, მაგრამ ასევე (0x45) არა? ეს ნიშნავს, რომ ეს არის რეგისტრი SRAM– ში, მაგრამ ის ასევე არის გარკვეული ტიპის რეგისტრი, რომელსაც ეწოდება „პორტი“(ან i/o რეგისტრი). თუ გადახედავთ ინსტრუქციის შემაჯამებელ ცხრილს "out" ბრძანების გვერდით, დაინახავთ, რომ ის იღებს ღირებულებებს "სამუშაო რეგისტრებიდან", როგორიცაა R16 და აგზავნის მათ პორტში. ასე რომ, ჩვენ შეგვიძლია გამოვიყენოთ "out" TCCR0B- ზე წერისას და შევინახოთ საათის ციკლი. ახლა კი მოძებნეთ TIMSK0 რეგისტრაციის ცხრილში. ხედავთ, რომ მას აქვს მისამართი 0x6e. ეს არის პორტების დიაპაზონის მიღმა (რომლებიც SRAM– ის მხოლოდ პირველი 0x3F ადგილებია) და ასე რომ თქვენ უნდა დაუბრუნდეთ sts ბრძანების გამოყენებას და ამის გაკეთება CPU– ს ორი საათის ციკლს. გთხოვთ წაიკითხოთ შენიშვნა 4 ინსტრუქციის შემაჯამებელი ცხრილის ბოლოს 615 გვერდზე ახლავე. ასევე გაითვალისწინეთ, რომ ყველა ჩვენი შემავალი და გამომავალი პორტი, როგორიცაა PORTD, მდებარეობს ცხრილის ბოლოში. მაგალითად, PD4 არის ბიტი 4 მისამართი 0x0b (ახლა ხედავთ საიდან მოვიდა ყველა 0x0b მასალა ჩემს დაუკომენტარებელ კოდში!).. კარგი, სწრაფი შეკითხვა: თქვენ შეცვალეთ "სტ" "გარეთ" და ნახეთ რა ხდება? დაიმახსოვრეთ ჩვენი ფილოსოფია! გატეხე! ნუ მიიღებ ჩემს სიტყვას რამეზე.

კარგი, სანამ გავაგრძელებდით, გადადით მონაცემთა გვერდზე 19 წუთის განმავლობაში. თქვენ ხედავთ მონაცემთა მეხსიერების სურათს (SRAM). SRAM– ში პირველი 32 რეგისტრი (0x0000– დან 0x001F– მდე) არის „ზოგადი დანიშნულების სამუშაო რეგისტრები“R0– დან R31– მდე, რომელსაც ჩვენ ყოველთვის ვიყენებთ, როგორც ცვლადები ჩვენს კოდში.მომდევნო 64 რეგისტრი არის I/O პორტები 0x005f- მდე (ანუ ის, რაზეც ჩვენ ვსაუბრობდით, მათ აქვთ რეგისტრაციის ცხრილში მითითებული არა-დახაზული მისამართები, რომლებიც შეგვიძლია გამოვიყენოთ "out" ბრძანების ნაცვლად "sts") SRAM– ის შემდეგი ნაწილი შეიცავს ყველა სხვა რეგისტრს შემაჯამებელ ცხრილში 0x00FF მისამართამდე, და ბოლოს დანარჩენი არის შიდა SRAM. ახლა სწრაფად, წამით გადავიდეთ მე -12 გვერდზე. აქ ხედავთ "ზოგადი დანიშნულების სამუშაო რეგისტრების" ცხრილს, რომელსაც ჩვენ ყოველთვის ვიყენებთ ჩვენს ცვლადებად. ხედავთ სქელ ხაზს რიცხვებს შორის R0 to R15 და შემდეგ R16 to R31? ეს ხაზი არის ის, რის გამოც ჩვენ ყოველთვის ვიყენებთ R16- ს, როგორც ყველაზე პატარას და მე მას უფრო მეტად შევეხები შემდეგ გაკვეთილში, სადაც ასევე დაგვჭირდება სამი 16 ბიტიანი არაპირდაპირი მისამართების რეგისტრატორი, X, Y და Z. მე არ ჩაერთეთ ამაში, თუმცა ჩვენ მას ახლა არ ვჭირდებით და საკმარისად ვიძირებით აქ.

გადაატრიალეთ ერთი გვერდი მონაცემთა ცხრილის 11 გვერდზე. თქვენ ნახავთ SREG რეგისტრის დიაგრამას ზედა მარჯვნივ? თქვენ ხედავთ, რომ იმ რეგისტრის ბიტ 7 -ს ჰქვია "მე". ახლა გადადით გვერდზე და წაიკითხეთ ბიტ 7 -ის აღწერა… კაი ეს არის გლობალური შეფერხების ჩართვის ბიტი. ეს არის ის, რაც ჩვენ უნდა დავადგინოთ იმისათვის, რომ გავიაროთ მეორე გადაწყვეტილება ჩვენს ზემოთ მოცემულ დიაგრამაზე და დავუშვათ ტაიმერის/მრიცხველის გადინება ჩვენს პროგრამაში. ასე რომ, ჩვენი პროგრამის შემდეგი სტრიქონი უნდა წაიკითხოს:

sbi SREG, ი

რომელიც ადგენს ბიტს სახელწოდებით "I" SREG რეესტრში. თუმცა, ამის ნაცვლად ჩვენ გამოვიყენეთ ინსტრუქცია

სეი

სამაგიეროდ. ეს ბიტი იმდენად ხშირად არის დაყენებული პროგრამებში, რომ მათ უბრალოდ გააკეთეს ამის მარტივი გზა.

Კარგი! ახლა ჩვენ გვაქვს გადავსების შეფერხებები, რომ ჩვენი "jmp overflow_handler" შესრულდეს, როდესაც ეს მოხდება.

სანამ გავაგრძელებდით, გადახედეთ SREG რეგისტრს (სტატუსის რეგისტრაცია), რადგან ის ძალიან მნიშვნელოვანია. წაიკითხეთ რას წარმოადგენს თითოეული დროშა. კერძოდ, ბევრი ინსტრუქცია, რომელსაც ჩვენ ვიყენებთ, დაადგენს და ამოწმებს ამ დროშებს ყოველთვის. მაგალითად, მოგვიანებით ჩვენ ვიყენებთ ბრძანებას "CPI", რაც ნიშნავს "შეადარეთ დაუყოვნებლივ". გადახედეთ ამ ინსტრუქციის ინსტრუქციის შემაჯამებელ ცხრილს და შენიშნეთ რამდენ დროშს აწესებს იგი "დროშების" სვეტში. ეს ყველაფერი დროშებია SREG– ში და ჩვენი კოდი იქნება მათი დაყენება და მათი მუდმივი შემოწმება. მაგალითებს მალე ნახავთ. დაბოლოს, კოდის ამ ნაწილის ბოლო ნაწილი არის:

clr ტემპერატურა

გარეთ TCNT0, temp sbi DDRD, 4

ბოლო ხაზი აქ საკმაოდ აშკარაა. ეს მხოლოდ ადგენს PortD– ის მონაცემთა მიმართულების რეესტრის მე –4 ბიტს, რამაც გამოიწვია PD4 გამოსავალი.

პირველი ადგენს ცვლადის ტემპერატურას ნულამდე და შემდეგ ასლებს მას TCNT0 რეგისტრში. TCNT0 არის ჩვენი ტაიმერი/მრიცხველი 0. ეს მას ნულამდე აყენებს. როგორც კი კომპიუტერი ასრულებს ამ ხაზს, ტაიმერი 0 დაიწყება ნულიდან და ითვლის 15625 -ჯერ ყოველ წამში. პრობლემა ისაა, რომ TCNT0 არის "8 ბიტიანი" რეგისტრატორი, არა? რა არის ყველაზე დიდი რიცხვი, რომელსაც 8 ბიტიანი რეგისტრი იტევს? კარგად 0b11111111 ეს არის. ეს არის რიცხვი 0xFF. რომელია 255. ხედავთ რა ხდება? ტაიმერი მოძრაობს წამში 15625 -ჯერ და ყოველ ჯერზე, როდესაც ის 255 -ს აღწევს, ის "გადმოდის" და კვლავ ბრუნდება 0 -ზე. ამავე დროს, როდესაც ის ნულს უბრუნდება, ის აგზავნის ტაიმერის გადავსების შეწყვეტის სიგნალს. კომპიუტერი იღებს ამას და იცით რას აკეთებს ახლა? დიახ ის გადადის პროგრამის მეხსიერების ადგილას 0x0020 და ასრულებს ინსტრუქციას, რომელსაც აღმოაჩენს იქ.

დიდი! თუ ისევ ჩემთან ხარ, მაშინ დაუღალავი სუპერგმირი ხარ! გავაგრძელოთ…

ნაბიჯი 6: გადავსების დამმუშავებელი

მოდით ვივარაუდოთ, რომ ტაიმერი/counter0 რეგისტრი ახლახანს გადავსებულია. ჩვენ ახლა ვიცით, რომ პროგრამა იღებს შეწყვეტის სიგნალს და ასრულებს 0x0020, რომელიც ეუბნება პროგრამის მრიცხველს, კომპიუტერს გადავიდეს ლეიბლზე "overflow_handler". ქვემოთ მოცემულია კოდი, რომელიც დავწერეთ ამ ლეიბლის შემდეგ:

overflow_handler:

inc overflows cpi overflows, 61 brne PC+2 clr overflows reti

პირველი რასაც აკეთებს არის ცვლადი "overflows" (რაც ჩვენი სახელია ზოგადი დანიშნულების სამუშაო რეგისტრი R17), შემდეგ ის "ადარებს" გადავსების შინაარსს ნომერ 61. -თან. ორი რიცხვი და თუ შედეგი ნულის ტოლია, ის ადგენს Z დროშას SREG რეესტრში (მე გითხარით, რომ ჩვენ ამ რეესტრს ყოველთვის ვნახავთ). თუ ორი რიცხვი ტოლია მაშინ Z დროშა იქნება 1, თუ ორი რიცხვი არ არის ტოლი მაშინ ეს იქნება 0.

მომდევნო სტრიქონი ამბობს "brne PC+2" რაც ნიშნავს "ფილიალს თუ არა თანაბარს". არსებითად, ის ამოწმებს Z დროშას SREG– ში და თუ ის არ არის ერთი (ანუ ორი რიცხვი არ არის თანაბარი, თანაბარი რომ იყოს, ნულოვანი დროშა დაყენებული იქნება) კომპიუტერის ფილიალი PC+2 – ზე, რაც იმას ნიშნავს, რომ გამოტოვებს შემდეგს ხაზი და მიდის პირდაპირ "reti" - ზე, რომელიც წყვეტილიდან ბრუნდება იქ, სადაც ეს ადგილი იყო კოდში, როდესაც შეფერხება მოვიდა. თუ brne ინსტრუქციამ აღმოაჩინა 1 ნულოვანი დროშის ბიტში, ის არ განშტოდება და სამაგიეროდ ის უბრალოდ გააგრძელებს შემდეგ სტრიქონს, რომელიც clr overflows აღადგენს მას 0 -ზე.

რა არის ამ ყველაფრის წმინდა შედეგი?

ჩვენ ვხედავთ, რომ ყოველ ჯერზე, როდესაც ტაიმერი ივსება, ეს დამმუშავებელი ზრდის "გადავსების" მნიშვნელობას ერთით. ასე რომ, ცვლადი "overflows" ითვლის რაოდენობის overflows როგორც ხდება. როდესაც რიცხვი 61 -ს აღწევს, ჩვენ მას ნულამდე ვაყენებთ.

ახლა რატომ ვაკეთებთ ამას მსოფლიოში?

Მოდი ვნახოთ. შეგახსენებთ, რომ ჩვენი საათის სიჩქარე ჩვენი CPU– სთვის არის 16 MHz და ჩვენ „მოვამზადეთ“ის TCCR0B გამოყენებით ისე, რომ ტაიმერი ითვლის მხოლოდ 15625 დათვლის სიჩქარით წამში? და ყოველ ჯერზე, როდესაც ტაიმერი 255 -ს აღწევს, ის გადმოდის. ეს ნიშნავს, რომ იგი გადმოდის 15625/256 = 61.04 ჯერ წამში. ჩვენ თვალყურს ვადევნებთ გადავსების რაოდენობას ჩვენი ცვლადი "overflows" და ჩვენ ვადარებთ ამ რიცხვს 61. ამრიგად, ჩვენ ვხედავთ, რომ "overflows" ექნება 61 -ს წამში ერთხელ! ასე რომ, ჩვენი დამმუშავებელი გადააყენებს "გადავსებას" ნულამდე ყოველ წამში ერთხელ. ასე რომ, თუ ჩვენ უბრალოდ მონიტორინგს ვაკეთებთ ცვლადი „გადავსების“შესახებ და გავითვალისწინებთ ყოველ ჯერზე, როდესაც ის ნულამდე გადავა, ჩვენ ვითვლით მეორე-წამს რეალურ დროში (გაითვალისწინეთ, რომ მომდევნო გაკვეთილში ჩვენ ვაჩვენებთ, თუ როგორ უნდა მივიღოთ უფრო ზუსტი მილიწამიანი დაყოვნება ისევე, როგორც არდუინოს რუტინული „დაგვიანება“მუშაობს).

ახლა ჩვენ "გავუმკლავდით" ტაიმერის გადავსების შეფერხებებს. დარწმუნდით, რომ გესმით როგორ მუშაობს ეს და შემდეგ გადადით შემდეგ საფეხურზე, სადაც ჩვენ ვიყენებთ ამ ფაქტს.

ნაბიჯი 7: გადადება

ახლა, როდესაც ჩვენ დავინახეთ, რომ ჩვენი ქრონომეტრის გადავსების შეწყვეტის დამმუშავებელი "overflow_handler" რუტინა ცვლადს "overflows" ნულს უტოვებს ყოველ წამში, ჩვენ შეგვიძლია გამოვიყენოთ ეს ფაქტი "დაგვიანების" ქვეგეგმის შესაქმნელად.

შეხედეთ შემდეგ კოდს ჩვენი დაგვიანებით: ეტიკეტი

დაგვიანება:

clr ადიდებს sec_count: cpi ადიდებს, 30 brne sec_count ret

ჩვენ ვაპირებთ დავარქვათ ეს ქვეგეგმა ყოველ ჯერზე, როდესაც დაგვჭირდება პროგრამის შეფერხება. მისი მუშაობის პრინციპი არის ის, რომ ის ცვლადს "გადავსებას" ნულამდე აყენებს. შემდეგ ის შემოდის ზონაში, სახელწოდებით "sec_count" და ადარებს გადავსებას 30 -ით, თუ ისინი თანაბარი არ არის, ის ტოვებს ეტიკეტს sec_count- ს და ადარებს ისევ და ისევ და ა.შ. სანამ საბოლოოდ არ გახდება თანაბარი (გახსოვდეთ, რომ მთელი დრო ჩვენს ქრონომეტრზე შეფერხების დამმუშავებელი აგრძელებს ცვლადი გადავსების ზრდას და ასე იცვლება ყოველ ჯერზე, როდესაც ჩვენ ვივლით აქ. როდესაც გადინება საბოლოოდ უდრის 30 -ს, ის გამოდის მარყუჟიდან და ბრუნდება იქ, სადაც დაგვიძახეს დაგვიანება: დან. წმინდა შედეგი არის დაგვიანებით 1/2 წამი

სავარჯიშო 2: შეცვალეთ overflow_handler რუტინა შემდეგში:

overflow_handler:

inc overflows reti

და გაუშვით პროგრამა. არის რამე განსხვავებული? Რატომ ან რატომ არ?

ნაბიჯი 8: დახუჭე თვალები

დაბოლოს, გადავხედოთ მოციმციმე რუტინას:

თვალის დახამხამება:

sbi PORTD, 4 rcall delay cbi PORTD, 4 rcall delay rjmp blink

ჯერ ჩვენ ჩართავთ PD4- ს, შემდეგ ჩვენ ვიძახებთ ჩვენს დაგვიანებულ ქვეგეგმას. ჩვენ ვიყენებთ rcall- ს ისე, რომ როდესაც კომპიუტერი მიიღებს "ret" განცხადებას, ის დაბრუნდება rcall– ის შემდეგ ხაზზე. შემდეგ დაგვიანების რუტინული გადადება ცვლის ცვლაში 30 -ით, როგორც ვნახეთ და ეს არის ზუსტად ზუსტად 1/2 წამი, შემდეგ ჩვენ ვთიშავთ PD4- ს, ვაგვიანებთ კიდევ 1/2 წამს და შემდეგ ისევ საწყისს ვუბრუნდებით.

წმინდა შედეგი არის მოციმციმე LED!

ვფიქრობ, თქვენ ახლა დამეთანხმებით, რომ "დახუჭვა" ალბათ არ არის ასამბლეის ენაზე საუკეთესო "hello world" პროგრამა.

სავარჯიშო 3: შეცვალეთ პროგრამაში არსებული სხვადასხვა პარამეტრები ისე, რომ LED აციმციმდეს სხვადასხვა სიჩქარით, როგორიცაა მეორე ან 4 -ჯერ წამში და ა.შ. სავარჯიშო 4: შეცვალეთ ის ისე, რომ LED იყოს ჩართული და გამორთული სხვადასხვა დროის განმავლობაში. მაგალითად, ჩართეთ 1/4 წამი, შემდეგ გამორთეთ 2 წამი ან მსგავსი რამ. სავარჯიშო 5: შეცვალეთ TCCR0B საათი, შეარჩიეთ ბიტი 100 -ზე და შემდეგ განაგრძეთ მაგიდაზე ასვლა. რა ეტაპზე ხდება ის განურჩეველი ჩვენი "hello.asm" პროგრამისგან მეცადინეობიდან 1? სავარჯიშო 6 (სურვილისამებრ): თუ თქვენ გაქვთ სხვა ბროლის ოსცილატორი, მაგალითად 4 MHz ან 13.5 MHz ან სხვა, შეცვალეთ თქვენი 16 MHz ოსცილატორი ახლის დაფაზე და ნახე როგორ აისახება ეს მოციმციმე შუქის მაჩვენებელზე. ახლა თქვენ უნდა შეძლოთ ზუსტი გაანგარიშების გავლა და ზუსტად განსაზღვროთ, თუ როგორ იმოქმედებს ეს განაკვეთზე.

ნაბიჯი 9: დასკვნა

მათ შორის, ვინც თქვენ გაჭირვებულებმა მიაღწიეთ აქამდე, გილოცავთ!

მე ვხვდები, რომ საკმაოდ ძნელია დგომა, როდესაც უფრო მეტს კითხულობ და მაღლა იყურები ვიდრე აკეთებ ექსპერიმენტებს, მაგრამ ვიმედოვნებ, რომ თქვენ ისწავლეთ შემდეგი მნიშვნელოვანი რამ:

  1. როგორ მუშაობს პროგრამის მეხსიერება
  2. როგორ მუშაობს SRAM
  3. როგორ მოვძებნოთ რეგისტრები
  4. როგორ მოიძიოთ ინსტრუქციები და იცოდეთ რას აკეთებენ
  5. როგორ განვახორციელოთ შეფერხებები
  6. როგორ ასრულებს CP კოდს, როგორ მუშაობს SREG და რა ხდება შეფერხებების დროს
  7. როგორ გავაკეთოთ მარყუჟები და გადახტომა და გადახტომა კოდში
  8. რამდენად მნიშვნელოვანია მონაცემთა ფურცლის წაკითხვა!
  9. მას შემდეგ რაც იცით, როგორ გააკეთოთ ეს ყველაფერი Atmega328p მიკროკონტროლერისთვის, ეს იქნება ტორტის ნათესავი გასეირნება ახალი კონტროლერების შესასწავლად, რაც გაინტერესებთ.
  10. როგორ შევცვალოთ პროცესორის დრო რეალურ დროში და გამოვიყენოთ იგი დაგვიანებულ რუტინაში.

ახლა, როდესაც ჩვენ გვაქვს ბევრი თეორია, ჩვენ შეგვიძლია დავწეროთ უკეთესი კოდი და გავაკონტროლოთ უფრო რთული საგნები. ასე რომ, შემდეგი გაკვეთილი ჩვენ ამას გავაკეთებთ. ჩვენ ავაშენებთ უფრო რთულ, უფრო საინტერესო, წრედ და გავაკონტროლებთ მას სახალისო გზებით.

სავარჯიშო 7: "დაარღვიე" კოდი სხვადასხვა გზით და ნახე რა მოხდება! მეცნიერული ცნობისმოყვარეობა პატარავ! ვინმეს შეუძლია ჭურჭლის რეცხვა? სავარჯიშო 8: შეიკრიბეთ კოდი "-l" პარამეტრის გამოყენებით, რომ შექმნათ სიის ფაილი. ანუ "avra -l blink.lst blink.asm" და გადახედე სიის ფაილს. დამატებითი საკრედიტო: უკომენტარო კოდი, რომელიც მე დასაწყისში მივეცი და კომენტარი, რომელსაც ჩვენ მოგვიანებით განვიხილავთ, განსხვავდება! არსებობს კოდის ერთი ხაზი, რომელიც განსხვავებულია. შეგიძლიათ მისი პოვნა? რატომ არ აქვს ამ განსხვავებას მნიშვნელობა?

იმედია გაერთეთ! შევხვდებით შემდეგ ჯერზე…

გირჩევთ: