predpostavimo, da nam deluje npr. UART, ki sprejema in oddaja znake preko dveh funkcij:
- Koda: Izberi vse
int32_t GetChar (); // vrne -1, če ni noben znak na voljo, sicer pa 8 bitno kodo sprejetega znaka
PutChar(int32_t znak); // pošlje znak
Uporaba 32 bitnih predznačenih vrednosti za 8 bitne znake je sicer precej redundančna zadeva, vendar pri uporabi 32 bitnih ARM mikrokontrolerjev to ne igra vloge. Elegantno rešimo tudi razpoložljivost novega znaka z ne-negativno vrednostjo. Vse negativne vrednosti pa lahko predstavljajo status. Na tak način ne potrbujemo dodatnih funkcij, kot npr. "NewCharAvailable()" ali kaj podobnega.
Sprejem znakov teče ponavadi znotraj glavne neskončne zanke, če uporabljamo RTOS, pa je ponavadi to eno od opravil (task), oz. niti (thread).
V samo zanko lahko dodamo še preprost linijski urejevalnik vnosne vrstice, tako da je obdelan tudi backspace in simbola za programski nadzor pretoka. Najprej si določimo nekaj nadzornih znakov, da bo koda preglednejša:
- Koda: Izberi vse
#define CNTLQ 0x11
#define CNTLS 0x13
#define DEL 0x7F
#define BACKSPACE 0x08
#define CR 0x0D
#define LF 0x0A
ter določimo max. dolžino ukazne vrstice in parametrov ukaza (RAM na sodobnih mikrokontrolerjih ni več hud problem in si lahko "privoščimo"). Rezerviramo tudi pomnilnik za oboje.
- Koda: Izberi vse
#define MAX_CMD_LEN 40
/** Pomnilnik za ukazno vrstico in argumente */
static char cmdstr_buf [1 + MAX_CMD_LEN];
static char argstr_buf [1 + MAX_CMD_LEN];
"Urejevalnik" ukazne vrstice sedaj zgleda takole:
- Koda: Izberi vse
int rx_char;
char line_buf[2*MAX_CMD_LEN]; // Potrebujemo dvojno dolzino: za ukaz in za argumente
int line_idx = 0;
while (1)
{
rx_char = GetKey();
while (rx_char>0)
{
if (rx_char == CR) rx_char = LF;
if (rx_char == BACKSPACE || rx_char == DEL)
{ // uporabnik se je zmotil
if (line_idx != 0)
{
line_idx--; // zmanjsajmo index
SendChar (BACKSPACE); // izpisi backspace na terminal
SendChar (' ');
SendChar (BACKSPACE);
}
}
else
{ // Znak je OK
SendChar (rx_char); // echo
line_buf[line_idx++] = rx_char; // shrani znak in povecaj index
}
// preveri, ali smo na koncu bufferja in ce je prisel CR/LF
if ((line_idx == 0xff) || (rx_char == LF))
{
line_buf[line_idx-1] = 0; // Oznacimo se konec stringa
line_idx = 0;
cmd_proc(line_buf); // zazeni masinerijo za obdelavo vrstice
}
rx_char = GetKey();
}
// ....... Tu naredi se kaj drugega ..........
}