Internet Windows Android
Kengaytirish

Atmel AVR mikrokontrollerlari uchun C tilidagi misollar. Tugmani ulash - CV AVR da dasturlash? Avr-da tugmalar bilan tajribalar

Ba'zan siz juda kichik qurilma qilishingiz kerak, masalan, velosiped kompyuteri. Yoki dizayn ko'plab tugmachalarni joylashtirishga imkon bermaydi. Umuman olganda, bizda bitta kiritish tugmasi bor va boshqa hech narsa yo'q.

Spartan sharoitlari, lekin bu erda ham siz kuchli funksionallikni, ko'p darajali menyularni va hayotning boshqa lazzatlarini qo'llashingiz mumkin. Endi men bunday nazoratning amalga oshirilishidan birini ko'rsataman.

Xo'sh, bizning tugma nima qila oladi?

  • Uni qisqa bosish mumkin
  • Siz uzoqroq bosishingiz mumkin
  • Siz presslarning turli kombinatsiyalarini qilishingiz mumkin
  • U kerakli vaqtda chiqarilishi mumkin


Ko'p emas, lekin juda yaxshi. Keyin bitta tugma uchun. Buni yozishda asosiy muammo - bu baxtsiz tugmani qayta ishlash uchun juda ko'p tizim resurslarini (CPU vaqti, taymerlar va minglab) behuda sarflamaslikdir. Axir, biz bosish faktini, bosish faktini, bosish vaqtini, turli vaqtlar bilan bosish sonini kuzatishimiz kerak bo'ladi. Men ushbu interfeysning shu qadar dahshatli ilovalarini ko'rdimki, men bu bir qarag'ay daraxtiga shunchalik ko'p ahmoqona narsalar va sekinlashuvlarni to'plash va hatto barcha taymerlarni behuda sarflash mumkinligiga hayron bo'ldim :)

Shunday qilib, biz texnik xususiyatlarni quyidagicha o'rnatamiz:

  • Dispetcher taymeridan tashqari apparat taymerlari yo'q.
  • Vaqtni kechiktirish yo'q, shunchaki taymerda o'zingizga qo'ng'iroq qiling.
  • Tsiklda bosish va nashrlarni kutishning hojati yo'q. Ular kirib, tekshirishdi va nazoratdan voz kechishdi.
  • Keling, vaqt oralig'ini mode_time kiritamiz, uning davomida biz bosish kombinatsiyasini kuzatamiz. Aytaylik, 2s
  • Chiqish ma'lum bir interval uchun qisqa va uzoq bosishlar soni bo'ladi

Algoritm
Keling, hamma narsani cheklangan mashinada qilaylik. U uchta holatga ega bo'ladi:

  • Yuqoriga - tugmasi bosilmagan
  • Dn - tugmasi bosildi
  • Al - tugmasi uzoq bosilgandan keyin qo'yib yuborildi

