【问题标题】:Cannot send serial data from raspberry pi pico ( c sdk )无法从树莓派 pico (c sdk) 发送串行数据
【发布时间】:2021-10-18 08:18:57
【问题描述】:

我正在制作一台远程控制机器,使用 pi pico 驱动电机并读取一些传感器,并使用 raspberry pi 4 通过串行向 pi pico 发送命令并托管 Web 界面。

我目前正在测试来自 pi pico 的串行操作。为此,我通过以下方式将 pi pico 与覆盆子连接起来:

目前,我正在使用以下文件:

1. main.c to receive and send
2. ring_queue.h where the code for the ring queue is located

main.c

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/irq.h"
#include "ring_queue.h"

#define UART_ID uart0
#define BAUD_RATE 115200
#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


volatile int chars_rxed = 0;
volatile char uCommand[32];
volatile queue *rx_queue;
volatile queue *tx_queue;


void receive_rx(){
    while(uart_is_readable(UART_ID)){
      char ch = uart_getc(UART_ID);
      printf("Got a ch! %c\n", ch);
      if(ch != 10){
        uCommand[chars_rxed] = ch;
      }
      printf("Should have added it to uCommand: %s\n", uCommand);
      if(uCommand[chars_rxed] == '/'){
        printf("End of the command\n");
        queue_enqueue((queue*)rx_queue, (char*)uCommand);
        memset((char*)uCommand, 0, sizeof(uCommand));
        chars_rxed = 0;
        break;
      }
      if(ch != 10) chars_rxed++;
    }
}

void send_tx(){
  if(queue_empty((queue*)tx_queue) == 1){
   return;
 }
 else{
   printf("Trying to send something\n");
   char *foo = queue_dequeue((queue*)tx_queue);
   uart_write_blocking(UART_ID, (char*)foo, 32);
   //printf("%s\n", queue_dequeue((queue*)tx_queue));
 }
}

int main(){

  stdio_init_all();

  memset((char*)uCommand, 0, sizeof(uCommand));
  rx_queue = create_queue(32);
  tx_queue = create_queue(32);

  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, true);

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

  irq_set_exclusive_handler(UART_IRQ, receive_rx);
  irq_set_enabled(UART_IRQ, true);
  uart_set_irq_enables(UART_ID, true, false);

    while (1){
        tight_loop_contents();
        if(queue_size((queue*)rx_queue) != 0){
          printf("Moving from rx to tx to print the received command\n");
          queue_enqueue((queue*)tx_queue, queue_dequeue((queue*)rx_queue));
        }
        send_tx();
      }
}

ring_queue.h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


typedef struct {
    unsigned int tail;      // current tail
    unsigned int head;      // current head
    unsigned int size;      // current number of items
    unsigned int capacity;  // Capacity of queue
    char** data;                // Pointer to array of data
} queue;


queue *create_queue(unsigned int _capacity){
    printf("Malloc!\n");
    queue *myQueue = malloc(sizeof(queue));
    printf("Malloc done!\n");
    if (myQueue == NULL ){
        printf("Malloc failed!\n");
        return NULL;
    }
    else {
        printf("Malloc succeed!\n");
        myQueue->tail = -1;
        myQueue->head = 0;
        myQueue->size = 0;
        myQueue->capacity = _capacity;
        myQueue->data = malloc(_capacity * sizeof(char*));

        return myQueue;
    }
}


int queue_empty(queue *q) {
    if(q == NULL) return -1;
    else if(q->size == 0) return 1;
    else return 0;
}


int queue_full(queue *q) {
    if(q == NULL) return -1;
    else if(q->size == q->capacity) return 1;
    else return 0;
}


int queue_enqueue(queue *q, const char *item) {
    if (q == NULL) return -1;
    else if (queue_full(q) == 1) return 0;
    else {
      q->tail = (q->tail + 1) % q->capacity;
    q->data[q->tail] = strdup(item);
      q->size++;

      return 1;
    }
}

char *queue_dequeue(queue *q) {
    if(q == NULL) return NULL;
    else if(queue_empty(q) == 1) return '\0';
    else {
        char *item = q->data[q->head];
        q->head = (q->head + 1) % q->capacity;
        q->size--;

        return item;
    }
}


unsigned int queue_size(queue *q) {
    if (q == NULL) return - 1;
    else return q->size;
}


void free_queue(queue *q) {
  for(int i = 0; i < q->capacity; i++) free(q->data[i]);
  free(q->data);
    free(q);
}

我正在使用 USB 进行调试,当我发送一个简单的命令(通过 arduino IDE)像 $MOVE / 我可以正确接收它但不能将它作为串行发送回来,而是使用 USB 我可以( printf在 uart_write_blocking 下)。 当我尝试通过 uart 发送时,我在 arduino 串行提示符上得到随机字符,并且 pico 似乎也收到了它发送的一些字符。

【问题讨论】:

  • 此外,我们通常不会在嵌入式系统上使用动态内存管理,但这就是这里出现一些内存泄漏和错误的原因。 strdup() --> 在dequeue() 之后你永远不会释放,除了释放整个队列实现。出队返回 '\0' 而不是 char*。发送 32 个字节而不是从队列中取出的字符串的长度,还是 uart_write_blocking() 正在检查 '\0'

标签: c++ c embedded microcontroller raspberry-pi-pico


【解决方案1】:

串口提示符上的随机字符是什么?你期待什么角色?

uart_write_blockingthird argument (length) 被硬编码为 32,因此此函数将始终尝试将 32 个字节发送回树莓派 - 如果 pico 尝试发送的字符串可能会导致显示一些随机字符发送实际上小于那个。我会尝试将此代码 sn-p 更改为此,看看是否会停止随机字符。

printf("Trying to send something\n");
char *foo = queue_dequeue((queue*)tx_queue);
uart_write_blocking(UART_ID, (char*)foo, strlen(foo)); // only send as many bytes as are in the string

【讨论】:

    猜你喜欢
    • 2022-12-16
    • 2023-01-10
    • 2021-07-29
    • 2022-11-13
    • 2016-12-07
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    相关资源
    最近更新 更多