Միկրոկարգավորիչների ծրագրավորման կարգը avr. avr միկրոկոնտրոլերի ծրագրավորում

Բարի օր սիրելի ռադիոսիրողներ:
Ես ողջունում եմ ձեզ կայք ""

Ինչ է միկրոկոնտրոլերը և ինչու է այն անհրաժեշտ: Դիտարկենք դրա սահմանումը.

- միկրոսխեմա, որը նախատեսված է էլեկտրոնային սարքերը կառավարելու համար, կամ այլ կերպ՝ պարզ համակարգիչ (միկրոհամակարգիչ), որն ունակ է կատարել պարզ առաջադրանքներ։

Այսինքն, իրականում միկրոկոնտրոլերը սարք է, որը մեզ թույլ է տալիս իրականացնել մեր գաղափարները (նույնիսկ խելագարները), բայց, իհարկե, իր հնարավորությունների սահմաններում։ Եվ ամենակարևորը, գաղափարի իրականացումը ձեռք է բերվում ոչ թե բարդ էլեկտրոնային կառույցների ստեղծմամբ, այլ միայն, հիմնականում, մեր մտքի ուժով (կուզենայի՞ք կախարդ դառնալ):
Ռադիոսիրողների շրջանում ամենատարածվածը երկու տեսակի միկրոկոնտրոլերներ են.
PIC- Միկրոչիպերի տեխնոլոգիա
AVR- Atmel-ի կողմից

Կցանկանայի մի կարճ շեղում անել և հստակեցնել իմ դիրքորոշումներից մեկը. Չեմ պատրաստվում քննարկել այս կամ այն ​​տեսակի միկրոկոնտրոլերների, այս կամ այն ​​ծրագրային ապահովման և ընդհանրապես միկրոկոնտրոլերների հետ կապված ամեն ինչի արժանիքները, ինչ-որ բան խորհուրդ տալ, և առավել եւս՝ պարտադրել ընթերցողներին։ Այս ամենը ճաշակի, անձնական նախասիրությունների և միկրոկոնտրոլերներ սովորելու ձեր վերջնական նպատակների խնդիրն է: Դե, քանի որ «անսահմանությունը չի կարող գրկվել», ես կանցկացնեմ իմ հետագա շարադրանքը AVR միկրոկառավարիչների և ոչ շատ տարածված, բայց իմ սիրելի «Ալգորիթմ Builder» ծրագրի վերաբերյալ: Տարբեր տեսակի միկրոկոնտրոլերներ, ծրագրեր, իհարկե, ունեն տարբերություններ, բայց նաև շատ ընդհանրություններ ունեն: Եվ միկրոկոնտրոլերների աշխարհը մենք կսովորենք այնպես, որ հետագայում ձեռք բերված գիտելիքները առանց որևէ խնդրի կիրառվեն PIC-ների և ցանկացած ծրագրաշարի վրա: Եվ ևս մեկ անգամ հիշեցնեմ, որ այս հոդվածաշարը իմ փորձն է օգնելու նրանց, ովքեր առաջին անգամ լսել են միկրոկոնտրոլերների գոյության մասին և ցանկանում են հասկանալ, թե ինչպես աշխատել դրանց հետ։

Ի՞նչ է ձեզ անհրաժեշտ, որպեսզի սովորեք, թե ինչպես աշխատել միկրոկոնտրոլերների հետ: Ես կառանձնացնեի մի քանի, իմ կարծիքով, հիմնական պայմանները.
1. Ցանկություն և հաստատակամություն .
Այստեղ ամեն ինչ շատ պարզ է՝ ցանկություն կա՝ ամեն ինչ կստացվի։ Իսկ համառությամբ ցանկությունն ընդհանրապես սուպեր բան է։
2. Միկրոկառավարիչ սարքի իմացություն.
Խորը գիտելիքն այստեղ կարևոր չէ (և միգուցե ընդհանրապես անհրաժեշտ չէ), բայց անհրաժեշտ է իմանալ, թե ինչ է «բավականին» միկրոկառավարիչը: Միայն իմանալով, թե ինչից է բաղկացած միկրոկոնտրոլերը, ինչ սարքեր ունի այն, դրանց հնարավորությունները, ինչպես են աշխատում, միայն այդ դեպքում մենք կկարողանանք առավելագույնս օգտագործել միկրոկառավարիչի հնարավորությունները:
3. Ծրագրավորման լեզվի և միկրոկոնտրոլերի կառավարման հրամանների իմացություն:
Ինչպես կաշխատի միկրոկոնտրոլերը, ինչ առաջադրանքներ եք հանձնարարում նրան և ինչպես է դրանք կատարելու, որոշվում է դրանում ներկառուցված ծրագրով. այն ծրագիրը, որը դուք ինքներդ եք կազմում միկրոկառավարիչի համար: Եվ այս կետի վրա մենք կանդրադառնանք ավելի մանրամասն, որպեսզի դիտարկենք այն խնդիրները, որոնք կարող են առաջանալ ապագայում։

Ծրագիր(Թարգմանության մեջ այս բառը նշանակում է «դեղատոմս») - առաջիկա իրադարձությունների կամ գործողությունների նախնական նկարագրություն:

Օրինակ, մենք ցանկանում ենք, որ միկրոկոնտրոլերը թարթի LED-ը: Պարզ առաջադրանք, բայց, այնուամենայնիվ, որպեսզի միկրոկոնտրոլերը կատարի այս առաջադրանքը, մենք նախ պետք է քայլ առ քայլ նկարագրենք միկրոկառավարիչի բոլոր գործողությունները, գրենք ծրագիր, որը այն պետք է կատարի մեզ անհրաժեշտ արդյունքը ստանալու համար՝ թարթող LED: . Նման մի բան.
♦ Լուսադիոդը լուսավորեք.
- կարգավորեք այն ելքը, որին միացված է LED-ը, որպեսզի աշխատի տեղեկատվության ելքի վրա
- կիրառեք տրամաբանական մակարդակ այս քորոցին, որը թույլ կտա լուսավորել LED-ը
♦ Մի քիչ սպասեք.
- անցեք ենթածրագրին, որը կազմում է դադար (որը նույնպես պետք է «ծամել»)
- դադարի ենթածրագրի ավարտից հետո վերադարձեք հիմնական ծրագիր
♦ Անջատեք լուսադիոդը.
- կիրառեք տրամաբանական մակարդակ ելքի վրա՝ մարելով LED-ը
եւ այլն։
ժամկետով Ծրագիրմեկ այլ տերմին անքակտելիորեն կապված է. Ալգորիթմ(ինչպես Գայլն ու Նապաստակը, Թոմը և Ջերին):

Ալգորիթմ- հրահանգների մի շարք, որոնք նկարագրում են ցանկալի արդյունքի հասնելու կարգը:

Եթե ​​ծրագրում մենք ամենամանրամասն ձեւով ենք գործողություններ սահմանելմիկրոկոնտրոլեր, ապա ալգորիթմում մենք որոշել գործողությունների ընթացքըմիկրոկոնտրոլեր, որի հիման վրա մենք այնուհետ կստեղծենք ծրագիր: Վերոնշյալ օրինակի նման.
♦ Լուսադիոդը լուսավորեք
♦ Մի քիչ սպասեք
♦ Անջատեք լուսադիոդը
եւ այլն։
Այս կերպ, ալգորիթմը ծրագրի նախորդն է. Եվ որքան ուշադիր և մտածված ստեղծվի ալգորիթմ, այնքան ավելի հեշտ կլինի ստեղծել ծրագիր:

Ընդհանուր առմամբ, միկրոկոնտրոլերի համար ծրագիրը միկրոկարգավորիչի գործողությունների հաջորդականությունն է մի շարք հրամանների և հրահանգների տեսքով, որոնք այն պետք է կատարի մեր նպատակներին հասնելու համար:

Միկրոկառավարիչի հրամանները նման են մեկերի և զրոների մի շարքի.
00110101 011000100
այսպես կոչված - հրամանի կոդերը,իսկ հրամանի կոդերը այն լեզուն են, որը հասկանում է միկրոկառավարիչը: Եվ որպեսզի մեր ալգորիթմը ռուսերենից թարգմանվի միկրոկառավարիչի լեզվի՝ հենց այս զրոների և միավորների մեջ, կան հատուկ ծրագրեր:
Այս ծրագրերը թույլ են տալիս մեզ քիչ թե շատ հասկանալի լեզվով նկարագրել միկրոկոնտրոլերի աշխատանքի կարգը, այնուհետև թարգմանել այս կարգը միկրոկարգավորիչին հասկանալի լեզվի, որի արդյունքում առաջանում է այսպես կոչված. մեքենայի կոդը- հրամանների և հրահանգների հաջորդականություն (հենց զրոյականները և մեկերը), որոնք միայն միկրոկառավարիչը հասկանում է: Ծրագրավորողի կողմից գրված ծրագրի տեքստը կոչվում է աղբյուր կոդը. Ծրագիրը ծրագրավորման լեզվից (աղբյուրային կոդը) թարգմանվում է միկրոկոնտրոլերի լեզվի (մեքենայի կոդ) թարգմանիչներ. Թարգմանիչը ծրագրի տեքստը փոխակերպում է մեքենայի կոդերի, որոնք այնուհետև գրվում են միկրոկառավարիչի հիշողության մեջ։
Նման ծրագրերում միկրոկոնտրոլերի աշխատանքի կարգը նկարագրվում է հատուկ լեզվով՝ ծրագրավորման լեզվով։ Ծրագրավորման լեզուն տարբերվում է մեր մարդկային լեզվից: Եթե ​​մեր հաղորդակցման լեզուն հիմնականում տեղեկատվության փոխանակման համար է, ապա.

Ծրագրավորման լեզու - սա հրամանների, հրահանգների փոխանցման միջոց է, միկրոկառավարիչի գործողությունների հստակ ուղեցույց:

Կան բազմաթիվ ծրագրավորման լեզուներ, և դրանք կարելի է բաժանել երկու տեսակի.
ցածր մակարդակի ծրագրավորման լեզուներ
բարձր մակարդակի ծրագրավորման լեզուներ
Որն է տարբերությունը. Եվ դրանք տարբերվում են միկրոկարգավորիչին մոտիկությամբ:
Միկրոպրոցեսորային տեխնոլոգիայի առաջացման արշալույսին ծրագրերը գրվում էին մեքենայական կոդերով, այսինքն՝ աշխատանքի ողջ ալգորիթմը հաջորդաբար գրվում էր զրոների և միավորների տեսքով։ Ահա թե ինչ տեսք ուներ ծրագիրը.

01000110
10010011
01010010

