Fórum témák
» Több friss téma |
Urak, gondom akadt. A GPIOB regiszter alsó 8 bitjét használom egy képernyőre kiíró adatnak. A felső bitek viszont egyéb funkciókat képviselnek, bitenként mást.
Hogyan tudom csak az alsó 8-at írni? (jó lenne valami assembly betét, de ha csak a kiolvasás/maszkolás/vagyolás/visszaírás működik, azt is szívesen fogadom. Előre is köszönöm.
Valami ilyesmivel próbálkozhatsz:
GPIOB->ODR=(GPIOB->ODR & 0xFF00) | X X 16 bites változó, melyben a 8 bites kiírandó adat van...
BSRR regiszterrel is lehet játszani:
A hozzászólás módosítva: Jún 7, 2022
Ez így működik? Ugye van egy 0-ba állítás alsó 8 biten, és egy 1-be állítás(data8 értékétől függően) egyszerre, a BSRR-en keresztül.
BRR és BSRR regiszterek együtt használata is lehetséges. A kiementet nem csak data latch-ként lehet írni (ODR-reggel), hanem SR flip-flopként is.
BRR regiszter adott bitpozíciójára 1-et írva, a kimenet Reset funkcióját hívod (0-ba vált), míg BSRR regiszter adott bitpozíciójára 1-et írva, a kimenet Set funkcióját hívod (1-be vált). Egyes M3-tól eltérő architecktúrákon BSRRL és BSRRH van.
A kérdésem nem arra vonatkozott, hogy bitenként, vagy szavanként lehet e írni, hanem az elv, hogy egyszerre két egymásnak ellentmondó eredmény keletkezik a BSRR fenti módon történő írásakor! Vagy nem..., ez ami nem világos számomra....
A hozzászólás módosítva: Jún 7, 2022
Készíts egy olyan függvényt, mely a kívánt portállapotot úgy hozza létre, hogy a jelenlegi és a kívánt értéket össze XOR-olod:
valtoztatando_bitek-ben 1-es lesz minden olyan bit, amit változtatnod kellene. Más megoldásként létrehozhatsz egy set és egy reset xor maszkot is, és az asm barátabb megoldás, úgy két xor-olt eredményed lesz, egyiket BRR-be másikat BSRR-be írod, és nem kell levizsgálnod sem, hogy igaz vagy hamis a xor, mert csak akkor lesz 1, ha változtatnod kell az adott bit, és változtatni is 1 beírásával lehet. Szerk, kódból ért az ember:
A hozzászólás módosítva: Jún 7, 2022
Igen, az a minta, amit benjami írt, szerintem is elírást tartalmaz (és-el már jobb, de nem kész lenne). Persze ha azokat a biteket ahol az FF van mindig be akarja kapcsolni, akkor nem hibás
Szerk: Benéztem, a szemet ki nem szúrta, hogy nem ODR hanem BSRR resetes. A hozzászólás módosítva: Jún 7, 2022
A gondom az, hogy bármelyiket próbálom, ilyesmiket kapok:
Inc/ili9341_stm32_parallel8.h:180:33: error: invalid type argument of '->' (have 'long unsigned int') #define ILI_WRITE_8BIT(d) {GPIOB->ODR=(GPIOB->ODR & 0xFF00) | d; ILI_WR_STROBE;}
Csonkold az ODR regiszter tartalmát 16 bitesre.
Elvileg nem hibás..., ha feltételezzük, hogy előbb reseteli a biteket, majd utána állítja be őket!
Megnéztem a doksiban..., ha mind a két állítási eset forog fenn, csak az egyik, a bit beállítás fog érvényesülni, annak van prioritása... Ez alapján valóban nem fog jól működni a példa.... A hozzászólás módosítva: Jún 7, 2022
libopencm3 gyanús a kódod, ott nem struct a GPIOx ezért nem használhatod struct pointerként, azért nincs "->"
Ha megengedett a két lépcsős port állítás, akkor szerintem sokkal egyszerűbb ez:
GPIOB->BSRR=0x00FF0000; GPIOB->BSRR=8bit adat;
Akkor mit tudok tenni? (valóban libopencm3-as) kezdek megőrülni a sok libtől...
Ezt nem tudom, mit jelent, de egyszerre kellene írni vagy csak az adatot vagy az egészet.
Semmi különös módosítás nem kell, libopencm3 alatt a GPIOx->BSRR az GPIOx_BSRR, annyi a fontos, hogy a BSRR és a BRR regiszterek write-only regiszterek, azokat sosem olvashatod (vagyis nincs értelme pontosabban).
A probléma az, hogy minden más megoldás mint az ODR direkt read-write használata csak lassabb lesz a Te esetedben most. Ügyes a fordító, nagyon rövid kódot generál azért. A hozzászólás módosítva: Jún 7, 2022
Valamiért nem akarja a jót:
Sajnos, a C++-al alapszinten is alig értek. Inc/ili9341_stm32_parallel8.h:182:39: error: lvalue required as left operand of assignment #define ILI_WRITE_8BIT(d) {GPIOB_BSRR = 0x00FF0000 | d; ILI_WR_STROBE;} ^ Inc/ili9341_stm32_parallel8.h:201:2: note: in expansion of macro 'ILI_WRITE_8BIT' ILI_WRITE_8BIT(cmd); ^~~~~~~~~~~~~~
És azért fog működni, mert: Note: If both BSx and BRx are set, BSx has priority. (ahogy sdrlab írta is, hogy prio a set, szóval a set majd felülírja) Sebességben ennek kell a leggyorsabbnak lennie, utána ODR módszer és utána bármi más. Idézet: „A probléma az, hogy minden más megoldás mint az ODR direkt read-write használata csak lassabb lesz a Te esetedben most. Ügyes a fordító, nagyon rövid kódot generál azért.” Számold csak ki, hány utasítással maszkolgatsz a példádban?!! Ennél az ODR-es példa is gyorsabb... És az 1 lépcsős!
Ez így jól működik. A BSRR 32 bites, csak írható regiszter regiszter. Az alsó 16 bitje 1-be billenti azokat a kimeneteket ahova 1 kerül, a felső 16 bit pedig 0-ba billenti. A 0x00FF0000 azért kell, hogy az alsó 8 bitet (itt a PB0..PB7 kimenetet) 0-ba billentse. Az alsó 8 bitbe írt 1 értékű bitek viszont 1-be billentik azokat a kimenetek ahova 1 kerül. Mivel a SET funkció (azaz az alsó 16 bitbe írt érték) prioritása magasabb, ezért az fog érvényesülni. Ezzel lehet a leggyorsabb kódot csinálni, mert nem kell a perifériából olvasni a periféria írása előtt. A periféria írása és olvasása ugye lassabb, mert lassabb buszt kell hozzá a procinak igénybe vennie.
Semmiben, ez ugyan az, csak libopencm3-ra átírva, ahogyan a kérdezőnek kellett
Csak az első hozzászólásoknál még nem volt ismert számomra, hogy libopencm3-ra várja a megoldást a kérdező, és nem a BSRR felső resetes megoldását akarja elkerülni, csak egyszerűen nem tudta lefordítani. A hozzászólás módosítva: Jún 7, 2022
Tehát végrehajtódik mind a reset, mind a set funkció, és mivel a set a magasabb prioritás, az marad meg a végén??! Érdekes.... )
Nekem a doksi alapján korántsem egyértelmű helyzet volt ez... Ez tuti így működik a valóságban? Jobban belegondolva tényleg jó ez így! Ügyes... A hozzászólás módosítva: Jún 7, 2022
Köszönöm, de egyáltalán nem akarja ismerni a BSSR-t.
Inc/ili9341_stm32_parallel8.h: In function '_ili_write_command_8bit': Inc/ili9341_stm32_parallel8.h:184:34: warning: implicit declaration of function 'GPIO_BSRR'; did you mean 'GPIO_BC'? [-Wimplicit-function-declaration] #define ILI_WRITE_8BIT(d) {GPIO_BSRR(GPIOB) = (uint32_t)(0x00FF0000 | ((d) & 0xFF)); ILI_WR_STROBE;} ^ Inc/ili9341_stm32_parallel8.h:201:2: note: in expansion of macro 'ILI_WRITE_8BIT' ILI_WRITE_8BIT(cmd); ^~~~~~~~~~~~~~ Inc/ili9341_stm32_parallel8.h:184:51: error: lvalue required as left operand of assignment #define ILI_WRITE_8BIT(d) {GPIO_BSRR(GPIOB) = (uint32_t)(0x00FF0000 | ((d) & 0xFF)); ILI_WR_STROBE;} ^ I
Kérnék szépen egy olyan funkciót, ami DIREKTBEN írja a portot (ha ugyan ebben az átkozott c++-ban van ilyen).
Olvasni - úgy tűnik - sikerül az #define ILI_READ_8BIT(d) {d = (uint16_t)GPIO_IDR(ILI_PORT_DATA) & 0x00FF;} makróval.Az ili port data az a gpiob.
Ez már csak hibás include. Nézd meg, hogy include-olva van-e egyrészt:
#include <libopencm3/stm32/gpio.h> másrészt pedig szerepel-e valahol stm32 family define, pl.: #define STM32F1 mert a gpio.h, további elágazásokat tartalmaz, aminél a proci típus alapján ágazik el: lásd lib headert
Igazából ez egy gd32f130c6t6.
Van valami gd-s könyvtár, de nagyon keveredik az stm-el.
Így jár az, aki nem képes leírni, hogy ugyan milyen kontrollerrel milyen környezetben foglalatoskodik. A GD adatlapján GPIOx_BOP regiszternek hívják az ominózus regisztert. Hogy a prioritás ott is jól működik-e az sajnos nem derül ki az adatlapból (az STM32 esetén igen, ott le van írva, hogy a set a magasabb prioritású). Így marad az, hogy kipróbálod. Ha jól megy akkor örülsz, ha nem, akkor marad a lassabb módszer.
A legnagyobb gondom a szintaxissal van, illetve a könyvtárstruktúrával, hogy honnan veszi a standard perifériákat. Holnap megkérek egy hozzáértőt, hogy nézzük át együtt vagy ha nem ér rá, akkor valami szűz könyvtárban kísérletezgetek.
Mindenesetre köszönöm mindenkinek, hogy foglalkozott velem, a lendítés megvolt, folyt köv A hozzászólás módosítva: Jún 7, 2022
|
Bejelentkezés
Hirdetés |