首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在STM32F1蓝丸上发布多个USART连接之间的中继消息

在STM32F1蓝丸上发布多个USART连接之间的中继消息
EN

Stack Overflow用户
提问于 2021-04-22 14:32:08
回答 1查看 201关注 0票数 0

我已经设置了一个STM32F103C8T8和两个模块(SARA和ESP82)在USART连接上。我们目前正在使用libopencm3和FreeRTOS库。

目标

我希望STM将AT命令发送到SARA模块,接收响应并将此消息从SARA模块转发到ESP模块。都是通过USART连接的。

设置说明:

STM连接到USART2上的SARA LTE-M/NB板,ESP8266连接在USART3上。

R412的PWR_ON和RST分别连接到A5和A4。这些都用于电源循环,以正确打开SARA模块。

STM32有一些硬编码命令,这些命令被发送到USART2上的SARA模块,作为回报,应答应该由STM32转发给ESP8266 on USART3。

为了测试目的,ESP没有连接atm,我们只是使用TTL监听相同的USART端口。

下面是TTL到STM连接的图像:

下面是STM到SARA连接的图片( SARA板上的RX和TX被切换):

问题:

当将消息从萨拉转发到ESP8266时,有些事情是不对的。我们正在经历一些连接,在那里消息被正确地传递,但是它是非常不一致的,并且大部分时间它被卡在一个字符上。

我们尝试过的是:我们正在使用TTL连接器和minicom来监听USART连接,看看问题在哪里发生。我们观察到SARA模块正确地接收了来自STM32的命令,并且正确地回答了相应的消息。接下来发生的事情是STM32应该正确地接收消息,但是当侦听USART3 (ESP连接)时,消息有时是正确的,有时是不正确的。

我们也尝试降低波特率,但结果没有差别。

STM32可以很好地在USART2和USART3上发送命令,但是应该中继的答案有时没有正确转发(或者根本不正确)。

我们怀疑问题存在于我们的usart_get_string方法中,该方法将消息从一个USART中继到另一个USART连接:

代码语言:javascript
复制
static void usart_get_string(uint32_t usartSrc, uint32_t usartDst, uint16_t str_max_size)
{
    uint8_t received = 'V';
    uint16_t itr = 0;
    uint8_t recvPrev;

    while (itr < str_max_size)
    {
        if (!((USART_SR(USART2) & USART_SR_RXNE) == 0))
        {
            received = usart_recv_blocking(usartSrc);
        }
        uart_putc(received, usartDst);

        if (recvPrev == 'O' && received == 'K')
        {
            break;
        }
        recvPrev = received;
        uart_putc_blocking(itr, usartDst); // Somehow doesn't work at all without this
        itr++;
    }
}

该方法非常天真,received = usart_recv_blocking(usartSrc);部件可能应该在第一个if -语句中,但是如果这样做,则不会返回任何内容。

包括了完整的代码:

代码语言:javascript
复制
#include <FreeRTOS.h>
#include <task.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/usart.h>

#define MSG_LENGTH 512

static void
uart_setup(void)
{

    // SARA SETUP
    rcc_periph_clock_enable(RCC_GPIOA);
    rcc_periph_clock_enable(RCC_USART2);

    gpio_set_mode(GPIOA,
                  GPIO_MODE_OUTPUT_50_MHZ,
                  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
                  GPIO_USART2_TX);

    usart_set_baudrate(USART2, 115200);
    usart_set_databits(USART2, 8);
    usart_set_stopbits(USART2, USART_STOPBITS_1);
    usart_set_mode(USART2, USART_MODE_TX_RX);
    usart_set_parity(USART2, USART_PARITY_NONE);
    usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
    usart_enable(USART2);

    // ESP SETUP
    rcc_periph_clock_enable(RCC_GPIOB);
    rcc_periph_clock_enable(RCC_USART3);

    gpio_set_mode(GPIOB,
                  GPIO_MODE_OUTPUT_50_MHZ,
                  GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
                  GPIO_USART3_TX);

    usart_set_baudrate(USART3, 115200);
    usart_set_databits(USART3, 8);
    usart_set_stopbits(USART3, USART_STOPBITS_1);
    usart_set_mode(USART3, USART_MODE_TX_RX);
    usart_set_parity(USART3, USART_PARITY_NONE);
    usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
    usart_enable(USART3);
}

static inline void
uart_putc(uint8_t ch, uint32_t usart_port)
{
    usart_send(usart_port, ch);
}

static inline void
uart_putc_blocking(uint8_t ch, uint32_t usart_port)
{
    usart_send_blocking(usart_port, ch);
}

static inline void uart_puts(uint8_t *s, uint32_t usart_port)
{
    while (*s != '\0')
    {
        uart_putc_blocking(*s, usart_port);
        gpio_toggle(GPIOC, GPIO13);
        vTaskDelay(pdMS_TO_TICKS(100));
        s++;
    }
    uart_putc_blocking('\r', usart_port);
    uart_putc_blocking('\n', usart_port);
}


static void usart_get_string(uint32_t usartSrc, uint32_t usartDst, uint16_t str_max_size)
{
    uint8_t received = 'V';
    uint16_t itr = 0;
    uint8_t recvPrev;

    while (itr < str_max_size)
    {
        if (!((USART_SR(USART2) & USART_SR_RXNE) == 0))
        {
            received = usart_recv_blocking(usartSrc);
        }
        uart_putc(received, usartDst);

        if (recvPrev == 'O' && received == 'K')
        {
            break;
        }
        recvPrev = received;
        uart_putc_blocking(itr, usartDst); // Somehow doesn't work at all without this
        itr++;
    }
}