Դժվար թե որևէ մեկը կարողանա պարզել երկու թվերի համակցությունների նման մի շարք, և առաջին ծրագրավորողների աշխատանքը շատ աշխատատար էր: Իրենց կյանքը հեշտացնելու համար ծրագրավորողները սկսեցին ստեղծել առաջին ծրագրավորման լեզուները։ Այսպիսով, որքան մոտ է ծրագրավորման լեզուն նման զրոների և միավորների շարքին, այնքան ավելի «ցածր մակարդակ» է այն, և որքան հեռու է դրանցից, այնքան ավելի «բարձր մակարդակ»:
Ամենատարածված ծրագրավորման լեզուները միկրոկոնտրոլերների համար.
- ցածր մակարդակի լեզու - հավաքող
- բարձր մակարդակի լեզու - C (Ci)
Դիտարկենք դրանց տարբերության օրինակը (այս օրինակները վերացական են):
Ենթադրենք, պետք է երկու թիվ գումարել՝ 25 և 35։
Մայրենի կոդում այս հրամանը կարող է այսպիսի տեսք ունենալ.
00000101 1101001
Ցածր մակարդակի լեզվով.
ADD Rd, Rr
Բարձր մակարդակի լեզվով.
25+35
Ցածր և բարձր մակարդակի լեզուների տարբերությունը տեսանելի է անզեն աչքով, մեկնաբանությունները, ինչպես ասում են, ավելորդ են։
Բայց եկեք ավելի խորանանք այս օրինակների մեջ: Մենք չենք վերլուծի մեքենայական կոդի օրինակը, քանի որ այն նույնական է ասեմբլերի օրինակին: Իր հիմքում հավաքման հրահանգները նույն մեքենայի կոդերն են (հրամանները), որոնց ուղղակի նշանակվում են տառերի հապավումներ՝ զրոների և միավորների մեջ չկորչելու համար: ADD Rd, Rr մոնտաժողի հրահանգով մենք միկրոկառավարիչը սահմանում ենք, որ ավելացնի հայտնաբերված երկու թվերը (և դրա համար նախ պետք է դրանք գրենք այնտեղ) - առաջինը Rd-ում, երկրորդը Rd-ում և տեղադրենք գումարման արդյունքը: րդ. Ինչպես տեսնում եք, միկրոկոնտրոլերի համար մենք շատ կոնկրետ խնդիր ենք դրել՝ որտեղից ստանալ այն, ինչ անել դրա հետ և որտեղ դնել արդյունքը: Այս դեպքում մենք աշխատում ենք անմիջապես միկրոկոնտրոլերի հետ:
Հրաման բարձր մակարդակի լեզվով՝ 25+35, մեզ ծանոթ մաթեմատիկական նշում, մեր աչքին հաճելի։ Բայց այս դեպքում մենք ուղղակիորեն չենք աշխատում միկրոկոնտրոլերի հետ, մենք նրան ուղղակի խնդիր ենք դնում ավելացնել երկու թվեր։ Արդյունքն ու գործողությունների հաջորդականությունը այս դեպքում կլինի նույնը, ինչ assembler հրամանը կատարելիս՝ նախ այս երկու թվերը կգրվեն ինչ-որ տեղ, հետո գումարվեն և արդյունքը կտեղադրվի ինչ-որ տեղ։
Եվ այստեղ է բարձր մակարդակի և ցածր մակարդակի լեզուների հիմնական տարբերությունը։ Եթե ​​Assembler-ում մենք վերահսկում ենք ամբողջ գործընթացը (ուզենք, թե ոչ). մենք գիտենք, թե որտեղ են գրված այս երկու թվերը, և գիտենք, թե որտեղ կլինի արդյունքը, ապա բարձր մակարդակի լեզվով մենք չենք վերահսկում գործընթացը: Ծրագիրն ինքն է որոշում, թե որտեղ պետք է նախօրոք գրել թվերը և որտեղ տեղադրել արդյունքը: Շատ դեպքերում մենք դա պետք չէ իմանալ, քանի որ մեզ համար հիմնական արդյունքը 60 թիվն է ելքի մեջ: Արդյունքում, բարձր մակարդակի լեզուներով ծրագրերն ավելի ընթեռնելի են, հաճելի են աչքին և ավելի փոքր չափերով. ի վերջո, մենք ստիպված չենք «մագլցել բոլոր անցքերի մեջ» և ներկել միկրոկառավարիչի, ծրագրի յուրաքանչյուր քայլ: դա անում է ավելի ուշ մեզ համար, երբ այն կազմում է - թարգմանում է այն մեքենայի կոդերի: Բայց կա նաև բացասական կողմ. Assembler-ում և C-ում գրված երկու նույնական ալգորիթմները, դրանք մեքենայական կոդերի վերածելուց հետո, կունենան տարբեր չափսեր. Assembler-ում գրված ծրագիրը 20-40%-ով ավելի կարճ կլինի, քան C-ով գրված ծրագիրը. սատանան գիտի, թե որ ճանապարհով է գնում C-ն: հասնել մեզ անհրաժեշտ արդյունքի: Եվ լինում են դեպքեր, երբ բարձր մակարդակի լեզվի նկատմամբ վստահություն չկա ու C ծրագրում տեղադրում են Assembler-ով գրված կոդ։
Պրոֆեսիոնալ ծրագրավորողները, որպես կանոն, գիտեն ծրագրավորման մի քանի լեզուներ (կամ աշխատում են թիմում, որը ներառում է տարբեր լեզուների մասնագետներ)՝ ստեղծագործորեն համատեղելով իրենց առանձնահատկություններն ու առավելությունները մեկ ծրագրում: Դե, մենք՝ սիրողականներս, պետք է գոնե մեկ լեզու իմանանք (սկզբի համար), և մենք պետք է սկսենք (և ես դրանում հաստատ համոզված եմ, և ինձ ոչ ոք չի համոզի) ցածր մակարդակի լեզվից՝ ասամբլեայից։

Դե, կարծում եմ, և այստեղ ամեն ինչ պարզ է մեզ համար՝ պետք է սովորել ծրագրավորման լեզու, այլ կերպ՝ ոչ մի կերպ։

Հրահանգներ և հրահանգներ միկրոկոնտրոլերի կառավարման համար:
AVR միկրոկոնտրոլերներն ունեն ավելի քան 130 տարբեր հրամաններ, որոնք թույլ են տալիս իրացնել իրեն բնորոշ բոլոր հնարավորությունները: Բայց ես անմիջապես կասեմ, որ սիրողականներից քչերը գիտեն դրանք բոլորը, էլ ուր մնաց՝ բոլորն օգտագործել: Սովորաբար, սիրողական պրակտիկայում կա բավարար գիտելիքներ և թիմերի կեսը, կամ նույնիսկ ավելի քիչ: Բայց դուք պետք է սովորեք հրամաններ: Որքան շատ հրամաններ իմանաք, այնքան ավելի բարդ (բառի լավ իմաստով) և էլեգանտ ծրագրերը կլինեն:

Թվաբանական տրամաբանական միավոր և հիշողության կազմակերպում - ծրագրային հիշողություն, տվյալների հիշողություն, ոչ անկայուն հիշողություն



Avr-ի այս ձեռնարկում ես փորձեցի նկարագրել բոլոր ամենահիմնական բաները, որոնք սկսնակների համար ծրագրավորում են միկրոկարգավորիչներ: ավր. Բոլոր օրինակները կառուցված են միկրոկոնտրոլերի վրա atmega8. Սա նշանակում է, որ բոլոր դասերը կրկնելու համար ձեզ անհրաժեշտ կլինի ընդամենը մեկ MK: Որպես էլեկտրոնային սխեմայի էմուլյատոր, Proteus-ը օգտագործվում է, իմ կարծիքով լավագույն տարբերակը սկսնակների համար: Բոլոր օրինակների ծրագրերը գրված են avr CodeVision AVR-ի C կոմպիլյատորի վրա: Ինչու ոչ ինչ-որ assembler-ում: Քանի որ սկսնակն արդեն բեռնված է տեղեկատվությամբ, և երկու թվերը բազմապատկող ծրագիրը հավաքում է մոտ հարյուր տող անսամբլերում, և նրանք օգտագործում են C-ն բարդ համարձակ նախագծերում: CodeVision AVR կոմպիլյատորը սրված է atmel միկրոկոնտրոլերների համար, ունի հարմար կոդի գեներատոր, լավ ինտերֆեյս և անմիջապես դրանից կարող է թարթվել միկրոկառավարիչով:

Այս ձեռնարկը ցույց կտա և պարզ օրինակներով կբացատրի, թե ինչպես.

  • Սկսեք ծրագրավորել միկրոկոնտրոլերներ, որտեղից սկսել, ինչ է ձեզ անհրաժեշտ դրա համար:
  • Ինչ ծրագրեր օգտագործել avr-ի համար որոնվածը գրելու, համակարգչի վրա կոդի մոդելավորման և վրիպազերծման համար,
  • Ինչ ծայրամասային սարքեր կան MK-ի ներսում, ինչպես կառավարել դրանք՝ օգտագործելով ձեր ծրագիրը
  • Ինչպես գրել պատրաստի որոնվածը միկրոկառավարիչին և ինչպես կարգաբերել այն
  • Ինչպես պատրաստել PCB ձեր սարքի համար
MK ծրագրավորման ուղղությամբ առաջին քայլերն անելու համար ձեզ ընդամենը երկու ծրագիր է անհրաժեշտ.
  • Proteus-ը էմուլյատոր ծրագիր է (դուք կարող եք դրա մեջ շղթա մշակել՝ առանց իրական զոդման դիմելու և այնուհետև փորձարկել մեր ծրագիրը այս սխեմայի վրա): Մենք նախ կգործարկենք Proteus-ում բոլոր նախագծերը, իսկ հետո արդեն իսկական սարքը կարող ենք զոդել:
  • CodeVisionAVR-ը C ծրագրավորման լեզվի կոմպիլյատոր է AVR-ի համար: Դրանում մենք ծրագրեր կմշակենք միկրոկոնտրոլերի համար, և հնարավոր կլինի անմիջապես դրանից իսկական MK-ն բռնկել։
Proteus-ը տեղադրելուց հետո գործարկեք այն
Նա մեզ առաջարկում է տեսնել իր հետ գնացող նախագծերը, մենք քաղաքավարի մերժում ենք։ Այժմ եկեք ստեղծենք դրա մեջ ամենապարզ շղթան։ Դա անելու համար սեղմեք պատկերակի վրա տեսողականորեն ոչինչ չի պատահում: Այժմ դուք պետք է սեղմեք փոքր տառի վրա R (ընտրել գրադարանից)բաղադրիչների ցանկի վահանակում կբացվի բաղադրիչի ընտրության պատուհանը
դիմակ դաշտում մուտքագրեք բաղադրիչի անունը, որը մենք ցանկանում ենք գտնել գրադարանում: Օրինակ, մենք պետք է ավելացնենք mega8 միկրոկոնտրոլեր
արդյունքների ցանկում սեղմեք mega8-ը և սեղմեք կոճակը լավ. Մենք ունենք mega8 միկրոկոնտրոլեր բաղադրիչների ցանկում
Այսպիսով, մենք ավելացնում ենք ևս մեկ ռեզիստոր բաղադրիչների ցանկին՝ մուտքագրելով բառը դիմակ դաշտում ռեսև LED առաջնորդվել է

