🧠 Aktív Felidézés • Kódrészletek Memorizálásra
Kódrészletek — Deklarációk & Interjúkérdések
48 gyakorlófeladat kártya: olvasd el a feladatot, próbáld meg fejből leírni/elmondani a választ, majd kattints a "Megoldás mutatása" gombra az ellenőrzéshez. Az aktív felidézés (active recall) hatékonyabb memorizálási módszer, mint a passzív olvasás.
48 kártya
PIC18 Regiszterek
Deklarálj egy bitmezős union-t egy 8 bites porthoz úgy, hogy minden bit külön néven (pl. RB0..RB7) elérhető legyen — a `pic18f4620.h` stílusában.
C
typedef union {
struct {
unsigned RB0:1;
unsigned RB1:1;
unsigned RB2:1;
unsigned RB3:1;
unsigned RB4:1;
unsigned RB5:1;
unsigned RB6:1;
unsigned RB7:1;
};
uint8_t byte;
} LATBbits_t;
extern volatile LATBbits_t LATBbits __at(0xF8A);
PIC18 Regiszterek
Hogyan érhető el közvetlenül, pointerrel egy SFR regiszter egy fix memóriacímen (pl. PORTB = 0xF81), a compiler-specifikus `__at` kulcsszó nélkül?
C
#define PORTB_REG (*(volatile uint8_t*)0xF81)
PORTB_REG = 0x55;
PIC18 Regiszterek
Írd fel egy magas prioritású megszakítási rutin (ISR) helyes XC8 függvényfejlécét PIC18-on.
C (XC8)
void __interrupt(high_priority) HighISR(void) {
// ISR törzs
}
PIC18 Regiszterek
Írd fel az alacsony prioritású ISR függvényfejlécét, és mutasd meg, hogyan kell engedélyezni a prioritásos megszakítási módot.
C (XC8)
void __interrupt(low_priority) LowISR(void) {
// ISR törzs
}
// main()-ben, induláskor:
RCONbits.IPEN = 1; // Prioritásos megszakítási mód engedélyezése
PIC18 Regiszterek
Hogyan olvasható ki egy 10 bites, jobbra igazított ADC eredmény egyetlen 16 bites változóba az ADRESH:ADRESL regiszterpárból?
C
uint16_t result = ((uint16_t)ADRESH << 8) | ADRESL;
PIC18 Regiszterek
Hogyan olvasható ki race-condition-mentesen egy 16 bites szabadonfutó időzítő (pl. Timer1) értéke, amely olvasás közben átfordulhat (túlcsordulhat)?
C
uint16_t read_tmr1_safe(void) {
uint8_t high1, high2, low;
do {
high1 = TMR1H;
low = TMR1L;
high2 = TMR1H;
} while (high1 != high2); // Ha eltér, közben átfordult -> újra
return ((uint16_t)high1 << 8) | low;
}
PIC18 Regiszterek
Hogyan kell konfigurációs biteket (Configuration Bits) beállítani XC8-ban `#pragma config` direktívával, pl. belső oszcillátorra és a Watchdog letiltására?
C (XC8)
#pragma config FOSC = INTIO67 // Belső oszcillátor, RA6/RA7 GPIO-ként
#pragma config WDT = OFF // Watchdog Timer letiltva
#pragma config LVP = OFF // Low-Voltage Programming letiltva
PIC18 Regiszterek
Írd le a Data EEPROM egy bájtjának beolvasásához szükséges regisztersorozatot (EEADR, EECON1 bitjei).
C
uint8_t eeprom_read(uint8_t address) {
EEADR = address;
EECON1bits.EEPGD = 0; // 0 = Data EEPROM (nem programmemória)
EECON1bits.CFGS = 0; // 0 = EEPROM/Flash elérés (nem config bit)
EECON1bits.RD = 1; // Olvasás indítása
return EEDATA;
}
PIC18 Regiszterek
Írd le a Data EEPROM egy bájtjának írásához szükséges "unlock" szekvenciát, a kötelező 0x55/0xAA sorrenddel.
C
void eeprom_write(uint8_t address, uint8_t data) {
EEADR = address;
EEDATA = data;
EECON1bits.EEPGD = 0;
EECON1bits.CFGS = 0;
EECON1bits.WREN = 1; // Írás engedélyezése
INTCONbits.GIE = 0; // Megszakítások letiltása az unlock alatt
EECON2 = 0x55; // Kötelező unlock szekvencia (adatlap szerint)
EECON2 = 0xAA;
EECON1bits.WR = 1; // Írás indítása
INTCONbits.GIE = 1;
EECON1bits.WREN = 0; // Írás letiltása (véletlen írás elleni védelem)
}
PIC18 Regiszterek
Hogyan léptethető a mikrovezérlő alacsony fogyasztású Sleep módba XC8-ban?
C (XC8)
Sleep(); // XC8 beépített intrinsic: kiadja a SLEEP gépi utasítást
PIC18 Regiszterek
Mutasd be egy periféria "szentháromságát" (Flag, Enable, Priority bit) konkrét példán, az UART vételi megszakításnál.
C
PIR1bits.RCIF; // Flag: beérkezett egy bájt (a hardver állítja)
PIE1bits.RCIE = 1; // Enable: UART vételi megszakítás engedélyezése
IPR1bits.RCIP = 1; // Priority: magas prioritásúra állítás (ha IPEN=1)
PIC18 Regiszterek
Írd le helyesen, hogy egy GPIO láb kimenet legyen és induláskor alacsony (0) szintre álljon — ügyelve a helyes sorrendre, hogy elkerüljük a rövid, nem kívánt kimeneti tüskét (glitch)!
C
LATDbits.LATD0 = 0; // 1. Előbb a kimeneti retesz (LAT) tartalmát állítjuk be
TRISDbits.TRISD0 = 0; // 2. ...majd konfiguráljuk a lábat kimenetre (TRIS)
// Fordított sorrendnél a láb egy pillanatra a láb korábbi/ismeretlen
// LAT-tartalmával indulhatna kimenetként, mielőtt beírnánk a kívánt értéket.
Bit-makrók
Írj egy makrót, amely beállít (1-be állít) egy adott bitet egy regiszterben.
C
#define SET_BIT(reg, n) ((reg) |= (1U << (n)))
Bit-makrók
Írj egy makrót, amely törli (0-ra állít) egy adott bitet egy regiszterben.
C
#define CLR_BIT(reg, n) ((reg) &= ~(1U << (n)))
Bit-makrók
Írj egy makrót, amely invertálja (toggle-eli) egy adott bit értékét.
C
#define TOGGLE_BIT(reg, n) ((reg) ^= (1U << (n)))
Bit-makrók
Írj egy makrót, amely megvizsgálja, hogy egy adott bit be van-e állítva egy regiszterben.
C
#define CHECK_BIT(reg, n) ((reg) & (1U << (n)))
Bit-makrók
Hogyan írható be egy többbites mező (pl. a CCP1CON<5:4> 2 bites almező) egy regiszterbe úgy, hogy a mezőn kívüli bitek érintetlenek maradjanak?
C
// CCP1CON<5:4> beírása a 'value' (0..3) alapján:
CCP1CON = (CCP1CON & 0xCF) | ((value & 0x03) << 4);
// 0xCF = 0b11001111: a bit5:4 pozíciót nullázza, a többit megtartja
Bit-makrók
Hogyan olvasható ki egy többbites mező (pl. bit 6:4) egy regiszterből, tiszta, jobbra igazított értékként?
C
uint8_t field = (reg >> 4) & 0x07; // bit 6:4 kiemelése és jobbra igazítása
Bit-makrók
Írd le a klasszikus MAX makrót, és nevezd meg a benne rejlő buktatót.
C
#define MAX(a, b) ((a) > (b) ? (a) : (b))
// Buktató: ha 'a' vagy 'b' mellékhatásos kifejezés (pl. i++),
// a makró akár kétszer is kiértékelheti -> a mellékhatás duplán lefut!
// Pl. MAX(i++, j) esetén 'i' kétszer nőhet.
Bit-makrók
Írj egy makrót, amely futásidőben (sizeof alapján) megadja egy statikus tömb elemszámát.
C
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
Bit-makrók
Hogyan cserélhető fel egy bájt két nibble-je (felső 4 bit <-> alsó 4 bit) egyetlen kifejezéssel?
C
uint8_t swapped = (uint8_t)((byte << 4) | (byte >> 4));
Bit-makrók
Hogyan kerekíthető felfelé egy `value` egész szám a legközelebbi `n` többszörösére, tiszta egész aritmetikával?
C
#define ROUND_UP(value, n) (((value) + (n) - 1) / (n) * (n))
// Pl. a 74 dummy SD órajel kerekítése egész bájtokra:
// ROUND_UP(74, 8) == 80 (azaz 10 bájt)
Bit-makrók
Írj egy függvényt, amely egy csomagolt BCD bájtot (pl. 0x59) decimális egész számmá alakít (pl. 59).
C
uint8_t bcd_to_decimal(uint8_t bcd) {
return (uint8_t)((bcd >> 4) * 10 + (bcd & 0x0F));
}
Bit-makrók
Írj egy függvényt, amely egy 0–99 közötti decimális számot csomagolt BCD bájttá alakít.
C
uint8_t decimal_to_bcd(uint8_t decimal) {
return (uint8_t)(((decimal / 10) << 4) | (decimal % 10));
}
Labor Idiómák
Hogyan kell deklarálni egy olyan globális jelzőváltozót, amelyet egy ISR módosít, a main() ciklus pedig olvas?
C
volatile bool data_ready = false;
Labor Idiómák
Hogyan tartható meg egy állapotgép (FSM) belső állapota két függvényhívás között, globális változó bevezetése nélkül?
C
void debounce_task_10ms(void) {
static btn_state_t state = BTN_RELEASED; // megőrzi értékét hívások között
static uint8_t timer = 0;
// ...
}
Labor Idiómák
Deklarálj egy enum típust egy nyomógomb-debounce állapotgéphez.
C
typedef enum {
BTN_RELEASED,
BTN_DEBOUNCE_PRESS,
BTN_PRESSED,
BTN_DEBOUNCE_RELEASE
} btn_state_t;
Labor Idiómák
Hogyan léptethető előre egy körkörös (ring buffer) index biztonságosan, hogy a tömb végén visszaforduljon?
C
uint8_t next_head = (rx_head + 1) % RX_BUFFER_SIZE;
Labor Idiómák
Deklarálj egy függvénypointer típust egy olyan callback számára, amely egy uint8_t paramétert kap és nem tér vissza értékkel.
C
typedef void (*callback_t)(uint8_t data);
callback_t on_byte_received = NULL;
// Meghívás: if (on_byte_received) on_byte_received(received_byte);
Labor Idiómák
Deklarálj egy struktúrát, amely egy 16 elemű mozgóátlag-szűrő teljes állapotát (puffer, index, futó összeg) egyetlen egységben tárolja.
C
typedef struct {
uint16_t buffer[16];
uint8_t idx;
uint32_t sum;
} moving_avg_t;
Labor Idiómák
Hogyan deklarálható egy nagy, csak olvasható lookup tábla úgy, hogy Flash memóriában maradjon és ne foglaljon szűkös SRAM-ot?
C
const uint16_t sine_table[256] = { /* ... */ };
Labor Idiómák
Hogyan állítható össze egy 10 bites PWM/ADC érték két bájtból (8 MSB + 2 LSB) egyetlen 16 bites értékké?
C
uint16_t value10bit = ((uint16_t)msb_8bit << 2) | (lsb_2bit & 0x03);
Labor Idiómák
Hogyan bontható szét egy 16 bites, 10 bites tartalmú érték 8 MSB-re és 2 LSB-re, hardveres PWM regiszterekbe íráshoz?
C
CCPR1L = (uint8_t)(value10bit >> 2);
CCP1CON = (CCP1CON & 0xCF) | ((uint8_t)(value10bit & 0x03) << 4);
Labor Idiómák
Deklarálj egy `bool` visszatérési típusú függvényt, amely egy körkörös pufferből próbál egy bájtot kiolvasni, és jelzi, ha a puffer üres.
C
bool uart_read_byte(uint8_t *byte) {
if (rx_head == rx_tail) return false; // üres a puffer
*byte = rx_buf[rx_tail];
rx_tail = (rx_tail + 1) % RX_BUFFER_SIZE;
return true;
}
Labor Idiómák
Hogyan implementálható egy blokkoló várakozás egy hardveres "busy" biten (pl. ADC GO/DONE), helyes polaritással?
C
ADCON0bits.GO = 1;
while (ADCON0bits.GO_nDONE); // amíg 1 (folyamatban van), várunk
Labor Idiómák
Hogyan deklarálható és inicializálható egy `#define`-nal paraméterezett, fordítási időben ismert méretű tömb egy szűrőhöz?
C
#define FILTER_SIZE 16
static uint16_t buffer[FILTER_SIZE] = {0};
Interjúkérdés
Mit jelent, ha egy változó egyszerre `const` ÉS `volatile`? Mikor van erre szükség?
C
const volatile uint8_t STATUS_REG;
// const: a PROGRAM nem módosíthatja (csak olvashatja).
// volatile: az ÉRTÉK mégis megváltozhat a program tudta nélkül
// (pl. hardver írja) -> a fordító mindig ténylegesen
// újraolvassa, nem cache-eli regiszterben.
// Tipikus eset: csak olvasható hardveres státuszregiszter.
Interjúkérdés
Mi a különbség a `typedef` és a `#define` között egy típus elnevezésénél?
C
typedef unsigned char my_u8_t; // a fordító típusrendszere ismeri
#define MY_U8 unsigned char // csak szöveges csere, nincs típusellenőrzés
typedef my_u8_t *ptr_t; // ptr_t helyesen "unsigned char*" típus
#define PTR_T my_u8_t *
// PTR_T a, b; -> "unsigned char *a, b;" lesz (csak 'a' pointer, 'b' NEM!)
Interjúkérdés
Mutass egy egyszerű példát struct paddingre (kitöltésre), és magyarázd meg, miért keletkezik.
C
struct example {
uint8_t a; // 1 bájt
// 3 bájt kitöltés (padding) a 4 bájtos igazítás miatt
uint32_t b; // 4 bájt
};
// sizeof(struct example) == 8, NEM 5!
// Ok: a CPU hatékonyabban éri el a 4 bájtos adatokat, ha a
// memóriacímük 4-gyel osztható (igazított/aligned hozzáférés).
Interjúkérdés
Hogyan határozható meg futásidőben, kódból, hogy a rendszer Little-Endian vagy Big-Endian?
C
uint16_t x = 1;
bool is_little_endian = (*(uint8_t*)&x == 1);
// Little-Endian esetén a legkisebb helyiértékű bájt (1) van elöl,
// az alacsonyabb memóriacímen -> ezért olvassuk ki 1-esként.
Interjúkérdés
Mi a különbség egy változó deklarációja és definíciója között? Mutasd be `extern`-nel.
C
extern uint8_t counter; // Deklaráció: "ez a változó VALAHOL létezik"
// (pl. egy header fájlban, más .c fájlokból)
uint8_t counter = 0; // Definíció: ténylegesen lefoglalja a tárhelyet
// (pontosan egyszer, egy .c fájlban)
Interjúkérdés
Mit jelent a `static` kulcsszó egy .c fájl (fordítási egység) szintjén deklarált függvénynél vagy globális változónál?
C
static uint8_t internal_counter; // Csak EBBEN a .c fájlban látható,
// más fordítási egységek nem érhetik el
// (belső láncolás / internal linkage).
Interjúkérdés
Írd le a szabványos header include guard mintát, amely megelőzi egy fejlécfájl többszörös beillesztését.
C
#ifndef MY_HEADER_H
#define MY_HEADER_H
// ... deklarációk ...
#endif // MY_HEADER_H
Interjúkérdés
Milyen buktatót rejt a `sizeof` használata egy tömbként átadott függvényparaméternél?
C
void process(uint8_t arr[]) {
size_t size = sizeof(arr); // HIBA: itt 'arr' már csak POINTER!
// sizeof(arr) a pointer méretét adja vissza (pl. 2 bájt PIC18-on),
// NEM a ténylegesen átadott tömb elemszámát.
// A méretet mindig külön paraméterként kell átadni.
}
Interjúkérdés
Miért nem hordozható (implementation-defined) a bitmezők (bitfield) bitsorrendje C-ben, és mi ennek a gyakorlati következménye?
C
struct {
unsigned a:4;
unsigned b:4;
} reg;
// A C szabvány NEM írja elő, hogy 'a' a bájt alsó vagy felső nibble-je
// legyen -- ez fordítófüggő! Ezért a gyártói fejlécek (pl. pic18f4620.h)
// mindig egy konkrét fordítóhoz (pl. XC8) vannak hangolva, és nem
// hordozhatók változtatás nélkül más fordítóra/architektúrára.
Interjúkérdés
Mi a különbség a `&`/`|` (bitwise) és a `&&`/`||` (logikai) operátorok között?
C
if (flag1 & flag2) // Bitenkénti ÉS: attól függ, mely BITEK közösek
if (flag1 && flag2) // Logikai ÉS: csak azt nézi, mindkét oldal NEM NULLA-e
// Példa: flag1 = 0b0101 (5), flag2 = 0b0010 (2)
// (flag1 & flag2) == 0 (nincs közös bit -> hamis érték)
// (flag1 && flag2) == true (mindkettő nem-nulla -> igaz)
Interjúkérdés
Hogyan kombinálható több, egymást nem átfedő bitjelentésű enum "flag" érték egyetlen változóban?
C
typedef enum {
FLAG_NONE = 0,
FLAG_READY = 1 << 0,
FLAG_ERROR = 1 << 1,
FLAG_BUSY = 1 << 2
} status_flags_t;
status_flags_t status = FLAG_READY | FLAG_BUSY; // több flag egyszerre
if (status & FLAG_ERROR) { /* ... */ }
Interjúkérdés
Milyen két klasszikus "undefined behavior" (definiálatlan viselkedés) helyzet fordulhat elő bitléptetésnél (shift)?
C
int x = 1;
int y = x << 32; // UB: a shift mennyisége >= a típus bitszélessége
int z = -1 << 2; // UB: negatív szám balra léptetése (C szabvány szerint)
// Beágyazott rendszerben mindig ellenőrizzük a shift mennyiségét,
// és előjeles típusoknál kerüljük a balra léptetést negatív értéken.
🔍 Nincs találat a keresésre. Próbálj más kulcsszót vagy válts vissza az "Összes" kategóriára!