Forum: Mikrocontroller und Digitale Elektronik Implementierung TUI über UART mit HAL für STM32F1xx


von Johan (arm-programmer)


Lesenswert?

Hallo Leute! Ich bin neu hier und brauch Hilfe.

Note: Deutsch ist nicht meine Muttersprache. Danke

Ich entwickle eine App mit ASCII-TUI über UART mit HAL für STM32F1xx. 
Ich möchte, damit dieses Modul nächste Punkte könnte:
- Nicht-blockierende I/O (durch Interrupten)
- Backspace löscht letztes Zeichen, wenn es solches gibt
- Bücher und Nummern sind sichtbar (echo)
- Enter beendet I/O

Dabei sollte die App auch mit Interrupten (nur HAL) und Circularbuffer 
implementiert sein. Das Circularbuffer stellt einen Library dar.

Mein Code:
```
static UART_HandleTypeDef *console_uart = NULL;
static char line_buffer[CONSOLE_MAX_RX_DATA_LENGTH];
static uint16_t line_len = 0;

// TX Buffer
static ring_buffer_t tx_buffer;
static volatile uint8_t tx_busy = 0;
static volatile uint8_t tx_byte;

// RX Buffer
static ring_buffer_t rx_buffer;
static volatile uint8_t rx_byte;
static volatile uint8_t rx_ready = 0;

static void console_rx_callback(UART_HandleTypeDef *);
static void console_tx_callback(UART_HandleTypeDef *);

uint8_t console_init(UART_HandleTypeDef *huart) {
    if (huart == NULL || console_uart != NULL) {
        return 1;
    }

    console_uart = huart;

    ring_buffer_init(&tx_buffer);
    tx_busy = 0;

    ring_buffer_init(&rx_buffer);
    rx_ready = 0;

    HAL_UART_RegisterCallback(
        console_uart,
        HAL_UART_RX_COMPLETE_CB_ID,
        console_rx_callback
    );

    HAL_UART_RegisterCallback(
        console_uart,
        HAL_UART_TX_COMPLETE_CB_ID,
        console_tx_callback
    );

    HAL_UART_Receive_IT(console_uart, (uint8_t *) &rx_byte, 1);
    return 0;
}

void console_print(const char *str) {
    HAL_UART_Transmit(console_uart, (uint8_t *) str, strlen(str), 10);
    // ring_buffer_write(&tx_buffer, (uint8_t *) str, strlen(str));

    // if (tx_busy == 0) {
    //     tx_busy = 1;
    //     tx_byte = ring_buffer_pop(&tx_buffer);
    //     HAL_UART_Transmit_IT(console_uart, &tx_byte, 1);
    // }
}

void console_clear() {
    console_print("\033[2J\033[H");
}

// Берет на себя всю обработку символов: backspace, enter и echo
void console_poll() {
    while (ring_buffer_get_length(&rx_buffer) > 0 && rx_ready == 0) {
        uint8_t ch = ring_buffer_pop(&rx_buffer);
        if ((ch == '\b' || ch == 0x7F) && line_len > 0) {
            line_len--;
            console_print("\b \b");
        }
        else if (ch == '\r' || ch == '\n') {
            line_buffer[line_len] = '\0';
            rx_ready = 1;
            console_print("\r\n");
            return;
        }
        else if (line_len < CONSOLE_MAX_RX_DATA_LENGTH - 1) {
            line_buffer[line_len++] = ch;
            char echo[2] = {ch, 0};
            console_print(echo);
        }
    }
}

uint8_t console_ready() {
    return rx_ready;
}

void console_read(char *buffer) {
    if (buffer == NULL || rx_ready == 0) {
        return;
    }

    strcpy(buffer, line_buffer);
    rx_ready = 0;
    line_len = 0;
    line_buffer[0] = '\0';
}

static void console_tx_callback(UART_HandleTypeDef *console) {
    if (ring_buffer_get_length(&tx_buffer) == 0) {
        tx_busy = 0;
    }
    else {
        tx_byte = ring_buffer_pop(&tx_buffer);
        HAL_UART_Transmit_IT(console_uart, &tx_byte, 1);
    }
}

static void console_rx_callback(UART_HandleTypeDef *console) {
    ring_buffer_push(&rx_buffer, rx_byte);
    HAL_UART_Receive_IT(console_uart, &rx_byte, 1);
}
```

Man benutzt es so:
```
while(1) {
    console_poll();
    if (console_ready()) {
        console_read(consoleBuffer);
        // Действия с console buffer
    }
}
```

Während der Verbindung über UART (115200 Baud), schreibt der Program 
etwas schlechtes (das ist ein Teil des Menü in der App):
```
Rebooeot system
?. menu
cm>>
Unknoan
oy en
symenu
cm
```

Richtig Output ist:
```
cmd>? <--- das ist mein Input
Reboot. Reboot system
?. Display menu

Wenn es unbekannt Kommand ist, schreibt der Program "Unknown command"
```

Bitte, erklären mir, was hier falsch ist und warum der Program nicht 
korrekt funktioniert. Das ChatGPT hilft mir nicht, DMA will ich jetzt 
nicht benutzt.

Danke für eure Hilfe!

von Harry L. (mysth)


Lesenswert?

Schau mal hier:
Beitrag "Re: [STM32/HAL] simples U(S)ART-Library"

Johan schrieb:
> - Nicht-blockierende I/O (durch Interrupten)
Macht mein Code so.
> - Backspace löscht letztes Zeichen, wenn es solches gibt
Kann der Code im Line-Mode. (zur Laufzeit umschaltbar auf Char-Mode)
> - Bücher und Nummern sind sichtbar (echo)
Ebenfalls vorhanden und ggf. abschaltbar.
> - Enter beendet I/O
Auch dabei...

von Nemopuk (nemopuk)


Lesenswert?

Johan schrieb:
> Das ChatGPT hilft mir nicht

Dann hast du ein Problem, denn es geht nicht. In Zukunft werden wir auf 
viele tolle Programme verzichten müssen, weil die KI sie nicht bauen 
kann.

von Wastl (hartundweichware)


Lesenswert?

Johan schrieb:
> Mein Code:

----> Wichtige Regeln - erst lesen, dann posten!
    .............
    Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

von Johan (arm-programmer)


Lesenswert?

Okay, danke

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.