Դիագրամի վրա մասեր տեղադրելու համար սեղմեք մասի վրա, այնուհետև կտտացրեք գծապատկերի դաշտը, ընտրեք բաղադրիչի տեղը և կրկին սեղմեք: Ձախ կողմում գտնվող շղթային հիմք կամ ընդհանուր մինուս ավելացնելու համար սեղմեք «Տերմինալ» և ընտրեք Հող: Այսպիսով, ավելացնելով բոլոր բաղադրիչները և միացնելով դրանք, մենք ստանում ենք այսպիսի պարզ միացում
Ամեն ինչ, հիմա մեր առաջին սխեման պատրաստ է: Բայց դուք կարող եք հարցնել, թե ինչ կարող է նա անել: Բայց ոչինչ։ Ոչինչ, քանի որ միկրոկոնտրոլերը աշխատելու համար պետք է դրա համար ծրագիր գրել։ Ծրագիրը հրահանգների ցանկ է, որը միկրոկառավարիչը կկատարի: Մեզ անհրաժեշտ է միկրոկոնտրոլեր՝ ոտքի վրա տեղադրելու համար PC0տրամաբանություն 0 (0 վոլտ) և տրամաբանություն 1 (5 վոլտ):

Միկրոկառավարիչի համար ծրագիր գրելը

Ծրագիրը կգրենք C լեզվով՝ օգտագործելով CodeVisionAVR կոմպիլյատորը։ CV-ն գործարկելուց հետո այն մեզ հարցնում է, թե ինչ ենք ուզում ստեղծել՝ Աղբյուր կամ Նախագիծ Ընտրում ենք վերջինս և սեղմում OK կոճակը։ Հաջորդը, մեզ կառաջարկվի գործարկել CVAVR CodeWizard-ը (սա անգնահատելի գործիք է սկսնակների համար, քանի որ այն կարող է ստեղծել ծրագրի հիմնական կմախքը) ընտրել Այո՛
Վիզարդը սկսվում է Chip ներդիրից ակտիվ, այստեղ մենք կարող ենք ընտրել մեր MK-ի մոդելը՝ սա mega8-ն է, և այն հաճախականությունը, որով կգործի MK-ը (մեգա8-ը լռելյայն սահմանված է 1 մեգահերց), այնպես որ մենք ամեն ինչ դրեցինք, ինչպես ցույց է տրված նկարում։ վերևում գտնվող սքրինշոթը: Գնացեք «Պորտեր» ներդիր
Atmega8 միկրոկոնտրոլերն ունի 3 պորտ՝ Port C, Port D, Port B։ Յուրաքանչյուր պորտ ունի 8 կապ։ Նավահանգիստների կապերը կարող են լինել երկու վիճակում.
  • Ելք
DDRx.y ռեգիստրի օգնությամբ մենք կարող ենք փին սահմանել որպես մուտքային կամ ելք։ Եթե ​​ներս
  • DDRx.y = 0 - ելքը աշխատում է նման ՄՈՒՏՔ
  • DDRx.y = 1 փին աշխատում է ԵԼՔ
Երբ փին կարգավորվում է որպես ելք, մենք կարող ենք այն դնել տրամաբանական 1 (+5 վոլտ) և տրամաբանական 0 (0 վոլտ): Դա արվում է՝ գրելով PORTx.y ռեգիստրին: Հաջորդը մանրամասն կքննարկվի մուտքային-ելքային նավահանգիստների մասին: Եվ հիմա մենք ամեն ինչ դնում ենք այնպես, ինչպես ցույց է տրված սքրինշոթում, և սեղմում ենք File->Generate, Save and Exit: Հաջորդը, CodeWizard-ը մեզ կառաջարկի պահպանել նախագիծը, մենք պահպանում ենք այն և նայում կոդը.

#ներառում //ժամանակային ուշացումների ստեղծման գրադարան void main(void) ( PORTB=0x00; DDRB=0x00; PORTC=0x00; DDRC=0x01; // կատարել PC0 ոտքի ելք PORTD=0x00; DDRD=0x00; // Ժամաչափ/Հաշվիչի 0 սկզբնավորում TCCR0=0x00; TCNT0=0x00; // Ժամաչափ/Հաշվիչի 1 սկզբնավորում TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x0H000 OCR1L=0x0H0000; ; OCR1BL=0x00; // Ժամաչափ/Հաշվիչ 2 սկզբնավորում ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // Արտաքին ընդհատում(ներ) սկզբնավորում MCUCR=0x00; // Ժամաչափ(ներ)/Հաշիվ(ներ) ) Ընդհատում(ներ)ի սկզբնավորում TIMSK=0x00; // Անալոգային համեմատիչի սկզբնավորում ACSR=0x80; SFIOR=0x00; while (1) ( );)


Այստեղ ամեն ինչ կարող է ձեզ սարսափելի և անծանոթ թվալ, բայց իրականում ամեն ինչ այդպես չէ։ Կոդը կարելի է պարզեցնել՝ դուրս նետելով MK ծայրամասային սարքերի սկզբնավորումը, որոնք մենք չենք օգտագործում: Պարզեցումից հետո այն ունի հետևյալ տեսքը.

#ներառում //գրադարան միկրոկոնտրոլերի հետ աշխատելու համար mega8 #include //ժամանակային ուշացումների ստեղծման գրադարան void main(void) ( DDRC=0x01; /* դարձնել PC0 ոտքը, որ ելքային մուտքագրումը 0x01 կարող է ձեզ անծանոթ թվալ, և սա ընդամենը 1 թիվն է տասնվեցականում, այս տողը համարժեք կլինի 0b00000001-ին: Երկուական տարբերակով, այնուհետև ես կգրեմ հենց այսպես: */ մինչդեռ (1) ( ); )


Ամեն ինչ լավ է. Բայց որպեսզի LED-ը թարթվի, մենք պետք է փոխենք տրամաբանական մակարդակը PC0 ոտքի վրա: Դա անելու համար հիմնական հանգույցին մի քանի տող ավելացրեք.

#ներառում //գրադարան միկրոկոնտրոլերի հետ աշխատելու համար mega8 #include //ժամանակային ուշացումների ստեղծման գրադարան void main(void) ( DDRC=0x01; /* դարձնել PC0 ոտքը, որ ելքային մուտքագրումը 0x01 կարող է ձեզ անծանոթ թվալ, և սա ընդամենը 1 թիվն է տասնվեցականում, այս տողը համարժեք կլինի 0b00000001-ին: Երկուական տարբերակով, այնուհետև ես կգրեմ հենց այսպես։*/ մինչդեռ (1)//ծրագրի հիմնական հանգույցը (// ծրագրի հիմնական օղակի օպերատորի փակագիծը բացում է PORTC.0=1; 0 delay_ms(500); //հետաձգել 500 միլիվայրկյանով PORTC.0=0; // C 0 պորտը սահմանել 0 delay_ms(500); // կատարել 500 միլիվայրկյան ուշացում);// փակել օպերատորի փակագիծը ծրագրի հիմնական օղակից)


Ամեն ինչ, այժմ կոդը պատրաստ է: Մենք սեղմում ենք Build all Project files պատկերակը, որպեսզի կազմենք (թարգմանենք MK պրոցեսորի հրահանգների) մեր ծրագիրը: Exe թղթապանակում, որը գտնվում է մեր նախագծում, պետք է հայտնվի hex ընդլայնմամբ ֆայլ, սա մեր որոնվածը MK-ի ֆայլն է: Որպեսզի մեր որոնվածը սնվի Proteus-ի վիրտուալ միկրոկառավարիչին, դուք պետք է կրկնակի սեղմեք Proteus-ի միկրոկառավարիչի պատկերի վրա: Նման պատուհան կհայտնվի
Ծրագրի ֆայլ դաշտում կտտացրեք թղթապանակի պատկերակին, ընտրեք մեր որոնվածի ֆայլը hex և սեղմեք OK կոճակը: Այժմ մենք կարող ենք գործարկել մեր շղթայի մոդելավորումը: Դա անելու համար սեղմեք «Խաղալ» կոճակը Proteus պատուհանի ստորին ձախ անկյունում:

Ես մեկ-երկու անգամ ասել եմ, որ MK-ի ուսումնասիրությունը պետք է սկսել assembler-ից։ Կայքում մի ամբողջ դասընթաց նվիրված էր դրան (թեև դա այնքան էլ համահունչ չէ, բայց աստիճանաբար ես այն ադեկվատ տեսք եմ տալիս): Այո, դժվար է, արդյունքը չի լինի առաջին օրը, բայց դուք կսովորեք հասկանալ, թե ինչ է կատարվում ձեր վերահսկիչում։ Դուք կիմանաք, թե ինչպես է այն աշխատում, այլ ոչ թե կապիկի պես պատճենեք այլ մարդկանց աղբյուրները և փորձեք հասկանալ, թե ինչու է այն հանկարծակի դադարեց աշխատել: Բացի այդ, C-ի համար շատ ավելի հեշտ է խառնվել redneck կոդի հետ, որն ամենաանպատեհ պահին դուրս կգա պատառաքաղով:

