Küsimus:
Kas keegi saaks seda imeliku välimusega koodi kasutada, mida taimerite seadistamiseks kasutatakse?
The Guy with The Hat
2014-02-24 08:06:06 UTC
view on stackexchange narkive permalink

Vaadates teiste inimeste kirjutatud visandeid, satun aeg-ajalt koodi välja, mis näeb välja umbes selline:

  TCCR1A = 0; TCCR1B = 0; TCNT1 = 34286; TCCR1B | = (1 << CS12); TIMSK1 | = (1 << TOIE1);  

Ma tean ainult seda, et sellel on midagi ajastuse / taimeritega (ma arvan). Kuidas ma saan sellist koodi lahti mõtestada ja luua? Mis on TCCR1A , TCCR1B , TCNT1 , CS12 , TIMSK1 ja TOIE1 ?

Ei tea piisavalt vastust, kuid: http://electronics.stackexchange.com/questions/92350/what-is-the-difference-between-tccr1a-and-tccr1b, http://forum.arduino.cc/index .php? topic = 134602.0 ja http://stackoverflow.com/questions/9475482/pulse-width-modulation-pwm-on-avr-studio. Ei tea, kas olete neid juba näinud.
Laadige oma seadme jaoks täielik andmeleht alla [Atmeli veebisaidilt] (http://atmel.com/) ja lugege taimerite kohta käivaid peatükke. Andmelehte on minu arvates üllatavalt hea lugeda.
Kolm vastused:
#1
+15
Connor Wolf
2014-02-24 09:54:06 UTC
view on stackexchange narkive permalink

See pole imelik välimus. See näeb välja tavaline MCU-kood.

Siin on näide mäluga kaardistatud välisseadmete mõistest. Põhimõtteliselt on MCU riistvaral spetsiaalsed asukohad talle määratud MCU SRAM-i aadressiruumis. Neile aadressidele kirjutades kontrollivad aadressile kirjutatud baidi bitid n perifeersete m käitumist.

Põhimõtteliselt on teatud mälupankades sõna otseses mõttes vähe juhtmeid, mis jooksevad SRAM-lahtrist riistvarani. Kui kirjutate selles baidis sellele bitile "1", seab see selle SRAM-i lahtri loogiliseks kõrgeks, mis lülitab siis osa riistvarast sisse.

Kui uurite MCU päiseid , seal on suured märksõna<-> aadressi vastendused tabelid. Nii lahendatakse kompileerimise ajal sellised asjad nagu TCCR1B jne ...

Seda mälu kaardistamise mehhanismi kasutatakse MCU-des äärmiselt laialdaselt. Arduino ATmega MCU kasutab seda, nagu ka PIC, ARM, MSP430, STM32 ja STM8 MCU seeriad, samuti palju MCU-sid, mis pole mulle kohe tuttavad.


Arduino kood on imelik värk, funktsioonidega, mis pääsevad kaudselt juurde MCU juhtimisregistritele. Kuigi see on mõnevõrra "kenama" väljanägemisega, on see ka palju aeglasem ja kasutab palju rohkem programmiruumi.

Salapäraseid konstante on kõiki üksikasjalikult kirjeldatud ATmega328P andmelehel, mida peaksite tõesti lugema, kui olete huvitatud arduino nööpnõelade vahetamisest.

Valige väljavõtted ülaltoodud andmelehelt:

enter image description here enter image description here enter image description here

Nii näiteks TIMSK1 | = (1 << TOIE1); määrab biti TOIE1 jaotises TIMSK1 . See saavutatakse binaar 1 ( 0b00000001 ) nihutamisega vasakule bittide TOIE1 abil, kusjuures päisefailis on TOIE1 määratletud kui 0. See on siis bitipõhiselt OR-iga sisestatud TIMSK1 -i praeguse väärtuse, mis selle ühe biti kõrgeks seadis.

Vaadates TIMSK1 -i biti 0 dokumentatsiooni, näeme, et seda kirjeldatakse järgmiselt:

Kui see bitt on kirjutatud ühele ja olekuregistri I-lipp on seatud (katkestused on globaalselt lubatud), on taimeri / loenduri1 ülevoolu katkestus lubatud . Vastav katkestusvektor (vt „Katkestused” lk 57) käivitatakse siis, kui seatakse TIFR1-s asuv TOV1 lipp.

Kõiki teisi ridu tuleks tõlgendada samal viisil.


Mõned märkused:

Võite näha ka selliseid asju nagu TIMSK1 | = _BV (TOIE1); . _BV () on tavaliselt kasutatav makro, mis pärineb algselt AVR libc juurutamisest. _BV (TOIE1) on funktsionaalselt identne funktsiooniga (1 << TOIE1) , parema loetavuse huvides.

Samuti võite näha selliseid ridu: järgmiselt: TIMSK1 & = ~ (1 << TOIE1); või TIMSK1 & = ~ _BV (TOIE1); . Sellel on vastupidine funktsioon TIMSK1 | = _BV (TOIE1); , kuna see tühistab biti TOIE1 jaotises TIMSK1 kood>. Selle saavutamiseks võetakse _BV (TOIE1) toodetud bittmask, sooritatakse sellega bitipidi NOT-toiming ( ~ ) ja seejärel ANDing TIMSK1 kood> selle märkimata väärtuse (mis on 0b11111110) järgi.

Pange tähele, et kõigil neil juhtudel on selliste asjade väärtus nagu (1 << TOIE1) või _BV (TOIE1) täielikult lahendatud kompileerimise ajal , nii et nad taanduvad funktsionaalselt lihtsaks konstandiks ja seetõttu ei kulu käitamiseks arvutuseks aega.


Korralikult kirjutatud koodi üldiselt kommentaarid on kooskõlas kood, mis täpsustab registrite määramist. Siin on üsna lihtne pehme SPI rutiin, mille hiljuti kirjutasin:

  uint8_t transactByteADC (uint8_t outByte) {// Teisaldab ühe baidi ADC-le ja saab korraga ühe baidi // teeb miski kiibiga select // MSB kõigepealt, andmed on tõusvas servas kellaga uint8_t loopCnt; uint8_t retDat = 0; for (loopCnt = 0; loopCnt < 8; loopCnt ++) {if (outByte & 0x80) // kui praegune bitt on kõrge PORTC | = _BV (ADC_MOSI); // määra andmerida muu PORTC & = ~ (_BV (ADC_MOSI)); // muul moel see lahti tehaByte << = 1; // ja teisaldage järgmise iteratsiooni väljundandmed üle retDat << = 1; // ümberlugemine loetud andmete üle PORTC | = _BV (ADC_SCK); // Seadke kell kõrge, kui (PINC & _BV (ADC_MISO)) // proovige sisendjoont retDat | = 0x01; // ja määrake bitt retvalis, kui sisend on kõrge PORTC & = ~ (_BV (ADC_SCK)); // madala kella määramine} return retDat;}  

PORTC on register, mis kontrollib väljundnõelte väärtust ATmega328P-s PORTC . PINC on register, kus on saadaval PORTC sisend väärtused. Põhimõtteliselt toimuvad sellised asjad seesmiselt, kui kasutate funktsioone digitalWrite või digitalRead . Siiski on olemas otsinguoperatsioon, mis muudab arduino "pin-numbrid" tegelikeks riistvara pin-numbriteks, mis võtab aega kuskil 50 kellatsükli piirkonnas. Nagu arvata võib, on kiire naeratuse korral 50 naeruvõimalust raiskamine toimingule, mis peaks nõudma ainult ühte, natuke naeruväärne.

Eespool toodud funktsioon võtab tõenäoliselt kuskil 100 sfääri. -200 kella tsüklit 8 bitti ülekandmiseks. See tähendab 24 pin-kirjutamist ja 8 lugemist. See on mitu korda mitu korda kiirem kui funktsioonide digital {stuff} kasutamine.

Pange tähele, et see kood peaks töötama ka Atmega32u4-ga (kasutatakse Leonardos), kuna see sisaldab rohkem taimereid kui ATmega328P.
+1 Suurepärane vastus !! Kas saaksite palun veidi arutada, mida mõtlete selle all, et Arduino kood on imelik värk? Mis täpselt on Arduino koodil ainulaadne, mida teistel platvormidel tavaliselt ei leidu?
@Ricardo - arvatavasti 90% + väikeste MCU-de manustatud koodist kasutab otsest registrimanipulatsiooni. Kaudsete utiliidifunktsioonidega toimingute tegemine ei ole väga levinud IO / välisseadmete manipuleerimise viis. Riistvarajuhtimise eemaldamiseks on mõned tööriistakomplektid (näiteks Atmel ASF), kuid see on tavaliselt kirjutatud selleks, et kompileerida võimalikult palju, et vähendada tööaja üldkulusid, ja peaaegu alati nõuab see välisseadmete mõistmist, lugedes andmelehti.
Põhimõtteliselt ei ole arduino värk, öeldes "siin on funktsioonid, mis teevad X", ilma et oleks vaja viitsida viidata tegelikule dokumentatsioonile või sellele, kuidas riistvara * teeb * oma asju. Mõistan, et see on väärtus tutvustava tööriistana, kuid välja arvatud kiire prototüüpimine, ei tehta seda tegelikult kunagi tegelikus professionaalses keskkonnas.
Selguse huvides pole asi, mis muudab arduino koodi manustatud MCU püsivara jaoks ebatavaliseks, arduino koodi jaoks * ainulaadne *, see on üldise lähenemisviisi funktsioon. Põhimõtteliselt, kui olete * tegelikust * MCU-st korralikult aru saanud, võtab õigesti asjade tegemine (nt otse riistvararegistrite kasutamine) vähe või üldse mitte rohkem aega. Iseenesest, kui soovite õppida tõelisi MCU arendajaid, on palju parem lihtsalt maha istuda ja mõista, mida teie MCU * tegelikult * teeb, pigem toetuda kellegi * teise * abstraktsioonile, mis kipub lekkima.
Põhimõtteliselt on kogu arduino süsteem enam-vähem välja töötatud nii, et see võimaldaks madala sissepääsutõkega juurdepääsu * mitte * programmeerijatele. See teeb seda hästi, kuid samal ajal ei tee see head tööd, sundides lõppkasutajaid riistvarast tegelikult * aru saama, lihtsalt sellepärast, et see on madala sissepääsutõkkega antiteetiline. Mõistan, et see võib (ja on) tarkvara / MCU arendamise õppimise teel olevate inimeste jaoks väärtuslikuks sammuks, kuid igaüks, kes seda kasutab, ei tohiks olla illusioonides, et arduino viis on tingimata parim või isegi mõnikord hea viis, kuidas seda teha.
Pange tähele, et ma võin siin olla natuke küüniline, kuid palju käitumisi, mida ma näen arduino kogukonnas, programmeeritakse anti-mustreid. Ma näen palju "copy-paste" programmeerimist, raamatukogude käsitlemist mustade kastidena ja lihtsalt üldist kehva kujundamistava kogukonnas. Muidugi olen EE.stackexchange'i osas üsna aktiivne, nii et mul võib olla mõnevõrra kaldus vaade, kuna mul on mõned moderaatori tööriistad ja sellisena näen paljusid suletud küsimusi. Arduino küsimustes, mida ma seal nägin, on kindlasti kallutatus "ütle mulle, mida C&P-le parandada", pigem "miks see ei tööta".
Tõenäoliselt väärib märkimist ka see, et C ++ kasutamine on * mõnevõrra * ebatavaline. Enamik väikesi MCU töid tehakse ainult puhta C-ga.
Sain aru! Mulle ei olnud selge, mida nimetasite Arduino kaudseks juurdepääsuks registritele, kuid nüüd tean selle abstraktsuse tüüpi „digitalWrite ()“. See küll vähendab barjääri sisenemisel, kuid muutub hiljem tõkkeks edasiliikumisel. Kuid teie vastus on selle takistuse eemaldamine suur samm edasi. Vähemalt minu jaoks.
@Ricardo - jah. Üks asi, mis mulle arduino kui õppevahendi puhul tõesti * meeldib *, on see, et see annab teile töökeskkonna riistvaraga otse mängimiseks, ilma et peaksite tegelema sageli kõige ärritavama osaga: esialgne esiletoomine. Olen töötanud platvormidel, kus mul oli ainult Interneti-teenuse pakkuja ja puudusid toimivad näited. Pead proovima tõrkeotsingut, miks seeria silumisliides üritasin ilma reaalse silumisliideseta tööle asuda. Platvormi omamine hõlpsasti kasutatavate jadliibidega on väga tore.
#2
+3
TheDoctor
2014-02-24 09:07:30 UTC
view on stackexchange narkive permalink

TCCR1A on taimeri / loenduri 1 juhtimisregister A

TCCR1B on taimeri / loenduri 1 juhtimisregister B

TCNT1 on taimeri / loenduri 1 loenduri väärtus

CS12 on taimeri / loenduri 1 3. kella valimisbit

TIMSK1 on taimeri / loenduri 1 katkestusmaski register

TOIE1 on taimeri / loenduri 1 ülevoolu katkestuse lubamine

Nii et kood lubab taimeri / counter 1 sagedusel 62,5 kHz ja määrab väärtuseks 34286. Seejärel lubab see ülevoolu katkestuse, nii et kui see jõuab 65535-ni, käivitab see katkestusfunktsiooni, mis on tõenäoliselt tähistatud kui ISR (timer0_overflow_vect)

#3
+1
VENKATESAN
2020-01-18 22:44:35 UTC
view on stackexchange narkive permalink

CS12 väärtus on 2, kuna see tähistab registri TCCR1B bitti 2.

(1 << CS12) võtab väärtuse 1 (0b00000001) ja nihutab vasakule 2 korda, et saada (0b00000100). Toimingute järjekord nõuab, et asjad () juhtuksid kõigepealt, nii et see tehakse enne "| =" hinnatakse.

(1 << CS10) võtab väärtuse 1 (0b00000001) ja nihutab selle 0 korda vasakule, et saada (0b00000001). Toimingute järjekord nõuab, et asjad () juhtuksid kõigepealt , nii et see tehakse enne, kui "| =" hinnatakse.

Nüüd saame TCCR1B | = 0b00000101, mis on sama mis TCCR1B = TCCR1B | 0b00000101.

Kuna "|" on "OR", see ei mõjuta kõiki TCCR1B-s olevaid bitte peale CS12.



See küsimus ja vastus tõlgiti automaatselt inglise keelest.Algne sisu on saadaval stackexchange-is, mida täname cc by-sa 3.0-litsentsi eest, mille all seda levitatakse.
Loading...