Shuningdek, bitta xizmat protsedurasi bo'ladi, bu tugma bilan birinchi amaldan so'ng mode_time (2c) barcha natijalarni oladi va ular bilan biror narsa qiladi. Nima - endi muhim emas. Dasturga bog'liq.
Va bu axlatlarning barchasi har 20 msda bir marta dispetcher orqali (yoki boshqa yo'l bilan) o'zini chaqirib, halqada aylanadi.

Yuqoriga
Keling, ichkariga kiramiz.
Ko'ramiz, tugma bosilganmi? Agar yo'q bo'lsa, biz ketamiz. Agar bosilsa, mashinani Dn holatiga o'tkazing
Bu intervalni birinchi marta tekshiryapmizmi? Agar birinchi bo'lsa, biz xizmat ko'rsatish tartibimizni kechiktirilgan ishga tushiramiz (2 soniyadan keyin) va jarayon boshlangan bayroqni ko'taramiz.
Tashqariga chiqaylik.

Dn
Keling, ichkariga kiramiz.
Hali ham bosilganmi? Agar yo'q bo'lsa, tugma allaqachon qo'yib yuborilgan, yuqoriga holatiga qaytaring va qisqa bosish hisoblagichini oshirib, bir marta qisqa bosishni hisoblang. cnt_s. Agar u hali ham bosilsa, vaqtni bosish davomiyligini o'lchash uchun vaqt hisoblagichini bosing. Biz mashinaning iteratsiyasida davomiylikni o'lchaymiz. Bir iteratsiya 20 ms. Men uzoq bosish chegarasini 20 iteratsiyaga qo'ydim, bu taxminan 400 ms beradi. 0,4 soniyadan uzunroq bo'lgan har qanday narsa uzoq bosish hisoblanadi. 20 dan ortiq iteratsiya o'tgandan so'ng, biz bitta uzoq bosishni hisoblaymiz va mashinani Al holatiga o'tkazamiz. Tashqariga chiqaylik.

Al
Keling, ichkariga kiramiz.
Hali qo'yib yubormadingizmi? Agar yo'q bo'lsa, biz ketamiz. Agar tugma qo'yib yuborilsa, biz Time o'zgaruvchisini tashlab, Yuqoriga o'tamiz.


mode_time vaqtida, biz urish uchun vaqtimiz bo'lgan ikki soniya ichida hamma narsa bizniki. Yig'ilgan ma'lumotlarni tahlil qilish tartibi boshlanadi va tartibsizlikni tozalaydi. U erda hamma narsa allaqachon oddiy. Biz kerakli harakatni yaratish uchun banal holatdan foydalanamiz. Misol uchun, men boshqa vazifa tomonidan to'xtatilgan tasdiqlash qutilarini o'rnatdim. Asosiysi, keyingi kombinatsiyani o'tkazib yubormaslik uchun bu vazifani og'ir narsa bilan to'sib qo'ymaslikdir.

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 #o'z ichiga oladi u08 bt1, bt2, bt3, bt4, bt5, bt_l, bt_l2, bt_al; // O'zgaruvchilar - bu bosilgan tugmalarning bayroqlari. // Ularni bitli maydonlarga aylantirish samaraliroq // Lekin men dangasa edim. O'zingizni optimallashtiring :) u16 bt_mode_time = 2000; // Tahlil ketma-ketligi davomiyligi // Doimiy emas, o'zgaruvchi yaratildi // tezda o'zgartirishingiz mumkin. Kamaytirish // bu erda uzoq kombinatsiyalarni kutish shart emas // bu interfeysning sezgirligini sezilarli darajada oshiradi u08 bt_cnt; // Ketma-ketlik tahlil qilinayotganligini bildiruvchi belgi u08 bt_cnt_s; // Qisqa bosish hisoblagichi u08 bt_cnt_l; // Hisoblagichni uzoq bosib turing void bt_scan(void) // Bu funksiya skanerdir. U har 20 msda bir marta chaqirilishi kerak { #define up 0 // Mashinaning holatini belgilaydi. 0 - sukut bo'yicha.#define dn 1 #define al 3 statik u08 bt_state= 0 ; // Mashinaning holati o'zgaruvchisi statik u08 bt_time = 0; // Mashinaning ishlash vaqti o'zgaruvchisi almashtirish (bt_state) // Haqiqiy mashina(katta: ( agar (yopish) // Agar tugma bosilsa(bt_state = dn; // Pastdagi bosqich bt_time = 0; // Vaqt hisoblagichini tiklash agar (bt_cnt== 0 ) // Agar birinchi marta kombinatsiyalangan bo'lsa(SetTimerTask(bt_ok, bt_mode_time) ; // Tahlil jarayonini boshlang bt_cnt = 1; // Hisoblash boshlandi! )) sindirish; // Chiqish ) case dn: ( agar (Yopish) // Hali ham bosilganmi?(agar (20 > bt_vaqt) // 20*20ms dan kamroq vaqt davomida bosildimi?( // Ha bt_time++; //Iteratsiya hisoblagichini oshiring) else ( bt_state = al; // Yo'q, ko'proq! Ha, bizda uzoq vaqt bor! Keling, ALga boraylik bt_time = 0; // Klik o'lchash vaqtini qayta o'rnating bt_cnt_l++; // Bir marta uzoq bosishni hisoblang) ) else ( bt_state = yuqoriga; // Tugma qo'yib yuborildimi? bt_time = 0; // O'lchash vaqti nolga bt_cnt_s++; // Qisqa bosish hisoblagichi) sindirish; // Exit ) case al: // Agar uzoq bosilgan bo'lsa, biz shu yerdamiz( if (Ochish) // Chiqarilganmi? ( bt_state = up; // Ha! Bosqich yuqorida bt_time = 0 ; // Vaqt 0 da bt_al = 1 ; // "Uzoqdan keyin chiqarish" hodisasi qayd etildi) sindirish; ) ) SetTimerTask(bt_scan, 20 ); // Dispetcher orqali aylantirildi. } // Va bu 2 soniyadan keyin ishlaydigan va barcha hisoblash natijalarini tanlaydigan funksiya void bt_ok(void) // Biz bu erda voqealarning dekodlanishini ushlaymiz(switch(bt_cnt_s) // Qancha qisqa bosish borligini ko'ring(1-holat: bt1 = 1; tanaffus; // Biz bu bayroqni qo'ydik 2-holat: bt2 = 1; sindirish; 3-holat: bt3 = 1; sindirish; 4-holat: bt4 = 1; sindirish; 5-holat: bt5 = 1; sindirish; standart: tanaffus; ) almashtirish (bt_cnt_l) // Qancha uzun bosish borligini ko'ring(1-holat: bt_l = 1; tanaffus; // Biz bu bayroqni qo'ydik 2-holat: bt_l2 = 1; sindirish; standart: tanaffus; ) bt_cnt = 0; // Hisoblagichlarni tiklash bt_cnt_s = 0; bt_cnt_l = 0; )

#o'z ichiga oladi u08 bt1, bt2, bt3, bt4, bt5, bt_l, bt_l2, bt_al; // O'zgaruvchilar - bu bosilgan tugmalarning bayroqlari. // Ularni maydonlarni bit qilish samaraliroq // Lekin men juda dangasa edim. O'zingizni optimallashtiring :) u16 bt_mode_time = 2000; // Tahlil ketma-ketligining davomiyligi // Doimiy emas, o'zgaruvchi yaratildi // uni tezda o'zgartirish uchun. Qisqartirish // bu erda uzoq kombinatsiyalarni kutishning hojati yo'q // u08 bt_cnt interfeysining sezgirligini sezilarli darajada oshiradi; // Ketma-ket tahlil qilinayotganini bildiruvchi belgi u08 bt_cnt_s; // Qisqa bosishlar hisoblagichi u08 bt_cnt_l; // Uzoq bosish hisoblagichi void bt_scan(void) // Bu funksiya skanerdir. U har 20 msda bir marta chaqirilishi kerak ( #define up 0 // Mashinaning holatini aniqlash. 0 - sukut bo'yicha. #define dn 1 #define al 3 static u08 bt_state=0; // Mashina holati o'zgaruvchisi static u08 bt_time =0; // Mashina kalitining o'zgaruvchan ish vaqti(bt_state) // Mashinaning o'zi ( katta: ( if(Yopish) // Agar tugma bosilsa ( bt_state = dn; // Bosqichni pastga tushirish bt_time = 0; // Vaqtni qayta o'rnatish) counter if(bt_cnt==0 ) // Agar kombinatsiyada birinchi marta bo'lsa ( SetTimerTask(bt_ok,bt_mode_time); // Tahlil jarayonini boshlang bt_cnt =1; // Hisoblash boshlandi! ) ) tanaffus; case dn: ( if(Close) // Hali ham bosilganmi? ( if (20 > bt_time) // 20*20ms dan kamroq bosilganmi? ( // Ha bt_time++; // Iteratsiya hisoblagichini oshiring ) else ( bt_state = al; / / Yo'q, ko'proq bosamiz! tugma chiqarildimi bt_time = 0 // o'lchash vaqti nolga bt_cnt_s++; // Qisqa bosish hisoblagichi ) sindirish; // Chiqish ) case al: // Va agar uzoq bosilgan bo'lsa, mana biz ( if (Ochish) // Chiqarilganmi? ( bt_state = yuqoriga; // Ha! Bosqich yuqoriga bt_time = 0; // Vaqt 0 bt_al = 1; // "Uzoqdan keyin chiqarish" hodisasi yozildi ) ) SetTimerTask(bt_scan,20); // Dispetcher orqali aylantirildi. ) // Va bu funksiya 2 soniyadan so'ng ishlaydi va barcha hisoblash natijalarini tanlaydi void bt_ok(void) // Biz bu erda voqealar shifrini ushlaymiz ( switch(bt_cnt_s) // Qancha qisqa bosish borligini ko'rib chiqamiz ( case 1: bt1 = break; // Bu bayroqcha 2: bt2 = 1 hol: break 4: break 5: ko'ramiz; = 1; bu katakchani belgilang: bt_cnt = 0;

Kod shunday yozilganki, tom ma'noda bir nechta satr AVRga bog'langan. Hech bo'lmaganda tugmachada ishlov beruvchi kodini bosing. Uskuna uchun barcha biriktirmalar sarlavhaga kiradi va u erda umuman hech narsa yo'q:

1 2 3 4 5 6 7 8 9 10 11 #o'z ichiga oladi #o'z ichiga oladi #define Open (BTN_PIN & 1<#define Yopish (!Ochish) extern void bt_scan(void ) ; void bt_ok(void) ; extern u08 bt1, bt2, bt3, bt4, bt5, bt_l, bt_l2, bt_al; extern u16 bt_mode_time;

#o'z ichiga oladi #o'z ichiga oladi #define Open (BTN_PIN & 1<

Shunday qilib, buni boshqa arxitekturaga o'tkazish ikki qatorni o'zgartirish masalasidir. Xo'sh, siz autorun mexanizmini o'zgartirishingiz va ishlov beruvchi funktsiyasini ishga tushirishingiz kerak bo'lishi mumkin. Agar siz o'zingizning dispetcheringizdan, operatsion tizimingizdan yoki proshivkani tashkil qilish uchun boshqa tizimdan foydalansangiz. Ammo bu tuzatish uchun ikkita kod qatori.

Maqolada tasvirlangan barcha go'sht ikkita faylda mavjud. tugmasi.c Va tugma.h

Ish haqida video

Jiringlash
Endi shitirlash bilan shug'ullanishning hojati yo'q. Chunki skanerlash chastotasi past, shuning uchun TM2 modelining yalang'och va kuchli oksidlangan tugmasi ham shitirlash ovozini chiqarmadi - u keyingi skanerlash boshlanishidan oldin tugadi. Lekin bu erda qo'shishingiz mumkin bo'lgan narsa shovqin natijasida noto'g'ri signallardan himoyalanishdir. Oxir oqibat, shovqin o'qish paytida chiziq bo'ylab surilishi bilanoq, bir marta bosish ishi hisobga olinadi. Mashinaning holatini tekshirish orqali buning oldini olish mumkin. Aytaylik, ikki yoki uch marta tugma bosilganligini tasdiqlash uchun Up ga iteratsiya hisoblagichini qo'shing va shundan keyingina Dn ga o'ting.

Variantlar
To'g'ri, loyihamda men ishlov berishni biroz o'zgartirdim. Chunki Menga bir nechta uzoq bosish kerak emas edi, shuning uchun men darhol AL ishlov beruvchisida "Uzoq bosish" bayrog'ini o'rnatdim va shu bilan birga uzoq bosish sonini hisoblashni olib tashladim. Bu qurilma interfeysining sezgirligini oshirishga imkon berdi, bu erda menyu bandiga kirish uchun uzoq bosish ishlatilgan va ikkita uzun bosish bilan kombinatsiyalar umuman ishlatilmagan.

Albatta, xuddi shu chekli avtomat har qanday narsani tahlil qilish uchun ishlatilishi mumkin. Masalan, matritsali klaviatura yoki ba'zi signalizatsiya qurilmasidan boshqa bayroqni kuzatish uchun.

Vazifa: Keling, bitta LEDni boshqarish dasturini ishlab chiqaylik. Tugma bosilganda LED yonadi va qo'yib yuborilganda o'chadi.

Birinchidan, qurilmaning sxematik diagrammasini ishlab chiqamiz. I/U portlari har qanday tashqi qurilmalarni mikrokontrollerga ulash uchun ishlatiladi. Portlarning har biri ham kirish, ham chiqish sifatida ishlashga qodir. Keling, LEDni portlardan biriga, tugmani esa boshqasiga ulaymiz. Ushbu tajriba uchun biz boshqaruvchidan foydalanamiz Atmega8. Ushbu chip 3 ta kiritish/chiqarish portiga ega, 2 ta sakkiz bitli va 1 ta o'n olti bitli taymer/taymerga ega. Shuningdek, bortda 3-kanalli PWM, 6-kanalli 10-bitli analog-raqamli konvertor va boshqalar mavjud. Menimcha, mikrokontroller dasturlash asoslarini o'rganish uchun juda yaxshi.

LEDni ulash uchun biz PB0 chizig'idan foydalanamiz va tugmadan ma'lumotni o'qish uchun biz PD0 chizig'idan foydalanamiz. Diagramma 1-rasmda ko'rsatilgan.

Guruch. 1

R2 rezistori orqali PD0 kirishiga ortiqcha ta'minot kuchlanishi beriladi, bu mantiqiy bitta signalga mos keladi. Tugma yopilganda, kuchlanish nolga tushadi, bu mantiqiy nolga to'g'ri keladi. Kelajakda R2 sxemadan chiqarib tashlanishi mumkin, uni ichki yuk qarshiligi bilan almashtirib, dasturga kerakli sozlamalarni kiritadi. LED oqim cheklovchi R3 rezistori orqali PB0 portining chiqishiga ulangan. LEDni yoqish uchun siz PB0 liniyasiga mantiqiy bitta signalni qo'llashingiz kerak. Biz 4 MGts chastotada ichki asosiy soat generatoridan foydalanamiz, chunki qurilma chastota barqarorligi uchun yuqori talablarga ega emas.

Endi dasturni yozamiz. Men dasturlarni yozish uchun dasturlash muhitidan foydalanaman AVR Studio Va WinAvr. AVR Studio-ni oching, xush kelibsiz oynasi ochiladi, "Yangi loyiha yaratish" tugmasini bosing, keyin loyiha turini tanlang - AVR GCC, loyiha nomini yozing, masalan, "cod1", "Loyiha papkasini yaratish" va "Yaratish" ni tekshiring. ishga tushirish fayli" katakchalarini belgilang, "Keyingi" tugmasini bosing, chap oynada "AVR Simulator" ni tanlang va o'ng oynada "Atmega8" mikrokontroller turini tanlang, "Finish" tugmasini bosing, muharrir va loyiha toifasi daraxti ochiladi - dastlabki sozlamalar tugallandi.

Birinchidan, tashqi fayllarni biriktirish uchun operator yordamida Atmega8 uchun standart tavsif matnini qo'shamiz: #o'z ichiga oladi

direktiv sintaksisi #o'z ichiga oladi

#o'z ichiga oladi<имя_файла.h>
# "fayl nomi.h" ni kiriting

Burchakli qavslar< и >kompilyatorga kiritilgan fayllarni birinchi navbatda "include" nomli standart WinAvr papkasida izlash kerakligini ko'rsating. Ikki qo'shtirnoq " va " kompilyatorga loyiha saqlanadigan katalogda qidirishni boshlashni aytadi.

Har bir turdagi mikrokontroller o'zining sarlavha fayliga ega. ATMega8 uchun bu fayl iom8.h, ATtiny2313 uchun - iotn2313.h deb ataladi. Har bir dasturning boshida biz foydalanayotgan mikrokontrollerning sarlavha faylini kiritishimiz kerak. Ammo io.h nomli umumiy sarlavha fayli ham mavjud. Preprotsessor ushbu faylni qayta ishlaydi va loyiha sozlamalariga qarab, bizning dasturimizga kerakli sarlavha faylini o'z ichiga oladi.

Biz uchun dasturning birinchi qatori quyidagicha ko'rinadi:

#o'z ichiga oladi

Har qanday C dasturi bitta asosiy funktsiyani o'z ichiga olishi kerak. U asosiy deb nomlanadi. Dasturning bajarilishi har doim asosiy funktsiyani bajarishdan boshlanadi. Funktsiya sarlavhaga ega - int main(void) va tanasi - u jingalak qavslar () bilan ajratilgan.

int asosiy (yaroqsiz)
{
funktsiya tanasi
}

Biz kodimizni funktsiya tanasiga qo'shamiz. Qaytish turi funksiya nomidan oldin ko'rsatilgan. Agar funktsiya qiymatni qaytarmasa, kalit ishlatiladi bekor.

int- bu 2 baytlik butun son, qiymatlar diapazoni - 32768 dan 32767 gacha

Funksiya nomidan keyin funksiya chaqirilganda unga uzatiladigan parametrlar qavs ichida ko'rsatilgan (). Agar funktsiyada hech qanday parametr bo'lmasa, kalit so'z ishlatiladi bekor. Funktsiya asosiy buyruqlar to'plamini, tizim sozlamalarini va asosiy dastur tsiklini o'z ichiga oladi.

Keyin portni sozlaymiz D kiraverishda. Portning ishlash rejimi registrning mazmuni bilan belgilanadi DDRD(ma'lumot uzatish yo'nalishi reestri). Ushbu registrga "0x00" raqamini yozamiz (0b0000000 - ikkilik shaklda); Siz registrning har bir bitiga (0-kirish, 1-chiqish) 0 yoki 1 raqamlarini yozish orqali portni bit-bit sozlashingiz mumkin, masalan, DDRD = 0x81 (0b10000001) - D portining birinchi va oxirgi qatorlari quyidagicha ishlaydi. chiqish, qolganlari kirish sifatida. Ichki yuk qarshiligi ham ulanishi kerak. PORTx registri port kiritish rejimida bo'lganda ichki rezistorlar yoqilgan yoki o'chirilganligini nazorat qiladi. Keling, u erda birliklarni yozamiz.

Portni sozlash B chiqishga. Portning ishlash rejimi registrning mazmuni bilan belgilanadi DDRB. Portga LEDdan boshqa hech narsa yo'q B ulanmagan, shuning uchun butun portni chiqish sifatida sozlash mumkin. Bu registrga yozish orqali amalga oshiriladi DDRB"0xFF" raqamlari. LEDni birinchi marta yoqilganda yonib ketishining oldini olish uchun portga yozing B mantiqiy nollar. Bu ro'yxatga olish orqali amalga oshiriladi PORTB= 0x00;

Qiymatlarni belgilash uchun "=" belgisi qo'llaniladi va "teng" belgisi bilan adashtirmaslik uchun belgilash operatori deb ataladi.

Port konfiguratsiyasi quyidagicha ko'rinadi:

DDRD = 0x00;
PORTD = 0xFF;
DDRB = 0xFF;
PORTB = 0x00;

Biz dasturning asosiy tsiklini yozamiz. esa(«while» ingliz tilidan) - bu buyruq shart bajarilmaguncha, ya'ni qavs ichidagi ifoda to'g'ri bo'lgunga qadar tsiklning tanasini ko'p marta takrorlab, tsiklni tashkil qiladi. C tilida ifoda nolga teng bo'lmasa to'g'ri, bo'lsa noto'g'ri deb hisoblanadi.

Buyruq shunday ko'rinadi:

while (shart)
{
halqa tanasi
}

Bizning holatda, asosiy tsikl faqat bitta buyruqdan iborat bo'ladi. Bu buyruq registrni tayinlaydi PORTB o'zgartirilishi kerak bo'lgan registr qiymati PORTD.

PORTB = ~PIND; // D portidagi qiymatni oling, uni o'zgartiring va PORTB ga belgilang (PORTB ga yozing)

// C ifodalari o'ngdan chapga o'qiladi

PIND ma'lumotlarni kiritish registri. Tekshirish moslamasining tashqi chiqishidan ma'lumotni o'qish uchun siz avval portning kerakli bitini kirish rejimiga o'tkazishingiz kerak. Ya'ni, registrning tegishli bitiga yozing DDRx nol. Shundan keyingina ushbu pinga tashqi qurilmadan raqamli signal berilishi mumkin. Keyinchalik, mikrokontroller baytni registrdan o'qiydi PINx. Tegishli bitning tarkibi portning tashqi pinidagi signalga mos keladi. Bizning dasturimiz tayyor va quyidagicha ko'rinadi:

#o'z ichiga oladi int main (void) ( DDRD = 0x00; // port D - kirish PORTD = 0xFF; // yuk qarshiligini ulang DDRB = 0xFF; // B porti - chiqish PORTB = 0x00; // chiqishni 0 ga o'rnating while(1) ) ( PORTB = ~PIND; //~ bitli inversiya belgisi ))

Sharhlar C tilida keng qo'llaniladi. Yozishning ikki yo'li mavjud.

/*Izoh*/
//Izoh

Bunday holda, kompilyator izohda yozilgan narsalarga e'tibor bermaydi.

Agar siz xuddi shu dasturdan foydalansangiz va 2-rasmda ko'rsatilganidek, mikrokontrollerga 8 ta tugma va 8 LEDni ulasangiz, u holda portning har bir biti aniq bo'ladi. D uning port bitiga mos keladi B. SB1 tugmachasini bosish bilan HL1 yonadi, SB2 tugmachasini bosish bilan HL2 yonadi va hokazo.

2-rasm

Maqolada A.V.Belovning kitobidan foydalanilgan. "AVR qurilmalarini ishlab chiquvchilar uchun qo'llanma"

Mikrokontrollerli deyarli hech qanday mahsulot tugmalarsiz to'liq bo'lmaydi. Bu mavzu allaqachon buzilgan va ko'pchilikka ma'lum. Ushbu maqolani yozish bilan men g'ildirakni qayta ixtiro qilmoqchi emasman. Men faqat sxema bo'yicha barcha ma'lumotlarni bir joyga to'plashga qaror qildim. O'ylaymanki, material yangi boshlanuvchilar uchun foydali bo'ladi, sizni chalkashtirmaslik uchun quyidagi raqamlar mikrokontrollerlar uchun quvvat manbai, qayta o'rnatish va soat sxemalarini ko'rsatmaydi.

Birinchi usul - an'anaviy

shakl1a shakl1b

Agar bir nechta tugma bo'lsa va MC pinlarining etishmasligi bo'lmasa, biz an'anaviy ulanish usulidan foydalanamiz.

Tugma bo'shatilganda, m chiqishi qarshilik orqali quvvat manbaining "ortiqcha" ga ulanadi (1a-rasm). Tugma bosilganda m pin yerga ulanadi. R1 tortishish qarshiligi kalit pallasida oqimni cheklaydi. Agar u yo'q bo'lsa, biz tugmani bosganimizda, biz shunchaki elektr ta'minotini qisqa tutashtiramiz.

Ko'pgina zamonaviy mikrokontrollerlar o'rnatilgan tortishish rezistorlariga ega, shuning uchun siz tashqi rezistorlarni o'rnatishingiz shart emas (1b-rasm). Mikrokontroller dasturida siz kirish sifatida ishlatiladigan pinni sozlashingiz va ichki tortishish qarshiligini yoqishingiz kerak.

Mikrokontroller pinining chiqish rejimida bo'lsa nima bo'ladi? Bu pinning holatiga bog'liq bo'ladi. Chiqishda "mantiqiy nol" bo'lsa, hech qanday yomon narsa bo'lmaydi, chunki birinchi holatda (1a-rasm) kiruvchi oqim miqdori R1 qarshiligi bilan cheklanadi, ikkinchi holatda (1b-rasm) oqim yo'q. umuman oqadi. Tugmani bosganingizda, hech narsa bo'lmaydi, chunki bu holda chiqish va "tuproq" o'rtasidagi potentsial farq nolga teng bo'ladi.

Agar chiqishda "mantiqiy" bo'lsa va tugma bosilsa, u holda mikrokontroller chiqishi orqali erga bir necha o'nlab milliamperli oqim oqadi va port chiqishi "yoqib ketishi" mumkin. Hujjatlarga muvofiq AVR mikrokontrollerining chiqishi uchun ruxsat etilgan maksimal oqim 40 mA ni tashkil qiladi. Shuning uchun, ba'zan m pin va tugma orasiga bir necha yuz ohm qiymatiga ega bo'lgan qarshilikni, masalan, 330 ni qo'yish foydali bo'ladi (1c-rasm). Masalan, STK500 disk raskadrovka taxtasidagi tugmalar shu tarzda ulanadi. Bu xavfsizlik tarmog'i sifatida amalga oshiriladi, shunda foydalanuvchi o'z tajribalari davomida mikrokontrollerni tasodifan yoqib yubormaydi.

O'zingizning prototiplaringiz uchun siz ushbu rezistorsiz ham qilishingiz mumkin.

Ikkinchi usul - diodlardan foydalanish

U ikkitadan ortiq tugma mavjud bo'lganda ishlatiladi va siz MC pinlariga pul tejashni xohlaysiz. Bunda har bir tugma o'zining raqamli kodiga ega bo'lib, N pinga shu tarzda osib qo'yiladigan tugmalar soni m = 2 N - 1. Ya'ni uchta pinga 7 ta, to'rt pinga 15 ta tugmani osib qo'yish mumkin. , va hokazo... lekin men 7 dan ortiq osmagan bo'lardim. Qo'shimcha tashqi komponentlar soni ortadi, mikrokontrollerning sxemasi va dasturi murakkablashadi. Bundan tashqari, ko'p sonli tugmalar uchun boshqa kommutatsiya sxemalari mavjud. Pull-up rezistorlari diagrammada ko'rsatilmagan, ichki rezistorlar ishlatilgan deb taxmin qilinadi.

Aytgancha, diodlar orqali siz tugmalardan signallarni boshqaruvchining tashqi uzilish chiqishiga ham yuborishingiz mumkin (3-rasm). Har qanday tugma bosilganda, diod orqali tashqi uzilish chiqishi erga qisqa tutashadi va uzilishga olib keladi (albatta, u sozlangan va yoqilgan bo'lsa). Shunday qilib, boshqaruvchiga doimiy ravishda tugmalarni so'rash kerak bo'lmaydi, bu protsedura faqat tashqi uzilish sodir bo'lganda ishga tushiriladi.

Ushbu sxema barcha AVR mikrokontrollerlari uchun tegishli emas, chunki ba'zi mikrokontroller modellarida har qanday pindagi har qanday o'zgarish tufayli tashqi uzilish paydo bo'lishi mumkin. (masalan, ATmega164P da)

Uchinchi usul matritsali klaviatura uchun

Ushbu ulanish opsiyasi odatda matritsali sxema yordamida tizimli ravishda birlashtirilgan va elektr bilan bog'langan bir nechta tugma bloklari uchun ishlatiladi. Lekin hech kim oddiy tugmachalarni yoqish uchun ushbu sxemadan foydalanishni taqiqlamaydi, lekin bu tugmalar soni bo'yicha haqiqiy tejashni ta'minlaydimi? 9.

PC0, PC1, PC2, PC3 pinlari matritsaning qatorlari, PB0, PB1, PB2 pinlari matritsaning ustunlaridir. Tugmalarni satr yoki ustun bo'yicha so'rash mumkin. Aytaylik, biz ularni ustunga ustun so'raymiz. So'rov jarayoni quyidagicha ko'rinadi. Barcha pinlarning dastlabki holati tortishish qarshiligi yoqilgan kirishdir. PB0 pinini chiqish rejimiga o'rnating va uni nolga qo'ying. Endi S1, S2, S3, S4 tugmalarini bosish PC0, PC1, PC2, PC3 pinlarini 0 quvvat manbaiga yopadi. Biz ushbu chiqishlarni so'roq qilamiz va hozirda biron bir tugma bosilganligini aniqlaymiz. PB0 pinini chiqish rejimiga o'rnating va tortishish qarshiligini yoqing. PB1 pinini chiqish rejimiga o'rnatamiz va uni nolga o'rnatamiz. Biz yana PC0, PC1, PC2, PC3 pinlarini so'raymiz. Endi S5, S6, S7, S8 tugmalarini bosish PC0, PC1, PC2, PC3 pinlarini yopadi. Biz tugmachalarning oxirgi ustunini xuddi shu tarzda so'raymiz.

Matritsa qatorlari diodlar orqali tashqi uzilish piniga ulanishi mumkin. Keyin dastur mantig'ini shunday qurish mumkin. Agar klaviatura bir necha daqiqa davomida ishlatilmasa, mikrokontroller past quvvat rejimiga o'tadi. Bunday holda, PB0, PB1, PB2 pinlari nol mantiqiy darajaga ega chiqishlar sifatida tuzilgan. Tugmalardan biri bosilganda, uzilish pin diod orqali nolga qisqaradi. Bu tashqi uzilishga olib keladi, mikrokontroller uyg'onadi va klaviatura skanerlangan signallarga asoslangan taymerni ishga tushiradi. Shu bilan birga, vaqt hisoblagichi ishga tushiriladi, u har qanday tugma bosilganda qayta o'rnatiladi. U to'lib ketishi bilan mikrokontroller yana kam quvvat rejimiga o'tadi.

Shunday qilib, biz ko'pgina mikrokontroller loyihalarining ajralmas qismiga - tugmalarga etib oldik. Tugma juda oddiy qurilma bo'lib, odatda dasturlash tilida faqat ikkita holatga ega, bu mantiqiy 1 (kontaktlar yopiq) va mantiqiy 0 (kontaktlar ochiq). Keling, diagrammani ko'rib chiqaylik.

Bizda hali ham etti segmentli ko'rsatkichlar bilan bir xil sxema mavjud, ammo 4 ta tugma qo'shildi. A guruhi tugmalari yordamida dastlabki uchta ko'rsatkich bo'yicha ko'rsatilgan qiymatni oshiramiz yoki kamaytiramiz va B guruh tugmalari yordamida oxirgi ikkita ko'rsatkichning qiymatini o'zgartiramiz.

Birinchidan, tugmalar haqida qisqacha gapiraylik. Tugmalar odatda ochiq kontaktlar bilan qulflanmagan holda ishlatilishi mumkin. Biz bir kontaktni erga, ikkinchisini esa mikrokontrollerning alohida pinlariga ulaymiz. Biz tortishish rezistorini musbatga o'rnatmaymiz, chunki u mikrokontrollerning o'zida mavjud. Faqatgina tugmachalarni (mikrokontroller pinlarining holati) so'rov qilish uchun dastur yozish va natijani indikatorlarda ko'rsatish qoladi. Sxemaning soddaligi va o'quvchilarning C dasturini tushunishdagi qiyinchiliklari tufayli,Ushbu bo'limda asosiy e'tibor dasturni tahlil qilishga qaratiladi.

Shunday qilib, dastur.

#o'z ichiga oladi //kutubxonalarni kiriting #include #define SPI_SS PB2 //SS output #define SPI_MOSI PB3 //MOSI output #define SPI_MISO PB4 //MISO output #define SPI_SCK PB5 //SCK output #define BUTTON_AP PD4 //A+ button output #define BUTTON_AM PD5 //A button output - #define BUTTON_BP PD6 //B+ tugmasining chiqishi #define BUTTON_BM PD7 //B-tugmasining chiqishi char di; void spi(char cmd,char ma'lumotlari) //SPI protokoli orqali ikkita 8-bitli paketlarni uzatish funktsiyasi ( PORTB &= ~(1)<999)a=999; //a o'zgaruvchisi maksimal qiymatiga yetganligini tekshiring, agar(a<0)a=0; //проверка достижения минимального значения переменной a if(b>99)b=99; //b o'zgaruvchining maksimal qiymatiga erishilganligini tekshiring, agar (b<0)b=0; //проверка достижения минимального значения переменной b } return 0; }

Qani boshladik. C dasturiOdatda ular tashqi kutubxonalarni ulash bilan boshlanadi. Buning uchun dasturning ikkita qatori javobgar:

#o'z ichiga oladi #o'z ichiga oladi

avr/io.hBu I/U kutubxonasi kompilyatorga mikrokontrollerning qanday kiritish/chiqarish portlari borligini, ular qanday etiketlanganligini va nimaga qodirligini tushuntirib beradi. Va eng qizig'i shundaki, ushbu kutubxonaning o'zi loyiha sozlamalaridan qaysi mikrokontroller uchun tavsiflar qo'llanilishi kerakligini tanlaydi, bu sizga ushbu kutubxonadan turli mikrokontrollerlar uchun foydalanish imkonini beradi. Avval ushbu kutubxonani kiritish kerak.

Ikkinchi tez-tez ishlatiladigan kutubxona - util/delay.hdasturni bajarishda kechikishlarni yaratishga yordam beradi, bu juda qulay.

#define BUTTON_AP PD4

chiqishda nima borligini ko'rsatadiPD4 (4 port registriB)tugmachani ulaymizA+ (diagrammaga qarang). Bu zarur, agar biz to'satdan tugmani boshqa chiqishga o'tkazishga qaror qilsak, dastur bo'ylab qidirishimiz shart emas, shunchaki uni o'zgartirishaniqlashchiqish nomiPD4keraklisiga va u dasturda qoladiBUTTON_AP.Lekin uchun xulosalar taqdirdaSPIhech narsani o'zgartirib bo'lmaydi, chunki qo'llab-quvvatlashSPIapparat va ishlab chiqaruvchi tomonidan mikrokontroller pinlariga qattiq bog'langan.

Dasturning keyingi qiziqarli qismi portlarning tavsifidir.

DDRB |= (1<

Portning sanab o'tilgan bitlari chiqishga shunday o'tkazildiB(sukut bo'yicha barcha portlarning barcha bitlari kirishga o'rnatiladi). EUshbu qatorni so'l ta'rifidan foydalanmasdan quyidagicha yozish mumkinaniqlash

DDRB |= (1<

Ushbu yozuvlar ekvivalent bo'lib, reestrdagi 1 ni almashtirish uchun mo'ljallanganDDRBtegishli toifagaBR3 (3-darajali), BR5 (5-darajali) VaBR2 (2-darajali). Registrning boshqa bitlariDDRBo'zgarishsiz qoladi. Bu qatorni shunday yozishingiz ham mumkin

DDRB |= (1<<3)|(1<<5)|(1<<2);

Bu, albatta, yanada chalkash.

Kirish 1<<3 ikkilik birlikni chapga 3 pozitsiyaga siljitish kerakligini anglatadi,o'ngdagi pozitsiyalar nollar bilan to'ldiriladi.

1 <<3 ikkilik tizimda 1000 (bir nol nol) ni bildiradi. Va operatsiyani bajarishda(1<<3)|(1<<5) biz ikkilik tizimda 101000 ni olamiz.

Dasturning keyingi qatorida biz tugmalar uchun tortishish rezistorlarini ulaymiz. Birliklarni registrning mos bitlariga yozamizPORTD

PORTD |= (1<

Ushbu rezistorlar mikrokontrollerga o'rnatilgan. Ular port bitlariga ulanishi mumkin, agar bu bitlar kirish sifatida belgilangan bo'lsa. Rezistorlar mikrokontrollerning kerakli pinini mantiq 1 ga tortadi.

Qolgan sozlamalar mikrokontrollerning tegishli registrlari yordamida xuddi shu tarzda amalga oshiriladi.

Endi dasturning asosiy qismini ko'rib chiqaylik, mikrokontroller, asosiy sozlamalardan so'ng, cheksiz ishlaydi. Dasturning bu qismi cheksiz tsiklga o'ralgan.

while(1) ( );

Jingalak qavslar orasiga kiritilgan barcha dastur qatorlari aylana shaklida bajariladi. Ushbu cheksiz pastadir ichida o'nlik raqam etti segmentli ko'rsatkichning alohida raqamlariga bo'linadi. Bo'lingandan so'ng, biz orqali bitli ma'lumotlarni jo'natamizSPIhar bir alohida ko'rsatkich uchun.

Kechikish_ms(100);

tugma kontaktlarini "sakrash" dan noto'g'ri ishga tushirishni oldini olish uchun. Va ikkinchi marta biz tugmachalarni bosish haqida so'rov o'tkazamiz va bosish haqida avval o'rnatilgan bayroqlarni tekshiramiz. Agar shartlar bajarilsa, biz indikatorlarda ko'rsatilgan qiymatlarni o'zgartiramiz. Keyin tugmani bosish bayroqlarini 0 ga qaytaramiz.Shundan so'ng, tsikl takrorlanadi.

Keyingi - yakuniy qismda - ADC (analog-raqamli konvertor) va amaliyotda ilgari o'rganilgan barcha narsalarni qo'llash ko'rib chiqiladi.

Tugmani I/U port liniyasiga ulash

Ko'p sonli misollar bilan hamma narsa batafsil tavsiflangan ushbu materialni o'rganib chiqqandan so'ng, siz AVR mikrokontrollerlarining kirish/chiqish portlarini osongina o'zlashtirishingiz va dasturlashingiz mumkin.

Biz mikrokontrollerdagi misolni ko'rib chiqamiz ATMega8 .

Biz dasturni yozamiz Atmel Studio 6.0 .

Biz sxemani taqlid qilamiz Proteus 7 Professional .

Mikrokontrollerlar uchun loyihalarni yaratishda eng keng tarqalgan vazifa tugmalarni ulashdir. Oddiyligiga qaramay, bu vazifa muhim, ehtimol aniq bo'lmagan xususiyatlarga ega.
Agar siz tugma kontaktlaridan birini, masalan, umumiy simga ("tuproq") va ikkinchisini "Kirish" rejimiga o'tgan mikrokontrollerning kirish/chiqish portining tanlangan chizig'iga ulasangiz, siz bu usul ishlamasligini bilib oladi. Tugmani bosganingizda, mikrokontroller port liniyasi erga ulanadi va dastur ushbu I/U port liniyasidan "0" mantiqini o'qiydi, lekin tugma bo'shatilganda mikrokontroller pin hech narsaga ulanmaydi, bu esa. ko'pincha "havoda osilgan" deb ataladi. Bunday holda, dastur chiqishdan tasodifiy mantiqiy "0" va mantiqiy "1" ni o'qiydi, chunki I/U portining ulanmagan chizig'ida shovqin paydo bo'ladi.
To'g'ri ulanish ochiq holatda mikrokontroller pinini rezistor orqali, masalan, quvvat avtobusiga, yopiq holatda esa - erga ulash kerakligini nazarda tutadi yoki aksincha. Rezistorning qarshiligi juda kichik bo'lmasligi kerak, shunda tugma kontaktlari yopilganda u orqali o'tadigan oqim juda katta bo'lmaydi. Odatda 10-100 kOhm tartib qiymatlari qo'llaniladi.

Rasm: Siqilgan quvvat shinasi bilan tugmaning ulanishlari.

- tugma bosilganda u “1” ga teng bo'ladi;
- tugma bosilganda u “0” ga teng bo'ladi;

Shakl: Tuproqqa ulangan tugma ulanishlari.
Ushbu ulanish bilan I/U port liniyasining holati quyidagicha bo'ladi:
- tugma bosilganda u “0” ga teng bo'ladi;
- tugma bosilganda u “1” ga teng bo'ladi;

- yuqori quvvat shinasi bilan tugmaning kirish/chiqish port liniyasiga ulanish:

#o'z ichiga oladi // Asosiy dastur int main(void) ( // Kirish/chiqish portlarini sozlash DDRB = 0b11111111; // B portining barcha bitlarini "Chiqish" rejimiga sozlang PORTB = 0b00000000; // B portining barcha bitlarini jurnalga o'rnating "0" (Port chiqishidagi kuchlanish GND ga teng) DDRD = 0b00000000 // D portining barcha bitlarini "Kirish" rejimiga o'rnating PORTD = 0b11111111 // D portining barcha bitlarini "1" ga o'rnating; (Port chiqishidagi kuchlanish Vcc ga teng) // Abadiy sikl esa (1) ( //Tekshirish: agar PD0 holati mantiqiy “0” bo‘lsa, u holda tugma bosiladi, agar ((PIND&(1))<< PD0)) == 0) { //Состояние PB0 устанавливаем в лог.«1» PORTB |= (1 << PB0); } else { //Состояние PB0 устанавливаем в лог.«0» PORTB &= ~(1 << PB0); } } }

- ulangan tuproqli tugmachaning I/U port liniyasiga ulanish:

// Tashqi kutubxonalarni kiriting #include #o'z ichiga oladi // Asosiy dastur int main(void) ( // Kirish/chiqish portlarini sozlash DDRB = 0b11111111; // B portining barcha bitlarini "Chiqish" rejimiga sozlang PORTB = 0b00000000; // B portining barcha bitlarini jurnalga o'rnating "0" (Port chiqishidagi kuchlanish GND ga teng) DDRD = 0b00000000 // D portining barcha bitlarini "Kirish" rejimiga o'rnating PORTD = 0b11111111 // D portining barcha bitlarini "1" ga o'rnating; (Port chiqishidagi kuchlanish Vcc ga teng) / / Abadiy sikl esa (1) ( //Tekshirish: agar PD0 holati mantiqiy “1” bo'lsa, u holda tugma bosiladi, agar ((PIND&(1)<< PD0)) == 1) { //Состояние PB0 устанавливаем в лог.«1» PORTB |= (1 << PB0); } else { //Состояние PB0 устанавливаем в лог.«0» PORTB &= ~(1 << PB0); } } }