Ցավոք սրտի, բոլորն ուզում են անմիջապես արդյունք ստանալ: Հետևաբար, ես որոշեցի գնալ այլ ճանապարհով` պատրաստել C-ի ուսուցում, բայց նրա ներքնազգեստի ցուցադրմամբ: Լավ ներկառուցող ծրագրավորողը միշտ ամուր բռնում է իր երկաթի կտորը ձագից՝ թույլ չտալով այն մեկ քայլ անել առանց թույլտվության: Այսպիսով, ինչ կլինի նախ C կոդը, հետո ինչ է ծնել կոմպիլյատորը և ինչպես է այդ ամենը աշխատում իրականում :)

Մյուս կողմից, C-ի ուժեղ կողմը կոդի տեղափոխելիությունն է: Եթե, իհարկե, ամեն ինչ ճիշտ գրելու համար։ Աշխատանքային ալգորիթմների և դրանց երկաթյա իրականացումների տարանջատում նախագծի տարբեր մասերում: Այնուհետև ալգորիթմը մեկ այլ MK տեղափոխելու համար բավական կլինի վերաշարադրել միայն ինտերֆեյսի շերտը, որտեղ գրված է ապարատային բոլոր մուտքերը, և թողնել բոլոր աշխատանքային ծածկագիրը այնպես, ինչպես կա։ Եվ, իհարկե, ընթեռնելիություն: Sish-ի սկզբնաղբյուրն ավելի հեշտ է հասկանալ մի հայացքով (չնայած .. օրինակ, ինձ չի հետաքրքրում, թե ինչ պետք է մատնեմ. գոնե si, գոնե asm :)), բայց, նորից, եթե ամեն ինչ ճիշտ է գրված: Այս կետերին նույնպես ուշադրություն կդարձնեմ։

Որպես փորձնական երկաթի կտոր, որի վրա կտեղադրվի բոլոր օրինակների առյուծի բաժինը, իմ կարգաբերման տախտակը կլինի։

Առաջին C ծրագիրը AVR-ի համար

Կոմպիլյատորի ընտրություն և միջավայրի տեղադրում
Կան բազմաթիվ տարբեր C կոմպիլյատորներ AVR-ի համար.
Առաջին հերթին սա IAR AVR C- գրեթե միանշանակ ճանաչվել է որպես AVR-ի լավագույն կոմպիլյատոր, tk. վերահսկիչն ինքնին ստեղծվել է Atmel-ի և IAR-ի մասնագետների սերտ համագործակցությամբ: Բայց ամեն ինչի համար պետք է վճարել։ Եվ այս կոմպիլյատորը ոչ միայն թանկարժեք կոմերցիոն ծրագրային ապահովում է, այլև այն ունի այնպիսի պարամետրեր, որ դուք պարզապես պետք է շատ աշխատեք այն հավաքելու համար: Ես իսկապես ընկերություն չեմ ունեցել նրա հետ, նախագիծը փտել է կապող փուլում տարօրինակ սխալների պատճառով (հետագայում իմացա, որ դա ծուռ ճեղք էր):

Երկրորդը գնում է WinAVR GCCհզոր օպտիմիզացնող կոմպիլյատոր է: Full open source, cross-platform, ընդհանրապես կյանքի բոլոր ուրախությունները։ Այն նաև հիանալի կերպով ինտեգրվում է AVR Studio-ին՝ թույլ տալով վրիպազերծել հենց այնտեղ, ինչը դժոխային հարմար է: Ընդհանրապես, ես դա եմ ընտրել։

Ունենալ նաև CodeVision AVR Cշատ հայտնի կոմպիլյատոր է: Այն հայտնի դարձավ իր պարզության շնորհիվ: Դուք կարող եք դրանում աշխատանքային ծրագիր ստանալ մի քանի րոպեում. մեկնարկի կոդերի մոգը մեծապես նպաստում է դրան՝ կնքելով ցանկացած արկերի սկզբնավորման ստանդարտները: Անկեղծ ասած, ես ինչ-որ կերպ կասկածանքով եմ վերաբերվում նրան. մի անգամ ես ստիպված էի ապամոնտաժել այս կոմպիլյատորի գրած ծրագիրը, ստացվեց ինչ-որ շիլա և ոչ կոդ: Սարսափելի քանակությամբ անհարկի ժեստեր և գործողություններ, որոնք հանգեցրել են բավականին մեծ քանակությամբ կոդի և դանդաղ կատարման: Այնուամենայնիվ, հավանաբար սկզբնական որոնվածը գրողի ԴՆԹ-ում սխալ է եղել: Բացի այդ, նա փող է ուզում: Ոչ այնքան, որքան IAR, բայց նկատելի: Իսկ դեմո ռեժիմում այն ​​թույլ է տալիս գրել ոչ ավելի, քան 2կբ կոդ։
Իհարկե ճեղք կա, բայց եթե գողանաս, ապա միլիոն՝ IAR-ի իմաստով :)

Կա նաեւ Image Craft AVR Cև MicroCմիկրոէլեկտրոնիկայից։ Ստիպված չէի նաև օգտագործել, բայց... SWGշատ գովեստներ միկրոպասկալ, ասում են՝ ահավոր հարմար ծրագրավորման միջավայր ու գրադարաններ։ Կարծում եմ, MicroC-ը ոչ ավելի վատ, այլ նաև վճարովի կլինի:

Ինչպես ասացի, ես ընտրեցի WinAVRերեք պատճառով՝ անվճար, այն ինտեգրվում է AVR Studio-ին և պատրաստի կոդերի մի փունջ գրված է նրա համար բոլոր առիթների համար:

Այսպիսով, ներբեռնեք WinAVR-ը և AVR Studio-ն: Այնուհետև նախ տեղադրվում է ստուդիան, այնուհետև, վերևից, WinAVR-ը գլորվում է և կառչում է ստուդիայից՝ plug-in-ի տեսքով: Ես խստորեն խորհուրդ եմ տալիս WinAVR-ը դնել կարճ ճանապարհի վրա՝ C:\WinAVR-ի նման, այդպիսով դուք կխուսափեք ուղիների հետ կապված բազմաթիվ խնդիրներից:

Նախագծի ստեղծում
Այսպիսով, ստուդիան ստեղծվել է, C-ն պտուտակված է, ժամանակն է փորձել ինչ-որ բան ծրագրավորել: Սկսենք պարզից, ամենապարզից: Գործարկեք ստուդիան, այնտեղ ընտրեք նոր նախագիծ որպես AVR GCC կոմպիլյատոր և մուտքագրեք նախագծի անունը:

Աշխատանքային տարածքը բացվում է դատարկ *.c ֆայլով:

Այժմ ստուդիայի էջանիշերում ուղիների ցուցադրումը կարգավորելը չի ​​խանգարում: Դա անելու համար անցեք.
Մենյու Գործիքներ - Ընտրանքներ - Ընդհանուր - FileTabs և բացվող ցանկից ընտրեք «Միայն ֆայլի անունը»: Հակառակ դեպքում անհնար կլինի աշխատել՝ ներդիրը կպարունակի ֆայլի ամբողջական ուղին և էկրանին չի լինի ավելի քան երկու կամ երեք ներդիր:

Ծրագրի կարգավորում
Ընդհանուր առմամբ, դասական է համարվում make ֆայլի ստեղծումը, որտեղ նկարագրված կլինեն բոլոր կախվածությունները: Եվ սա, հավանաբար, ճիշտ է: Բայց ինձ համար, ով մեծացել է լիովին ինտեգրված IDE-ներով, ինչպիսիք են uVisionկամ AVR ստուդիաայս մոտեցումը խորապես խորթ է: Ուստի ես դա կանեմ իմ ձևով, ստուդիայի բոլոր միջոցներով։

Կտտացրեք հանդերձանքի կոճակին:


Սրանք ձեր նախագծի կարգավորումներն են, ավելի ճիշտ՝ make ֆայլի ավտոմատ ստեղծման կարգավորումները: Առաջին էջում դուք պարզապես պետք է մուտքագրեք այն հաճախականությունը, որով կաշխատի ձեր MK-ն: Դա կախված է ապահովիչների բիթերից, ուստի մենք ենթադրում ենք, որ հաճախականությունը 8000000 Հց է:
Ուշադրություն դարձրեք նաև օպտիմալացման գծին: Այժմ կա -Os-ը չափի օպտիմալացում է: Թողեք այնպես, ինչպես կա առայժմ, ապա կարող եք փորձել խաղալ այս պարամետրով: -O0-ն ընդհանրապես օպտիմալացում չէ:

Հաջորդ քայլը ուղիների տեղադրումն է: Նախ, այնտեղ ավելացրեք ձեր նախագծի գրացուցակը. այնտեղ կտեղադրեք երրորդ կողմի գրադարաններ: Ցանկում կհայտնվի «.\» ճանապարհը

Ստեղծված է make ֆայլը, կարող եք այն նայել ձեր նախագծի լռելյայն թղթապանակում, պարզապես նայեք, տեսեք, թե ինչ կա այնտեղ:


Առայժմ այսքանը: Սեղմեք OK ամենուր և գնացեք աղբյուրը:

Խնդրի ձևակերպում
Դատարկ թերթիկը գայթակղիչ է մարմնավորելու ինչ-որ խորամանկ գաղափար, քանի որ դիոդի սովորական փայլատակումը այլևս չի ներդնում: Եկեք անմիջապես բռնենք ցուլի եղջյուրներից և կապ հաստատենք համակարգչի հետ. սա առաջին բանն է, որ անում եմ:

Այն կաշխատի այսպես.
Երբ միավորը հասնի COM պորտին (կոդ 0x31), մենք կմիացնենք դիոդը, իսկ երբ զրոյին հասնի (կոդ 0x30), մենք այն կհանգցնենք։ Ավելին, ամեն ինչ կկատարվի ընդհատումների վրա, իսկ ֆոնային առաջադրանքը կլինի մեկ այլ դիոդի թարթումը։ Պարզ և իմաստալից:

Սխեմայի հավաքում
Մենք պետք է միացնենք USB-USART փոխարկիչի մոդուլը միկրոկառավարիչի USART կապին: Դա անելու համար մենք վերցնում ենք երկու լարերի ցատկող և դրանք խաչաձև դնում ենք կապումներին: Այսինքն՝ կարգավորիչի Rx-ը կապում ենք փոխարկիչի Tx-ի հետ, իսկ փոխարկիչի Tx-ը՝ կարգավորիչի Rx-ի հետ։

Ի վերջո, պարզվում է, որ սխեման հետևյալն է.


Մնացած ելքերի միացում, սնուցում, ռեսեթ չեմ համարում, ստանդարտ է

Մենք գրում ենք կոդը

Ես անմիջապես վերապահում կանեմ, որ ես հատուկ չեմ խորանալու հենց C լեզվի նկարագրության մեջ: Դա անելու համար պարզապես հսկայական քանակությամբ նյութ կա՝ սկսած դասական «C ծրագրավորման լեզվից»՝ K&R-ից մինչև տարբեր ձեռնարկներ:

Այդպիսի մի մեթոդ գտնվեց իմ պահոցում, ես մի անգամ ուսումնասիրեցի այս լեզուն՝ օգտագործելով այն: Ամեն ինչ կարճ է, պարզ և ճիշտ: Ես աստիճանաբար մուտքագրում եմ այն ​​և քաշում եմ իմ կայք։

Ճիշտ է, դեռ ոչ բոլոր գլուխներն են այնտեղ տեղափոխվել, բայց կարծում եմ՝ երկար ժամանակ չէ։

Քիչ հավանական է, որ ես ավելի լավ նկարագրեմ այն, հետևաբար, վերապատրաստման դասընթացից, Cish-ի բարդությունների մանրամասն բացատրության փոխարեն, ես ուղղակի հղումներ կտամ այս ձեռնարկի առանձին էջերին:

Գրադարանների ավելացում:
Առաջին հերթին մենք ավելացնում ենք անհրաժեշտ գրադարաններն ու վերնագրերը սահմանումներով։ Ի վերջո, C-ն ունիվերսալ լեզու է, և պետք է բացատրել, որ մենք աշխատում ենք AVR-ի հետ, այնպես որ մուտքագրեք տողը աղբյուրի կոդը.

1 #ներառում

#ներառում

Այս ֆայլը գտնվում է թղթապանակում WinAVRև այն պարունակում է վերահսկիչի բոլոր ռեգիստրների և նավահանգիստների նկարագրությունը: Եվ այնտեղ ամեն ինչ բարդ է, կոնկրետ վերահսկիչի հետ կապված, որը փոխանցվում է կոմպիլյատորի միջոցով դարձնելֆայլ պարամետրով MCUև այս փոփոխականի հիման վրա ձեր նախագծին միացված է վերնագրի ֆայլ՝ այս կոնկրետ կարգավորիչի բոլոր նավահանգիստների և ռեգիստրների հասցեների նկարագրությամբ: Ինչպես! Առանց դրա, դուք նույնպես կարող եք, բայց հետո չեք կարողանա օգտագործել SREG-ի կամ UDR-ի նման խորհրդանշական ռեգիստրի անունները, և դուք պետք է հիշեք յուրաքանչյուրի հասցեն, ինչպիսին է «0xC1»-ը, և դա կոտրում է ձեր գլուխը:

Նույն թիմը #ներառում<имя файла> թույլ է տալիս ձեր նախագծին ավելացնել ցանկացած տեքստային ֆայլի բովանդակություն, օրինակ՝ ֆունկցիաների նկարագրությամբ ֆայլ կամ այլ կոդ: Եվ որպեսզի հրահանգը կարողանա գտնել այս ֆայլը, մենք նշել ենք մեր նախագծի ուղիները (WinAVR գրացուցակը արդեն գրանցված է այնտեղ լռելյայնորեն):

հիմնական գործառույթը.
C ծրագիրը կապված է գործառույթների հետ: Նրանք կարող են բնադրվել և միմյանցից կանչվել ցանկացած կարգով և տարբեր ձևերով: Յուրաքանչյուր գործառույթ ունի երեք պահանջվող պարամետր.

  • Վերադարձի արժեքը, օրինակ, մեղք (x)վերադարձնում է x-ի սինուսի արժեքը: Ինչպես մաթեմատիկայում, մի խոսքով։
  • Փոխանցված պարամետրերը, նույն x.
  • Ֆունկցիոնալ մարմին:

Բոլոր փոխանցված և վերադարձված արժեքները պետք է լինեն ինչ-որ տեսակի՝ կախված տվյալներից:

Յուրաքանչյուր C ծրագիր պետք է պարունակի գործառույթ հիմնականորպես հիմնական ծրագրի մուտքի կետ, հակառակ դեպքում դա ընդհանրապես C չէ :): Ուրիշի մեկ միլիոն ֆայլերի աղբյուրում main-ի առկայությամբ դուք կարող եք հասկանալ, որ սա ծրագրի հիմնական մասն է, որտեղից սկսվում է ամեն ինչ: Այստեղ մենք սահմանելու ենք.

1 2 3 4 5 int main(void) (վերադարձ 0;)

int main(void) (վերադարձ 0;)

Վերջ, առաջին ամենապարզ ծրագիրը գրվել է, կապ չունի, որ ոչինչ չի անում, նոր ենք սկսել։

Տեսնենք՝ ինչ արեցինք։
միջայն տվյալների տեսակն է, որը վերադարձնում է հիմնական գործառույթը:

Իհարկե, միկրոկոնտրոլերում հիմնականսկզբունքորեն ոչինչ չի կարելի վերադարձնել, և տեսականորեն այդպես էլ պետք է լինի դատարկ հիմնական (անվավեր), բայց GCC-ն ի սկզբանե սրված է ԱՀ-ում, և այնտեղ ծրագիրը կարող է արժեքը վերադարձնել օպերացիոն համակարգին ավարտից հետո: Հետևաբար GCC-ն միացված է դատարկ հիմնական (անվավեր)երդվում է Զգուշացումով:

Սա սխալ չէ, կստացվի, բայց ես զգուշացումներ չեմ սիրում։

անվավերսա այն տվյալների տեսակն է, որը մենք փոխանցում ենք ֆունկցիային, այս դեպքում հիմնականնույնպես դրսից ոչինչ չի կարող ընդունել, բանաստեղծը անվավեր- դատարկ: Հավաքածուն օգտագործվում է, երբ ոչինչ պետք չէ փոխանցել կամ վերադարձնել:

Ահա սրանք { } գանգուր փակագծերը ծրագրային բլոկ է, այս դեպքում ֆունկցիայի մարմինը հիմնական, կոդը կտեղակայվի այնտեղ։

վերադարձ- սա այն վերադարձի արժեքն է, որը հիմնական ֆունկցիան կտա ավարտին, քանի որ մենք ունենք int, այսինքն՝ թիվ, ապա պետք է վերադարձնենք թիվ։ Թեեւ դա դեռ իմաստ չունի, քանի որ. միկրոկոնտրոլերի վրա հիմնականից, մենք կարող ենք միայն ոչ մի տեղ գնալ: Ես վերադարձնում եմ անվավեր: Նեֆգի համար. Իսկ կոմպիլյատորը սովորաբար խելացի է և այս դեպքի համար կոդ չի ստեղծում։
Թեեւ, եթե այլասերված, ապա ից հիմնականդուք կարող եք գնալ MK, օրինակ, ընկնել bootloader բաժին և գործարկել այն, բայց այստեղ ձեզ արդեն անհրաժեշտ կլինի որոնվածի ցածր մակարդակի ընտրություն՝ անցումային հասցեները շտկելու համար: Ստորև կտեսնեք և կհասկանաք, թե ինչպես դա անել։ Ինչի համար? Հիմա սա այլ հարց է, 99,999% դեպքերում դա անհրաժեշտ չէ :)

Կատարված է, առաջ գնացեք: Ավելացնենք փոփոխական, մեզ դա իրականում պետք չէ և առանց դրա չպետք է փոփոխականներ ներմուծենք, բայց սովորում ենք։ Եթե ​​փոփոխականներ ավելացվում են ֆունկցիայի մարմնի ներսում, ապա դրանք տեղական են և գոյություն ունեն միայն այս ֆունկցիայի մեջ։ Երբ դուք դուրս եք գալիս ֆունկցիայից, այս փոփոխականները ջնջվում են, և RAM հիշողությունը տրվում է ավելի կարևոր կարիքներին: .

1 2 3 4 5 6 int main(void) (անստորագիր char i; վերադարձ 0;)

int main(void) (անստորագիր char i; վերադարձ 0;)

անստորագիրնշանակում է անստորագիր: Փաստն այն է, որ երկուական ներկայացման մեջ նշանին վերագրվում է ամենակարևոր բիթը, ինչը նշանակում է, որ +127/-128 թիվը տեղավորվում է մեկ բայթի մեջ (char), բայց եթե նշանը դեն նետվի, այն կտեղավորվի 0-ից մինչև 255. Սովորաբար նշանը պետք չէ։ Այնպես, որ անստորագիր.
եսպարզապես փոփոխական անուն է: Ոչ ավելին:

Այժմ մենք պետք է նախաստորագրենք նավահանգիստները և UART. Իհարկե, դուք կարող եք վերցնել և միացնել գրադարանը և զանգահարել մի տեսակ UartInit (9600); բայց հետո չես իմանա, թե իրականում ինչ է տեղի ունեցել:

Մենք անում ենք սա.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main(void) (չստորագրված char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1)#define HI(x) ((x)>>8) #define LO(x) ((x)& 0xFF) UBRRL = LO(bauddivider) ; UBRRH = HI (bauddivider) ; UCSRA = 0; UCSRB=1<< RXEN| 1 << TXEN| 1 << RXCIE| 0 << TXCIE; UCSRC = 1 << URSEL| 1 << UCSZ0| 1 << UCSZ1; }

int main(void) ( unsigned char i; #define XTAL 8000000L #define baudrate 9600L #define bauddivider (XTAL/(16*baudrate)-1) #define HI(x) ((x)>>8) #define LO( x) ((x)& 0xFF) UBRRL = LO (bauddivider); UBRRH = HI (bauddivider); UCSRA = 0; UCSRB = 1<

Վախկոտ? Փաստորեն, իրական կոդի ընդամենը հինգ վերջին տող կա: Ամեն ինչ, դա #սահմանելդա նախապրոցեսորային մակրո լեզու է: Գրեթե նույն գագաթները, ինչ Assembler-ում, բայց շարահյուսությունը փոքր-ինչ տարբեր է:

Նրանք կհեշտացնեն ձեր սովորական գործողությունները՝ պահանջվող գործակիցների հաշվարկման համար: Առաջին տողում մենք ասում ենք, որ փոխարեն XTALԴուք կարող եք ապահով կերպով փոխարինել 8000000, և Լ- տիպի ցուցում, ասում են երկարը պրոցեսորի ժամացույցի հաճախականությունն է։ Նույնը բոդրատ- UART-ի միջոցով տվյալների փոխանցման հաճախականությունը:

բուդդիվիդերարդեն ավելի բարդ, դրա փոխարեն կփոխարինվի նախորդ երկու բանաձևով հաշվարկված արտահայտությունը։
Դե և LOև ՈՂՋՈՒ՜ՅՆԱյս արդյունքից կվերցվեն ցածր և բարձր բայթերը, քանի որ այն ակնհայտորեն չի կարող տեղավորվել մեկ բայթի մեջ: AT ՈՂՋՈՒ՜ՅՆ x-ը (մակրոյի մուտքային պարամետրը) ութ անգամ տեղափոխվում է աջ, արդյունքում դրանից կմնա միայն բարձր բայթը։ Եվ մեջ LO 00FF թվով անում ենք բիթային AND՝ արդյունքում թողնելով միայն ցածր բայթը։

Այսպիսով, այն ամենը, ինչ արվել է, նման է #սահմանելԴուք կարող եք ապահով կերպով նետել այն և հաշվարկել անհրաժեշտ թվերը հաշվիչի վրա և անմիջապես մուտքագրել դրանք UBBRL = ... տողերի մեջ: և UBBRH=…..

Կարող է. Բայց! Արեք սա ԽԻՍՏ ԱՆՀՆԱՐ!

Այսպես-այնպես կաշխատի, բայց կունենաք այսպես կոչված կախարդական թվեր- ոչ մի տեղից վերցված արժեքներ և անհասկանալի է, թե ինչու, և եթե մի քանի տարի անց բացեք նման նախագիծ, ապա անիծյալ դժվար կլինի հասկանալ, թե որոնք են այդ արժեքները: Իսկ հիմա, եթե ուզում ես փոխել արագությունը, կամ փոխել քվարցի հաճախականությունը, ու պետք է ամեն ինչ վերահաշվարկես, և ուրեմն կոդի մեջ մի երկու թիվ ես փոխել ու վերջ։ Ընդհանրապես, եթե դուք չեք ցանկանում, որ ձեզ համարեն վատ կոդավորող, ապա կոդն այնպես պատրաստեք, որ այն հեշտ ընթեռնելի, հասկանալի և հեշտությամբ փոփոխվող լինի։

Այնուհետև ամեն ինչ պարզ է.
Այս բոլոր «UBRLL and Co»-ն UART հաղորդիչի կոնֆիգուրացիայի ռեգիստրներն են, որոնցով մենք շփվելու ենք աշխարհի հետ։ Եվ հիմա մենք նրանց նշանակել ենք անհրաժեշտ արժեքները՝ սահմանելով դրանք ցանկալի արագության և ցանկալի ռեժիմի վրա։

Դիտել մուտքը 1<Նշանակում է հետևյալը` վերցրեք 1-ը և դրեք այն իր տեղում RXENբայթով: RXENսա ռեգիստրի 4-րդ բիթն է UCSRB, ուրեմն 1<կազմում է 00010000 երկուական թիվը, TXEN 3-րդ բիթն է, և 1<կտա 00001000 Մեկ «|» դա բիթային է ԿԱՄ, ուրեմն 00010000 | 00001000 = 00011000: Նույն կերպ, մնացած անհրաժեշտ կոնֆիգուրացիայի բիթերը դրվում և ավելացվում են ընդհանուր կույտին: Արդյունքում հավաքված համարը գրվում է UCSRB: Այն ավելի մանրամասն նկարագրված է USART բաժնում MK-ի տվյալների թերթիկում: Այսպիսով, մի շեղվեք տեխնիկական մանրամասներից:

