Pinbni qanday almashtirish mumkin 1. AVR mikrokontroller portlari. A port kirish ma'lumotlari reestri - PINA

CodeVision AVR -da port sozlamalari misollarini ko'rib chiqaylik
Masalan, DDRB = 0x02; bu yozuv B portining ikkinchi oyog'i chiqish sifatida tuzilgan degan ma'noni anglatadi, lekin bu raqam qaerdan kelgan ????

Birinchidan, keling, ushbu yozuvni biz uchun tushunarli shaklga o'tkazaylik:
0x prefiksi raqam o'n oltilik belgilar bilan yozilganligini anglatadi, uning mohiyatini oson tushunish uchun uni ikkilik tizimga tarjima qilish kerak. Bu erda standart dasturlar to'plamidagi Windows kalkulyatori bizga yordam beradi, biz uni darhol dasturchi rejimiga o'tkazamiz.

Biz uni o'n oltilik tizim rejimiga o'tkazamiz (HEX belgisini belgilang) va 0x02 raqamimizni 2 ga kiriting.

endi biz hech qanday tenglamani bosmaymiz va hokazo, faqat ikkilik sanoq tizimiga o'ting (Binni belgilang)

Biz 10 raqamini oldik. Bu nimani anglatadi? Bizning ATmega8 -ning B portida 8 ta oyog'i bor (rasmda aylana shaklida)

Shunday qilib, agar siz 10 raqamini 00000010 sifatida ifodalasangiz, bu shuni anglatadiki, faqat ikkinchi oyoq chiqish, qolgan qismi esa kirish sifatida tuzilgan.

PORTB.7 PORTB.6 PORTB.5 PORTB.4 PORTB.3 PORTB.2 PORTB.1 PORTB.0
0 0 0 0 0 0 1 0

Shuni ta'kidlash kerakki, agar uning o'rniga
DDRB = 0x02;
yozing
DDRB = 0b00000010;
keyin u ham ishlaydi, ya'ni. bu turli xil sanoq sistemalarida bir xil sonli ekvivalent yozuvlar.

DDRB yordamida 1-chiqish, 0-kirish va bu nimani anglatadi
PORTB = 0x01;
Bu erda printsip bir xil, lekin:
agar oyoq chiqish sifatida tuzilgan bo'lsa va PORTB qiymati bir oyog'idagi qiymatga teng bo'lsa, dasturiy ta'minotdan keyingi oyog'i sukut bo'yicha yoqiladi (ya'ni unda kuchlanish bo'ladi), agar 0 bo'lsa, u holda oyoq o'chirilgan. Birinchi darsda biz PORTB.0 = 1 o'rnini bosa olardik; yozish orqali PORTB = 0x01; va bir xil natijaga erishdi.

Aslida, quyidagi tuzilmalar oyoqni C tili nuqtai nazaridan yoqish / o'chirish uchun to'g'ri echimdir:

PORTD | = (1<<3); //включить ножку 3 порта D PORTD |= (1<<2)|(1<<5)|(1<<6); //включить ножки 2, 5, 6 порта D PORTD &= ~(1<<2); //выключить ножку 2 PORTD &= (~((1<<0)|(1<<2)|(1<<4))); //выключить ножки 0, 2, 4

Agar oyoq kirish sifatida konfiguratsiya qilingan bo'lsa va PORTB qiymati bir oyog'idagi qiymatga teng bo'lsa, shovqinni yo'qotish uchun oyoqqa tortuvchi qarshilik ulanadi. Agar sizga ichki qarshilik kerak bo'lmasa, bu oyog'iga 0 qo'ying.

Umid qilamanki, hamma narsa aniq, agar biror narsa yozsangiz, savol bering.

Mikrokontrollerlarni dasturlashda siz doimo bitlar bilan ishlashga to'g'ri keladi. Ularni o'rnating, asl holatini tiklang, ularning ma'lum bir registrda mavjudligini tekshiring. Buning uchun AVR assambleyasida bir qancha buyruqlar mavjud. Birinchidan, bu bit operatsiyalari buyruqlar guruhi - ular mikrokontrollerning har xil registrlarida bitlarni o'rnatish yoki tozalash uchun mo'ljallangan, ikkinchidan, boshqaruv uzatuvchi buyruqlar guruhi - dastur tarmoqlarini tashkil qilish uchun mo'ljallangan. Tabiiyki, C tilida bunday buyruqlar yo'q, shuning uchun yangi dasturchilarda ko'pincha C tilida bitlar bilan ishlash haqida savol tug'iladi. Biz hozir bu mavzuni tahlil qilmoqchimiz.

Bitlarda manipulyatsiya qilish uchun Cda 6 ta operator mavjud. Ular har qanday imzo qo'yilgan yoki imzosiz tamsayı o'zgaruvchilar turiga qo'llanilishi mumkin.

<< - сдвиг влево
>> - o'ngga siljitish
~ - bitli inversiya
| - bitli OR
& - bitli VA
^ - bitly eksklyuziv OR

_______________ chapga siljish<< _______________

Chapga n ta sonni siljitadi. Bunday holda, eng muhim n bit yo'qoladi va eng kichik n bit nol bilan to'ldiriladi.


imzosiz belgi tmp = 3; // 0b00000011
tmp = tmp<< 1;
// endi tmp o'zgaruvchisi 6 yoki 0b00000110 raqamini o'z ichiga oladi

Tmp = tmp<< 3;
// endi tmp o'zgaruvchisi 48 yoki 0b00110000 raqamini o'z ichiga oladi

Amaliyot o'zgaruvchida bajariladi, so'ngra operatsiya natijasi o'sha o'zgaruvchiga beriladi, ifodalarni murakkab operatorlar yordamida qisqacha yozish mumkin.

Tmp = 7; // 0b00000111
tmp<<= 2; // stenografiya versiyasi
// endi tmp o'zgaruvchisi 28 yoki 0b00011100 raqamini o'z ichiga oladi

Chapga n bit bilan o'tish operatsiyasi o'zgaruvchini 2 n ga ko'paytirishga tengdir.

_______________ o'ngga siljish >> _______________

N sonini o'ngga siljitadi. Bu holda eng kichik n bit yo'qoladi. Eng muhim n bitni to'ldirish o'zgaruvchining turiga va uning qiymatiga bog'liq. Eng muhim n bit ikkita holatda nol bilan to'ldiriladi - agar o'zgarmaydigan belgisiz bo'lsa yoki o'zgaruvchiga imzo qo'yilgan bo'lsa va uning joriy qiymati ijobiy bo'lsa. O'zgaruvchiga imzo qo'yilganda va uning qiymati manfiy bo'lganda, eng muhim bitlar ular bilan to'ldiriladi.

Belgisiz o'zgaruvchiga misol

imzosiz belgi tmp = 255; // 0b11111111
tmp = tmp >> 1;
// endi tmp o'zgaruvchisi 127 yoki 0b01111111 raqamini o'z ichiga oladi

Tmp >> = 3; // stenografiya versiyasi
// endi tmp o'zgaruvchisi 15 yoki 0b00001111 raqamini o'z ichiga oladi

Imzolangan o'zgaruvchiga misol

int tmp = 3400; // 0b0000110101001000
tmp >> = 2;
// endi o'zgaruvchi 850 yoki 0b0000001101010010 raqamini o'z ichiga oladi

Tmp = -1200; // 0b1111101101010000
tmp >> = 2;
// endi tmp raqami -300 yoki 0b1111111011010100
// ko'rasiz - ikkita eng muhim raqamlar raqamlar bilan to'ldirilgan

N bit bilan o'ngga siljish 2 n ga bo'lishga teng. Biroq, ba'zi nuanslar mavjud. Agar yo'qolgan kichik tartibli bitlar o'z ichiga olgan bo'lsa, unda bunday "bo'linish" ning natijasi qo'pol bo'lib chiqadi.

Masalan 9/4 = 2,5 a 9 >> 2 (1001 >> 2) 2 ga teng
11/4 = 2.75 va 11 >> 2 (1011 >> 2) 2 ga teng
28/4 = 7 va 28 >> ​​2 (11100 >> 2) 7 ga teng

Ikkinchi holda, xato kattaroqdir, chunki past darajadagi bitlar ham bitta. Uchinchi holatda, xato bo'lmaydi, chunki yo'qolgan bitlar nolga teng.

_______________ bitli inversiya ~ _______________

