Проблемы с кодом для отправки запроса и получения ответа через UART на Atmel SAM L21 Xplained Pro

В настоящее время я разрабатываю систему, которая включает отправку строки запроса на сенсорное устройство, подключенное через UART к плате Atmel SAML21 Xplained Pro. Я тестирую плату Arduino в качестве «сенсорного устройства», но в конечном итоге это будет датчик Rotronic HC-2.

Процесс происходит примерно так:

MCU sends string { 99RDD} over UART to sensor
-> delay of up to 500ms
-> Response string of 99 bytes sent back via UART
-> Response transmitted to virtual com port on embedded debugger

Моя проблема в том, что по какой-то причине я либо ничего не возвращаю, либо возвращает переменную request_msg

Я знаю, что ответ от датчика должен быть 99 байтов ASCII, и я проверил как фактический датчик, так и тестовую плату Arduino через последовательные разъемы, чтобы убедиться, что показания возвращаются правильно.

Программное обеспечение использует Atmel ASF v4.0, и это здорово, когда оно работает, но документация довольно ненадежная, поэтому я надеялся, что кто-нибудь с большим опытом сможет указать мне, где я ошибаюсь в коде.

У меня есть следующий код для моего основного приложения:

#include "atmel_start.h"
#include "atmel_start_pins.h"
#include <string.h>

static uint8_t example_hello_world[14] = "Hello World!\n";
static uint8_t example_error_msg[13] = "UART Error!\n";
static uint8_t request_msg[24] = "Sending Sensor Request\n";
static uint8_t rotronic_ascii[8] = "{ 99RDD}";

volatile static uint32_t data_arrived = 0;
volatile static uint32_t reading_received = 0;

static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
    /* Transfer completed */
    gpio_toggle_pin_level(LED0);
}

static void rx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
    /* Receive completed */
    data_arrived = 1;
}

static void err_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
    /* error handle */
    io_write(&EDBG_COM.io, example_error_msg, 13);
}

static void tx_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
    /* Transfer completed */
    gpio_toggle_pin_level(LED0);
}

static void rx_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
    /* Receive completed */
    reading_received = 1;
}

static void err_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
    /* error handle */
    io_write(&COM1.io, example_error_msg, 13);
}

int main(void)
{
    volatile uint8_t recv_char[99];

    atmel_start_init();

    // Setup the EDBG Serial Port
    usart_async_register_callback(&EDBG_COM, USART_ASYNC_TXC_CB, tx_cb_EDBG_COM);
    usart_async_register_callback(&EDBG_COM, USART_ASYNC_RXC_CB, rx_cb_EDBG_COM);
    usart_async_register_callback(&EDBG_COM, USART_ASYNC_ERROR_CB, err_cb_EDBG_COM);
    usart_async_enable(&EDBG_COM);

    // Send a test string to ensure EDBG Serial is working
    io_write(&EDBG_COM.io, example_hello_world, 14);

    // Setup the Rotronic [Arduino] Serial Port
    usart_async_register_callback(&COM1, USART_ASYNC_TXC_CB, tx_cb_COM1);
    usart_async_register_callback(&COM1, USART_ASYNC_RXC_CB, rx_cb_COM1);
    usart_async_register_callback(&COM1, USART_ASYNC_ERROR_CB, err_cb_COM1);
    usart_async_enable(&COM1);

    while (1) {
        if (reading_received == 0)
        {
            // Delay for a Bit
            delay_ms(5000);

            // Notify the EDBG COM Port
            io_write(&EDBG_COM.io, request_msg, 24);

            // Send the Rotronic ASCII
            io_write(&COM1.io, rotronic_ascii, 8);
        }

        // Check if Reading has been Received
        if (reading_received == 1)
        {
            while (io_read(&COM1.io, &recv_char, 99) == 99)
            {
                // Write what's on the buffer from the receiver
                io_write(&EDBG_COM.io, recv_char, 99);
            }

            // Reset the flag
            reading_received = 0;
        }
    }
}

person Andy Mills    schedule 13.01.2017    source источник
comment
delay_ms(5000) не должен ждать полсекунды   -  person tofro    schedule 13.01.2017


Ответы (1)


Вы, кажется, кодируете для ASFv3 - v4 будет запускать ваш обратный вызов для любых входящих байтов, а не только один раз, когда ваш буфер заполнен (и вы получили каждые 99 символов).

Это означает, что io_read, скорее всего, никогда не вернет 99 (потому что это было лишь частичное чтение вашего сообщения), и вы, скорее всего, никогда ничего не отправите обратно.

Обратите внимание, что документы говорят (Прокрутите вниз до «различного поведения функции чтения...»):

В ASFv4 обратный вызов типа приема данных в драйвере с кольцевым буфером запускается для каждых полученных данных.

UART, по-видимому, является драйвером с кольцевым буфером.

Вам нужно неоднократно вызывать io_read и суммировать количество полученных байт, пока не получите 99. Только после этого продолжайте. В документации ASF есть пример для этого. Убедитесь, что вы скопировали оттуда код, который соответствует вашей версии.

person tofro    schedule 13.01.2017
comment
У вас есть ссылка на этот документ? Кажется, я смотрел старую документацию. Также спасибо за ответ! Завтра проверю и отмечу этот ответ как правильный :) - person Andy Mills; 14.01.2017
comment
Ссылка на цитату вставлена ​​выше. - person tofro; 14.01.2017