Ավարտված է, ժամանակն է տեսնել, թե ինչ է տեղի ունենում: Կտտացրեք կոմպիլյացիան և սկսեք էմուլյացիան (Ctrl+F7):

Վրիպազերծում
Բոլոր տեսակի առաջընթացի գծերը անցան միջով, ստուդիան փոխվեց, և հիմնական գործառույթի մուտքի մոտ դեղին սլաք հայտնվեց: Այստեղ է գտնվում պրոցեսորը, և սիմուլյացիան դադարեցված է:

Փաստն այն է, որ ի սկզբանե, ըստ էության, այն եղել է UBRRL = LO (bauddivider) գծում; Ի վերջո, այն, ինչ մենք սահմանում ենք, կոդ չէ, այլ պարզապես նախնական հաշվարկներ, ուստի սիմուլյատորը մի փոքր ձանձրալի է: Բայց հիմա նա հասկացավ, որ առաջին հրահանգը կատարվել է, և եթե բարձրանաս ծառի վրա I/O View, դեպի USART բաժին և այնտեղ նայիր UBBRL բայթը, կտեսնես, որ այնտեղ արդեն արժեք կա։ 0x33.

Եվս մեկ քայլ արա. Տեսեք, թե ինչպես կփոխվի մեկ այլ ռեգիստրի բովանդակությունը: Այսպիսով, անցեք բոլորի միջով, ուշադրություն դարձրեք այն փաստին, որ բոլոր նշված բիթերը դրված են այնպես, ինչպես ասացի ձեզ, և դրանք տեղադրվում են միաժամանակ ամբողջ բայթի համար: Գործերն ավելի հեռու չեն գնա, քան Վերադարձը. ծրագիրն ավարտված է:

