SPI en palabra extra - STM32F4

3

Estoy intentando establecer una interfaz con el TLE5012B (hoja de datos ) utilizando SPI. El maestro en este caso es un Nucleo F411RE, que utiliza un procesador STM32F4. El sensor se comunica en palabras de 16 bits, así que configuro el chip en Cube como se muestra (algunos otros periféricos que no se utilizarán en el código de esta pregunta también están activados):

Parecíaquetodoibabien,perosurgióunproblemacuandonotéqueSCLKhabíaregistradounapalabraadicionalcuandonoserecibíanadadelalíneadedatos,loquedabacomoresultadounpícaro0x0000sealmacenaenelbúfer,loquedesordenalaslecturasfuturas.

Aquíestámicódigo:

#include"app_main.h"
#include "stm32f4xx_hal.h"
#include <stdint.h>

extern SPI_HandleTypeDef hspi2;


uint16_t command = 0x8088;
uint16_t safety = 0;
uint16_t data1[8];

int app_main()
{
    HAL_Delay(1000);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
    HAL_Delay(1);
    HAL_SPI_Transmit(&hspi2, (uint8_t *)(&command), 1, 0xFF);
    HAL_SPI_Receive(&hspi2, (uint8_t*)data1, 8, 0xFF);
    HAL_SPI_Receive(&hspi2, (uint8_t *)(&safety), 1, 0xFF);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
    HAL_Delay(1);

    while (1) {
    }
    return 0;
}

Y esto es lo que sucede en el SPI, leer usando un analizador lógico (las líneas en orden descendente son CS, MOSI / DATA, SCLK, CS cae bajo / se establece alto fuera del área ampliada):

Comosepuedeverenelcódigo,deberíaesperarenviarunapalabrayrecibir8másunapalabradeseguridad;sinembargo,seestánsincronizando10palabras,conelúltimo0x0000debidoaquenohaydatosenlalínea,queluegopermanecebajadurantealgúntiempo.

Paratenerunamejorideadeloqueestabapasando,modifiquéligeramentemicódigo:

#include"app_main.h"
#include "stm32f4xx_hal.h"
#include <stdint.h>

extern SPI_HandleTypeDef hspi2;


uint16_t command = 0x8088;
uint16_t safety = 0;
uint16_t data1[8];

int app_main()
{
    HAL_Delay(1000);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
    HAL_Delay(105);
    HAL_SPI_Transmit(&hspi2, (uint8_t *)(&command), 1, 0xFF);
    HAL_Delay(75);
    for(int i = 0; i < 8; i++)
    {
        HAL_Delay(15);
        HAL_SPI_Receive(&hspi2, (uint8_t*)&data1[i*2], 1, 0xFF);
    }
    HAL_Delay(50);
    HAL_SPI_Receive(&hspi2, (uint8_t *)(&safety), 1, 0xFF);
    HAL_Delay(10);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);

    while (1) {
    }
    return 0;
}

Esto produjo el siguiente resultado:

Desdeladistancia,estoparececorrecto;8palabrasrecibidasdevuelta,máslaseguridad.Alacercarse,sinembargo,elproblemasehacevisible;latransmisióndelcomandoestábien:

Sinembargo,laprimerapalabrarecibidanoesunapalabra,sinodosgrabadasalavezporSCLK:

Mientrasquelassiguientespalabrasestánbien:

Loquepareceestarhaciendoestadoblepalabraesempujarelbúferderecepciónantesdeloquerealmenteseestáleyendo,esdecir,cuandolapalabradeseguridaddebeleerse,seagrega0x0000albúfer,yaquelapalabradeseguridadyarecibidoyalmacenado.

Podría valer la pena notar que algunos de los retrasos son un poco más pequeños / grandes de lo que deberían ser, pero mi pregunta es, ¿qué podría estar causando que se lea esta palabra doble? Intenté cambiar el periférico SPI al modo de 8 bits en lugar de 16; esto no solucionó el problema, simplemente hizo que la palabra adicional fuera de 8 bits en lugar de 16. Ejecutar un código similar en un procesador F3 también dio resultados incorrectos. El TLE no puede conducir la línea SCLK, por lo que debe ser el micro que está haciendo algo mal, pero no puedo, por mi vida, averiguar qué.

EDITAR: Hice algunos problemas con los cables y configuré el STM en dúplex completo con una resistencia en la línea MOSI. Esto solucionó el problema, pero no me dice qué lo causó en primer lugar. ¿Half-duplex tiene algún protocolo extraño que no conozco?

    
pregunta Isaac Middlemiss

1 respuesta

4

el acuerdo básico con el modo semidúplex es que va a funcionar hasta que se desactive la marca SPE en SPI_CR1. El HAL_SPI_Receive no desactiva esto hasta que recibe un byte. Cuando llega el momento de desactivar este indicador, la próxima transferencia ya ha comenzado.

Para recibir correctamente la cantidad de bytes que desea, utilizando el modo semidúplex, siga el procedimiento en 20.3.8 del manual de referencia. El esquema básico es:

  1. Espere a que el segundo se produzca por última vez de RXNE = 1 (n-1) (fin de los datos1)
  2. Espere un ciclo de reloj SPI y luego deshabilite SPE (SPE = 0) (al comienzo del byte rx de seguridad).
  3. Luego espere el último RXNE = 1 y su último byte lo está esperando en el registro. (agarra el byte de seguridad).

En una nota más general, los HAL proporcionados por los fabricantes son bastante buenos para comenzar, pero generalmente no cubren todos los casos posibles. Es mejor utilizarlo como punto de partida o sugerencia, especialmente si no hace exactamente lo que quiere que haga.

    
respondido por el pgvoorhees

Lea otras preguntas en las etiquetas