我非常不安。
我正在制作一台遥控机器,使用pi pico驱动马达并读取一些传感器,并使用raspberry pi 4通过串行和主机网络接口向pi pico发送命令。
下面的代码似乎有效..。但是..。如果我用uart_is_writable编码和它的内容删除If,它就不能工作。有人知道为什么吗?
#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));
}
}
}
发布于 2021-08-11 21:52:04
链接到的示例代码用于一个简单的tty/echo实现。
您需要为用例调整它。
由于Tx中断被禁用,发送到发射机的所有输出都必须被轮询I/O。此外,uart中的FIFO也被禁用,因此只使用单个字符I/O。
因此,uart_is_writable
检查一个字符是否可以传输。
链接密码..。
echos返回Rx ISR中接收到的字符。因此,它需要调用上述函数。请注意,如果Tx尚未准备好(即已满),则不会回显该字符并将其删除。
我不知道uart_putc
和uart_puts
是否以这种方式检查是否可以随时传送.
所以,我会假设他们没有。这意味着,如果调用uart_putc/uart_puts
,而Tx已满,则uart中的当前/未决字符可能会被破坏/损坏。
因此,应该调用uart_is_writable
来发送任何/每个字符。
或者. uart_putc/uart_puts
会检查并阻塞,直到uart中的空间可用为止。对于用例来说,这样的阻塞是不可取的。
你想要的..。
附带注意:我在RPi上做了类似的产品/商业级编程,通过uart控制电机,所以其中一些是我自己的经验。
对于您的用例,您不希望回显接收到的字符。您希望将其附加到接收缓冲区中。
要实现这一点,您可能需要使用环形队列:一个用于接收的字符,另一个用于要传输的字符。
我假设您已经或将要设计某种简单的数据包协议来发送/接收命令。Rpi发送的命令如下(例如):
另一方应响应这些命令并执行所需的操作或返回所需的数据。
这两个处理器可能都需要有类似的服务循环和ISR。
Rx ISR只检查Rx环队列中可用的空间。如果空间可用,它将从uart获取一个char并对其进行排队。如果在uart中没有Rx char可用,则ISR可能退出。
基本级别的代码服务循环应该:
uart_is_writable
),如果可以的话,它可以从Tx环队列中排出一个char并发送它(通过uart_putc
)。它可以对此进行循环,以使uart发射机保持忙碌。。
。
如果基本级别需要发送消息,则
一些额外的想法..。
链接代码只允许Rx中断并在轮询模式下运行Tx。这可能就够了。但是,为了最大的吞吐量和最低的延迟,您可能希望Tx中断也是驱动的。
您也可能希望启用uart中的FIFO,这样您就可以对多个字符进行排队。这可以减少对ISR的调用次数,并提供更好的吞吐量/延迟,因为服务循环不必频繁轮询。
https://stackoverflow.com/questions/68747899
复制相似问题