Raqamni asta -sekin teskari aylantiradi. Nol bo'lgan raqamlar raqamlar bilan to'ldiriladi. Raqamlar nol bilan to'ldirilgan. Bitli inversiya operatori yagona operator, ya'ni bitta operand bilan ishlatiladi.

imzosiz belgi tmp = 94; // 0b01011110
tmp = ~ tmp;
// endi tmp o'zgaruvchisi 161 yoki 0b10100001 raqamini o'z ichiga oladi

Tmp = ~ tmp;
// endi tmp -da yana 94 yoki 0b01011110 raqami

_______________ bitli yoki | ______________

Operator | ikkita operandning tegishli bitlari o'rtasida mantiqiy YO'Q operatsiyasini bajaradi. Ikki bit orasidagi mantiqiy YOKI operatsiyaning natijasi 0 bo'ladi, agar ikkala bit ham 0 ga teng bo'lsa. Boshqa barcha hollarda natija 1 bo'ladi. Bu haqiqat jadvalida tasvirlangan.

Operator | odatda o'zgaruvchining berilgan bitlarini bittaga o'rnatish uchun ishlatiladi.

Tmp = 155
tmp = tmp | 4; // tmp o'zgaruvchining ikkinchi bitini bittaga o'rnating

155 0b100110 11
4 0b00000 1 00
159 0b100111 11

Bitlarni o'rnatish uchun o'nli raqamlardan foydalanish juda noqulay. Buni chapga siljish yordamida bajarish ancha qulayroq.<<.


tmp = tmp | (1<<4); // tmp o'zgaruvchining to'rtinchi bitini bittaga o'rnating

Biz o'ngdan chapga o'qiymiz - to'rtta raqamni chapga siljiting, qabul qilingan raqam va tmp o'zgaruvchining qiymati o'rtasida OR operatsiyasini bajaring, natijani tmp o'zgaruvchisiga belgilang.


Siz shunga o'xshash bir nechta bitni o'rnatishingiz mumkin

Tmp = tmp | (1<<7)|(1<<5)|(1<<0);
// tmp o'zgaruvchining ettinchi, beshinchi va nolli bitlarini bittaga o'rnating

| = Birikma tayinlash operatori yordamida siz yozuvni ixchamroq qilishingiz mumkin.

Tmp | = (1<<4);
tmp | = (1<<7)|(1<<5)|(1<<0);

_______________ bitli VA & _______________

& Operatori ikkita operandning tegishli bitlari o'rtasida mantiqiy VA operatsiyani bajaradi. Ikki bit orasidagi mantiqiy VA operatsiyaning natijasi 1 bo'ladi, agar ikkala bit ham 1 ga teng bo'lsa, qolgan barcha hollarda natija 0 bo'ladi. Bu haqiqat jadvalida tasvirlangan.

& Operatori odatda bir yoki bir nechta bitni nol qilish uchun ishlatiladi.

Tmp = 155;
tmp = tmp & 247; // nol tmp o'zgaruvchining uchinchi biti

155 0b10011 011
&
247 0b1111 0 111
147 0b10010 011

Ko'ryapsizmi, uchinchi bit 0 ga aylandi, qolgan bitlar o'zgarmadi.

O'nli kasrlarni ishlatib bitlarni nollashtirish noqulay. Ammo siz operatorlar yordamida hayotingizni osonlashtirasiz<< и ~

Tmp = 155;
tmp = tmp & (~ (1<<3)); // uchinchi bit nol

1<<3 0b00001 000
~(1<<3) 0b11110 111
tmp & (~ (1<<3)) 0b10011 011 & 0b11110 111
natija 0b10010 011

Biz o'ngdan chapga o'qiymiz - bitta uchta raqamni chapga siljiting, natijadagi sonni teskari aylantiring, tmp o'zgaruvchisi va teskari raqam o'rtasidagi & operatsiyani bajaring, natijani tmp o'zgaruvchisiga belgilang.


Siz shunga o'xshash bir nechta bitni nolga qo'yishingiz mumkin

tmp = tmp & (~ ((1<<3)|(1<<5)|(1<<6))); // uchinchi, beshinchi va oltinchi bitlarni nolga aylantiring



& = Birikma tayinlash operatoridan foydalanib, ifodani ixchamroq yozish mumkin

Tmp & = (~ ((1<<3)|(1<<5)|(1<<6)));

O'zgaruvchiga bit o'rnatilganligini qanday tekshirish mumkin?
Tekshiruvdan tashqari barcha bitlarni nolga qo'yish kerak, so'ngra olingan qiymatni nol bilan solishtirish kerak

agar((tmp va (1<<2)) != 0){
// blok faqat o'rnatilgan bo'lsa bajariladi

}

agar((tmp va (1<<2)) == 0){
// blok o'rnatilmagan taqdirdagina bajariladi
// tmp o'zgaruvchining ikkinchi biti

}

_______________ bitli eksklyuziv yoki ^ _______________


^ Operatori ikkita operandning tegishli bitlari o'rtasida mantiqiy eksklyuziv YOKI operatsiyasini bajaradi. Agar bitlar teng bo'lsa, mantiqiy eksklyuziv YO 0 ga olib keladi. Boshqa barcha hollarda, natija 1 bo'ladi. Bu haqiqat jadvalida tasvirlangan.

^ Operatori boshqa bitli operatorlar kabi tez -tez ishlatilmaydi, lekin buning uchun qilinadigan ishlar bor. Masalan, u o'zgaruvchining bir yoki bir nechta bitini teskari aylantirish uchun ishlatilishi mumkin.


tmp = 155;
tmp = tmp ^ 8; // to'rtinchi bitni tmp bilan teskari aylantiring

155 0b10011 011
^
8 0b0000 1 000
147 0b10010 011

To'rtinchi bit o'z ma'nosini teskari tomonga o'zgartirdi, qolgan bitlar esa o'zgarishsiz qoldi.

Tmp = tmp ^ 8; // yana to'rtinchi bitni tmp bilan teskari aylantiring

147 0b10010 011
^
8 0b000 0 1 000
155 0b10011 011

Ko'ryapsizmi, to'rtinchi bit o'z ma'nosini yana teskarisiga o'zgartirdi.

Ifodani shunday yozish ancha qulayroq.

Tmp = tmp ^ (1<<3); // uchinchi bitni tmp bilan teskari aylantiring

Va shuning uchun u qulay va ixchamdir

Tmp ^ = (1<<4); // to'rtinchi bitni teskari aylantiring

Bir vaqtning o'zida bir nechta bitni o'zgartirishi mumkin

Tmp ^ = ((1<<4)|(1<<2)|(1<<1)); // 4,2 va 1 bitni teskari aylantiring

Bitwise eksklyuziv OR boshqa qiziqarli xususiyatga ega... U ikkita o'zgaruvchining qiymatlarini almashtirish uchun ishlatilishi mumkin. Bu odatda uchinchi o'zgaruvchini talab qiladi.


tmp = var1;
var1 = var2;
var2 = tmp;

^ Operatoridan foydalanib, siz qiymatlarni quyidagicha o'zgartirishingiz mumkin:

var1 ^ = var 2;
var 2 ^ = var 1;
var 1 ^ = var 2;

Sof sehr, garchi rostini aytsam, men hech qachon bunday texnikani ishlatmaganman.

________________ Direktiv #ta'rifi __________________


Endi biz bitlarni qanday o'rnatish, nol va teskari aylantirishni bilamiz, bit o'rnatilgan yoki o'rnatilmaganligini tekshirishni bilamiz. Yuqorida muhokama qilingan iboralar juda og'ir, lekin #define preprocessor direktivasi yordamida ularni yanada yoqimli qilish mumkin.

#Define direktivasi doimiy va makrolarga ramziy nomlar berish uchun ishlatiladi. Ramziy nomlardan foydalanish dasturni yanada o'zgaruvchan va ko'chma qiladi.

Masalan, siz dastur matnida doimiydan foydalanasiz va to'satdan uning qiymatini o'zgartirishingiz kerak bo'ladi. Agar u faqat uchta joyda bo'lsa, uni qo'lda tuzatishingiz mumkin, lekin agar u ellik qatorda sodir bo'lsa -chi? Tuzatish nafaqat ko'p vaqtni oladi, balki bu holatda xato qilish ham oson. Bu erda #define direktivasi yordam beradi. Dastur boshida dastur davomida ishlatiladigan doimiyning ramziy nomi ko'rsatiladi. Agar biz bu qiymatni o'zgartirishimiz kerak bo'lsa, bu faqat bitta joyda amalga oshiriladi. Va kompilyatsiya qilishdan oldin, oldingi protsessorning o'zi doimiy qiymat nomi o'rniga hamma ifodalarda o'z qiymatini almashtiradi.