Բացում
Այժմ վերակայեք սիմուլյացիան զրոյի: Սեղմեք այնտեղ Վերականգնել (Shift+F5). Բացեք ապամոնտաժված ցանկը, այժմ կտեսնեք, թե իրականում ինչ է կատարվում կարգավորիչում: Դիտել -> Ապամոնտաժող. Եվ ոչ թե ՅԱԱԱԱ!!! Հավաքող!!! ՍԱՐՍԱՓԵԼԻ!!! ԲԱՅՑ ԴՈՒ ՊԵՏՔ Է. Որպեսզի ավելի ուշ, երբ ինչ-որ բան սխալ է լինում, դուք կոդի մեջ հիմար չլինեք և ֆորումներում ավելի խուճապ հարցեր չտաք, այլ անմիջապես մտնեք խրճիթների մեջ և նայեք, թե որտեղ ունեք վարդակից: Այնտեղ ոչ մի սարսափելի բան չկա։

Սկզբում կլինեն գագաթներ շարքից.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +00000000: 940C002A JMP 0x0000002A Jump +00000002: 940C0034 JMP 0x00000034 Jump +00000004: 940C0034 JMP 0x00000034 Jump +00000006: 940C0034 JMP 0x00000034 Jump +00000008: 940C0034 JMP 0x00000034 Jump +0000000A: 940C0034 JMP 0x00000034 Jump +0000000C: 940C0034 JMP 0x00000034 Jump + 0000000E: 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00000014: 940C0034 JMP 0x00000034 Jump +00000016: 940C0034 JMP 0x00000034 Jump +00000018: 940C0034 JMP 0x00000034 Jump +0000001A: 940C0034 JMP 0x00000034 Jump +0000001C : 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00000022: 940C0034 JMP 0x00000034 Jump +00000024: 940C0034 JMP 0x00000034 Jump +00000026: 940C0034 JMP 0x00000034 Jump +00000028: 940C0034 JMP 0x00000034 Jump

00000000: 940C002A JMP 0x0000002A Jump +00000002: 940C0034 JMP 0x00000034 Jump +00000004: 940C0034 JMP 0x00000034 Jump +00000006: 940C0034 JMP 0x00000034 Jump +00000008: 940C0034 JMP 0x00000034 Jump +0000000A: 940C0034 JMP 0x00000034 Jump +0000000C: 940C0034 JMP 0x00000034 Jump +0000000E : 940C0034 JMP 0x00000034 Jump +00000010: 940C0034 JMP 0x00000034 Jump +00000012: 940C0034 JMP 0x00000034 Jump +00000014: 940C0034 JMP 0x00000034 Jump +00000016: 940C0034 JMP 0x00000034 Jump +00000018: 940C0034 JMP 0x00000034 Jump +0000001A: 940C0034 JMP 0x00000034 Jump +0000001C: 940C0034 JMP 0x00000034 Jump +0000001E: 940C0034 JMP 0x00000034 Jump +00000020: 940C0034 JMP 0x00000034 Jump +00000022: 940C0034 JMP 0x00000034 Jump +00000024: 940C0034 JMP 0x00000034 Jump +00000026: 940C0034 JMP 0x00000034 Jump +00000028: 940C0034 JMP 0x00000034 Jump

Սա ընդհատումների վեկտորի աղյուսակն է: Մենք դրան կանդրադառնանք ավելի ուշ, առայժմ, միայն նայեք և հիշեք, որ այն կա։ Առաջին սյունակը ֆլեշ բջիջի հասցեն է, որում գտնվում է հրամանը, երկրորդը՝ հրամանի կոդը, երրորդ հրամանը՝ մնեմոնիկ, նույն assembler հրահանգը, հրամանի երրորդ օպերանդները։ Օհ, և ավտոմատ մեկնաբանություն:
Այսպիսով, եթե նայեք, ապա կան շարունակական անցումներ։ Իսկ JMP հրամանի կոդը չորս բայթ է, այն պարունակում է հետընթաց գրված թռիչքի հասցեն՝ ցածր հասցեում ցածր բայթը և 940C jump հրամանի կոդը:

0000002B՝ BE1F OUT 0x3F, R1 Ելք դեպի մուտքի/ելք գտնվելու վայր

Գրեք այս զրոն 0x3F հասցեին: Եթե նայեք I/O դիտման սյունակում, կտեսնեք, որ 0x3F հասցեն SREG ռեգիստրի հասցեն է՝ վերահսկիչի դրոշակային ռեգիստրը: Նրանք. մենք վերակայում ենք SREG-ը, որպեսզի ծրագիրը աշխատի զրոյական պայմաններում:

1 2 3 4 +0000002C՝ E5CF LDI R28,0x5F Բեռնվում է անմիջապես +0000002D՝ E0D4 LDI R29,0x04 Բեռնվում է անմիջապես +0000002E՝ BFDE OUT 0x3E,R29 Դուրս է I/O դիրք +00000002F:

0000002C՝ E5CF LDI R28,0x5F Բեռնվում է անմիջապես +0000002D՝ E0D4 LDI R29,0x04 Բեռնվում է անմիջապես +0000002E՝ BFDE OUT 0x3E,R29 Դուրս է I/O դիրք +000000002F:

Սա բեռնում է կույտի ցուցիչը: Դուք չեք կարող ուղղակիորեն բեռնել ռեգիստրները I/O-ում, միայն միջանկյալ ռեգիստրի միջոցով: Հետևաբար, նախ LDI-ն մինչև միջանկյալ, իսկ հետո այնտեղից OUT դեպի I/O: Ես ձեզ ավելին կպատմեմ նաև ստեկի մասին: Միևնույն ժամանակ, իմացեք, որ սա այնքան դինամիկ հիշողության տարածք է, այն կախված է RAM-ի վերջում և պահում է հասցեներն ու միջանկյալ փոփոխականներն իր մեջ: Այժմ մենք նշել ենք, թե որտեղից է սկսվելու դարակը:

00000032: 940C0041 JMP 0x00000041 Անցնել

Անցում դեպի ծրագրի saaaaamy վերջ, և այնտեղ մենք ունենք ընդհատումներ անջատված և սերտորեն պտտվող իր վրա.

1 2 +00000041: 94F8 CLI Համաշխարհային ընդհատում Անջատել +00000042: CFFF RJMP PC-0x0000 Հարաբերական թռիչք

00000041: 94F8 CLI Համաշխարհային ընդհատում Անջատել +00000042: CFFF RJMP PC-0x0000 Հարաբերական ցատկ

Սա անկանխատեսելի հանգամանքների դեպքում, օրինակ՝ հիմնական գործառույթից դուրս գալու դեպքում։ Կարգավորիչը կարող է դուրս հանվել նման օղակից կամ ապարատային վերակայման, կամ, ավելի հավանական է, հսկիչի զրոյացման միջոցով: Դե, կամ, ինչպես ասացի վերևում, ուղղեք այս տեղերը hex editor-ում և քշեք ուր ուզում ենք: Նաև նշեք, որ կան երկու տեսակի ցատկեր JMP և RJMP, առաջինը ուղիղ ցատկում է դեպի հասցե: Այն զբաղեցնում է չորս բայթ և կարող է ուղիղ թռիչք կատարել հիշողության ողջ տարածքով: Անցման երկրորդ տեսակը՝ RJMP, հարաբերական է: Նրա հրամանը տեւում է երկու բայթ, բայց նա ցատկում է ընթացիկ դիրքից (հասցեն) 1024 քայլ առաջ կամ հետ: Եվ դրա պարամետրերը ցույց են տալիս ընթացիկ կետից օֆսեթը: Ավելի հաճախ օգտագործվում է, tk. բռնում է ֆլեշի տարածության կեսը, և երկար անցումներ հազվադեպ են անհրաժեշտ:

1 +00000034: 940C0000 JMP 0x00000000 Jump