static void
task1(void *args __attribute__((unused)))
{

    uint8_t esp[] = "Hi ESP";
    uint8_t AT[] = "ATI";

    uart_puts(esp, USART3);

    // Power_on Start for SARA module
    vTaskDelay(pdMS_TO_TICKS(500));
    gpio_clear(GPIOA, GPIO5);
    vTaskDelay(pdMS_TO_TICKS(5000));
    gpio_set(GPIOA, GPIO5);

    gpio_set_mode(
        GPIOA,
        GPIO_MODE_OUTPUT_2_MHZ,
        GPIO_CNF_INPUT_FLOAT,
        GPIO4); //RESET_N
    gpio_set_mode(
        GPIOA,
        GPIO_MODE_OUTPUT_2_MHZ,
        GPIO_CNF_OUTPUT_PUSHPULL,
        GPIO5); //PWR_ON

    vTaskDelay(pdMS_TO_TICKS(10000));

    for (;;)
    {
        uart_puts(esp, USART3);
        vTaskDelay(pdMS_TO_TICKS(500));

        uart_puts(AT, USART2);

        usart_get_string(USART2, USART3, MSG_LENGTH);
        vTaskDelay(pdMS_TO_TICKS(10000));
    }
}

int main(void)
{

    rcc_clock_setup_in_hse_8mhz_out_72mhz(); // Blue pill
    // PC13:
    rcc_periph_clock_enable(RCC_GPIOC);
    gpio_set_mode(
        GPIOC,
        GPIO_MODE_OUTPUT_2_MHZ,
        GPIO_CNF_OUTPUT_PUSHPULL,
        GPIO13);

    uart_setup();

    xTaskCreate(task1, "task1", 100, NULL, configMAX_PRIORITIES - 1, NULL);
    vTaskStartScheduler();

    for (;;)
        ;
    return 0;
}

下面是minicom在监听USART3时观察到的输出的一个例子。

我们已经证实,通过与其他模块(如其他ESP)进行交互,布线应该是正确的,而且布线也应该是正确的。电源来自TTL ( 3v3),进入面包板,STM32和SARA R412板从这里获得电源。

编辑:

我按照建议测试了FreeRTOS计时器,但不幸的是无法解决我的问题:

我以以下方式在main方法中创建了一个FreeRTOS计时器:

代码语言:javascript
复制
    timerHndl1 = xTimerCreate(
      "timer1", /* name */
      pdMS_TO_TICKS(400), /* period/time */
      pdFALSE, /* auto reload */
      (void*)0, /* timer ID */
      vTimerCallback1SecExpired); /* callback */

get_string()方法中,我首先重置计时器。更新后的方法如下:

代码语言:javascript
复制
static bool usart_get_string(uint32_t usartSrc, uint32_t usartDst, uint16_t str_max_size)
{
    uint8_t received = 'V';
    uint16_t itr = 0;
    uint8_t recvPrev = 'Q';
    bool timeoutflag;



    // TODO for you: check the UART for error conditions here (like 
    // overrun or framing errors, and clear the errors if any have occurred
    // before we start the receive

    //restart timer:
    if ( xTimerReset(timerHndl1, 10 ) != pdPASS )
    {
        timeoutflag = true;
    }
    else
    {
        timeoutflag = false;
    }

    while ((itr < str_max_size) && (!timeoutflag))
    {
        while ( (!((USART_SR(USART2) & USART_SR_RXNE) == 0)) &&
                (itr < str_max_size) )
        {
            received = usart_recv_blocking(usartSrc);
            uart_putc(received, usartDst);

            if (recvPrev == 'O' && received == 'K')
            {
                return;
            }
            recvPrev = received;
            itr++;
        }


        // if timer times out
        if ( xTimerIsTimerActive(timerHndl1) == pdFALSE )
        {
            timeoutflag = true;
        }
    }

    return !timeoutflag;
}
EN

回答 1

Stack Overflow用户

发布于 2021-04-22 17:12:23

看起来,条件(!((USART_SR(USART2) & USART_SR_RXNE) == 0))再也不是真了。请记住,字符是在有限的时间内接收到的,您必须留出一些时间来接收它们。

我会考虑修改usart_get_string函数如下所示:

代码语言:javascript
复制
// timeout in ms
static bool usart_get_string(uint32_t usartSrc, uint32_t usartDst, uint16_t str_max_size, uint16_t timeout)
{
    uint8_t received = 'V';
    uint16_t itr = 0;
    uint8_t recvPrev;
    bool timeoutflag;

    // TODO for you: check the UART for error conditions here (like 
    // overrun or framing errors, and clear the errors if any have occurred
    // before we start the receive

    // add some code here
    // TODO: start a timer in the RTOS here (using timeout)
    // pseudo code
    Start a timer of "timeout" ms

    timeoutflag = false;

    while ((itr < str_max_size) && (!timeoutflag))
    {
        while ( (!((USART_SR(USART2) & USART_SR_RXNE) == 0)) &&
                (itr < str_max_size) )
        {
            received = usart_recv_blocking(usartSrc);
            uart_putc(received, usartDst);

            if (recvPrev == 'O' && received == 'K')
            {
                return;
            }
            recvPrev = received;
            itr++;
        }

        // psueudo code
        if (RTOS timer has timed out)
        {
            timeoutflag = true;
        }
    }

    return !timeoutflag;
}

我还删除了uart_putc_blocking函数的调用,因为它现在应该工作。(我怀疑这形成了某种延迟,足以让下一个角色被接收到。我还建议对usart_get_string函数进行某种超时。如果发生超时,该函数将返回false。

您可能会考虑的另一个建议:目前您检查字母'O‘和'K',但是您可能希望将usart_get_string例程扩展到\r\n (或调制解调器发送的行序列的任何末端)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67215309

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档