Mikrokontroller dasturlashi uning apparati va ko'pincha tashqi jabduqlar bilan uzviy bog'liqdir. Masalan, tugmachalarni olaylik - ularni dasturimizda so'rab, biz mikrokontrollerning haqiqiy chiqishiga murojaat qilamiz. Agar biz to'satdan tugmachalarni boshqa pinlarga ulangan boshqa sxemada tugmachalarni tanlash dasturidan foydalanishimiz kerak bo'lsa -chi? Biz dasturni tuzatishimiz kerak. Shunga qaramay, #define ko'rsatmasidan foydalangan holda mos keladigan pinlar uchun ramziy nom ko'rsatib, dasturni o'zgartirish nokni otish kabi oson bo'ladi.


Misol:

#"iom8535.h" ni qo'shing

// tugmalar ulangan port
#PORT_BUTTON PORTA ni aniqlang
#PIN_BUTTON PINA ni aniqlang
#DDRX_BUTTON DDRA ni aniqlang

// tugmalar ulangan pinlar
#DOWN 3 ni aniqlang
#ta'rifni bekor qilish 4
#UP 5 ni aniqlang
#ta'rif ENTER 6

int asosiy ()
{
// kirish uchun portni sozlash,
// va tortishish rezistorlarini yoqing

DDRX_BUTTON = 0;
PORT_BUTTON = 0xff;

Ramziy nomni belgilashda siz iboralarni ham ishlatishingiz mumkin

#MASK_TUGMALARINI belgilang ((1<

foydalanish misoli :
tmp = PORTB & MASK_BUTTONS;

#Define dan foydalanganda, ifodalarni baholash ketma -ketligini aniq belgilash uchun qavsni ayamang!

Ba'zi iboralarni "funktsiyalar" sifatida yashirish mumkin.

#decine ADC_OFF () ADCSRA = 0

foydalanish misoli:
ADC_OFF ();

Har bir satr oxiridagi \ belgisidan foydalanib, ko'p qatorli ta'riflardan foydalanishingiz mumkin.

#deinfine INIT_Timer () TIMSK = (1<TCCR0 = (1<TCNT0 = 0; \
OCR0 = 0x7d

foydalanish misoli:
INIT_Timer ();

Xo'sh, #define direktivasining eng kuchli ishlatilishi makrolarni (yoki shunchaki makrolarni) sozlashdir. Yuqorida muhokama qilingan bit operatsiyalari uchun makrolarni o'rnatish uchun #define -dan qanday foydalanishingiz mumkin.

#debine SetBit (reg, bit) reg | = (1<#define ClearBit (reg, bit) reg & = (~ (1<#devine InvBit (reg, bit) reg ^ = (1<#deitine BitIsSet (reg, bit) ((reg & (1<#deitine BitIsClear (reg, bit) ((reg & (1<

foydalanish misoli:

SetBit (PORTB, 0); // B portining nol bitini o'rnating
InvBit (tmp, 6); // tmp o'zgaruvchining oltinchi bitini teskari aylantiring


agar(BitIsClear (PIND, 0))) ( // agar PIND registridagi nol bit tozalansa
... .. // blokni bajaring
}

Kompilyatsiya oldidan, oldingi protsessor bu satrlarni oldindan e'lon qilingan iboralar bilan almashtiradi va ulardagi tegishli dalillarni almashtiradi.

Makrolar juda kuchli, lekin ulardan ehtiyotkorlik bilan foydalanish kerak. Mana, dasturlash bo'yicha barcha darsliklarda yozilgan eng keng tarqalgan raklar.

Keling, sonning kvadratini hisoblaydigan so'lni aniqlaylik:

#define SQUARE (x) x * x

ifoda
tmp = Kvadrat (my_var);
to'g'ri natijani beradi.

Agar my_var + 1 ifodasini so'l ta'rifiga dalil sifatida ishlatsangiz nima bo'ladi

tmp = Kvadrat (my_var +1);

Old protsessor bu qatorni almashtiradi

tmp = my_var + 1 * my_var +1;

va bu biz kutgan natija emas.

Bunday xatolarga yo'l qo'ymaslik uchun makrolarni e'lon qilishda qavsni tejamang!

Agar siz shunga o'xshash so'lni e'lon qilsangiz

#kvadratni belgilang (x) ((x) * (x))

ifoda
tmp = Kvadrat (my_var +1);
to'g'ri natijani beradi, chunki oldingi protsessor bu qatorni o'rnini bosadi
tmp = ((my_var + 1) * (my_var +1));

Biz ularni loyiha papkasiga yozamiz va main.c faylining boshiga #include "bits_macros.h" yozamiz.

Bit

O'qish / Yozish

Boshlang'ich qiymati

· Bit 7 - barcha uzilishlarni yoqish. Uzilishlarni yoqish uchun bu bit 1 ga o'rnatilishi kerak. Muayyan uzilishni yoqish EIMSK va TIMSK uzilish niqobi registrlari tomonidan nazorat qilinadi. Agar bu bit tozalansa (= 0), u holda uzilishlarning hech biri qayta ishlanmaydi. Bit uzilishdan keyin apparat tomonidan tozalanadi va keyinchalik RETI buyrug'i bilan uzilishni yoqish uchun o'rnatiladi.
· 6 -bit - nusxa ko'chirish bitini saqlang. BLD va BST bit nusxa ko'chirish buyruqlari bu bitni bit operatsiyalari uchun manba va manzil sifatida ishlatadi. BST buyrug'i umumiy registr bitini T bitiga, BLD buyrug'i esa T bitini umumiy registr bitiga ko'chiradi.
· 5 -bit - yarim bayroqchali bayroq. Bu bir qator arifmetik amallarni bajarishda tetradlar orasidagi uzatishni ko'rsatadi.
· 4 -bit - belgi. Bit S eksklyuziv OR (N (+) V) operatsiyasining natijasi salbiy (N) va ikkita to'ldiruvchi bayroq (V) bayrog'i qiymatiga ega.

· Bit 3 - Ikkita to'la bayroqni to'ldiruvchi. U ikkita qo'shma arifmetikani qo'llab -quvvatlaydi.
· 2 -bit - salbiy qiymat belgisi. Bu bayroq bir qator arifmetik va mantiqiy amallarning salbiy natijasini ko'rsatadi.
· Bit 1 - nol qiymatli bayroq. Bu bayroq bir qator arifmetik va mantiqiy amallarning nol natijasini ko'rsatadi.
· Bit 0 - bayroq ko'taring. Bu bayroq arifmetik va mantiqiy amallar uchun tashishni bildiradi.

AT90S8535 mikrokontrolerida 4 ta parallel A / B, C va D portlari mavjud.
A porti-8-bitli ikki tomonlama port. A porti bilan o'zaro ishlash ma'lumotlar xotirasining kirish / chiqish maydonidagi uchta registr orqali amalga oshiriladi: ma'lumotlar registri - PORTA, $ 1B ($ 3B), ma'lumotlar yo'nalishi registri - DDRA, $ 1A ($ 3A), kirish ma'lumotlari registri - PINA, 19 dollar (39 dollar). PINA reestri faqat o'qish uchun, PORTA va DDRA registrlari o'qish uchun yoziladi. PINA reestri so'zning to'liq ma'nosida registr emas. Unga kirish har bir port pinining jismoniy holatini o'qishni ta'minlaydi. A porti, shuningdek, analog A / D signallarini kiritish uchun xizmat qiladi.

Ma'lumotlar porti A porti -PORTA

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port A ma'lumot yo'nalishi reestri -DDRA

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port A kirish ma'lumotlari reestri -PINA

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port B-8-bitli ikki tomonlama kirish-chiqish porti. A porti bilan bir qatorda, B porti bilan o'zaro aloqa ma'lumotlar xotirasining kirish / chiqish maydonidagi uchta registr orqali amalga oshiriladi: ma'lumotlar registri - PORTB, 18 dollar (38 dollar), ma'lumotlar yo'nalishi registri - DDRB, 17 dollar (37 dollar) va kirish ma'lumotlari reestri - PINB, 16 dollar (36 dollar). PINB reestri faqat o'qish uchun. PINB reestri so'zning to'liq ma'nosida registr emas. Unga kirish har bir port pinining jismoniy holatini o'qishni ta'minlaydi. Port B pinlari jadvalda ko'rsatilganidek, boshqa funktsiyalarni bajarishi mumkin. 2.1.