00000034: 940C0000 JMP 0x00000000 Անցնել

Եվ սա ցատկում է կոդի հենց սկզբին: Մի տեսակ վերաբեռնում: Դուք կարող եք ստուգել, ​​թե արդյոք բոլոր վեկտորները ցատկում են այստեղ: Այս եզրակացությունից - եթե այժմ միացնեք ընդհատումները (դրանք անջատված են լռելյայնորեն) և ունեք ընդհատում, բայց կարգավորիչ չկա, ապա կլինի ծրագրային ապահովման վերակայում - ծրագիրը կուղարկվի հենց սկզբին:

հիմնական գործառույթը. Ամեն ինչ նույնն է, չես էլ կարող նկարագրել։ Նայեք հենց ռեգիստրներում արդեն հաշվարկված թիվը մուտքագրված է։ Կոմպիլյատոր նախապրոցեսորային քարեր!!! Այսպիսով, ոչ մի «կախարդական» թվեր:

1 2 3 4 5 6 7 8 9 10 11 12 <

00000036՝ E383 LDI R24,0x33 Անմիջապես բեռնել +00000037՝ B989 OUT 0x09,R24 Դուրս գալ դեպի մուտքի/ելք 15՝ ​​UBRRH = HI(bauddivider); +00000038. BC10 OUT 0x20,R1 Դուրս գալ դեպի մուտքի/ելք 16. UCSRA = 0; +00000039: B81B OUT 0x0B, R1 Դուրս գալ դեպի մուտքի/ելք 17. UCSRB = 1<

Եվ ահա ջամբը.

1 2 3 +0000003E: E080 LDI R24,0x00 Բեռնում անմիջապես +0000003F: E090 LDI R25,0x00 Բեռնում անմիջապես +00000040: 9508 RET Ենթածրագրի վերադարձ

0000003E: E080 LDI R24,0x00 Բեռնում անմիջապես +0000003F: E090 LDI R25,0x00 Բեռնում անմիջապես +00000040: 9508 RET Ենթածրագրի վերադարձ

Հարցն այն է, թե ինչու է կոմպիլյատորն ավելացնում նման գագաթներ: Եվ սա ոչ այլ ինչ է, քան Return 0, այնուհետև մենք սահմանեցինք ֆունկցիան որպես int main (void), ուստի ևս չորս բայթ ջարդեցինք, չեմ հասկանում ինչ :) Իսկ եթե դուք void main (void) դարձնեք, ապա կմնա միայն RET: բայց կհայտնվի նախազգուշացում, որ ասում են մեր հիմնական ֆունկցիան ոչինչ չի վերադարձնում։ Ընդհանրապես արա այն, ինչ ուզում ես :)

Դժվա՞ր: Կարծես թե չէ: Սեղմեք քայլ առ քայլ կատարումը disassembler ռեժիմում և տեսեք, թե ինչպես է պրոցեսորը կատարում առանձին հրահանգներ, ինչը տեղի է ունենում ռեգիստրների հետ: Ինչպես է շարժումը հրամանների և վերջնական օղակի միջոցով:

Շարունակությունը մի քանի օրից...

Վերևից դուրս՝
Ալեքսեյ 78Ես Firefox-ի համար պլագին եմ պատրաստել, որը հեշտացնում է իմ կայքը և ֆորումը նավարկելը:
Քննարկում և ներբեռնում,

AVR միկրոկոնտրոլերների համար կան տարբեր ծրագրավորման լեզուներ, բայց assembler-ը և C-ն, թերևս, ամենահարմարն են, քանի որ այս լեզուները ապահովում են բոլոր անհրաժեշտ հնարավորությունների լավագույն իրականացումը միկրոկոնտրոլերի ապարատը կառավարելու համար:

Assembler-ը ցածր մակարդակի ծրագրավորման լեզու է, որն օգտագործում է միկրոկոնտրոլերի ուղղակի հրահանգների հավաքածու: Այս լեզվով ծրագիր ստեղծելը պահանջում է ծրագրավորվող չիպի հրամանատարական համակարգի լավ իմացություն և բավարար ժամանակ՝ ծրագիրը մշակելու համար: Assembler-ը կորցնում է C-ին ծրագրի մշակման արագության և հարմարության առումով, բայց նկատելի առավելություններ ունի վերջնական գործարկվող կոդի չափի և, համապատասխանաբար, դրա կատարման արագության մեջ:

C-ն թույլ է տալիս ստեղծել ծրագրեր շատ ավելի մեծ հարմարավետությամբ՝ ծրագրավորողին տալով բարձր մակարդակի լեզվի բոլոր առավելությունները:
Հարկ է ևս մեկ անգամ նշել, որ AVR ճարտարապետությունը և հրամանատարական համակարգը ստեղծվել է C կոմպիլյատորի մշակողների անմիջական մասնակցությամբ և այն հաշվի է առնում այս լեզվի առանձնահատկությունները։ C-ով գրված ելակետային կոդը կազմելը արագ է և արտադրում է կոմպակտ, արդյունավետ կոդ:

C-ի հիմնական առավելություններն են assembler-ի նկատմամբ. ծրագրերի մշակման բարձր արագություն; բազմակողմանիություն, որը չի պահանջում միկրովերահսկիչի ճարտարապետության մանրակրկիտ ուսումնասիրություն. ալգորիթմի ավելի լավ փաստաթղթային և ընթեռնելիություն; գործառույթների գրադարանների առկայություն; աջակցություն լողացող կետի հաշվարկների համար:

C լեզուն ներդաշնակորեն համատեղում է ցածր մակարդակի ծրագրավորման հնարավորությունները բարձր մակարդակի լեզվի առանձնահատկությունների հետ։ Ցածր մակարդակի ծրագրավորման հնարավորությունը հեշտացնում է ուղղակիորեն սարքաշարի վրա աշխատելը, իսկ բարձր մակարդակի լեզվական հատկությունները թույլ են տալիս ստեղծել հեշտությամբ ընթեռնելի և փոփոխվող ծրագրի կոդ: Բացի այդ, գրեթե բոլոր C կոմպիլյատորները հնարավորություն ունեն օգտագործել assembler ներդիրները՝ ծրագրի կարևոր հատվածները գրելու համար՝ կատարման ժամանակի և ռեսուրսների առումով։

Մի խոսքով, C-ն ամենահարմար լեզուն է թե՛ սկսնակների համար AVR միկրոկոնտրոլերների հետ ծանոթանալու, թե՛ լուրջ մշակողների համար։

Կոմպիլյատորներն օգտագործվում են ծրագրի սկզբնական կոդը միկրոկոնտրոլերի որոնվածի ֆայլի փոխակերպելու համար:

Atmel-ը տրամադրում է հզոր assembler կոմպիլյատոր, որը ներառված է Windows-ի վրա հիմնված Atmel Studio մշակման միջավայրում: Կոմպիլյատորի հետ մեկտեղ զարգացման միջավայրը պարունակում է վրիպազերծիչ և էմուլյատոր:
Atmel Studio-ն ամբողջովին անվճար է և հասանելի է Atmel կայքից:

Ներկայումս AVR-ի համար բավականին շատ C կոմպիլյատորներ կան: Դրանցից ամենահզորը Ստոկհոլմից IAR Systems-ի կազմողն է։ Հենց նրա աշխատակիցներն էին 90-ականների կեսերին մասնակցում AVR հրամանատարական համակարգի զարգացմանը։ IAR C Կազմողն ունի կոդի օպտիմիզացման լայն հնարավորություններ և հանդես է գալիս որպես IAR Embedded Workbench (EWB) ինտեգրված զարգացման միջավայրի մաս, որը ներառում է նաև հավաքող կազմող, կապող, նախագծի և գրադարանի կառավարիչ և վրիպազերծիչ: Փաթեթի ամբողջական տարբերակի արժեքը 2820 եվրո է։ Ընկերության կայքում կարող եք ներբեռնել անվճար գնահատման տարբերակը 30 օրով կամ անսահմանափակ տարբերակ՝ 4 ԿԲ կոդի չափի սահմանաչափով:

Ամերիկյան Image Craft ընկերությունը Կալիֆորնիայի Պալո Ալտո քաղաքից արտադրում է C լեզվի կոմպիլյատոր, որը բավականին լայն տարածում է գտել։ JumpStart C-ն AVR-ի համար ունի ընդունելի կոդի օպտիմիզացիա և այնքան էլ թանկ չէ ($50-ից մինչև $499՝ կախված տարբերակից): JumpStart C-ի ցուցադրական տարբերակը AVR-ի համար լիովին գործում է 45 օր:

Ռումինական Code Vision AVR C Compiler-ը շահեց ոչ պակաս ժողովրդականություն, այս կոմպիլյատորի ամբողջական տարբերակի գինը համեմատաբար ցածր է և կազմում է 150 եվրո: Կոմպիլյատորը գալիս է ինտեգրված զարգացման միջավայրով, որը, բացի ստանդարտ հնարավորություններից, ներառում է բավականին հետաքրքիր գործառույթ՝ CodeWizardAVR Automatic Program Generator։ Զարգացման միջավայրում սերիական տերմինալի առկայությունը թույլ է տալիս վրիպազերծել ծրագրերը՝ օգտագործելով միկրոկառավարիչի սերիական պորտը: Մշակողները կարող են ներբեռնել անվճար գնահատման տարբերակը՝ 4 ԿԲ կոդի չափի սահմանաչափով և ստեղծած C աղբյուրի կոդի պահպանումն անջատված է:

MikroElektronika-ն, որը գտնվում է սերբական Բելգրադ քաղաքում, արտադրում է AVR միկրոկոնտրոլերների կոմպիլյատորների մի ամբողջ ընտանիք: MicroC PRO կոչվող C կոմպիլյատորը AVR-ի համար արժե 249 դոլար: Նույն գնով կան նաև mikroBasic և mikroPascal: Մշակողի կայքում կան ցուցադրություններ՝ 4096 բայթ կոդի չափի սահմանաչափով: Կոմպիլյատորների այս ընտանիքի առավելությունը մեկ հարթակ և մեկ գաղափարախոսություն է, որը կարող է ապահովել հեշտ անցում ոչ միայն լեզուների, այլ նաև միկրոկառավարիչների միջև (կան PIC, STM32, 8051 ... կոմպիլյատորների տարբերակներ):

