Կարդացեք տվյալների թերթիկները 2. SPI STM32-ում; PWM, ժամանակաչափեր և ընդհատումներ STM8-ում
В առաջին մասը Ես փորձեցի պատմել հոբբի էլեկտրոնիկայի ինժեներներին, ովքեր մեծացել են Arduino շալվարից, թե ինչպես և ինչու նրանք պետք է կարդան տվյալների թերթիկներ և այլ փաստաթղթեր միկրոկոնտրոլերների համար: Տեքստը մեծ էր, ուստի ես խոստացա գործնական օրինակներ ցույց տալ առանձին հոդվածում։ Դե, նա իրեն անվանել է կաթնային սունկ...
Այսօր ես ձեզ ցույց կտամ, թե ինչպես օգտագործել տվյալների թերթիկները՝ լուծելու համար բավականին պարզ, բայց անհրաժեշտ բազմաթիվ նախագծեր, առաջադրանքներ STM32 (Blue Pill) և STM8 կարգավորիչների վրա: Բոլոր ցուցադրական նախագծերը նվիրված են իմ սիրելի LED-ներին, մենք դրանք կվառենք մեծ քանակությամբ, ինչի համար ստիպված կլինենք օգտագործել բոլոր տեսակի հետաքրքիր ծայրամասային սարքերը:
Տեքստը կրկին հսկայական է, ուստի հարմարության համար ես պատրաստում եմ բովանդակությունը.
Հրաժարում. Ես ինժեներ չեմ, չեմ հավակնում ունենալ էլեկտրոնիկայի խորը գիտելիքներ, հոդվածը նախատեսված է ինձ նման սիրողականների համար։ Իրականում ես ինձ երկու տարի առաջ համարում էի որպես թիրախային լսարան։ Եթե այն ժամանակ ինչ-որ մեկն ինձ ասեր, որ անծանոթ չիպի տվյալների թերթիկները կարդալը սարսափելի չէ, ես երկար ժամանակ չէի ծախսի ինտերնետում որոշ կոդի կտորներ փնտրելու և մկրատով և կպչուն ժապավենով հենակներ հորինելու համար:
Այս հոդվածի ուշադրությունը կենտրոնացված է տվյալների թերթիկների վրա, այլ ոչ թե նախագծերի, ուստի ծածկագիրը կարող է շատ կոկիկ և հաճախ նեղ լինել: Նախագծերն իրենք շատ պարզ են, թեև հարմար են նոր չիպի հետ առաջին ծանոթության համար:
Հուսով եմ, որ իմ հոդվածը կօգնի որևէ մեկին, ով գտնվում է հոբբիի մեջ ընկղմվելու նմանատիպ փուլում:
STM32
16 LED DM634 և SPI-ով
Փոքր նախագիծ՝ օգտագործելով Blue Pill (STM32F103C8T6) և DM634 LED դրայվեր: Օգտագործելով տվյալների թերթիկները, մենք կպարզենք վարորդը, STM IO պորտերը և կկարգավորենք SPI-ն:
DM634
Թայվանական չիպը 16 16-բիթանոց PWM ելքերով, կարելի է միացնել շղթաներով: Ցածր 12-բիթանոց մոդելը հայտնի է ներքին նախագծից Lightpack. Ժամանակին, ընտրելով DM63x-ի և հայտնի TLC5940-ի միջև, ես ընտրեցի DM-ն մի քանի պատճառով. 1) DM-ն ունի ինքնավար PWM՝ սեփական հաճախականության գեներատորով. 2) Մոսկվայում այն կարելի էր էժան գնել, այլ ոչ թե Ալիից ծանրոց սպասել: Եվ, իհարկե, հետաքրքիր էր սովորել, թե ինչպես կառավարել չիպը ինքներդ, այլ ոչ թե օգտագործել պատրաստի գրադարան: Չիպերն այժմ հիմնականում ներկայացված են SSOP3 փաթեթում, դրանք հեշտ է զոդել ադապտերին:
Քանի որ արտադրողը թայվանցի է, տվյալների թերթիկ չիպը գրված է չինական անգլերենով, ինչը նշանակում է, որ զվարճալի կլինի: Սկզբում մենք նայում ենք պինաուտին (Փին միացում) հասկանալու համար, թե որ ոտքը ինչին միացնել, և քորոցների նկարագրությունը (Քորոցի նկարագրություն) 16 կապում:
DC լվացարանի աղբյուրներ (բաց արտահոսք)
Սուզվել / Բաց արտահոսքի ելք - արտահոսք; ներհոսող հոսանքի աղբյուր; ելքը միացված է գետնին ակտիվ վիճակում - LED-ները միացված են վարորդին կաթոդներով: Էլեկտրական առումով սա, իհարկե, «բաց արտահոսք» չէ (բաց արտահոսք), բայց տվյալների աղյուսակներում հաճախ հայտնաբերվում է արտահոսքի ռեժիմում գտնվող քորոցների այս նշանակումը:
Արտաքին դիմադրություններ REXT-ի և GND-ի միջև՝ ելքային հոսանքի արժեքը սահմանելու համար
REXT փին և հողի միջև տեղադրված է հղման դիմադրություն, որը վերահսկում է ելքերի ներքին դիմադրությունը, տես աղյուսակի 9-րդ էջի գրաֆիկը: DM634-ում այս դիմադրությունը կարող է վերահսկվել նաև ծրագրաշարի միջոցով՝ սահմանելով ընդհանուր պայծառությունը (գլոբալ պայծառություն); Ես այս հոդվածում մանրամասների մեջ չեմ մտնի, ես պարզապես այստեղ կտեղադրեմ 2.2 - 3 կՕհմ ռեզիստոր:
Հասկանալու համար, թե ինչպես կառավարել չիպը, եկեք նայենք սարքի ինտերֆեյսի նկարագրությանը.
Այո, ահա, չինական անգլերենն իր ողջ փառքով: Սա թարգմանելը խնդրահարույց է, եթե ցանկանաք, կարող եք դա հասկանալ, բայց կա ևս մեկ միջոց՝ տեսեք, թե ինչպես է նկարագրված ֆունկցիոնալորեն նման TLC5940 կապը տվյալների թերթիկում.
... Սարքի մեջ տվյալներ մուտքագրելու համար պահանջվում է ընդամենը երեք փին: SCLK ազդանշանի բարձրացող եզրը տվյալները տեղափոխում է SIN փինից դեպի ներքին ռեգիստր: Բոլոր տվյալները բեռնվելուց հետո կարճ բարձր XLAT ազդանշանը փակում է հաջորդաբար փոխանցված տվյալները ներքին ռեգիստրների մեջ: Ներքին ռեգիստրները դարպասներ են, որոնք գործարկվում են XLAT ազդանշանի մակարդակով: Բոլոր տվյալները նախ փոխանցվում են ամենակարևոր բիթը:
Կանգնեցրեք – սողնակ/սողնակ/կողպեք: Բարձրացող եզր - զարկերակի առաջատար եզրը MSB նախ – ամենակարևոր (ամենաձախ) բիթը առաջ: տվյալների ժամացույցի համար - փոխանցել տվյալները հաջորդաբար (փիթ առ բիթ):
Բառ փակվել հաճախ հանդիպում է չիպերի փաստաթղթերում և թարգմանվում է տարբեր ձևերով, ուստի հասկանալու համար ես ինձ թույլ կտամ
փոքր կրթական ծրագիրLED վարորդը, ըստ էության, հերթափոխի ռեգիստր է: «Հերթափոխ» (հերթափոխություն) անվանման մեջ՝ տվյալների բիթային շարժում սարքի ներսում. ներս խցկված յուրաքանչյուր նոր բիթ առաջ է մղում ամբողջ շղթան իր առջև: Քանի որ ոչ ոք չի ցանկանում դիտել LED-ների քաոսային թարթումը հերթափոխի ընթացքում, գործընթացը տեղի է ունենում բուֆերային ռեգիստրներում, որոնք անջատված են աշխատանքային ռեգիստրներից կափույրով (փակվել) սպասասրահի տեսակ է, որտեղ բիթերը դասավորված են ցանկալի հաջորդականությամբ։ Երբ ամեն ինչ պատրաստ է, կափարիչը բացվում է, և բիթերը անցնում են աշխատանքի՝ փոխարինելով նախորդ խմբաքանակը: Խոսք փակվել միկրոսխեմաների փաստաթղթերում գրեթե միշտ ենթադրում է նման կափույր, անկախ նրանից, թե ինչ համակցություններում է այն օգտագործվում:
Այսպիսով, տվյալների փոխանցումը DM634-ին կատարվում է այսպես. DAI մուտքագրումը սահմանեք հեռավոր LED-ի ամենակարևոր բիտի արժեքին, քաշեք DCK-ը վեր ու վար. սահմանեք DAI մուտքագրումը հաջորդ բիտի արժեքին, քաշեք DCK; և այսպես շարունակ, մինչև բոլոր բիթերը փոխանցվեն (ժամացույցով ներս), որից հետո մենք քաշում ենք LAT. Դա կարելի է անել ձեռքով (bit-bang), բայց ավելի լավ է օգտագործել SPI ինտերֆեյս, որը հատուկ հարմարեցված է դրա համար, քանի որ այն ներկայացված է մեր STM32-ում երկու օրինակով:
Կապույտ հաբ STM32F103
Ներածություն. STM32 կարգավորիչները շատ ավելի բարդ են, քան Atmega328-ը, քան նրանք կարող են սարսափելի թվալ: Ավելին, էներգախնայողության նկատառումներից ելնելով, սկզբում անջատված են գրեթե բոլոր ծայրամասային սարքերը, իսկ ժամացույցի հաճախականությունը 8 ՄՀց է ներքին աղբյուրից։ Բարեբախտաբար, STM ծրագրավորողները գրել են կոդ, որը չիպը հասցնում է «հաշվարկված» 72 ՄՀց-ի, և իմ իմացած բոլոր IDE-ների հեղինակները ներառել են այն սկզբնավորման ընթացակարգում, այնպես որ մենք պետք չէ ժամացույց անել (բայց դուք կարող եք, եթե իսկապես ցանկանում եք). Բայց դուք ստիպված կլինեք միացնել ծայրամասային սարքերը:
Փաստաթղթեր. Blue Pill-ը հագեցած է հայտնի STM32F103C8T6 չիպով, դրա համար կան երկու օգտակար փաստաթուղթ.
Տվյալների թերթ STM32F103x8 և STM32F103xB միկրոկառավարիչների համար;
Pinouts – chip pinouts – եթե մենք որոշենք ինքներս պատրաստել տախտակները;
Հիշողության քարտեզ – հիշողության քարտեզ կոնկրետ չիպի համար: Reference Manual-ն ունի քարտեզ ամբողջ տողի համար, և այն նշում է ռեգիստրներ, որոնք մերը չունի:
Pin Definitions Աղյուսակ – թվարկում է քորոցների հիմնական և այլընտրանքային գործառույթները; «Կապույտ հաբ»-ի համար ինտերնետում կարող եք գտնել ավելի հարմար նկարներ՝ քորոցների և դրանց գործառույթների ցանկով: Հետևաբար, մենք անմիջապես google-ում ենք Blue Pill pinout-ը և ձեռքի տակ ենք պահում այս նկարը.
Ն.Բ. համացանցից նկարում սխալ կար, որը նշված էր մեկնաբանություններում, շնորհակալություն դրա համար։ Նկարը փոխարինվել է, բայց սա դաս է. ավելի լավ է տեղեկատվությունը ստուգել ոչ տվյալների թերթիկներից:
Մենք հեռացնում ենք տվյալների թերթիկը, բացում ենք Reference Manual-ը և այսուհետ օգտագործում ենք միայն այն:
Ընթացակարգ. մենք գործ ունենք ստանդարտ մուտքի/ելքի հետ, կարգավորում ենք SPI-ն, միացնում ենք անհրաժեշտ ծայրամասային սարքերը:
Մուտքային ելք
Atmega328-ում I/O-ն իրականացվում է չափազանց պարզ, այդ իսկ պատճառով STM32 տարբերակների առատությունը կարող է շփոթեցնել: Այժմ մեզ միայն անհրաժեշտ են եզրակացություններ, բայց նույնիսկ դրանք ունեն չորս տարբերակ.
բաց արտահոսք, մղել-քաշել, այլընտրանքային մղել-քաշել, այլընտրանքային բաց արտահոսք
«Քաշել-հրել» (հրել-քաշել) սովորական ելքն է Arduino-ից, փին կարող է վերցնել կամ HIGH կամ LOW արժեքը: Բայց «բաց արտահոսքի» դեպքում կան դժվարություններ, չնայած իրականում այստեղ ամեն ինչ պարզ է.
Ելքի կոնֆիգուրացիա / երբ նավահանգիստը նշանակված է ելքին. / ելքային բուֆերը միացված է. / – բաց արտահոսքի ռեժիմ. «0»-ը ելքային ռեգիստրում միացնում է N-MOS-ը, «1»-ը ելքային ռեգիստրում թողնում է նավահանգիստը Hi-Z ռեժիմում ( P-MOS-ը միացված չէ ) / – push-pull ռեժիմ. «0»-ը ելքային ռեգիստրում ակտիվացնում է N-MOS-ը, «1»-ը ելքային ռեգիստրում ակտիվացնում է P-MOS-ը:
Բոլոր տարբերությունները բաց արտահոսքի միջև (բաց արտահոսք) «հրել-քաշել» -ից (հրել-քաշել) այն է, որ առաջին փինում չի կարող ընդունել HIGH վիճակը. ելքային ռեգիստրում մեկը գրելիս այն անցնում է բարձր դիմադրության ռեժիմի (բարձր Impedance, Hi-Z). Զրո գրելիս քորոցը նույնն է պահում երկու ռեժիմներում՝ և՛ տրամաբանական, և՛ էլեկտրական:
Նորմալ ելքային ռեժիմում փին պարզապես հեռարձակում է ելքային ռեգիստրի բովանդակությունը: «Այլընտրանքում» այն վերահսկվում է համապատասխան ծայրամասային սարքերով (տես 9.1.4).
Եթե պորտի բիթը կազմաձևված է որպես այլընտրանքային ֆունկցիայի փին, ապա փին ռեգիստրն անջատված է, և փին միացված է ծայրամասային փինին:
Յուրաքանչյուր քորոցի այլընտրանքային ֆունկցիոնալությունը նկարագրված է Քորոցային սահմանումներ Տվյալների թերթիկը ներբեռնված պատկերի վրա է: Հարցին, թե ինչ անել, եթե քորոցն ունի մի քանի այլընտրանքային գործառույթ, պատասխանը տրված է տվյալների թերթիկի տողատակով.
Եթե մի քանի ծայրամասային սարքեր օգտագործում են նույն փին, այլընտրանքային գործառույթների միջև կոնֆլիկտից խուսափելու համար, պետք է միաժամանակ օգտագործվի միայն մեկ ծայրամասային սարք՝ միացնելով ծայրամասային ժամացույցի միացման բիթը (համապատասխան RCC ռեգիստրում):
Վերջապես, ելքային ռեժիմում գտնվող կապումներն ունեն նաև ժամացույցի արագություն: Սա ևս մեկ էներգախնայողության հատկություն է, մեր դեպքում մենք այն դնում ենք առավելագույնի և մոռանում ենք:
Այսպիսով, մենք օգտագործում ենք SPI, ինչը նշանակում է, որ երկու պին (տվյալներով և ժամացույցի ազդանշանով) պետք է լինեն «այլընտրանքային push-pull ֆունկցիա», իսկ մյուսը (LAT) պետք է լինի «կանոնավոր push-pull»: Բայց մինչ դրանք հանձնարարելը, եկեք զբաղվենք SPI-ով։
SPI
Եվս մեկ փոքրիկ կրթական ծրագիր
SPI կամ Serial Peripheral Interface (սերիական ծայրամասային ինտերֆեյս) պարզ և շատ արդյունավետ ինտերֆեյս է MK-ն այլ MK-ների և ընդհանրապես արտաքին աշխարհի հետ կապելու համար: Դրա գործողության սկզբունքը արդեն նկարագրված է վերևում, որտեղ չինական LED վարորդի մասին է (տեղեկատու ձեռնարկում, տես բաժին 25): SPI-ն կարող է գործել հիմնական («վարպետ») և ստրուկ («ստրուկ») ռեժիմներում: SPI-ն ունի չորս հիմնական ալիք, որոնցից ոչ բոլորը կարող են օգտագործվել.
MOSI, Master Output / Slave Input. այս փին փոխանցում է տվյալները հիմնական ռեժիմում և տվյալներ ստանում ստրուկ ռեժիմում;
MISO, Master Input / Slave Output. ընդհակառակը, այն ստանում է վարպետի մեջ և փոխանցում է ստրուկի մեջ;
SCK, Serial Clock. սահմանում է տվյալների փոխանցման հաճախականությունը հիմնականում կամ ստանում է ժամացույցի ազդանշան ստրուկում: Ըստ էության հարվածում է ծեծում;
SS, Slave Select. այս ալիքի օգնությամբ ստրուկը գիտի, որ իրենից ինչ-որ բան են ուզում։ STM32-ում այն կոչվում է NSS, որտեղ N = բացասական, այսինքն. վերահսկիչը դառնում է ստրուկ, եթե այս ալիքում հիմք կա: Այն լավ համակցվում է Open Drain Output ռեժիմի հետ, բայց դա այլ պատմություն է:
Ինչպես մնացած ամեն ինչ, SPI-ն էլ STM32-ում հարուստ է ֆունկցիոնալությամբ, ինչը որոշ չափով դժվարացնում է այն հասկանալը: Օրինակ, այն կարող է աշխատել ոչ միայն SPI-ի, այլև I2S ինտերֆեյսի հետ, իսկ փաստաթղթերում դրանց նկարագրությունները խառնված են, անհրաժեշտ է ժամանակին կտրել ավելցուկը։ Մեր խնդիրը չափազանց պարզ է. մենք պարզապես պետք է տվյալներ ուղարկենք՝ օգտագործելով միայն MOSI և SCK: Մենք գնում ենք 25.3.4 բաժին (կիս-դուպլեքս հաղորդակցություն, կիսա-դուպլեքս հաղորդակցություն), որտեղ գտնում ենք. 1 ժամացույց և 1 միակողմանի տվյալների լար (1 ժամացույցի ազդանշան և 1 միակողմանի տվյալների հոսք).
Այս ռեժիմում հավելվածն օգտագործում է SPI միայն փոխանցման կամ միայն ստացման ռեժիմում: / Միայն փոխանցման ռեժիմը նման է դուպլեքս ռեժիմին. տվյալները փոխանցվում են փոխանցման փինով (MOSI հիմնական ռեժիմում կամ MISO՝ ստրուկ ռեժիմում), իսկ ստացող փին (համապատասխանաբար MISO կամ MOSI) կարող է օգտագործվել որպես սովորական I/O փին: . Այս դեպքում հավելվածը միայն պետք է անտեսի Rx բուֆերը (եթե այն կարդացվի, այնտեղ փոխանցված տվյալներ չեն լինի):
Հիանալի է, MISO փին անվճար է, եկեք միացնենք LAT ազդանշանը դրան: Եկեք նայենք Slave Select-ին, որը STM32-ի վրա կարելի է ծրագրավորել, ինչը չափազանց հարմար է։ Մենք կարդում ենք նույնանուն պարբերությունը 25.3.1 բաժնում SPI Ընդհանուր նկարագրություն.
Ծրագրային կառավարման NSS (SSM = 1) / ստրուկների ընտրության տեղեկատվությունը պարունակվում է SPI_CR1 ռեգիստրի SSI բիթում: Արտաքին NSS փին մնում է անվճար հավելվածի այլ կարիքների համար:
Ժամանակն է գրել գրանցամատյաններին։ Ես որոշեցի օգտագործել SPI2, փնտրել դրա բազային հասցեն տվյալների թերթիկում՝ 3.3 բաժնում Հիշողության քարտեզ.
Գրանցամատյանները հավաքվում են տեղեկատու ձեռնարկի համանուն բաժնում: Հասցեի հերթափոխ (Հասցեի օֆսեթ) CR1 – 0x00-ի համար, լռելյայնորեն բոլոր բիթերը մաքրված են (Վերականգնել արժեքը 0x0000):
BR բիթերը սահմանում են վերահսկիչի ժամացույցի բաժանարարը՝ այդպիսով որոշելով SPI-ի գործելու հաճախականությունը: Մեր STM32 հաճախականությունը կլինի 72 ՄՀց, LED դրայվերը, ըստ իր տվյալների թերթիկի, աշխատում է մինչև 25 ՄՀց հաճախականությամբ, ուստի պետք է բաժանել չորսի (BR[2:0] = 001):
2. Սահմանեք CPOL և CPHA բիթերը՝ տվյալների փոխանցման և սերիական ժամացույցի միջև կապը սահմանելու համար (տե՛ս գծապատկերը էջ 240):
Քանի որ մենք այստեղ կարդում ենք տվյալների աղյուսակը և չենք նայում սխեմաներին, եկեք ավելի սերտ նայենք CPOL և CPHA բիթերի տեքստի նկարագրությանը 704-րդ էջում (SPI Ընդհանուր նկարագրություն).
Ժամացույցի փուլ և բևեռականություն
Օգտագործելով SPI_CR1 ռեգիստրի CPOL և CPHA բիթերը, դուք կարող եք ծրագրային կերպով ընտրել ժամանակային չորս հարաբերություններ: CPOL (ժամացույցի բևեռականություն) բիթը վերահսկում է ժամացույցի ազդանշանի վիճակը, երբ տվյալներ չեն փոխանցվում: Այս բիթը վերահսկում է հիմնական և ստրուկ ռեժիմները: Եթե CPOL-ը զրոյացված է, SCK փին հանգստի ռեժիմում ցածր է: Եթե CPOL բիթը սահմանված է, SCK փին բարձր է հանգստի ռեժիմում:
Երբ CPHA (ժամացույցի փուլ) բիթը միացված է, բարձր բիթային թակարդը SCK ազդանշանի երկրորդ եզրն է (ընկնում է, եթե CPOL-ը պարզ է, բարձրանում է, եթե CPOL սահմանված է): Տվյալները հավաքվում են ժամացույցի ազդանշանի երկրորդ փոփոխությամբ: Եթե CPHA բիթը պարզ է, ապա բարձր բիթային թակարդը SCK ազդանշանի բարձրացող եզրն է (ընկնող եզրը, եթե CPOL-ը սահմանված է, բարձրացող ծայրը, եթե CPOL-ը մաքրված է): Տվյալները հավաքվում են ժամացույցի ազդանշանի առաջին փոփոխության ժամանակ:
Կլանելով այս գիտելիքը՝ մենք գալիս ենք այն եզրակացության, որ երկու բիթերն էլ պետք է մնան զրո, քանի որ Մենք ցանկանում ենք, որ SCK ազդանշանը ցածր մնա, երբ այն չի օգտագործվում, և տվյալները փոխանցվեն իմպուլսի բարձրացող եզրին (տես Նկ. Rising Edge DM634 տվյալների թերթիկում):
Ի դեպ, այստեղ մենք առաջին անգամ հանդիպեցինք ST տվյալների թերթիկների բառապաշարի մի առանձնահատկություն. դրանցում գրված է «զրոյացնել բիթը» արտահայտությունը. մի քիչ զրոյացնելԵւ ոչ մի քիչ մաքրելու համար, ինչպես, օրինակ, Atmega-ն:
3. Սահմանեք DFF բիթը՝ որոշելու, թե տվյալների բլոկը 8-բիթանոց է, թե 16-բիթանոց:
Ես հատուկ վերցրեցի 16-բիթանոց DM634, որպեսզի չանհանգստանամ 12-բիթանոց PWM տվյալների փոխանցման հետ, ինչպես DM633-ը: Իմաստ ունի DFF-ը դնել մեկին.
4. Կազմաձևեք LSBFIRST բիթը SPI_CR1 ռեգիստրում՝ բլոկի ձևաչափը որոշելու համար
LSBFIRST-ը, ինչպես ցույց է տալիս նրա անունը, առաջինը կարգավորում է փոխանցումը ամենաքիչ կարևոր բիթով: Բայց DM634-ը ցանկանում է ստանալ տվյալներ՝ սկսած ամենակարևոր բիթից: Հետևաբար, մենք թողնում ենք այն զրոյացնել:
5. Սարքավորման ռեժիմում, եթե անհրաժեշտ է մուտքագրում NSS փինից, կիրառեք բարձր ազդանշան NSS փին բայթերի փոխանցման ողջ հաջորդականության ընթացքում: NSS ծրագրային ռեժիմում սահմանեք SSM և SSI բիթերը SPI_CR1 ռեգիստրում: Եթե NSS փին պետք է օգտագործվի որպես ելք, ապա պետք է սահմանել միայն SSOE բիթը:
Տեղադրեք SSM և SSI՝ մոռանալու NSS ապարատային ռեժիմի մասին.
#define SSI 0x0100
#define SSM 0x0200
_SPI2_ (_SPI_CR1) |= SSM | SSI; //enable software control of SS, SS high
6. MSTR և SPE բիթերը պետք է սահմանվեն (դրանք կարգավորված են միայն այն դեպքում, եթե NSS ազդանշանը բարձր է)
Փաստորեն, այս բիթերով մենք մեր SPI-ին նշանակում ենք որպես վարպետ և միացնում այն.
SPI-ը կազմաձևված է, եկեք անմիջապես գրենք գործառույթներ, որոնք բայթ են ուղարկում դրայվերին: Շարունակեք կարդալ 25.3.3 «SPI-ի կազմաձևումը հիմնական ռեժիմում».
Տվյալների փոխանցման կարգը
Փոխանցումը սկսվում է, երբ բայթը գրվում է Tx բուֆերում:
Տվյալների բայթը բեռնվում է հերթափոխի ռեգիստրում ժամը զուգահեռ ռեժիմ (ներքին ավտոբուսից) առաջին բիթի փոխանցման ժամանակ, որից հետո այն փոխանցվում է հաջորդական MOSI փին ռեժիմ, առաջին կամ վերջին բիթ առաջ՝ կախված CPI_CR1 ռեգիստրում LSBFIRST բիթից: TXE դրոշը սահմանվում է տվյալների փոխանցումից հետո Tx բուֆերից դեպի հերթափոխ ռեգիստր, և նաև առաջացնում է ընդհատում, եթե CPI_CR1 ռեգիստրում TXEIE բիթը սահմանված է:
Թարգմանության մեջ ես ընդգծեցի մի քանի բառ, որպեսզի ուշադրություն հրավիրեմ STM կարգավորիչներում SPI-ի ներդրման մեկ հատկանիշի վրա: Atmega-ում TXE դրոշը (Tx Դատարկ, Tx-ը դատարկ է և պատրաստ է տվյալներ ստանալու համար) սահմանվում է միայն ամբողջ բայթն ուղարկելուց հետո արտաքին. Եվ այստեղ այս դրոշը դրվում է բայթը ներքին հերթափոխի ռեգիստրում տեղադրվելուց հետո: Քանի որ այն հրվում է այնտեղ բոլոր բիթերով միաժամանակ (զուգահեռաբար), և այնուհետև տվյալները փոխանցվում են հաջորդաբար, TXE-ն դրվում է մինչև բայթն ամբողջությամբ ուղարկելը: Սա կարևոր է, քանի որ մեր LED դրայվերի դեպքում, ուղարկելուց հետո մենք պետք է քաշենք LAT փին Ամբողջ տվյալներ, այսինքն. Միայն TXE դրոշը մեզ չի բավականացնի։
Սա նշանակում է, որ մեզ ևս մեկ դրոշ է պետք։ Եկեք նայենք 25.3.7 - «Կարգավիճակի դրոշներ».
<...>
Զբաղված դրոշ
BSY դրոշը տեղադրվում և մաքրվում է սարքաշարի միջոցով (դրա գրելը որևէ ազդեցություն չունի): BSY դրոշը ցույց է տալիս SPI կապի շերտի վիճակը:
Այն վերակայում է.
երբ փոխանցումն ավարտված է (բացառությամբ հիմնական ռեժիմի, եթե փոխանցումը շարունակական է)
երբ SPI-ն անջատված է
երբ հիմնական ռեժիմի սխալ է տեղի ունենում (MODF=1)
Եթե փոխանցումը շարունակական չէ, BSY դրոշը մաքրվում է յուրաքանչյուր տվյալների փոխանցման միջև
Լավ, սա օգտակար կլինի: Եկեք պարզենք, թե որտեղ է գտնվում Tx բուֆերը: Դա անելու համար կարդացեք «SPI տվյալների գրանցամատյան».
Bits 15:0 DR[15:0] Տվյալների գրանցում
Ստացված տվյալներ կամ փոխանցվող տվյալներ:
Տվյալների ռեգիստրը բաժանված է երկու բուֆերի՝ մեկը գրելու համար (փոխանցման բուֆեր) և մեկը՝ կարդալու (ստանալու բուֆեր): Տվյալների ռեգիստրում գրելը գրում է Tx բուֆերին, իսկ տվյալների ռեգիստրից կարդալը կվերադարձնի Rx բուֆերում պարունակվող արժեքը:
Դե, և կարգավիճակի ռեգիստրը, որտեղ գտնվում են TXE և BSY դրոշները.
Դե, քանի որ մենք պետք է փոխանցենք 16 անգամ երկու բայթ, ըստ LED վարորդի ելքերի քանակի, նման բան.
void sendLEDdata()
{
LAT_low();
uint8_t k = 16;
do
{ k--;
dm_shift16(leds[k]);
} while (k);
while (_SPI2_(_SPI_SR) & BSY); // finish transmission
LAT_pulse();
}
Բայց մենք դեռ չգիտենք, թե ինչպես պետք է քաշել LAT փին, այնպես որ մենք կվերադառնանք I/O:
Կցամասերի նշանակում
STM32F1-ում քորոցների վիճակի համար պատասխանատու ռեգիստրները բավականին անսովոր են: Հասկանալի է, որ դրանք ավելի շատ են, քան Atmega-ն, բայց դրանք տարբերվում են նաև մյուս STM չիպերից։ Բաժին 9.1 GPIO-ի ընդհանուր նկարագրությունը.
Ընդհանուր նշանակության I/O պորտերից յուրաքանչյուրը (GPIO) ունի երկու 32-բիթանոց կազմաձևման ռեգիստր (GPIOx_CRL և GPIOx_CRH), երկու 32-բիթանոց տվյալների ռեգիստր (GPIOx_IDR և GPIOx_ODR), 32-բիթանոց կարգավորող/վերակայման ռեգիստր (GPIOx_BSRR), 16-բիթանոց վերակայման ռեգիստր (GPIOx_BRR) և բիթերի արգելափակման ռեգիստր (GPIOx_LCKR):
Առաջին երկու գրանցամատյանները անսովոր են, և նաև բավականին անհարմար, քանի որ 16 պորտի փիները ցրված են դրանց վրա «չորս բիթ մեկ եղբորը» ձևաչափով: Նրանք. Զրո-յոթ կապում են CRL-ում, իսկ մնացածը՝ CRH-ում: Միևնույն ժամանակ, մնացած գրանցամատյանները հաջողությամբ պարունակում են նավահանգստի բոլոր քորոցների բիթերը, որոնք հաճախ մնում են կիսով չափ «պահեստավորված»:
Պարզության համար սկսենք ցուցակի վերջից։
Մեզ արգելափակող ռեգիստր պետք չէ։
Սահմանել և վերակայել ռեգիստրները բավականին զվարճալի են նրանով, որ դրանք մասամբ կրկնօրինակում են միմյանց. ամեն ինչ կարող եք գրել միայն BSRR-ում, որտեղ ավելի բարձր 16 բիթները կզրոյացնեն փին, իսկ ստորինները կդրվեն 1-ի, կամ կարող եք նաև. օգտագործեք BRR, որի ստորին 16 բիթերը վերակայում են միայն քորոցը: Ինձ դուր է գալիս երկրորդ տարբերակը. Այս ռեգիստրները կարևոր են, քանի որ դրանք ապահովում են ատոմային մուտք դեպի կապում.
Ատոմային կարգավորում կամ վերակայում
Կարիք չկա անջատել ընդհատումները GPIOx_ODR-ը բիթային մակարդակում ծրագրավորելիս. մեկ կամ մի քանի բիթ կարելի է փոխել մեկ ատոմային գրելու գործողությամբ APB2: Սա ձեռք է բերվում՝ գրելով «1» կարգավորվող/վերակայման ռեգիստրում (GPIOx_BSRR կամ միայն վերակայման համար՝ GPIOx_BRR), որը պետք է փոխվի: Մնացած բիթերը կմնան անփոփոխ:
Տվյալների ռեգիստրներն ունեն բավականին ինքնըստինքյան անուններ՝ IDR = Մուտքային Ուղղության ռեգիստր, մուտքագրման ռեգիստր; ODR = Արտադրողականություն Ուղղության ռեգիստր, ելքային ռեգիստր։ Ներկայիս նախագծում դրանք մեզ պետք չեն լինի:
Եվ վերջապես հսկիչ ռեգիստրներ։ Քանի որ մենք հետաքրքրված ենք երկրորդ SPI կապումներով, մասնավորապես PB13, PB14 և PB15, մենք անմիջապես նայում ենք CRH-ին.
Եվ մենք տեսնում ենք, որ մեզ անհրաժեշտ կլինի ինչ-որ բան գրել 20-ից 31 բիթերով:
Մենք վերևում արդեն հասկացել ենք, թե ինչ ենք ուզում կապից, այնպես որ այստեղ ես կանեմ առանց սքրինշոթի, պարզապես կասեմ, որ MODE-ը նշում է ուղղությունը (մուտքագրումը, եթե երկու բիթերը դրված են 0-ի վրա) և փին արագությունը (մեզ անհրաժեշտ է 50 ՄՀց, այսինքն. երկուսն էլ փին «1»), իսկ CNF-ը սահմանում է ռեժիմը. սովորական «հրում-քաշում» – 00, «այլընտրանք» – 10: Լռելյայն, ինչպես տեսնում ենք վերևում, բոլոր կապումներն ունեն երրորդ բիթը ներքևից (CNF0): այն դնում է նրանց ռեժիմի լողացող մուտքագրում.
Քանի որ ես նախատեսում եմ այլ բան անել այս չիպի հետ, պարզության համար ես սահմանել եմ բոլոր հնարավոր MODE և CNF արժեքները ինչպես ստորին, այնպես էլ վերին կառավարման ռեգիստրների համար:
(LAT_low պարզապես իներցիայով, միշտ այդպես է եղել, թող մնա)
Այժմ ամեն ինչ հիանալի է, բայց դա չի աշխատում: Քանի որ սա STM32 է, նրանք խնայում են էլեկտրաէներգիան, ինչը նշանակում է, որ դուք պետք է միացնեք անհրաժեշտ ծայրամասային սարքերի ժամացույցը:
Միացնել ժամացույցը
Ժամացույցը, որը նաև հայտնի է որպես Ժամացույց, պատասխանատու է ժամացույցի համար: Իսկ մենք արդեն կարող էինք նկատել RCC հապավումը։ Մենք փնտրում ենք այն փաստաթղթերում. սա Վերականգնել և Ժամացույցի վերահսկում է:
Ինչպես նշվեց վերևում, բարեբախտաբար, ժամացույցի թեմայի ամենադժվար մասը մեզ համար արել են STM-ի մարդիկ, ինչի համար մենք շատ շնորհակալ ենք նրանց (ևս մեկ անգամ հղում կտամ. Դի Հալտի կայքը, հասկանալու համար, թե որքան շփոթեցնող է): Մեզ անհրաժեշտ են միայն ռեգիստրներ, որոնք պատասխանատու են ծայրամասային ժամացույցը միացնելու համար (Peripheral Clock Enable Registers): Նախ, եկեք գտնենք RCC-ի բազային հասցեն, այն գտնվում է «Հիշողության քարտեզի» հենց սկզբում.
Եվ այնուհետև կամ կտտացրեք այն հղմանը, որտեղ դուք փորձում եք ինչ-որ բան գտնել ափսեի մեջ, կամ, շատ ավելի լավ, անցեք թույլատրող ռեգիստրների նկարագրությունները բաժիններից: միացնել գրանցամատյանները. Որտեղ մենք կգտնենք RCC_APB1ENR և RCC_APB2ENR.
Եվ դրանք, համապատասխանաբար, պարունակում են բիթեր, որոնք ներառում են SPI2, IOPB (I/O Port B) և այլընտրանքային գործառույթներ (AFIO) ժամացույցը:
Եթե ունեք փորձարկման հնարավորություն և ցանկություն, ապա միացրեք DM634-ը այսպես՝ DAI-ը PB15-ին, DCK-ին PB13-ին, LAT-ին PB14-ին: Վարորդին սնուցում ենք 5 վոլտից, մի մոռացեք միացնել հիմքերը։
STM8 PWM
PWM STM8-ում
Երբ ես նոր էի պլանավորում այս հոդվածը, ես որոշեցի, որպես օրինակ, փորձել տիրապետել անծանոթ չիպի որոշ ֆունկցիոնալությանը, օգտագործելով միայն տվյալների աղյուսակը, որպեսզի չհայտնվեմ կոշկակարի հետ առանց կոշիկների: STM8-ը իդեալական էր այս դերի համար. նախ՝ ես մի քանի չինական տախտակ ունեի STM8S103-ով, և երկրորդ՝ այն այնքան էլ տարածված չէ, և հետևաբար ինտերնետում կարդալու և լուծում գտնելու գայթակղությունը հիմնված է հենց այս լուծումների բացակայության վրա:
Լռելյայնորեն, STM8-ը գործում է 2 ՄՀց հաճախականությամբ, այն պետք է անմիջապես շտկվի:
HSI (բարձր արագությամբ ներքին) ժամացույց
HSI ժամացույցի ազդանշանը ստացվում է ներքին 16 ՄՀց հաճախականությամբ RC տատանվողից՝ ծրագրավորվող բաժանիչով (1-ից 8): Այն սահմանված է ժամացույցի բաժանարար ռեգիստրում (CLK_CKDIVR):
Ծանոթագրություն. սկզբում որպես ժամացույցի ազդանշանի առաջատար աղբյուր ընտրվում է HSI RC օսլիլատորը՝ 8 բաժանարարով:
Մենք գտնում ենք ռեգիստրի հասցեն տվյալների թերթիկում, նկարագրությունը refman-ում և տեսնում ենք, որ ռեգիստրը պետք է մաքրվի.
Քանի որ մենք պատրաստվում ենք գործարկել PWM-ը և միացնել LED-ները, եկեք նայենք պինութին.
Չիպը փոքր է, շատ գործառույթներ կասեցված են նույն կապում: Քառակուսի փակագծերում գտնվողը «այլընտրանքային ֆունկցիոնալություն» է, այն փոխարկվում է «օպցիոն բայթերով» (տարբերակ բայթեր) – Atmega ապահովիչների նման մի բան: Դուք կարող եք փոխել դրանց արժեքները ծրագրային կերպով, բայց դա անհրաժեշտ չէ, քանի որ Նոր գործառույթն ակտիվանում է միայն վերաբեռնումից հետո: Ավելի հեշտ է օգտագործել ST Visual Programmer-ը (ներբեռնված Visual Develop-ով), որը կարող է փոխել այս բայթերը: Գծապատկերը ցույց է տալիս, որ առաջին ժմչփի CH1 և CH2 քորոցները թաքնված են քառակուսի փակագծերում; անհրաժեշտ է STVP-ում տեղադրել AFR1 և AFR0 բիթերը, իսկ երկրորդը կփոխանցի նաև երկրորդ ժմչփի CH1 ելքը PD4-ից PC5:
Այսպիսով, 6 կապում կկառավարեն LED-ները՝ PC6, PC7 և PC3 առաջին ժմչփի համար, PC5, PD3 և PA3՝ երկրորդ:
STM8-ի վրա I/O փիների կարգավորումն ավելի պարզ և տրամաբանական է, քան STM32-ում.
առաջին հսկիչ ռեգիստրը CR1, երբ դուրս է գալիս, սահմանում է հրում-քաշման ռեժիմը (1) կամ բաց արտահոսքը (0); քանի որ LED-ները կապում եմ չիպին կաթոդներով, այստեղ զրոներ եմ թողնում.
երկրորդ կառավարման ռեգիստրը CR2, երբ դուրս է գալիս, սահմանում է ժամացույցի արագությունը՝ 1 = 10 ՄՀց
PWM հաճախականություն - հաճախականությունը, որով ժմչփը նշում է.
Ավտոմատ վերբեռնում, AR – ավտոմատ բեռնվող արժեք, որի չափը կհաշվի ժամանակաչափը (զարկերակային շրջան);
Թարմացնել իրադարձությունը, UEV – իրադարձություն, որը տեղի է ունենում, երբ ժամանակաչափը հաշվել է մինչև AR;
PWM Duty Cycle – PWM աշխատանքային ցիկլը, որը հաճախ կոչվում է «հերթական գործոն».
Գրավել/համեմատել արժեքը – ֆիքսման/համեմատության արժեք, որին հաշվել է ժամանակաչափը ինչ-որ բան կանի (PWM-ի դեպքում այն հակադարձում է ելքային ազդանշանը);
Նախաբեռնման արժեքը - նախապես բեռնված արժեք: Համեմատեք արժեքը չի կարող փոխվել, մինչ ժմչփը նշում է, հակառակ դեպքում PWM ցիկլը կխախտվի: Հետևաբար, փոխանցվող նոր արժեքները տեղադրվում են բուֆերի մեջ և դուրս են քաշվում, երբ ժմչփը հասնում է իր հետհաշվարկի ավարտին և վերականգնվում է.
Եզրին հավասարեցված и Կենտրոնական հավասարեցված ռեժիմներ - հավասարեցում սահմանի երկայնքով և կենտրոնում, նույնը, ինչ Atmel-ը Արագ PWM и Փուլային ճիշտ PWM.
OCiREF, Արդյունք Համեմատել Հղման ազդանշան – հղումային ելքային ազդանշան, փաստորեն, այն, ինչ հայտնվում է PWM ռեժիմում համապատասխան փինում:
Ինչպես արդեն պարզ է պինութից, երկու ժամանակաչափ ունեն PWM հնարավորություններ՝ առաջինը և երկրորդը: Երկուսն էլ 16-բիթանոց են, առաջինն ունի բազմաթիվ լրացուցիչ հնարավորություններ (մասնավորապես, այն կարող է հաշվել և՛ վերև, և՛ ներքև)։ Մեզ երկուսն էլ պետք է հավասարապես աշխատեն, ուստի ես որոշեցի սկսել ակնհայտորեն ավելի աղքատ երկրորդից, որպեսզի պատահաբար չօգտագործեմ մի բան, որը չկա: Որոշ խնդիր այն է, որ տեղեկատու ձեռնարկի բոլոր ժամանակաչափերի PWM ֆունկցիոնալության նկարագրությունը առաջին ժմչփի մասին գլխում է (17.5.7 PWM ռեժիմ), այնպես որ դուք պետք է անընդհատ ետ ու առաջ ցատկեք ամբողջ փաստաթղթում:
PWM-ը STM8-ում ունի կարևոր առավելություն Atmega-ի PWM-ի նկատմամբ.
Սահմանային հավասարեցված PWM
Հաշվի կազմաձևումը ներքևից վերև
Ներքևից վեր հաշվումն ակտիվ է, եթե TIM_CR1 ռեգիստրում DIR բիթը ջնջված է
Օրինակ
Օրինակը օգտագործում է առաջին PWM ռեժիմը: PWM հղման OCiREF ազդանշանը բարձր է պահվում այնքան ժամանակ, քանի դեռ TIM1_CNT < TIM1_CCRi: Հակառակ դեպքում դա ցածր մակարդակ է պահանջում: Եթե TIM1_CCRi ռեգիստրում համեմատական արժեքը ավելի մեծ է, քան ավտոմատ բեռնման արժեքը (TIM1_ARR ռեգիստր), ապա OCiREF ազդանշանը պահվում է 1-ում: Եթե համեմատական արժեքը 0 է, ապա OCiREF-ը պահվում է զրոյի վրա:...
STM8 ժամանակաչափ ընթացքում թարմացման իրադարձություն նախ ստուգում է համեմատել արժեքը, և միայն դրանից հետո արտադրում է հղման ազդանշան: Atmega-ի ժմչփը սկզբում պտտվում է, իսկ հետո համեմատում, արդյունքում ստացվում է compare value == 0 ելքը ասեղ է, որի հետ պետք է ինչ-որ կերպ վարվել (օրինակ՝ ծրագրային կերպով շրջելով տրամաբանությունը):
Այսպիսով, ինչ ենք ուզում անել՝ 8-բիթանոց PWM (AR == 255), ներքևից վերև հաշվում, եզրագծի երկայնքով հավասարեցում: Քանի որ լամպերը միացված են չիպերին կաթոդներով, PWM-ը պետք է թողարկի 0 (Միացված LED) մինչև համեմատել արժեքը և 1 հետո:
Որոշների մասին մենք արդեն կարդացել ենք PWM ռեժիմ, այնպես որ մենք գտնում ենք երկրորդ ժմչփի պահանջվող ռեգիստրը՝ փնտրելով տեղեկատու ձեռնարկում այս արտահայտությունը (18.6.8 - TIMx_CCMR1):
110. Առաջին PWM ռեժիմ – ներքևից վերև հաշվելիս առաջին ալիքն ակտիվ է, մինչդեռ TIMx_CNT < TIMx_CCR1: Հակառակ դեպքում առաջին ալիքն անգործուն է։ [Այնուհետև փաստաթղթում կա սխալ copy-paste ժմչփ 1-ից] 111. Երկրորդ PWM ռեժիմ – ներքևից վերև հաշվելիս առաջին ալիքը ակտիվ չէ, մինչդեռ TIMx_CNT < TIMx_CCR1: Հակառակ դեպքում առաջին ալիքն ակտիվ է։
Քանի որ LED-ները MK-ին միացված են կաթոդներով, երկրորդ ռեժիմը մեզ հարմար է (առաջինը նույնպես, բայց մենք դա դեռ չգիտենք):
Բիթ 3 OC1PE. Միացնել փին 1-ի նախնական բեռնումը
0. TIMx_CCR1-ում նախապես բեռնված ռեգիստրն անջատված է: Ցանկացած ժամանակ կարող եք գրել TIMx_CCR1-ին: Նոր արժեքը անմիջապես գործում է։
1. TIMx_CCR1-ում նախապես բեռնված ռեգիստրը միացված է: Կարդալ/գրել գործողությունները մուտք են գործում նախաբեռնման ռեգիստր: Նախապես բեռնված TIMx_CCR1 արժեքը բեռնվում է ստվերային ռեգիստրում յուրաքանչյուր թարմացման իրադարձության ժամանակ:
*Նշում. PWM ռեժիմը ճիշտ աշխատելու համար պետք է միացված լինեն նախաբեռնված ռեգիստրները: Սա անհրաժեշտ չէ մեկ ազդանշանային ռեժիմում (OPM բիթը սահմանված է TIMx_CR1 ռեգիստրում):
Լավ, եկեք միացնենք այն ամենը, ինչ մեզ անհրաժեշտ է երկրորդ ժամանակաչափի երեք ալիքների համար.
Երկրորդ ժմչփը կարող է հաշվել միայն ներքևից վեր, եզրագծի երկայնքով հավասարեցված, ոչինչ պետք չէ փոխել: Եկեք հաճախականության բաժանարարը դնենք, օրինակ, 256: Երկրորդ ժմչփի համար բաժանարարը դրված է TIM2_PSCR ռեգիստրում և երկուսի հզորություն է.
Մնում է միայն միացնել եզրակացությունները և երկրորդ ժմչփը: Առաջին խնդիրը լուծվում է ռեգիստրների միջոցով Նկարել/Համեմատել Թույլատրելկան երկու, երեք ալիքներ, որոնք ցրված են դրանց վրա ասիմետրիկորեն: Այստեղ մենք կարող ենք նաև սովորել, որ հնարավոր է փոխել ազդանշանի բևեռականությունը, այսինքն. սկզբունքորեն հնարավոր էր օգտագործել PWM Mode 1: Մենք գրում ենք.
Եկեք գրենք AnalogWrite(-ի պարզ անալոգը), որը համեմատության համար իրական արժեքները կփոխանցի ժամանակաչափին: Գրանցամատյանները կոչվում են կանխատեսելի Գրանցել / Համեմատել գրանցամատյանները, յուրաքանչյուր ալիքի համար դրանք երկուսն են՝ ցածր կարգի 8 բիթները TIM2_CCRxL-ում և բարձրակարգը՝ TIM2_CCRxH: Քանի որ մենք ստեղծել ենք 8-բիթանոց PWM, բավական է գրել միայն ամենաքիչ կարևոր բիթերը.
Ուշադիր ընթերցողը կնկատի, որ մենք ունենք մի փոքր թերի PWM, որը չի կարողանում արտադրել 100% լիցք (առավելագույնը 255 արժեքի դեպքում ազդանշանը շրջվում է մեկ ժամանակաչափի ցիկլի համար): LED-ների համար դա նշանակություն չունի, և ուշադիր ընթերցողն արդեն կարող է կռահել, թե ինչպես դա շտկել:
Երկրորդ ժմչփի վրա PWM-ն աշխատում է, անցնենք առաջինին:
Առաջին ժմչփն ունի նույն բիթերը նույն ռեգիստրներում (ուղղակի այն բիթերը, որոնք մնացել են «պահեստավորված» երկրորդ ժամանակաչափում, առաջինում ակտիվորեն օգտագործվում են բոլոր տեսակի առաջադեմ բաների համար): Ուստի բավական է տվյալների թերթիկում գտնել նույն ռեգիստրների հասցեները և պատճենել կոդը։ Դե, փոխեք հաճախականության բաժանարարի արժեքը, քանի որ... առաջին ժմչփը ցանկանում է ստանալ ոչ թե երկու ռեգիստրի հզորություն, այլ ճշգրիտ 16 բիթանոց արժեք Prescaler High и Ցածր. Մենք ամեն ինչ անում ենք ու... առաջին ժմչփը չի աշխատում։ Ինչ է պատահել?
Խնդիրը կարող է լուծվել միայն՝ նայելով ժմչփ 1-ի կառավարման ռեգիստրների մասին ամբողջ բաժինը, որտեղ մենք փնտրում ենք այն, որը չունի երկրորդ ժմչփը: Կլինի 17.7.30 Ընդմիջման գրանցամատյան (TIM1_BKR), որտեղ կա այս բիթը.
Երրորդ մինի-նախագիծը ութ RGB LED-ներ միացնելն է երկրորդ ժմչփին PWM ռեժիմում և ստիպել դրանք տարբեր գույներ ցուցադրել: Այն հիմնված է LED մուլտիպլեքսավորման հայեցակարգի վրա, որն այն է, որ եթե դուք շատ, շատ արագ միացնեք և անջատեք LED-ները, մեզ կթվա, որ դրանք անընդհատ միացված են (տեսողության համառություն, տեսողական ընկալման իներցիա): Ես մի անգամ արել եմ նման բան Arduino-ում.
Աշխատանքային ալգորիթմն ունի հետևյալ տեսքը.
միացրեց առաջին RGB LED- ի անոդը;
վառեց այն՝ ուղարկելով անհրաժեշտ ազդանշանները կաթոդներին;
սպասեց մինչև PWM ցիկլի ավարտը.
միացրեց երկրորդ RGB LED- ի անոդը;
վառեց այն...
Դե և այլն: Իհարկե, գեղեցիկ շահագործման համար անհրաժեշտ է, որ անոդը միացված լինի և LED-ը միաժամանակ «բռնկվի»: Դե, կամ գրեթե: Ամեն դեպքում, մենք պետք է գրենք կոդ, որը արժեքներ կարտադրի երկրորդ ժմչփի երեք ալիքներում, կփոխի դրանք UEV-ին հասնելու դեպքում և միևնույն ժամանակ կփոխի ներկայումս ակտիվ RGB LED-ը:
Քանի որ լուսադիոդային անջատումը ավտոմատ է, մենք պետք է ստեղծենք «վիդեո հիշողություն», որից ընդհատման կառավարիչը տվյալներ կստանա: Սա պարզ զանգված է.
uint8_t colors[8][3];
Հատուկ LED-ի գույնը փոխելու համար բավական կլինի գրել անհրաժեշտ արժեքները այս զանգվածում: Իսկ փոփոխականը պատասխանատու կլինի ակտիվ LED-ի քանակի համար
uint8_t cnt;
Դեմուքս
Պատշաճ մուլտիպլեքսավորման համար մեզ անհրաժեշտ է, տարօրինակ կերպով, CD74HC238 դեմուլտիպլեքսատոր: Demultiplexer - չիպ, որն իրականացնում է օպերատորը ապարատային համակարգում <<. Երեք մուտքային կապի միջոցով (բիթներ 0, 1 և 2) մենք այն կերակրում ենք եռաբիթ X համարով, և ի պատասխան այն ակտիվացնում է ելքային համարը (1<<X) Չիպի մնացած մուտքերը օգտագործվում են ամբողջ դիզայնը մասշտաբավորելու համար: Մեզ այս չիպն անհրաժեշտ է ոչ միայն միկրոկառավարիչի զբաղեցրած քորոցների քանակը նվազեցնելու համար, այլև անվտանգության համար, որպեսզի պատահաբար չմիացնենք հնարավորից ավելի LED-ներ և չվառենք MK-ն: Չիպն արժե մեկ կոպեկ և միշտ պետք է պահվի ձեր տնային բժշկության պահարանում:
Մեր CD74HC238-ը պատասխանատու կլինի ցանկալի LED-ի անոդին լարման մատակարարման համար: Լրիվ մուլտիպլեքսում այն լարումը կմատակարարեր սյունին P-MOSFET-ի միջոցով, բայց այս ցուցադրության դեպքում դա հնարավոր է ուղղակիորեն, քանի որ այն քաշում է 20 մԱ, ըստ բացարձակ առավելագույն գնահատականներ տվյալների թերթիկում: Սկսած Տվյալների թերթիկ CD74HC238 մեզ անհրաժեշտ են մատիտներ և այս խաբեության թերթիկը.
H = բարձր լարման մակարդակ, L = ցածր լարման մակարդակ, X – հոգ չէ
Մենք E2 և E1-ը միացնում ենք գետնին, E3, A0, A1 և A3-ը՝ STM5-ի PD3, PC4, PC5 և PC8 կապանքներին: Քանի որ վերը նշված աղյուսակը պարունակում է և՛ ցածր, և՛ բարձր մակարդակներ, մենք կարգավորել ենք այս կապանքները որպես հրում-քաշման կապում:
PWM
Երկրորդ ժմչփի վրա PWM-ը կազմաձևված է նույն կերպ, ինչպես նախորդ պատմության մեջ, երկու տարբերությամբ.
Նախ, մենք պետք է միացնենք ընդհատումը Թարմացնել Իրադարձությունը (UEV), որը կկանչի մի ֆունկցիա, որն անջատում է ակտիվ լուսադիոդը: Դա արվում է բիթը փոխելով Թարմացնել ընդհատումը Միացնել ռեգիստրում խոսուն անունով
Երկրորդ տարբերությունը կապված է մուլտիպլեքսավորման երեւույթի հետ, ինչպես, օրինակ ուրվական - դիոդների մակաբուծական փայլ: Մեր դեպքում դա կարող է հայտնվել այն պատճառով, որ ժմչփը, որը UEV-ի վրա ընդհատում է առաջացրել, շարունակում է նշել, և ընդհատման կառավարիչը ժամանակ չունի միացնել LED-ը, նախքան ժմչփը կսկսի ինչ-որ բան գրել կապում: Դրա դեմ պայքարելու համար դուք ստիպված կլինեք շրջել տրամաբանությունը (0 = առավելագույն պայծառություն, 255 = ոչինչ չի վառվում) և խուսափել աշխատանքային ցիկլի ծայրահեղ արժեքներից: Նրանք. համոզվեք, որ UEV-ից հետո լուսադիոդները ամբողջությամբ անջատվեն մեկ PWM ցիկլով:
Խուսափեք r, g և b-ին 255-ի վրա դնելուց և հիշեք դրանք շրջել դրանք օգտագործելիս:
Ընդհատում է
Ընդհատման էությունն այն է, որ որոշակի հանգամանքներում չիպը դադարում է կատարել հիմնական ծրագիրը և կանչում է ինչ-որ արտաքին ֆունկցիա: Ընդհատումները տեղի են ունենում արտաքին կամ ներքին ազդեցությունների պատճառով, ներառյալ ժամանակաչափը:
Երբ մենք առաջին անգամ ստեղծեցինք նախագիծ ST Visual Develop-ում, բացի main.c մենք առեղծվածային ֆայլով պատուհան ստացանք stm8_interrupt_vector.c, ավտոմատ կերպով ներառված նախագծում։ Այս ֆայլում յուրաքանչյուր ընդհատման հատկացվում է ֆունկցիա NonHandledInterrupt. Մենք պետք է կապենք մեր գործառույթը ցանկալի ընդհատմանը:
Տվյալների թերթիկը ունի ընդհատումների վեկտորների աղյուսակ, որտեղ մենք գտնում ենք մեզ անհրաժեշտները.
@far @interrupt void TIM2_Overflow (void)
{
PD_ODR &= ~(1<<5); // вырубаем демультиплексор
PC_ODR = (cnt<<3); // записываем в демультиплексор новое значение
PD_ODR |= (1<<5); // включаем демультиплексор
TIM2_SR1 = 0; // сбрасываем флаг Update Interrupt Pending
cnt++;
cnt &= 7; // двигаем счетчик LED
TIM2_CCR1L = ~colors[cnt][0]; // передаем в буфер инвертированные значения
TIM2_CCR2L = ~colors[cnt][1]; // для следующего цикла ШИМ
TIM2_CCR3L = ~colors[cnt][2]; //
return;
}
Մնում է միայն միացնել ընդհատումները: Դա արվում է assembler հրամանի միջոցով rim - դուք պետք է փնտրեք այն Mingրագրավորման ձեռնարկ:
//enable interrupts
_asm("rim");
Ասեմբլերի մեկ այլ հրաման է sim - անջատում է ընդհատումները: Նրանք պետք է անջատվեն, մինչ նոր արժեքներ են գրվում «վիդեո հիշողության մեջ», որպեսզի սխալ պահին առաջացած ընդհատումը չփչացնի զանգվածը:
Եթե գոնե ինչ-որ մեկին այս հոդվածը օգտակար է համարում, ապա ես այն իզուր չեմ գրել: Ուրախ կլինեմ ստանալ մեկնաբանություններ և դիտողություններ, կփորձեմ պատասխանել ամեն ինչին։