2.1 -jadval. Port B pinout muqobillari

Port pin

Muqobil funktsiya

T0 - Taymer / Hisoblagich 0 soatli kirish

T1 - Taymer / Hisoblagich 1 soatli kirish

AIN0 - taqqoslagichning musbat terminali

AIN1 - taqqoslagichning salbiy pimi

- qul SPI tanlash usuli

MOSI - asosiy chiqish / qulning SPI kirishini sozlash

MISO - asosiy kirish / qul SPI chiqishini sozlash

SCK - SPI soat signallari

Muqobil funktsiyalar uchun pinlardan foydalanganda, PORTB, DDRB registrlari mos ravishda o'rnatilishi kerak.

Port ma'lumotlari reestriBPORTB

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port B ma'lumotlarini yo'naltirish reestri -DDRB

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port B kirish ma'lumotlari reestri -PINB

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port C-8-bitli ikki tomonlama kirish-chiqish porti. A va B portlarida bo'lgani kabi, C porti bilan o'zaro ta'sir ma'lumotlar xotirasining kirish / chiqish maydonidagi uchta registr orqali amalga oshiriladi: ma'lumotlar registri - PORTC, 15 dollar (35 dollar), ma'lumotlar yo'nalishi registri - DDRC, 14 dollar (34 dollar) va kirish ma'lumotlari registri - PINC, $ 13 ($ 33). PINC reestri faqat o'qish uchun, PORTC va DDRC registrlari o'qish va yozish uchun mo'ljallangan. PINC reestri so'zning to'liq ma'nosida registr emas. Unga kirish har bir port pinining jismoniy holatini o'qishni ta'minlaydi.
Port Cda muqobil funktsiyalarni bajarishi mumkin bo'lgan ikkita pin bor: PC6 va PC7 pinlari TOSC1 va TOSC2 funktsiyalarini Timer / Counter 2 -ni bajaradi.

Port ma'lumotlari reestriCPORTC

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port C ma'lumot yo'nalishi reestri -DDRC

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port C kirish ma'lumotlari reestri -PINC

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port D-8-bitli ikki tomonlama kirish-chiqish porti. A, B va C portlaridagi kabi, D porti bilan o'zaro aloqa ma'lumotlar xotirasining kirish / chiqish maydonidagi uchta registr orqali amalga oshiriladi: ma'lumotlar registri - PORTD, $ 12 ($ 32), ma'lumotlar yo'nalishi registri - DDRD, $ 11 ($ 31) va kirish ma'lumotlari reestri - PIND, 10 dollar (30 dollar). PIND registri o'qiladi, PORTD va DDRD registrlari o'qiladi / yoziladi. PIND reestri so'zning to'liq ma'nosida registr emas. Unga kirish har bir port pinining jismoniy holatini o'qishni ta'minlaydi.
Port D pinlari jadvalda ko'rsatilganidek, boshqa funktsiyalarni bajarishi mumkin. 2.2.

2.2 -jadval. Port D Pin muqobil vazifalari

Port pin

Muqobil funktsiya

RxD - qabul qiluvchining kirishi UART

TxD - UART uzatuvchi chiqishi

INT0 - 0 ta tashqi uzilish

INT1 - 1 ta tashqi uzilish

OC1B - taymer / hisoblagich 1 B chiqishining taqqoslash pimi

OC1A - taymer / hisoblagichning A chiqishining chiqishini solishtirish 1

ICP - Taymer / hisoblagichni yozib olishni ishga tushirish 1

OC2 - taymer / hisoblagich 2 chiqishining chiqishini taqqoslash

Muqobil funktsiyalar uchun pinlardan foydalanilganda, PORTD, DDRD registrlari mos ravishda o'rnatilishi kerak.

Port ma'lumotlari reestriDPORTD

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port ma'lumotlarini yo'naltirish reestriDDDRD

Bit

O'qish / Yozish

Boshlang'ich qiymati

Port kirish ma'lumotlari reestriDPIND

Bit

O'qish / Yozish

Boshlang'ich qiymati

Ko'rib chiqilayotgan ish birinchisi bo'lgani uchun, talabalar tomonidan laboratoriya kompleksi bilan ishlash ko'nikmalarini egallash uchun, avvalo, hamma talabalar bir xil ishni bajaradilar. Ish joyidan ular kompyuterga 1.5.3.1 -bandda berilgan 5 -sondan 3 -raqamni olib tashlash muammosini kiritadilar. Dastur tuzilgandan so'ng u ish joyining mikrokontrolleriga yoziladi va uning ishi o'qituvchiga ko'rsatiladi.
Kompleks bilan shunday tanishgandan so'ng, talaba individual topshiriqqa o'tadi. Vaqt bo'lsa, o'qituvchi individual ishni murakkablashtirishi mumkin.

Siz hozir buni o'qiyapsiz va o'ylaysiz - xotira, registrlar, stek va boshqalar yaxshi. Lekin siz buni sezmaysiz, ko'rmaysiz. Bu simulyatorda, lekin men xuddi shu shart bilan delfida qila olaman. Go'sht qayerda !!!

U erda boshqa kurslarda, deyarli birinchi satrlardan boshlab, ular biron bir muhim ishni qilishadi - ular diodni miltillatib, bu bizning Salom olamimiz, deyishadi. Va bu erda? Qayerda ???

Ha, ha, ha, men sizni tushunaman. Bundan tashqari, ehtimol siz allaqachon raqobatchilaringizga yugurgansiz va ularga diod bilan qaragansiz;)))) Hech narsa kechirilmaydi.

Men shunchaki didodiklarning miltillashi bilan to'xtashni xohlamadim, lekin taraqqiyot uchun siz asoslar va tamoyillarni - kuchli nazariy asosni aniq tushunishingiz kerak. Ammo endi mashg'ulotlarga navbat keldi.

Biz allaqachon portlarni ko'rib chiqdik, sizda dastur shabloni bor, shuning uchun darhol boshlaylik.

Asboblar
Portlar bilan ishlash odatda bitlar bilan ishlashni anglatadi. Biroz o'rnatish, bir oz tozalash, bir oz teskari aylantirish. Ha, albatta, assambleyada qulay buyruqlar mavjud

cbi / sbi, lekin ular faqat kichik manzillar diapazonida ishlaydi (0 dan 1F gacha), shuning uchun biz kelgusida ularni ishlatishimiz va manzillar maydoni haqida qayg'urmasligimiz uchun universal makrolarni yozaylik.

Makrolar shunday nomlanadi:

  • SETB bayt, bit, temp
  • CLRB bayt, bit, temp
  • INVB bayt, bit, temp, temp2

Bundan tashqari, pastki PBB (0-1F manzili) bitlari bilan ishlaganda, TEMP parametrining qiymatini o'tkazib yuborish mumkin - u baribir almashtirilmaydi. Inversiya buyruqlaridan tashqari - har kimga oraliq registrlar kerak bo'ladi.

Harfsiz makroslar guruhiga ega bo'lish ham foydalidir. Aniqrog'i, ular registrlardan foydalanadilar, lekin avval ularni to'plamga saqlaydilar. Ularni oddiy buyruqlar kabi o'ylamasdan itarib yuborish mumkin. Ammo ularning ishlashiga ko'proq vaqt kerak bo'ladi va RAM talab qilinadi.

  • SETBM bayt, bit
  • CLRBM bayt, bit
  • INVBM bayt, bit

Mana ularning manba kodi. Ko'rib turganingizdek, so'l tilining shartlari faol ishlatiladi, bu esa universal makrolarni yaratishga imkon beradi. Kompilyator qaysi versiyani qayerga siljitish kerakligini aniqlaydi :)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 < 0x20 SBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ORI R17,1<<@1 OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ORI R17,1<<@1 STS @0,R17 POP R17 .endif .endif .ENDM ;SET BIT with REG .MACRO SETB .if @0 < 0x20 ; Low IO SBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ORI @2,1<<@1 OUT @0,@2 .else ; Memory LDS @2,@0 ORI @2,1<<@1 STS @0,@2 .endif .endif .ENDM ;............................................................. ;Clear BIT with REG .MACRO CLRB .if @0 < 0x20 ; Low IO CBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ANDI @2,~(1<<@1) OUT @0,@2 .else ; Memory LDS @2,@0 ANDI @2,~(1<<@1) STS @0,@2 .endif .endif .ENDM ;Clear BIT with STACK .MACRO CLRBM .if @0 < 0x20 CBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ANDI R17,~(1<<@1) OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ANDI R17,~(1<<@1) STS @0,R17 POP R17 .endif .endif .ENDM ;............................................................. .MACRO INVB .if @0 < 0x40 IN @2,@0 LDI @3,1<<@1 EOR @3,@2 OUT @0,@3 .else LDS @2,@0 LDI @3,1<<@1 EOR @2,@3 STS @0,@2 .endif .ENDM .MACRO INVBM .if @0 < 0x40 PUSH R16 PUSH R17 IN R16,@0 LDI R17,1<<@1 EOR R17,R16 OUT @0,R17 POP R17 POP R16 .else PUSH R16 PUSH R17 LDS R16,@0 LDI R17,1<<@1 EOR R17,R16 STS @0,R17 POP R17 POP R16 .endif .ENDM ;= End macro.inc ========================================