Ինտեգրված զարգացման միջավայրն իսկապես խորհրդանշական է դարձել: Այն ներառում է հզոր C և assembler կոմպիլյատորներ, AVRDUDE ծրագրավորող, վրիպազերծիչ, սիմուլյատոր և շատ այլ օժանդակ ծրագրեր և կոմունալ ծառայություններ: WinAVR-ը հիանալի կերպով ինտեգրվում է Atmel-ի AVR Studio-ի մշակման միջավայրին: Ասեմբլերը մուտքագրման կոդով նույնական է AVR Studio assembler-ին: C-ն և assembler կոմպիլյատորները հնարավորություն ունեն ստեղծելու վրիպազերծման ֆայլեր COFF ձևաչափով, ինչը թույլ է տալիս օգտագործել ոչ միայն ներկառուցված գործիքներ, այլև օգտագործել հզոր AVR Studio սիմուլյատորը։ Մեկ այլ կարևոր գումարած այն է, որ WinAVR-ն անվճար տարածվում է առանց սահմանափակումների (արտադրողները աջակցում են GNU Ընդհանուր հանրային լիցենզիան):

Որպես ամփոփում, WinAVR-ը իդեալական ընտրություն է նրանց համար, ովքեր սկսում են տիրապետել AVR միկրոկառավարիչներին: Հենց այս զարգացման միջավայրն է համարվում այս դասընթացի հիմնականը:

Bitwise գործողությունները հիմնված են տրամաբանական գործողությունների վրա, որոնք մենք արդեն անդրադարձել ենք ավելի վաղ: Նրանք առանցքային դեր են խաղում AVR միկրոկոնտրոլերների և այլ տեսակների ծրագրավորման գործում: Գրեթե ոչ մի ծրագիր չի կարող անել առանց բիթային գործողությունների օգտագործման: Մինչ այժմ մենք միտումնավոր խուսափել ենք դրանցից, որպեսզի հեշտացնենք MK ծրագրավորում սովորելը:

Բոլոր նախորդ հոդվածներում մենք ծրագրավորել ենք միայն I/O պորտերը և չենք օգտագործել լրացուցիչ ներկառուցված հանգույցներ, ինչպիսիք են ժամանակաչափերը, անալոգային թվային փոխարկիչները, ընդհատումները և այլ ներքին սարքեր, առանց որոնց MK-ն կորցնում է իր ողջ հզորությունը:

Նախքան ներկառուցված MK սարքերի յուրացմանը անցնելը, դուք պետք է սովորեք, թե ինչպես կառավարել կամ ստուգել AVR MK ռեգիստրների առանձին բիթերը: Նախկինում մենք ստուգում էինք կատարում կամ միանգամից դնում ամբողջ ռեգիստրի բիթերը: Եկեք տեսնենք, թե որն է տարբերությունը, ապա շարունակենք հետագա:

Բիթային գործողություններ

Ամենից հաճախ, AVR միկրոկոնտրոլերները ծրագրավորելիս մենք օգտագործում էինք այն, քանի որ այն ավելի մեծ պարզություն ունի, համեմատած և լավ հասկանալի է սկսնակ MK ծրագրավորողների համար: Օրինակ, մենք պետք է սահմանենք D պորտի միայն 3-րդ բիթը: Դրա համար, ինչպես արդեն գիտենք, կարող ենք օգտագործել հետևյալ երկուական կոդը.

PORTD = 0b00001000;

Այնուամենայնիվ, այս հրամանով մենք 3-րդ բիթը դնում ենք մեկի վրա, իսկ մնացած բոլորը (0, 1, 2, 4, 5, 6 և 7-րդ) վերակայում ենք զրոյի: Եվ հիմա եկեք պատկերացնենք իրավիճակը, որ 6-րդ և 7-րդ թվերն օգտագործվում են որպես ADC մուտքեր, և այս պահին ինչ-որ սարքից ազդանշան է հասնում MK-ի համապատասխան ելքերին, և մենք վերակայում ենք այդ ազդանշանները՝ օգտագործելով վերը նշված հրամանը: Արդյունքում միկրոկոնտրոլերը չի տեսնում դրանք և կարծում է, որ ազդանշանները չեն եկել։ Հետևաբար, նման հրամանի փոխարեն մենք պետք է օգտագործենք մեկ ուրիշը, որը միայն 3-րդ բիթը կդնի մեկ՝ չազդելով մնացած բիթերի վրա։ Դրա համար սովորաբար օգտագործվում է հետևյալ բիթային գործողությունը.

PORT |= (1<<3);

Ստորև մենք մանրամասն կվերլուծենք դրա շարահյուսությունը: Իսկ հիմա ևս մեկ օրինակ. Ենթադրենք, մենք պետք է ստուգենք PIND ռեգիստրի 3-րդ բիտի կարգավիճակը՝ դրանով իսկ ստուգելով կոճակի վիճակը։ Եթե ​​այս բիթը զրոյացված է, ապա մենք գիտենք, որ կոճակը սեղմված է, և այնուհետև գործարկվում է հրամանի կոդը, որը համապատասխանում է սեղմված կոճակի վիճակին։ Նախկինում մենք կօգտագործեինք հետևյալ նշումը.

եթե (փինդ == 0b00000000)

(ցանկացած կոդ)

Սակայն դրա օգնությամբ մենք ստուգում ենք ոչ թե մեկ՝ PIND ռեգիստրի 3-րդ, այլ միանգամից բոլոր բիթերը։ Հետևաբար, նույնիսկ եթե կոճակը սեղմված է և ցանկալի բիթը զրոյացված է, բայց այդ ժամանակ ազդանշան է ստացվում ցանկացած այլ նավահանգիստ D պինդում, համապատասխան բիթը կդրվի մեկի վրա, իսկ փակագծերում դրված պայմանը կլինի կեղծ: Արդյունքում, գանգուր փակագծերի ծածկագիրը չի գործարկվի նույնիսկ կոճակը սեղմելիս: Հետևաբար, PIND ռեգիստրի առանձին 3-րդ բիտի կարգավիճակը ստուգելու համար պետք է օգտագործվի բիթային գործողություն.

եթե (~ PIND & (1<<3))

(ցանկացած կոդ)

Առանձին միկրոկոնտրոլերի բիթերի հետ աշխատելու համար C ծրագրավորման լեզուն իր զինանոցում ունի, որով կարող եք փոխել կամ ստուգել մեկ կամ մի քանի առանձին բիթերի վիճակը միանգամից։

Մեկ բիթ սահմանելը

Մեկ բիթ սահմանելու համար, ինչպիսին է D պորտը, օգտագործվում է բիթային OR գործողությունը: Դա այն է, ինչ մենք օգտագործել ենք հոդվածի սկզբում:

PORTD = 0b00011100; // սկզբնական արժեքը

PORTD = PORTD | (մեկ<<0); применяем побитовую ИЛИ

PORT |= (1<<0); // сокращенная форма записи

PORTD == 0b00011101; // արդյունք

Այս հրամանը բիթը դնում է զրոյի, իսկ մնացածը թողնում է անփոփոխ:

Օրինակ՝ սահմանենք D պորտի 6-րդ բիթը։

PORTD = 0b00011100; // նավահանգստի սկզբնական վիճակ

PORT |= (1<<6); //

PORTD == 0b01011100; // արդյունք

Միանգամից մեկից մի քանի առանձին բիթ գրելու համար, օրինակ, զրո, վեցերորդ և յոթերորդ պորտ Բկիրառվում է հետևյալ նշումը.

PORTB = 0b00011100; // սկզբնական արժեքը

PORTB |= (1<<0) | (1<<6) | (1<<7); //

PORTB == 0b1011101; // արդյունք

Առանձին բիթերի զրոյացում (զրոյացում):

Մեկ բիթը վերականգնելու համար օգտագործվում են միանգամից երեք նախկինում քննարկված հրամաններ. .

Եկեք զրոյացնենք PORTC ռեգիստրի 3-րդ բիթը, իսկ մնացածը թողնենք անփոփոխ:

PORTC = 0b00011100;

PORTC &= ~ (1<<3);

PORTC == 0b00010100;

Կատարենք նմանատիպ գործողություններ 2-րդ և 4-րդ թվանշանների համար.

PORTC = 0b00111110;

PORTC &= ~((1<<2) | (1<<4));

PORTC == 0b00101010;

Փոխարկելով ռիթմը

Բացի կարգավորումից և զրոյից, օգտագործվում է նաև օգտակար հրաման, որը մեկ բիթ է փոխում հակառակ վիճակի` մեկ զրոյի և հակառակը: Այս տրամաբանական գործողությունը լայնորեն կիրառվում է տարբեր լուսային էֆեկտների կառուցման մեջ, օրինակ, օրինակ՝ Ամանորի ծաղկեպսակ: Դիտարկենք ՊՈՐՏԱ-ի օրինակը

ՊՈՐՏԱ = 0b00011111;

ՊՈՐՏԱ ^= (1<<2);

ՊՈՐՏԱ == 0b00011011;

Փոխեք զրոյական, երկրորդ և վեցերորդ բիթերի վիճակը.

ՊՈՐՏԱ = 0b00011111;

ՊՈՐՏԱ ^= (1<<0) | (1<<2) | (1<<6);

ՊՈՐՏԱ == 0b01011010;

Անհատական ​​բիտի կարգավիճակի ստուգում: Հիշեցնեմ, որ I/O պորտի ստուգումը (ի տարբերություն գրելու) իրականացվում է PIN ռեգիստրից տվյալների ընթերցմամբ:

Ամենատարածված թեստը կատարվում է երկու հանգույցի հայտարարություններից մեկի միջոցով՝ if և while: Մենք արդեն ծանոթ ենք այս օպերատորներին ավելի վաղ:

Ստուգելով լիցքաթափումը տրամաբանական զրոյի առկայության համար (վերակայում): եթե

եթե (0==(PIND & (1<<3)))

Եթե ​​D պորտի երրորդ բիթը ջնջված է, Code1-ը գործարկվում է: Հակառակ դեպքում, Code2-ը գործարկվում է:

Նմանատիպ գործողություններ կատարվում են ձայնագրման և այս ձևով.

եթե (~ PIND & (1<<3))

Ստուգելով լիցքաթափումը տրամաբանական միավորի (պարամետրի) առկայության համար եթե

եթե (0 != (PIND & (1<<3)))

եթե (PIND & (1<<3))

Վերոնշյալ երկու օղակներն աշխատում են նույն կերպ, սակայն C ծրագրավորման լեզվի ճկունության պատճառով դրանք կարող են տարբեր կերպ գրվել։ Գործողությունը != նշանակում է ոչ հավասար: Եթե ​​PD I/O պորտի երրորդ բիթը դրված է (մեկ), ապա գործարկվում է Code1, եթե ոչ՝ Code2:

Սպասում է մի փոքր վերակայման հետ մինչդեռ

մինչդեռ (PIND & (1<<5))

Code1-ը կկատարվի այնքան ժամանակ, քանի դեռ սահմանված է PIND ռեգիստրի 5-րդ բիթը: Վերականգնելով այն կսկսի գործարկել Code2-ը:

Սպասում է, որ բիթը կարգավորվի մինչդեռ

Այստեղ C լեզվի շարահյուսությունը թույլ է տալիս կոդ գրել երկու ամենատարածված եղանակներով։ Գործնականում օգտագործվում են երկու տեսակի ձայնագրություններ: