Fórum témák

» Több friss téma
Fórum » AVR - Miértek hogyanok
 
Témaindító: pakibec, idő: Márc 11, 2006
Témakörök:
WinAVR / GCC alapszabályok:
1. Ha ISR-ben használsz globális változót, az legyen "volatile"
2. Soha ne érjen véget a main() függvény
3. UART/USART hibák 99,9% a rossz órajel miatt van
4. Kerüld el a -O0 optimalizációs beállítást minden áron
5. Ha nem jó a _delay időzítése, akkor túllépted a 65ms-et, vagy rossz az optimalizációs beállítás
6. Ha a PORTC-n nem működik valami, kapcsold ki a JTAG-et
Bővebben: AVR-libc FAQ
Lapozás: OK   790 / 837
(#) Tomi_Bp válasza zolee1209 hozzászólására (») Feb 21, 2018 /
 
Először is szeretném megköszönni zolee1209 és mikrofarad válaszát is. Igen, számomra fontos az AVR Studio kompatibilitás. Erre sajnos egyik -a neten fellelhető- leírás sem hozott tartós megoldást. Csak a gép indításakor nyomott F8 billentyű és a "illesztőprogram aláírásának megkövetelésének kikapcsolása" menüpont, de csak arra az indulásra.
Az akkor megrendelt AVR ISP mk2 ma érkezett meg. Az eszköz kezelő szerint jól működik, de nem hajlandó az AVR Studio-val működni. Ki járt így és mi lett a megoldás végül?
(AVR Studio 4.16.638)
A hozzászólás módosítva: Feb 21, 2018
(#) borsozo hozzászólása Márc 1, 2018 /
 
Segítséget kérek megszakítás kezeléséhez. Studio4-et használok, asm-ben írom a programokat.
Atmega8A -ban a Timer0 és a Timer2 túlcsordulással indítják a saját megszakítási rutinjukat. Timer0 kb: 0,5ms-onként indít megszakítást, és egy portbitet átbillent. Timer2 kb: 17ms-os időközönként ad megszakítást, és billegtet portbitet.
Mindkettő a saját Prescalerén keresztül kapja a Clk.io órajelet, külső 15MHz kvarcról.
Mindkét portbitet szkóppal mértem.
Külön-külön, csak egy timert engedélyezek, akkor külön-külön mindkét megszakítás működik, szkópon látható.
A problémám:
1. Ha mindkét Timer engedélyezve van, akkor csak a Timer2 működik, Timer0 áll!!
2. Ha Timer2 megszakítását letiltom, ( TIMSK TOIE2 bit=0), akkor Timer0: 1ms négyszög jele a portbiten mérhető. (Értelemszerűen Timer2 áll)
Megjegyzem, Timer2 magasabb prioritású... Próbáltam, hogy mindkét rutin futása alatt a másik megszakítását tiltani/engedélyezni, de a hiba ugyanaz.
A) Szinkronban (azonos órajel ciklusban?!) beérkező megszakítás kéréseket (OVF bebillenéseket) milyen sorrendben kezeli le? Ha szinkronban érkeztek be, akkor mindkét Flag-et törli a magasabb prioritásúra ugráskor?
B) A magasabb prioritású megszakítás rutin a működése alatt beérkező alacsonyabb prioritású megszakítás bitet mikor olvassa ki, mikor ugrik a rutinjára? Úgy tűnik itt ez elmarad! Hol vész el a TOV0 bit?
Mi a megoldás? kérem segítsetek!
(#) Kovidivi válasza borsozo hozzászólására (») Márc 2, 2018 /
 
Szerintem a programodban mikor beállítod a második timert, akkor egyszerűen nem veszed figyelembe, hogy a regisztereknek már van tartalma, és felülírod. Nem ezt használod: regiszter|=(1<<3), hanem ezt: regiszter=0b00110011. Érted mire gondolok?
Atmega8-nál tudtommal nincs prioritás az interruptoknál. Ha benne vagy az interruptban, és jön egy megszakítás kérelem, akkor bebillen a megfelelő flag, kilépsz az interruptból, és azonnal jön a következő megszakítás feldolgozása. Kis csúszás lehetséges ilyenkor.
Jobb lenne, ha felraknád a programod, de csak a legfontosabb részekkel! Ne legyenek benne sallangok, és jól kommentezd is fel a timer beállítását! Ekkor tudunk segíteni.
Még mindig nem értem, miért írtál ilyen sokszor az interrupt prioritásáról, hiszen ilyen nincs Atmega8-ban.
(#) zolee1209 válasza Kovidivi hozzászólására (») Márc 2, 2018 /
 
Van prioritás abban az értelemben, hogy ha két interrupt egyszerre következik be, akkor az alacsonyabb vektorú fog előbb meghívódni. Pl a két timer ugyanazzal a beállításokkal, külső órajelről hajtva, egyszerre billen be az interrupt flag, de lefutni az fog, amelyik előrébb van a megszakítási címek sorában. A többivel egyetértek. Látni kell a kódot, mert ez beállítási gond. Semmi nem kellene akadályozza a két megszakítás lefutását, mindenféle trükk nélkül.
(#) rolandgw válasza Kovidivi hozzászólására (») Márc 2, 2018 /
 
Idézet:
„nincs prioritás az interruptoknál”

Ha egy megszakítás alatt beáll másik két flag, honnan tudná a uC melyiket kell végrehajtani? Feldobna egy pénzérmét?
(#) Kovidivi válasza rolandgw hozzászólására (») Márc 2, 2018 /
 
Oké, értem már. Tehát a vektor alapján bekövetkező meghívásra gondoltok (és a kérdező melyikre gondol?). Szerintem az esélye, hogy a fent megnevezett interrupt egy órajelre pontosan egyszerre érkezzen, elég ritka. Én arra gondoltam, hogy míg fut az alacsonyabb prioritású megszakítás, közben jön a magasabb, akkor a magas azonnal lefut, megszakítva az alacsonyabb megszakítást. Ez két különböző fajta prioritás.
"Ha egy megszakítás alatt beáll másik két flag, honnan tudná a uC melyiket kell végrehajtani?" - jelen esetben, két megszakítással egyszerű a helyzet. Az egyik fut, addig tiltva van másik megszakítás futása, tehát ami ez idő alatt jöhet, az csak a másik timer int. lehet. Tehát a megszakítás után jön a másik. Ebben a helyzetben nincs semmi prioritási függés! Ezért nem értettem én, hogy mi a gond. Két interruptnál ha fut az egyik, a másik nem futhat, csak utána. Ha egyszerre jön a két megszakítás, akkor a vektortáblázat alapján előrébb levő fut le először.
A hozzászólás módosítva: Márc 2, 2018
(#) borsozo válasza Kovidivi hozzászólására (») Márc 2, 2018 /
 
Mellékeltem az asm fájlt.
Elvileg:
A hw-ben lehetséges, hogy két számláló ua órajelről a cpu ua időjel fázisa alatt billenti be a túlcsordulás fag-et. Nálam is előfordulhat (?) de ritkán, mivel eltérő számig számlálok.
A uC hw prioritásvezérlőnek szerintem is a kisebb címűt kellene lekérdeznie először, és nem lenne szabad a teljes megszak flag regisztert törülnie .
Gyakorlatban:
miért nem működik mind a két megszakításom? Hiszen eltérő időközönként adnak megszakítást...
Az alacsonyabb megszak intr alatt természetesen a magasabb azt megszakítja, majd visszaadja avezérlést az alacsonyabb prioritásúnak : elvileg!
Mi a hiba a programomban? Előre is kösz mindenkinek a segítséget!!!

Kis kiegészítés: kb a 282. sorban tiltom/engedélyezem a Timer2 megszakítását a teszt ill. mérés során
A hozzászólás módosítva: Márc 2, 2018
(#) benjami válasza borsozo hozzászólására (») Márc 2, 2018 /
 
A 8 bites AVR-ek nem tudnak több megszakítást egymásba ágyazni. Amíg a megszakítás kiszolgálása be nem fejeződik, addig a közben beérkező további megszakítási igény kénytelen kivárni annak a befejeztét. Ha eközben több megszakítási igény is előállt, akkor a prioritási sorrend alapján dönti el a megszakítás kiszolgálásának a sorrendjét. Annak valóban kicsi az esélye, hogy pont egy időben keletkezzen két igény, de azért megtörténhet (a prioritás nem elsősorban ezen esemény kezelésére szolgál, hanem a hozzászólásom elején levő esetre). Olyan is lehet, hogy a programból egy ideig le van tiltva a megszakítás, ha közben több igény is keletkezett, akkor is a prioritás dönti el, hogy a tiltás feloldásakor milyen sorrendben legyenek kiszolgálva.
(#) Massawa válasza benjami hozzászólására (») Márc 2, 2018 /
 
Én egy megszakitást használok de abban több feladat van elrejtve igy áranylag egyszerüen lehet több egymástol független feladatot elvégezni. Pl az egyik feladat minden megszakitásban tesz valamit a másik meg csak pl minden negyedikben. Igy eddig aránylag könnyen csináltam olyan programokat is, ahol 4-5 feladat függ a megszakitástol.
(#) Kovidivi válasza borsozo hozzászólására (») Márc 2, 2018 /
 
Ne haragudj, de ezzel én nem sokat tudok kezdeni. Rendes C kódra gondoltam (abból is csak a timerek inicializálása, a lehető legegyszerűbb programmal), ASM-ben alig fogsz találni segítséget.
(#) benjami válasza Massawa hozzászólására (») Márc 2, 2018 /
 
Nem tudom mit értesz az alatt, hogy egy megszakítást használsz, de olyat én is szoktam csinálni, hogy ha van mondjuk 3 időzített feladatom, pl. óra léptetése másodpercenként, led villogtatási ütemezés tizedmásodpercenként, meg mondjuk még valami 3millisecenként, akkor 1msec sűrűségű timer megszakításban létrehozok 3 static változót számolni, és a számlálók tartalma alapján globális változókba adok kvázi indítóimpulzusokat a főprogramhurokban keringő programomnak, hogy mikor mit csináljon. A megszakításban tartózkodást ilyen módon igyekszem minél rövidebbre fogni, és ott csak azokat elvégezni, amik feltétlenül szükségesek.
(#) Massawa válasza benjami hozzászólására (») Márc 2, 2018 /
 
Az egyik mostani programban pl a léptetö motort léptetem néha leolvasom a nyomogombokat megint máskor meg kijelzem az LCD-re az állapotot. Ez a 3 feladat történik a timer megszakitásokban.
(#) zolee1209 válasza borsozo hozzászólására (») Márc 2, 2018 /
 
Megpróbáltam átrágni magamat a kódodon...
Makrók használatára még nem vettem rá magamat évek után sem, pedig egyszerűbb lenne. Így azt a részt csak nagyjából értem.

A stack inicializálást nem tudom, miért így csinálod?! Szerintem magadat hozod kényesebb helyzetbe, több dologra kell figyelni feleslegesen. A stack, -vagyis verem- úgymond alulról felfelé töltődik adatokkal. Reset esetén a legalsó pontra beállítod (RAMEND). .dseg-ben pedig elegendő a kívánt blokkokat lefoglalni, nálad az "UresBajtok". Én személy szerint egy regisztert fel szoktam áldozni, ha valami portot váltogatni kell, és máshova is kell például egy lassabb időzítés. Timer megszakításban regisztert inkrementálok. 0-ik bitje például egy LED villogtatás, másik bitje más funkciónak a "flag"-je. De ha csak adott kimeneti pin állapotát akarod invertálni, akkor:

  1. sbi pind,0 ;toggle
  2. sbi pind,0 ;toggle


Ha a TCNTx regisztert módosítod, állítsd meg a számlálót. Vagy, használd a CTC üzemmódot, mert látszólag ezt szeretnéd elérni, hogy ne 0-255 között számoljon a timer, így sűrűbben hozna létre megszakítást. SFIOR regisztert felesleges babrálnod itt. Megszakításba nem rakunk delayt. Nem számoltam utána, de az sincs kizárva, hogy a megszakításodból lényegében ki sem lép a program a delay miatt. Mivel ott várakozol, timer lejárhat, megszakítást generál és ugrik is az elejére. De mivel AVR studio-t használsz, ott a szimulátor, abban léptetgetheted a programod és látod mikor mi, milyen értéket vesz fel, vagy hol ragad meg a programod.
(#) zolee1209 válasza borsozo hozzászólására (») Márc 2, 2018 /
 
Mellékletben az én verzióm. A timer-t nem szükséges megállítani, ha módosítod TCNT regisztert, hülyeséget írtam.

HE_teszt.asm
    
(#) Tomi_Bp válasza Tomi_Bp hozzászólására (») Márc 2, 2018 /
 
Találtam magyarázatot, talán emiatt nem megy AVR Studio 4 alatt, csak AVR Studio 7 alatt a vadi új Kínából most érkezett AVRISP mkII-m , de sajnos a cím nem működik, így beljebb nem vagyok.

Idézet:
„Previously I used AVR Studio 4 successfully but when I installed Atmel Studio 7 I can no longer connect to AVR-ISP-MK2 in AVR Studio 4. What can I do to use AVR Stduio 4 and Atmel Studio 7 at the same time?
The drivers installed with Atmel Studio 7 overwrote the drivers that worked with AVR Studio 4. These drivers are not compatible you would have to downgrade the drivers manually. The official Atmel workaround can be found here: http://atmel.force.com/support/articles/en_US/FAQ/Downgrading-tools...driver


Valaki tudna ötletet adni?
A hozzászólás módosítva: Márc 2, 2018
(#) zolee1209 válasza zolee1209 hozzászólására (») Márc 2, 2018 /
 
Sajnos ATmega8-on szimulátorban nem működik a port bit toggle a fentebb írt módon és az adatlapjában sem találtam meg az erre utaló részt. ATmega328-ban van, így a kódon is javítottam.
(#) vargham hozzászólása Márc 2, 2018 /
 
"Once the CPU enters the ISR, the global interrupt enable bit (I-bit) in SREG will be cleared so that
all other interrupts are disabled. In order to use nested interrupts, the I-bit has to be set by software
when the CPU enters an ISR."
Tehát ha éppen egy ISR végrehajtása van folyamatban, akkor a megszakítások letiltásra kerülnek. Ha ez nem tetszik, akkor engedélyezni kell őket az ISR első sorában.

Forrás: Using External Interrupts for megaAVR Devices 6. oldal
(#) Hp41C válasza benjami hozzászólására (») Márc 2, 2018 /
 
Idézet:
„A 8 bites AVR-ek nem tudnak több megszakítást egymásba ágyazni.”

Idézet az AtMega8 adatlapjából:
Idézet:
„When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed.
There are basically two types of interrupts. The first type is triggered by an event that sets the Interrupt Flag. For these interrupts, the Program Counter is vectored to the actual Interrupt Vector in order to execute the interrupt handling routine, and hardware clears the corresponding Interrupt Flag. Interrupt Flags can also be cleared by writing a logic one to the flag bit position(s) to be cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is cleared, the Interrupt Flag will be set and remembered until the interrupt is enabled, or the flag is cleared by software. Similarly, if one or more interrupt conditions occur while the global interrupt enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the global interrupt enable bit is set, and will then be executed by order of priority.
The second type of interrupts will trigger as long as the interrupt condition is present. These
interrupts do not necessarily have Interrupt Flags. If the interrupt condition disappears before the interrupt is enabled, the in terrupt will not be triggered. When the AVR exits from an interrupt, it will always return to the main program and execute one more instruction before any pending interrupt is served.”

Az AVR nem menti a státus és egyéb regisztereket, így azt a programozónak kell megtennie. Mivel az AVR rendelkezik stack kezelési lehetőséggel és adatokat is elhelyezhet a stack -en, a regiszterek értékét a stack -re mentve ill. onnan visszaállítva megvalósítható a többszintű megszakítás kezelése. Ha a regiszterek értékét elmentettük, engedélyezhetjük a globális megszakítást, hogy más megszakításkérést is ki tudjunk szolgálni.
(#) benjami válasza Hp41C hozzászólására (») Márc 2, 2018 /
 
Akkor még is tud (kicsit figyelmetlenül olvastam bele az adatlapba ezek szerint). Szerintem a regiszterek elmentése előtt is engedélyezhetjük a globális megszakításkérést, csak annyi a lényeg, hogy a belépéskor és a kilépéskor a regiszterek értéke azonos legyen.
Ha valami nagyon időkritikus válaszidejű dolgot akarunk kezelni, akkor érdemes lehet használni ezt a módszert a kevésbé időkritikus megszakításoknál.
(#) rolandgw válasza borsozo hozzászólására (») Márc 2, 2018 /
 
Én sem értem ezt a stack mahinálást. Mivel resetnél nullára áll a mutató, a főprogramban RAMEND-re kell állítani.
(#) borsozo válasza zolee1209 hozzászólására (») Márc 2, 2018 /
 
Mindnyájatoknak köszönöm, hogy foglalkoztok a kérdéssel! Most rajtam a sor, hogy teszteljem amiket leírtatok.
Megjegyzés:
- természetesen ahol szükséges, stack-ba mentem a változókat, az SREG tartalmát is
- a portbitek beállítására sbi, cbi utasításokat ismerem, a 'TtoPort' macro-ban is azt alkalmazom (én szeretem a macro-kat, mert saját utasításkészletként lehet használni)
- az : ldi reg, (1<<n) utasításokat is ismerem, persze könnyű hibázni is
- a programomat a probléma tisztázásához nagyon leegyszerűsítettem (nem a portbitek billegetése a célom, az csak hibakeresésre szolgál)
- a Studio-4 szimulátorát szoktam használni, de az időfüggő részek, megszakítások tesztelése sokkal nehézkesebb, mint letölteni a hex-et a kontrollerbe, és szkópra adni (az időfüggő-) jeleket.

A megszakítások egyidejűségére tett megállapításotok igaz: nagyon kicsi az egyidejűségre az esély. Ez csak a megszakítások egymásba ágyazódásnak kezelési kérdését vetette fel. Erre is kaptam válaszokat Tőletek. Nem is ez az igazi problémám, hanem:

- a Timer2-be beillesztett sw hurok késleltetés kb 50usec, csak a szópos mérés miatt tettem bele, hogy a szkópon a Timer2 kb 50usec futásideje látható legyen. Az Timer2 megszakítás ismétlődési ideje kb 17msec (a TCNT2 255-ig számol...)
- a Timer0 minden lefutásakor invertálódik egy bit, ezt küldöm ki a portra: (Timer0 futásideje <10usec, ismétlődési ideje 0,5msec)
Tehát a szkópon ennek kellene látszani:
T:..................................17ms...........17ms............17ms
Timer2: 50us/17ms _________!__________!__________!________

Timer0: 10us/0,5ms !_!_!_!_!_!_!_!_!_!_!_!_!_!_!_!_!
portbit: 0,5ms/0,5ms _--_--_--_--_-- _--_--_--_--_-- _--_--

Látható, hogy a 17msec alatt2*17=34 db Timer0 megszakítás történhetne, de nem történik egy sem!... Ha a kétféle megszakítás egybeesne, és emiatt veszne el egy megszakítás, akkor is 33 db Timer0 megszakításnak látszódnia kellene a 17ms alatt.

A globális (SREG) megszakítás nincs letiltva, hiszen Timer2 megszakítása működik. Mitől van letiltva, vagy mitől tiltódik le(?) Timer0 ( 'OVF0' ) megszakítása?

Megpróbálom az idézett leírások szerinti működést is célirányosan ellenőrizni, hátha kiderül mi a hiba a programomban. (Feltételezem, hogy a leírás jó és érvényes, és a hw is tudja ezt...)
Feltétlenül megírom az eredményét, de továbbra is várom az észrevételeiteket, míg meg nem oldódik a probléma.
A hozzászólás módosítva: Márc 2, 2018
(#) borsozo válasza borsozo hozzászólására (») Márc 2, 2018 /
 
Huuuh!
Megvan a hiba!!!
A shiftelt bit beírás nem korrekt, csak korlátozottan ajánlatos használni!!! így nem sok előnye van más parancsokkal (ori, andi, bld/bst, sbi, cbi...) szemben...

1. A két timer megszakításainak egyetlen utasításban történő engedélyezésével működik mindkét megszakítás:
in r16, TIMSK ; ennek semmi értelme, mert az összes többi bitet úgyis törli! (lásd később)
ldi r16, (1<<TOIE2)|(1<<TOIE0) ;az egyidejű bit beírás mindkettőt engedélyezi, jó!!!
out TIMSK, r16

2. Én a két timer-t külön-külön, egyéb paramétereik megadásánál engedélyeztem a programomban (ha már bit művelet...) :

A) Timer0 paramétereit állítottam be először:
in r16, TIMSK
ldi r16, (1<<TOIE0) ;Timer0-t engedélyezem -> TOIE0 :=1
out TIMSK, r16
......
......

B) Timer2 paramétereit állítottam be az előbbi után:
in r16, TIMSK
ldi r16, (1<<TOIE2) ;Timer0-t engedélyezem -> TOIE2 :=1
out TIMSK, r16

HIÁBA HíVJÁK/íRJÁK BIT MŰVELETNEK, SORRENDBEN A MÁSODIK, B) PARANCS TÖRLI AZ A)-BAN BEíRT BITET!!! (illetve a teljes regisztert törli, és utána írja be a TOIE2 =1 értéket)

Tehát ugyanabba a regiszterbe egyidejűleg, egy utasításban kell minden bit értéket megadni. Amennyiben a prog futása során valamelyik bitet módosítani kell (be kell írni), akkor az összes többit is kell ismételni vele együtt!!!!!!!!!! Tehát nem igazi bit művelet.

ui: az egymásba ágyazott, prioritásos megszakítási rutin kezelés nem igazán szükséges a most készülő programomban, úgyhogy elnapolom a megoldását.

Mégegyszer köszönet mindenkinek, több mindenben okosodtam!
A hozzászólás módosítva: Márc 2, 2018
(#) kleinie válasza borsozo hozzászólására (») Márc 3, 2018 /
 
Az LDI és OUT nem bit művelet. Egyértelmű, hogy a B törli az A-ban beírt értéket. A << BIT művelet és a | is. Ha külön-külön akarsz biteket kapcsolgatni az egyes regiszterekben arra az SBI való egymagában.
(#) vargham válasza borsozo hozzászólására (») Márc 3, 2018 /
 
Ez C-ben is pont így van.
A TIMSK = (1 << TOIE2); alak nem jó, mert FELÜLÍRJA a regiszter korábbi tartalmát.
Helyette:
  1. //Set one bit
  2. TIMSK |= (1 << TOIE0);
  3. TIMSK |= (1 << TOIE2);
  4. //Clear one bit:
  5. TIMSK &= ~(1 << TOIE0);
  6. TIMSK &= ~(1 << TOIE2);
(#) rolandgw válasza kleinie hozzászólására (») Márc 3, 2018 /
 
Ez igaz, de ebben az esetben nem használható az sbi, mert 0x1F cím felett van a TIMSK.
(#) kleinie válasza rolandgw hozzászólására (») Márc 3, 2018 /
 
Én is most ismerkedek vele, de elsőre csak C-vel. Assembly-t, csak 6502-t ismerem nagyjából.
Ha in-el behozom egy regiszterbe, a regiszteren lehet játszani SBI-vel gondolom, utána out-al visszarakni. Mondjuk így plussz köröket futunk.
A hozzászólás módosítva: Márc 3, 2018
(#) killbill válasza borsozo hozzászólására (») Márc 3, 2018 /
 
Idézet:
„HIÁBA HíVJÁK/íRJÁK BIT MŰVELETNEK, SORRENDBEN A MÁSODIK, B) PARANCS TÖRLI AZ A)-BAN BEíRT BITET!!! (illetve a teljes regisztert törli, és utána írja be a TOIE2 =1 értéket)”
Nem hívják ezt bit műveletnek. És nem törli a regisztert és írja be... Egyszerűen betölt egy értéket egy regiszterbe.

Az (1 << TOIE2) az egy kifejezés. A << egy operátor, mégpedig a balra shift operáror. A TOIE2 pedig egy kosntans szám, ami valamelyik header file-ban van definiálva egy #define direktívával, és talán 6 az értéke. Az assembler (pontosabban a C előfeldolgozó) a TOIE2 szöveget egyszerűen behelyettesíti a 6-tal, igy az (1 << TOIE2) az valójában (1 << 6). Az (1 << 6) az annyit tesz, hogy az 1-et eltolja balra 6 bittel, azaz hat helyiértékkel: 2, 4, 8, 16, 32, 64. Így az (1 << TOIE2) az nem más, mint 64.

De szerintem te az LDI utasítással nem vagy tisztában. Mit csinál a programod:
  1. in   r16,TIMSK          ; betolti r16 regiszterbe a TIMSK erteket
  2. ldi  r16,(1<<TOIE2)  ; betolt r16 regiszterbe egy konstans erteket (64-et)
  3. out TIMSK,r16          ; kiirja TIMSK-ra az r16 regisztert, azaz az elobbi konstanst

Itt az 'in' utasitásnak semmi értelme, mert a következő utasítás felülírja a beolvasott értéket.
Ha azt akarod, hogy csak a TOIE2 bit valtozzon meg, akkor ANDI vagy ORI utasítást kell használnod az LDI helyett.
A hozzászólás módosítva: Márc 3, 2018
(#) borsozo válasza killbill hozzászólására (») Márc 3, 2018 /
 
Pontosan a << (shift) operátor tévesztett meg. A hibám, hogy azt feltételeztem, hogy a 'bst r16, b' illetve 'bld b, r16' típusú utasításokhoz hasonlóan a megcímzett bitre beilleszti, shifteli az 1 vagy 0 értéket, csak itt lehetőség van egy paranccsal több bitet is beírni.
Igazából az ori, andi utasításokkal nagyon jól elvoltam eddig. Az (1<<TOIE2) .... típusú kifejezések magyarázata az assemblerem helpjében nincs benne. (Csak az operátorok, stb felsorolása. én meg nem jártam utána.) A C nyelvet nem ismerem. Gondolom az assembler is az alap utasításokból rakja össze, helyettesíti be pl a (1<<TOIE2) kifejezést.
Vargham válaszából értettem meg pontosan, hogy hogyan is kell használni.
Köszönöm!
"a jó pap is holtig tanul"
(#) Kovidivi válasza borsozo hozzászólására (») Márc 3, 2018 /
 
Ezek szerint a sejtésem beigazolódott! Bővebben: Link
A hozzászólás módosítva: Márc 3, 2018
(#) killbill válasza borsozo hozzászólására (») Márc 3, 2018 /
 
Idézet:
„Gondolom az assembler is az alap utasításokból rakja össze, helyettesíti be pl a (1<< TOIE2) kifejezést.”
Akkor valamit még mindíg nem értesz. Az (1 << TOIE2) az egyszerűen 64, azaz egy sima konstans. Nincs ennek semmi köze utasításokhoz meg assemblerhez, meg semmihez. Ez egy matamatikai kifejezés, egy kétoperandusú operátor, aminek mindkét operandusa konstans, ezért az ertéke is konstans lesz.
Az, hogy nem azt írjuk, hogy ldi r16,64, hanem azt, hogy ldi r16,(1 << TOIE2), az csak azért van, hogy érthetőbb, olvashatóbb legyen a kód. És, hogy ha megváltozik TOIE2 értéke, akkor ne 100 helyen kelljen a forrást módosítani.
Vargham valaszában pont az volt, mint amit én is mondtam. Nem értéket adsz, hanem OR-olod az eredeti értéket valamivel. A C-ben leírt
  1. TIMSK |= 64;
az asseblyben
  1. in r16,TIMSK
  2. ori r16,64
  3. out TIMSK,r16
Következő: »»   790 / 837
Bejelentkezés

Belépés

Hirdetés
Lapoda.hu     XDT.hu     HEStore.hu
Az oldalon sütiket használunk a helyes működéshez. Bővebb információt az adatvédelmi szabályzatban olvashatsz. Megértettem