; = Macro.inc -ni ishga tushirish =====================================; BIT -ni to'plam bilan o'rnatish .MAKRO SETBM .if @ 0< 0x20 SBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ORI R17,1<<@1 OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ORI R17,1<<@1 STS @0,R17 POP R17 .endif .endif .ENDM ;SET BIT with REG .MACRO SETB .if @0 < 0x20 ; Low IO SBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ORI @2,1<<@1 OUT @0,@2 .else ; Memory LDS @2,@0 ORI @2,1<<@1 STS @0,@2 .endif .endif .ENDM ;............................................................. ;Clear BIT with REG .MACRO CLRB .if @0 < 0x20 ; Low IO CBI @0,@1 .else .if @0<0x40 ; High IO IN @2,@0 ANDI @2,~(1<<@1) OUT @0,@2 .else ; Memory LDS @2,@0 ANDI @2,~(1<<@1) STS @0,@2 .endif .endif .ENDM ;Clear BIT with STACK .MACRO CLRBM .if @0 < 0x20 CBI @0,@1 .else .if @0<0x40 PUSH R17 IN R17,@0 ANDI R17,~(1<<@1) OUT @0,R17 POP R17 .else PUSH R17 LDS R17,@0 ANDI R17,~(1<<@1) STS @0,R17 POP R17 .endif .endif .ENDM ;............................................................. .MACRO INVB .if @0 < 0x40 IN @2,@0 LDI @3,1<<@1 EOR @3,@2 OUT @0,@3 .else LDS @2,@0 LDI @3,1<<@1 EOR @2,@3 STS @0,@2 .endif .ENDM .MACRO INVBM .if @0 < 0x40 PUSH R16 PUSH R17 IN R16,@0 LDI R17,1<<@1 EOR R17,R16 OUT @0,R17 POP R17 POP R16 .else PUSH R16 PUSH R17 LDS R16,@0 LDI R17,1<<@1 EOR R17,R16 STS @0,R17 POP R17 POP R16 .endif .ENDM ;= End macro.inc ========================================

Vaqt o'tishi bilan, assambleyada yozganingizda, bunday makrolar juda ko'p bo'ladi. Ular alohida faylga joylashtirilgan va har qanday loyihangizga ulangan va kod yozish oson va yoqimli bo'ladi.

Ammo kodga qaytsak,
Keling, LED chiroqni miltillaymiz, keyin?

Albatta, muammo emas. LEDlar demo taxtasida allaqachon o'rnatilgan, nega ularni ishlatmasligingiz kerak? Ular PD4, PD5, PD7 port pinlariga osilgan. Siz shunchaki o'tish moslamalarini kiyishingiz kerak.

; Ichki uskunani ishga tushirish ===================================== SETB DDRD, 4, R16; DDRD.4 = 1 SETB DDRD, 5, R16; DDRD.5 = 1 SETB DDRD, 7, R16; DDRD.7 = 1; Ichki uskunani ishga tushirishni tugatish =================================

Bizning diodlarimizni yoqish qoladi. Ular PORT registriga bitlarni yozish orqali yoritiladi. Biz buni allaqachon dasturning asosiy qismida qilamiz.

; Asosiy ================================================ ======== Asosiy: SETB PORTD, 4, R16; LED1 SETB PORTD, 7, R16 -ni yoqing; LED3 JMP Asosiy -ni yoqish; Asosiy tugatish =============================================== ====

