Comparación entre uint8_t y String

Tengo una pregunta muy fundamental con respecto a la comparación de cadenas.

Implementé un USART a PC con placa Nucleo STM32L0, y puedo escribir algo en la terminal y recibirlo en el micro de la siguiente manera:

#define RXBUFFERSIZE 1
uint8_t aRxBuffer[RXBUFFERSIZE];

/** Put UART peripheral in reception process */
  if(HAL_UART_Receive(&huart2, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 0xFFFF) != HAL_OK)
    Error_Handler(); 

Quiero comparar los datos recibidos con una cadena, pero la comparación no funciona.

char *is_correct= "Y";
if (strcmp((char*) aRxBuffer, is_correct) == 0)
    DoSomething();
else
    DoSomethingElse();

¿Qué estoy haciendo mal? Gracias

Cómo configuro el USART:

/* USART2 init function */
void MX_USART2_UART_Init(void)
{

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 9600;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  HAL_UART_Init(&huart2);

}

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART2)
  {
    /* Peripheral clock enable */
    __USART2_CLK_ENABLE();

    /**USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  }

}
No ha mostrado todo el código relevante, pero una cosa es porque aRxBuffertiene un byte de longitud y no puede ser una cadena terminada en nulo.
@PeterJ ese es probablemente el problema, el RxBuffer está en algún lugar de la memoria y, dependiendo de las cosas detrás de él, será una cadena de longitud aleatoria.
@PeterJ Gracias. ¿Cómo convierto aRxBuffer en una cadena?
messagetodavía está fuera del alcance de los respondedores, el problema también podría estar relacionado con eso.
Si los datos recibidos no están destinados a ser terminados en nulo, entonces debe usar memcmpen lugar de strcmp, que solo requiere el tamaño de las áreas de memoria para comparar. Tenga en cuenta que el tamaño debe ser el tamaño de los datos que obtiene, no de todo el búfer (si no son iguales).
Oh, no es un terrible error, el 'mensaje' debería ser is_correct. Pero en cualquier caso, la respuesta de @PeterJ es perfecta.

Respuestas (3)

Para la strcmpfunción y todas las demás funciones de cadena, la cadena debe terminar en nulo. Para su ejemplo, una forma de hacerlo sería algo como lo siguiente para asignar un byte adicional en la matriz y poner un terminador nulo al final:

#define RXBUFFERSIZE 1
uint8_t aRxBuffer[RXBUFFERSIZE + 1];
if(HAL_UART_Receive(&huart2, (uint8_t *)aRxBuffer, RXBUFFERSIZE, 0xFFFF) != HAL_OK)
    ....
aRxBuffer[RXBUFFERSIZE] = 0;

Aunque para una comparación de un solo carácter como la que tiene en este momento no hay necesidad de una comparación de cadenas, podría usar una comparación de caracteres en el primer y único elemento de la matriz:

if (aRxBuffer[0] == 'Y')
    DoSomething();
else
    DoSomethingElse();

El strcmp necesita un terminador nulo, pero hay otra función que puede usar para comparar cadenas, que es strncmp , que toma la cantidad de caracteres que desea comparar. Así que podrías terminar haciendo:

char *is_correct= "Y";
if (strncmp((char*) aRxBuffer, message,strlen(message) ) == 0)
    DoSomething();
else
    DoSomethingElse();

Esto también supone que la messagevariable es una cadena fija.

Sin embargo, tenga cuidado: strncmpno es un reemplazo directo para strcmp. Por ejemplo, strncmp("YB", "YA", 1)dirá que las cadenas coinciden. Eso podría estar bien, pero también podría ser una trampa.

¿Por qué molestarse con strcmp o strncmp mientras simplemente puede hacer esto?

uint8_t aRxBuffer;
#define RXBUFFERSIZE (sizeof(aRxBuffer))

if(HAL_UART_Receive(&huart2, (uint8_t *)&aRxBuffer, RXBUFFERSIZE, 0xFFFF) != HAL_OK)
    Error_Handler();

if(aRxBuffer == message)
   DoSomething();
else
   DoSomethingElse(); 
¿ Cuál es el punto de lanzar pointer to uint8_tto pointer to uint8_t?
¿Quizás porque el otro enfoque es más fácil de escalar a una contraseña o algo así?
@Ruslan &aRxBufferno es un puntero sino un constpuntero y, según la firma de HAL_UART_Receive, no puede ingresar un constpuntero, por lo que debe descartarlo. (Sin embargo, el método debería usar un constpuntero)
@Arsenal bueno, la primera línea declara aRxBufferser uint8_t, no const uint8_t, por lo que el puntero no es un puntero a const ni puntero const. Aunque ahora veo que esto es solo una copia del OP, no el error de Alex.
@Ruslan no importa mi comentario, no sé lo que estaba mirando, probablemente inducido por las pelusas actuales para constla corrección ...
Aparte del elenco peculiar, no entiendo por qué esto está perdiendo votos. Si solo espera un solo carácter, no hay necesidad de inflar su código con numerosas funciones de manejo de cadenas. El sentido común es una herramienta muy útil a la hora de programar.
Es un estilo de codificación realmente malo... Me lo merezco...