首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用raspberry pi pico uart和c sdk的奇怪之处

使用raspberry pi pico uart和c sdk的奇怪之处
EN

Stack Overflow用户
提问于 2021-08-11 19:28:37
回答 1查看 1.6K关注 0票数 1

我非常不安。

我正在制作一台遥控机器,使用pi pico驱动马达并读取一些传感器,并使用raspberry pi 4通过串行和主机网络接口向pi pico发送命令。

下面的代码似乎有效..。但是..。如果我用uart_is_writable编码和它的内容删除If,它就不能工作。有人知道为什么吗?

代码语言:javascript
运行
复制
#include <stdlib.h>
#include <string.h>

#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"

//DEFINES
#define UART_ID uart0
#define BAUD_RATE 19200
#define DATA_BITS 8
#define STOP_BITS 1
#define PARITY    UART_PARITY_NONE
#define UART_TX_PIN 0
#define UART_RX_PIN 1
#define LED_PIN PICO_DEFAULT_LED_PIN

static int chars_rxed = 0;

volatile char uCommand[32] = {0, 0};

void on_uart_rx(void) {
   char tmp_string[] = {0, 0};
   new_command = true;
   while (uart_is_readable(UART_ID)) {
       uint8_t ch = uart_getc(UART_ID);
       tmp_string[0] = ch;
       strcat(uCommand, tmp_string);
       if(uart_is_writable(UART_ID)){
         uart_putc(UART_ID, '-');
         uart_puts(UART_ID, uCommand);
         uart_putc(UART_ID, '-');
       }
       chars_rxed++;
   }
}

int main(){

 uart_init(UART_ID, BAUD_RATE);

 gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
 gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);

 uart_set_hw_flow(UART_ID, false, false);

 uart_set_format(UART_ID, DATA_BITS, STOP_BITS, PARITY);

 uart_set_fifo_enabled(UART_ID, false);

 int UART_IRQ = UART_ID == uart0 ? UART0_IRQ : UART1_IRQ;

 irq_set_exclusive_handler(UART_IRQ, on_uart_rx);
 irq_set_enabled(UART_IRQ, true);

 uart_set_irq_enables(UART_ID, true, false);

 uart_puts(UART_ID, "\nOK\n");

   while (1){
       tight_loop_contents();
       if(uCommand[0] != 0){
         uart_putc(UART_ID, '/');
         uart_puts(UART_ID, uCommand);
         memset(uCommand, 0, sizeof(uCommand));
       }
     }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-11 21:52:04

链接到的示例代码用于一个简单的tty/echo实现。

您需要为用例调整它。

由于Tx中断被禁用,发送到发射机的所有输出都必须被轮询I/O。此外,uart中的FIFO也被禁用,因此只使用单个字符I/O。

因此,uart_is_writable检查一个字符是否可以传输。

链接密码..。

echos返回Rx ISR中接收到的字符。因此,它需要调用上述函数。请注意,如果Tx尚未准备好(即已满),则不会回显该字符并将其删除。

我不知道uart_putcuart_puts是否以这种方式检查是否可以随时传送.

所以,我会假设他们没有。这意味着,如果调用uart_putc/uart_puts,而Tx已满,则uart中的当前/未决字符可能会被破坏/损坏。

因此,应该调用uart_is_writable来发送任何/每个字符。

或者. uart_putc/uart_puts会检查并阻塞,直到uart中的空间可用为止。对于用例来说,这样的阻塞是不可取的。

你想要的..。

附带注意:我在RPi上做了类似的产品/商业级编程,通过uart控制电机,所以其中一些是我自己的经验。

对于您的用例,您不希望回显接收到的字符。您希望将其附加到接收缓冲区中。

要实现这一点,您可能需要使用环形队列:一个用于接收的字符,另一个用于要传输的字符。

我假设您已经或将要设计某种简单的数据包协议来发送/接收命令。Rpi发送的命令如下(例如):

  1. 设置电机速度
  2. 获取电流传感器数据

另一方应响应这些命令并执行所需的操作或返回所需的数据。

这两个处理器可能都需要有类似的服务循环和ISR。

Rx ISR只检查Rx环队列中可用的空间。如果空间可用,它将从uart获取一个char并对其进行排队。如果在uart中没有Rx char可用,则ISR可能退出。

基本级别的代码服务循环应该:

  1. 检查uart是否可以接受另一个字符(通过uart_is_writable),如果可以的话,它可以从Tx环队列中排出一个char并发送它(通过uart_putc)。它可以对此进行循环,以使uart发射机保持忙碌。

  1. 检查是否接收到足够多的字符以形成来自另一方的数据包/消息。如果有这样的包,它可以为包含在其中的“请求”服务,使字符排队,以便在Rx环队列中腾出更多的空间。

如果基本级别需要发送消息,则

  1. 应该将消息排队到Tx环队列中。它最终将在前面的步骤中发送。

一些额外的想法..。

链接代码只允许Rx中断并在轮询模式下运行Tx。这可能就够了。但是,为了最大的吞吐量和最低的延迟,您可能希望Tx中断也是驱动的。

您也可能希望启用uart中的FIFO,这样您就可以对多个字符进行排队。这可以减少对ISR的调用次数,并提供更好的吞吐量/延迟,因为服务循环不必频繁轮询。

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

https://stackoverflow.com/questions/68747899

复制
相关文章

相似问题

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