Biz kompilyatsiya qilamiz, siz uni kuzatuvchida ishga tushirishingiz mumkin, siz bitlarning qanday o'zgarganini darhol ko'rasiz. Biz miltillayapmiz ... va "RESET" tugmasini bosgandan so'ng va yuklovchini tushirgandan so'ng (agar sizda bo'lsa) quyidagi rasmni ko'rasiz:


Va II versiya uchun


Ichida! Oqim zerikarli. Keling, ularni yumib olaylik.

Keling, faqat makrolarni almashtiraylik.

; Asosiy ================================================ ======== Asosiy: SETB PORTD, 4, R16; Yorug'lik LED1 INVB PORTD, 7, R16, R17; Teskari LED3 JMP Asosiy; Asosiy tugatish =============================================== ====

Ular uni yoqishdi, o'chirishdi ...

Lekin anjir - ikkalasi ham yoqilgan, lekin bittasi biroz xira. U chayqaladi, lekin juda tez. Agar siz osiloskopni PD7 piniga qo'ysangiz, u erda daraja tez -tez o'zgarib turishini ko'rasiz:


Nima qilish kerak? Shubhasiz, sekinlashadi. Qanaqasiga? O'quv qo'llanmalarining ko'pchiligida va tez boshlanishida qo'llaniladigan eng oson yo'li - zerikarli kechikish. Bular. kabi kodni oling:

; Asosiy ================================================ ======== Asosiy: SETB PORTD, 4, R16; Yorug'lik LED1 INVB PORTD, 7, R16, R17; Teskari LED3 RCALL kechikish JMP Asosiy; Asosiy tugatish =============================================== ====; Protsedura ================================================ === .equ LowByte = 255 .equ MedByte = 255 .equ HighByte = 255 Kechikish: LDI R16, LowByte; Biz uchta baytni yuklaymiz LDI R17, MedByte; Bizning parchamiz LDI R18, HighByte pastadir: SUBI R16,1; 1 SBCI R17.0 ni chiqarib oling; Faqat C SBCI R18.0 ni chiqarib oling; Faqat BRCC Loop -dan chiqarib oling; Agar ko'chirish - filial RET bo'lmasa; Tugatish tartibi =============================================

Biz buni so'radik, ishga tushirdik ... Oh ha, endi miltillash seziladi.

255.255.255 parametrlari bilan 8 MGts chastotada ta'sir qilish vaqti taxminan 2,1 soniyani tashkil qiladi. Bit kechikishini yana bir necha baytga oshirish mumkin. Keyin siz kamida bir soat zaryad qilishingiz mumkin.

Lekin bu usul xato, endi nima uchun sizga ko'rsataman.

Keling, tugma qo'shamiz. LED3 teskari yonib tursin. Biz shunday qilamizki, tugma bosilganda biz uchun LED1 yonadi va u qo'yilganda LED2 yonadi.

A soatini tugma sifatida oling va uni PD6 portiga ulang.


Ikkinchi versiya uchun ham xuddi shunday. Tugmalar guruhidan tugmani oling va boshqaruvchining PD6 pinini tugmalar panelidagi COL1 piniga ulang.

Faqat tugma maydonining o'tish joylarida joylashgan jumperlarga e'tibor bering. Moviy ranglar shunga o'xshash. Shuningdek, o'ng o'q bilan ko'rsatilgan bitta qora jumper. U tugmalarning eng chap ustunini erga ulaydi. GND va ROW1 pinlariga tegadi. Hammasi taxtada imzolangan.

Tugmani tekshirish SBIC buyrug'i bilan amalga oshiriladi, lekin avval uni boshlash kerak. DDR = 0, PORT = 1 - tortishish kiritish.

Ushbu satrlarni "Ichki uskunani ishga tushirish" bo'limiga qo'shing:

; Asosiy ================================================ ======== Asosiy: SBIS PIND, 6; Agar tugma bosilsa - o'tish RJMP BT_Push SETB PORTD, 5; LED2 CLRB PORTD, 4; LEDni o'chirish1 Keyingi: INVB PORTD, 7, R16, R17; Teskari LED3 RCALL kechikish JMP Asosiy BT_Push: SETB PORTD, 4; LED1 CLRB PORTD, 5; LED2 RJMP ni keyingi o'chirish; Asosiy tugatish =============================================== ====

Xo'sh, u ishlaydi. Tugma bosiladi - diodlar o'zgaradi. Uchinchisi quvnoq ko'zlarini qisadi. Ammo zapadlo bor:

Dastur sekinlashmoqda! Men tugmani bosdim, lekin rasm o'zgarmadi, kutishim kerak, ushlab turing ... Nega? Va bu bizning qayta qulashimiz tufayli.

Eslaysizmi, men sizga aytgan edimki, MK hech narsa qilmaydigan ahmoqona kechikishlar do'zax yomonlikdir. Bu yerda! Endi bunga o'zingiz amin bo'ldingiz. Axir, yovuzlikka qarshi kurashish kerak. Qanaqasiga? Xo'sh, men ham aytdim - bayroqlar bilan uzluksiz tsikl qilish. Hech bo'lmaganda foydali ishni kechiktirishimizga qo'shing.

Qo'rqinchli
Endi men sizga qanday qilib raqamli organ yasashni ko'rsataman. Bu qanday ishlashini eslaysizmi?

Tirnoqlari turlicha va har xil tonnali buloqli baraban bor. Tirnoqlar aylanadi, buloqlar tortadi - ular jiringlaydilar. Ma'lum bo'lishicha, raskolbasny Mouzon. Va agar biz shoshilinch guruhimizni lentaga ochib qo'ysak nima bo'ladi? Tirnoqlar 1 ga o'xshamaydimi? ;))))

Lenta noldan, masalan, FF.FF.FF.FFgacha, keyin nolga yoki boshqa qiymatga qaytariladigan hisoblagich bo'ladi, va biz buni qilamiz. Va bizning kichik dasturlarimiz to'g'ri joylarga yopishib, buloqlar vazifasini bajaradi - ularning doimiyligini hisoblagichning joriy qiymati bilan solishtirish.

Tasodifmi? Biz "DRYN!"

Qaerda va nimalarni ishga tushirish kerakligini bizning shoshilinch guruximizning vaqt tsiklida ro'yxatdan o'tkazish kifoya. Va bu erda juda qulay xususiyat bor - tsiklik ketma -ketlikni yaratish uchun biz faqat bir oz ushlab olishimiz kerak.

Aytaylik, organ 0 dan 1000 gacha, va biz diodni 10 marta miltillashimiz kerak. Turli qiymatlarga ega 10 ta ishlov beruvchiga yopishib olish shart emas. Biri kifoya, lekin buning uchun ** 10 qiymatini olish mumkin. Qolgan hamma narsa biz uchun muhim emas. Va u 0010, 0110, 0210, 0310, 0410, 0510, 0610, 0710, 0810, 0910 da ishlaydi. Yana tez -tez intervallar kerak bo'lganda bo'linadi, boshqa toifaga o'tish kifoya. Bu erda siz yuqori darajadagi bitlarni to'sib qo'ymaslik uchun kesib olishni unutmang.

Qani boshladik. Birinchidan, ma'lumotlar segmentida hisoblagichimizni yarataylik:

LDS R16, CCNT LDS R17, CCNT + 1 LDS R18, CCNT + 2 LDS R19, CCNT + 3

Hammasi shu, endi R16 -da hisoblagichimizning eng kam bayti va R19 -da eng eskisi.

Ro'yxatdan o'tish kitoblarini oldindan yig'ib yuborish mumkin, lekin men sizga yana bir maslahat berishni afzal ko'raman - dastur yozayotganda, registrlarni qattiq TEMP ma'lumoti sifatida ishlatish uchun algoritmni o'ylab ko'ring, bu ma'lumot faqat shu erda va hozir. . Va keyingi protsedurada ular bilan nima sodir bo'lishi endi muhim emas - RAMda saqlanishi kerak bo'lgan hamma narsa.

Siz buni shunday qilishingiz mumkin:

LDI R20.1; Bizga bitta CLR R15 kerak; Va nol. QO'ShIMChA R16, R20; Agar registr 255 bo'lsa, 1 qo'shing, u holda C ADC R17, R15 bo'ladi; 0 + C ADC R18, R15 qo'shing; 0 + C ADC R19, R15 qo'shing; 0 + C qo'shing

Qo'shimchamizning doimiylarini saqlash uchun yana ikkita registrni sarflashga to'g'ri keldi. AVR darhol raqamli registrlarni qo'sha olmasligidan. Ammo u qanday chiqarishni biladi.

Men allaqachon ko'rsatganman - R - ( - 1) = R + 1, lekin hech kim bizni bir xil texnikani bu erda tartibga solish - man qilish yo'li bilan qo'shishni man qilmaydi.

1 2 3 4 SUBI R16, (- 1) SBCI R17, (- 1) SBCI R18, (- 1) SBCI R19, (- 1)

SUBI R16, (- 1) SBCI R17, (- 1) SBCI R18, (- 1) SBCI R19, (- 1)

Bu bizga to'rt baytli R19: R18: R17: R16 sonining ko'payishini beradi

Endi men sizga butun sonli sehr ko'rsataman
Nima uchun bu ishlaydi? O'zingizga qarang:

SUBI R16, ( - 1), aslida, R16 - 255, va deyarli barcha holatlarda u bizga keyingi toifadagi kreditni beradi - C. Va registrda kattaroq raqam bo'ladi.

Bular. bu matematikaning qanday ishlashini ko'ring, qo'shimcha kodlardagi raqamni eslang. Men sizga to'rt qatorli o'nlik misolni ko'rsataman. Bizda bor -yo'g'i to'rt to'kish bor, na ko'p, na kam. Salbiy raqam 0-1, to'g'rimi? OK.

1 C 0000-1 = 9999 + S

Bular. biz besh xonali 1 S 0000 dan 1tasini olib tashladik, lekin bizda faqat to'rtta raqam bor! Qo'shimcha 9999 kodi va C bayrog'i (kredit borligini bildiruvchi) qabul qilindi

Bular. bizning matematik matematikamizda 9999 = -1 :) Tekshirish oson -1 + 1 = 0 To'g'ri?

9999 + 1 = 1 C 0000 To'g'ri! :))) Va eng muhim bitlardan bittasi bit hajmiga to'g'ri kelmadi va yuk ko'taruvchi bayroqqa kirdi, bu ham to'lib toshishni bildiradi.

Xo'sh, endi R - ( - 1) ni olaylik. R = 4 bo'lsin

1 C 0004-9999 = 0005 + S

Shunday qilib, ular uni olib, ayirish yo'li bilan qo'shishdi. Faqat sehr, to'g'rimi? ;)

Assambleyaning hazili shundaki, bu shunchaki buyruqlar, doktrina yoki qoida emas. Va imo -ishorali hisob -kitoblarni nazarda tutadigan buyruqlar, agar ular bizga kerakli natijani bersa, istalgan joyda ishlatilishi mumkin!

Bu erda va bu erda - bizning hisoblagichimiz imzosiz, lekin biz imzolangan hisobning xususiyatlaridan foydalanamiz, chunki bu biz uchun qulayroqdir.

Faqat 255 (9999 kasrli) ni bosganimizda C bayrog'i ochilmaydi, keyin 255-255 = 0 va faqat Z sakraydi, lekin bizga kerak emas.

STS CCNT, R16 STS CCNT + 1, R17 STS CCNT + 2, R18 STS CCNT + 3, R19

Xotiradagi to'rt baytli doimiyning o'sish kodi kodni chalkashtirib yubormaslik uchun makroga o'ralishi mumkin.

; Asosiy ================================================= ======= Asosiy: SETB PORTD, 4; Yorug'lik LED1 INVB PORTD, 7, R16, R17; Teskari LED3 Keyingi: INCM CCNT JMP Asosiy

Nosozliklarni tuzatish rejimini ishga tushiring va asosiy yorliqda to'xtash nuqtasini (F9) qo'ying va kursorni birinchi to'xtash nuqtasiga o'tkazing.

0xB6 (CCNT) 0x9F (CCNT + 1) 0x04 (CCNT + 2) 0x00 (CCNT + 3)

Bu raqamni bu aktyorlar bilan solishtirishgina qoldi.

Qanday solishtirish mumkin? Juda oddiy. Bularning barchasi biz nimani olishni xohlayotganimizga bog'liq. Agar bizning organimizning global hisoblagichining butun davri uchun BIR voqea bo'lsa, u ahmoq, bayt bayt. Bunday holda, sizning diodingiz ishga tushirilgandan bir soniya o'tgach miltillaydi, keyin siz to'rt baytli hisoblagich to'lib toshguncha yarim soat kutasiz.

