Не удается отправить последовательные данные из raspberry pi pico ( c sdk )

#c #c #embedded #microcontroller #raspberry-pi-pico

Вопрос:

Я создаю машину с дистанционным управлением, использующую pi pico для управления двигателями и считывания некоторых датчиков, и raspberry pi 4 для отправки команд на pico pi по последовательному каналу и размещения веб-интерфейса.

В настоящее время я тестирую работу серийного устройства от pi pico. Для этого я соединил pi pico с малиной следующим образом:

схема подключения

В настоящее время я использую следующие файлы:

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

главная.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! %cn", ch);
      if(ch != 10){
        uCommand[chars_rxed] = ch;
      }
      printf("Should have added it to uCommand: %sn", uCommand);
      if(uCommand[chars_rxed] == '/'){
        printf("End of the commandn");
        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 somethingn");
   char *foo = queue_dequeue((queue*)tx_queue);
   uart_write_blocking(UART_ID, (char*)foo, 32);
   //printf("%sn", 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 commandn");
          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 '';
    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 для отключения, и когда я отправляю простую команду (через IDE arduino), такую как $MOVE/, я могу правильно ее получить, но не отправлять обратно как последовательную, вместо этого с помощью usb я могу ( printf под uart_write_blocking).
Когда я пытаюсь отправить через uart, я получаю случайные символы в приглашении на серийный номер arduino, и pico также, похоже, получает некоторые из отправленных.

Комментарии:

1. Кроме того, мы обычно не используем динамическое управление памятью во встроенных системах, но это является причиной нескольких утечек памяти и ошибок здесь. strdup() —> вы никогда не освобождаетесь после > dequeue() здесь, кроме освобождения всей реализации очереди. возврат из очереди » ' вместо char* » а». Отправка 32 байтов вместо длины строки, взятой из очереди, или выполняется uart_write_blocking() проверка '' ?

Ответ №1:

Каковы случайные символы в приглашении на серийный номер? и каких персонажей вы ожидаете увидеть?

Третий аргумент (длина) uart_write_blocking жестко закодирован до 32, поэтому эта функция всегда будет пытаться отправить 32 байта обратно в raspberry pi-это может привести к появлению некоторых случайных символов, если строка, которую пытается отправить pico, на самом деле меньше этой. Я бы попробовал изменить этот фрагмент кода на этот и посмотреть, остановит ли это случайные символы.

 printf("Trying to send somethingn");
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