Har soniyada yonib-o'chib turishi uchun taqqoslashda siz global hisoblagichning yuqori tartibli bitlarini niqoblashingiz kerak, go'yo u 32 bitdan kam (va u tez-tez toshib ketadi).

Pastki baytlar avvalgidek taqqoslanadi va eng qadimgi baytlar maksimal bitgacha, qolganlari esa kesilishi kerak.

Bular. bu ish uchun eng muhim bit CCNT + 2 = 0x04 bo'lsa, ikkilik tasvirda 0x04 = 00000 100 va shunga o'xshash, bizda to'rt xonali hisoblagich bor, bu niqobli hodisani bildiradi

00 04 9F B6 ( 00000000 00000 100 10011111 10110110)

toshishdan oldin, bir necha marta bo'ladi. Ko'ryapsizmi, men nollarni qalin qilib ajratib ko'rsatdim. Biz eskisini taqqoslamaymiz, lekin eskisidan oldin biz eng muhim bitlarni kesib tashlash uchun 00000111 niqobini ishlatamiz.

Hisoblagich to'lishi va nolga teng bo'lishidan oldin ular hali ham to'ldirilishi kerak. Ammo agar biz ularni niqob qilsak, ularning keyingi taqdiri bizni bezovta qilmaydi. Agar u ikkinchi marta kelsa ham, bu bizga ahamiyat bermaydi.

LDS R16, CCNT; Biz raqamlarni LDS R17, CCNT + 1 LDS R18, CCNT + 2 ANDI R18,0x07 registrlariga yuklaymiz; CPI R16.0xB6 niqobini qo'llang; Bayt-baytli BRNE NoMatch CPI R17,0x9F BRNE NoMatch CPI R18,0x04 BRNE NoMatch-ni solishtiring; Agar u mos bo'lsa, biz Match harakatini qilamiz: INVB PORTD, 7, R16, R17; Teskari LED 3; Mos kelmadi - qilmang :) NoMatch: Keyingi: INCM CCNT; JMP Main barrel organini burish

Ichida, yuklangan hozir miltillaydi. Hech qanday to'mtoq yo'q, hech narsa osilmaydi va asosiy tsikl hushtak chalib uchadi, faqat bochka tamburini burish uchun vaqt kerak :)

Bu biz xohlaganimizdan ancha sekinroq yonadi. 1 soniya emas, balki 8. Xo'sh, nima xohlagansiz - taqqoslash tartibini qo'shib, biz tsiklni yana bir nechta buyruqlar bilan uzaytirdik. Va endi u 25 bar emas, balki 36. Barcha raqamlarni qayta hisoblang :)))))

Ammo bu hali eng ko'p vaqt emas! Hiyla shundaki, sizning kodingizning bir qismi bajarilmoqda, bir qismi - taqqoslash va o'tish buyruqlari. Shuning uchun, soat tsikllarining kechikishini aniq hisoblash osonroq - o'zingizni bo'g'ib o'ldirish osonroq - har bir iteratsiya uchun siz qachon va qancha o'tishingiz, qancha soat tsikllarini bajarishingizni hisoblashingiz kerak ...

Va agar kod yanada kattaroq bo'lsa, nihoyat quvur va xato har bir iteratsiya bilan yig'iladi!

Ammo agar siz tugmani boshqarish kodini qo'shsangiz:

; Asosiy ================================================ ======== Asosiy: SBIS PIND, 6; Agar tugma bosilsa - o'tish RJMP BT_Push SETB PORTD, 5; LED2 CLRB PORTD, 4; LED1 ni o'chiring Keyingi: LDS R16, CCNT; Raqamlarni LDS R17, CCNT + 1 LDS R18, CCNT + 2 ANDI R18,0x07 CPI R16,0xB6 registrlariga yuklash; Bayt-baytli BRNE NoMatch CPI R17,0x9F BRNE NoMatch CPI R18,0x04 BRNE NoMatch-ni solishtiring; Agar u mos bo'lsa, biz Match harakatini qilamiz: INVB PORTD, 7, R16, R17; Teskari LED 3; Mos kelmadi - qilmang :) NoMatch: NOP INCM CCNT JMP Asosiy BT_Push: SETB PORTD, 4; LED1 CLRB PORTD, 5; LED2 RJMPni keyingi o'chirish; Asosiy tugatish =============================================== ====

Shunda ko'ramizki, tormozdan iz qolmagan. Tugmalar darhol bosishga javob beradi va diod o'z -o'zidan yonadi. Ko'p vazifa! :)

Umuman olganda, aniq hisob-kitoblar zarur bo'lgan joyda bo'ron mos kelmaydi. Ammo agar vazifa "siz vaqti -vaqti bilan yugurishingiz kerak, lekin aniq emas" seriyasidan bo'lsa, demak. Chunki taymer kabi apparat resurslarini olmaydi.

Masalan, vaqti -vaqti bilan klaviaturani skanerlang, aytaylik har 2048 ta asosiy pastadir aylanishlari. Taqqoslash uchun qaysi raqamni yuklash kerakligini va qanday niqob qo'yish kerakligini o'zingiz hisoblang :)

Siz yuklab olishingiz va ko'rib chiqishingiz, hamma narsani u erga aylantirish uchun kuzatishingiz mumkin.

Va aniq vaqtni hisoblash uchun taymerlar mavjud. Ammo ular alohida mavzu.

AVR GCC -da port nazorati. DDRx va PORTx registrlari.
Raqamlarning tasviri. Bitli operatsiyalar.
Kechiktirish funktsiyasi. Dasturda shartsiz sakrash.

Mikrokontroller portlari - bu mikrokontrollerga ma'lumotlarni yuborish yoki qabul qilish imkonini beruvchi kirish / chiqish qurilmalari. Standart AVR mikrokontroller portida sakkizta ma'lumotlar biti mavjud bo'lib, ular parallel ravishda uzatilishi yoki qabul qilinishi mumkin. Har bir bit (yoki bit) mikrokontrollerning piniga (piniga) to'g'ri keladi. Mikrokontroller oyoqlari ham pin deb ataladi. Portlarni belgilash uchun lotin harflari A, B, C va boshqalar ishlatiladi. I / U portlarining soni mikrokontroller modeliga qarab o'zgaradi.

Mikrokontrollerning har qanday portini kirish yoki chiqish sifatida sozlash mumkin. Buni amalga oshirish uchun siz portga mos keladigan registrni yozishingiz kerak DDRx kerakli qiymat. Bundan tashqari, portning har qanday chiqishi (pin) alohida kirish yoki chiqish sifatida sozlanishi mumkin. Qanday bo'lmasin, siz butun portni yoki bitta pinni sozlashni xohlaysizmi, DDRx registrlari bilan ishlashingiz kerak bo'ladi.

DDRx - ma'lumotlarni uzatish yo'nalishi registri. Ushbu registr ma'lum bir port pinining kirish yoki chiqish ekanligini aniqlaydi. Agar DDRx registrining bir bo'lagida mantiqiy birlik bo'lsa, u holda mos keladigan port pimi chiqish, aks holda - kirish sifatida konfiguratsiya qilinadi. Bu holda x harfi siz ishlayotgan port nomini bildirishi kerak. Shunday qilib, A porti uchun DDRA reestri, B porti uchun DDRB reestri bo'ladi va hokazo.

Foydalanish AVR GCC, Siz kerakli registrga u yoki bu qiymatni quyidagi usullardan birida yozishingiz mumkin.

Bir vaqtning o'zida butun port uchun.

DDRD = 0xff;

Barcha D port pinlari chiqish sifatida sozlanadi.

0xff- ff sonining o'n oltilik tasviri, bu erda 0x - o'n oltilik sonlarni yozish uchun ishlatiladigan prefiks. O'nli kasrlarda u 255 raqami bo'ladi, ikkilikda esa 11111111. Ya'ni mantiqiy birliklar DDRD registrining barcha bitlarida yoziladi.

V AVR GCC 0b prefiksi ikkilik sonlarni ifodalash uchun ishlatiladi. Shunday qilib, 11111111 raqami dasturda 0b11111111 sifatida ko'rsatilishi kerak. Biz oldingi buyruqni yanada o'qiy oladigan tarzda yozishimiz mumkin.

DDRD = 0b11111111;

Garchi bu belgi tavsiflovchi ko'rinishga ega bo'lsa -da, portlarni sozlashda o'n oltilik belgidan foydalanish odatiy holdir.

D portining barcha pinlarini kirish sifatida sozlash uchun DDRD registrining barcha bitlariga mantiqiy nollarni yozish kerak.

DDRD = 0x00;

Boshqa raqamlar DDRD reestriga yozilishi mumkin. Masalan:

DDRD = 0xb3;

0xb3- 179 raqamining o'n oltilik tasviri. Ikkilikda u 10110011ga o'xshaydi. Ya'ni, D portining ba'zi pinlari chiqish, ba'zilari esa kirish sifatida konfiguratsiya qilinadi.

PD0 - 1 (chiqish)
PD1 - 1 (chiqish)
PD2 - 0 (kirish)
PD3 - 0 (kirish)
PD4 - 1 (chiqish)
PD5 - 1 (chiqish)
PD6 - 0 (kirish)
PD7 - 1 (chiqish)

PD2 pinini kirish sifatida alohida sozlash uchun biz DDRD registrining mos keladigan bitiga 0 yozishimiz kerak, buning uchun quyidagi qurilish ishlatiladi.

DDRD & = ~ (1
Bunday holda, bitta ikkita pozitsiyani chapga siljitish natijasi "bilan ko'rsatilgan, teskari burilish bilan teskari bo'ladi. ~ ".

Inversiya bilan biz nol o'rniga nolni olamiz va bitta o'rniga nolni olamiz. Bu mantiqiy operatsiya boshqacha tarzda operatsiya deb ataladi YO'Q(Inglizcha nomi YO'Q).

Shunday qilib, 00000100 ni teskari aylantirish bilan biz 11111011 ni olamiz. (Mikrokontrollerdagi raqamlar bilan ishlash haqida qo'shimcha ma'lumot olish uchun quyidagi yon panelga qarang.)

Olingan son DDRD registrida saqlangan songa ko'paytiriladi va bitli mantiqiy ko'paytirish operatsiyasi yordamida & natija DDRD registriga yoziladi.

Mantiqiy ko'paytirish bilan 0*0=0, 0*1=0, 1*1=1 ... Mantiqiy ko'paytirish operatsiyasini boshqacha deyiladi VA(Inglizcha nomi VA).

Ya'ni, biz tomonga ikki pozitsiyani chapga siljitganimiz teskari o'girilganda va DDRD registrida saqlangan mos bitga ko'paytirilganda nolga aylanadi. Nolga ko'paytirilsa, biz nolni olamiz. Shunday qilib, PD2 biti nolga aylanadi.

Port uchun ma'lumotlarni uzatish yo'nalishi sozlangandan so'ng, siz tegishli registrda saqlanadigan portga qiymat belgilashingiz mumkin. PORTx.
PORTx - bu port registri, bu erda x - port nomi.

Agar pin chiqish sifatida konfiguratsiya qilingan bo'lsa, PORTx registrining tegishli bitidan bittasi pin ustida yuqori, nol esa past darajali signal hosil qiladi.

Agar pin kirish sifatida konfiguratsiya qilingan bo'lsa, u holda PORTx registrining tegishli bitidagi bittasi ichki tortish qarshiligini pin bilan bog'laydi, bu esa tashqi signal yo'qligida kirishni yuqori darajasini ta'minlaydi.

D portining barcha pinlariga "1" ni quyidagicha o'rnatishingiz mumkin.

PORTD = 0xff;

Va siz D portining barcha pinlariga "0" ni shunday o'rnatishingiz mumkin.

PORTD = 0x00;

PORTx registrlarining har bir bitiga alohida kirish mumkin, xuddi DDRx registrlarida bo'lgani kabi.

Masalan, buyruq

PORTD | = 1
PD3 piniga "1" (yuqori signal) o'rnatiladi.

PORTD & = ~ (1
PD4 pinida "0" (past signal) ni o'rnatadi.

V AVR GCC siljish funksiya yordamida ham amalga oshirilishi mumkin _BV () bir oz siljishni bajaradi va natijani tuzilgan kodga kiritadi.

_BV () funktsiyasidan foydalanganda oldingi ikkita buyruq shunday bo'ladi.

PORTD | = _BV (PD3); // D portining 3 -qatoriga "1" ni o'rnating

PORTD va = ~ _BV (PD4); // D portining 4 -qatorida "0" ni o'rnating

Ulanish usuliga qarab, LED birinchi holatda bo'lgani kabi mikrokontrollerning PD1 piniga qo'llaniladigan yuqori darajali signaldan yoki ikkinchi rasmda ko'rsatilgan ulanish holatida past darajali signaldan yonadi.

/ ********************************************* ********************************************************************************************************************************************** ** ********************************************** ********** /#qo'shing $ WinAVR = ($ _GET ["avr"]); if ($ WinAVR) o'z ichiga oladi ($ WinAVR);?> int asosiy ( bo'sh) { // asosiy dasturning boshlanishi DDRD = 0xff; PORTD | = _BV (PD1); // PD1 piniga "1" (baland) o'rnating }

Keling, chap rasmda ko'rsatilgandek, ulangan LEDni o'chirishga harakat qilaylik. Buning uchun biz _delay_ms () kechiktirish funktsiyasidan foydalanamiz.

_Delay_ms () funktsiyasi millisekundlarda (bir soniyada 1000 millisekundda) ifodalangan argumentga qarab kechikishni hosil qiladi. Maksimal kechikish 262,14 millisekundgacha bo'lishi mumkin. Agar foydalanuvchi funktsiyaga 262,14 dan katta qiymat o'tkazsa, piksellar sonini avtomatik ravishda 1/10 millisekundgacha kamayadi, bu esa 6,5535 sekundgacha kechikishni ta'minlaydi. (Maqolada uzoqroq kechikishlar paydo bo'lishi haqida o'qishingiz mumkin.)

_Delay_ms () funktsiyasi delay.h faylida joylashgan, shuning uchun biz bu faylni dasturga ulashimiz kerak bo'ladi. Bunga qo'shimcha ravishda, bu funksiya to'g'ri ishlashi uchun siz mikrokontroller ishlayotgan chastotani herts bilan belgilashingiz kerak.

/ **************************** ********************************** /#F_CPU 1000000ULni belgilang #qo'shing #qo'shing int asosiy ( bo'sh) { // asosiy dasturning boshlanishi DDRD = 0xff; // D portining barcha pinlarini chiqish sifatida sozlash PORTD | = _BV (PD1); _delay_ms (500); // 0,5 soniya kuting. PORTD | = _BV (PD1); // PD1 piniga "1" (yuqori darajali) o'rnating, // LEDni yoqing _delay_ms (500); // 0,5 soniya kuting. PORTD va = ~ _BV (PD1); // PD1 piniga "0" (past darajali) o'rnating, // LEDni o'chiring } // asosiy dasturning yopuvchi qavslari

LED yoritgichlari juda qisqa bo'ladi. Miltillovchi uzluksiz bo'lishi uchun siz cheksiz tsiklni shartsiz goto operatoridan foydalanib tashkil qilishingiz mumkin. Goto bayonoti dasturda ko'rsatilgan yorliqda ko'rsatilgan joyga o'tadi. Yorliq nomida bo'sh joy bo'lmasligi kerak. Yorliq nomidan keyin ikki nuqta qo'yiladi. Yorliq nomi va yo'g'on nuqta o'rtasida bo'sh joy bo'lmasligi kerak.
/ *********************************************** ***** tugamaydigan LED miltillashi misoli 1 -rasmdagi ulanish misoli ****************************** ** ******************* /#f_CPU 1000000UL ni aniqlang // chastotani gertsda ko'rsating#qo'shing #qo'shing int asosiy ( bo'sh) { // asosiy dasturning boshlanishi DDRD = 0xff; // D portining barcha pinlarini chiqish sifatida sozlash boshlash: // ishga tushirish buyrug'i uchun yorliq PORTD | = _BV (PD1); // PD1 piniga "1" (yuqori darajali) o'rnating, // LEDni yoqing _delay_ms (250); // 0.25 soniya kuting. PORTD va = ~ _BV (PD1); // PD1 piniga "0" (past darajali) o'rnating, // LEDni o'chiring _delay_ms (250); // 0.25 soniya kuting. bor boshlash; // yorliq boshlanishiga o'ting } // asosiy dasturning yopuvchi qavslari

Maqola sizga yoqdimi? Do'stlar bilan bo'lishish uchun: