STM32 SPI SCLK deja de marcar

0

Tengo STM32L052K8T6 (maestro) y estoy tratando de comunicarme con AD7124-4 ADC (esclavo) a través de SPI. Mi problema es que STM deja de transmitir los pulsos de reloj en SCLK inmediatamente después de transferir todos los datos desde el búfer tx (verificado en el osciloscopio externo) e ignora la solicitud de esperar una respuesta hasta que expire el tiempo de espera. El esclavo no tiene oportunidad de responder cuando no tiene reloj para sincronizar.

Mi inicio:

void initSPI (void)
{
GPIO_InitTypeDef GPIO_InitStructure;

__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_SPI1_CLK_ENABLE();

//GPIO - MOSI, MISO, CLK
GPIO_InitStructure.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF0_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

HAL_NVIC_SetPriority(SPI1_IRQn, 1, 1);
HAL_NVIC_EnableIRQ(SPI1_IRQn);

hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;

if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
    ErrorHandler();
}

HAL_SPI_MspInit(&hspi1);

__HAL_SPI_ENABLE(&hspi1);
}

Estoy llamando a esta función:

void SendReceiveData ()
{
    uint8_t tx = 64;
    while (hspi1.State != HAL_SPI_STATE_READY);
    HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 1, 10000);
}

Incluso cuando tengo un tiempo de espera largo, se ignora.

HAL_SPI_TransmitReceive () devuelve HAL_OK.

¿Hay algún problema en mi inicialización?

    
pregunta Jardo421

3 respuestas

0

Gracias chicos.

Combiné ambas respuestas a la solución de trabajo. Debido a que el ADC (esclavo) espera un comando y responde después, tuve que obligar a SCLK a seguir "marcando". La comunicación no funciona en ambos sentidos al mismo tiempo en este caso. Envío un carácter 0xFF (el esclavo lo ignora) después de un comando válido para mantener MOSI en lógica alta y funcionando el reloj. Envío tantos caracteres 0xFF como espero como respuesta y funciona. No es la mejor solución, sino la que funciona.

    
respondido por el Jardo421
4

Creo que entendiste mal la funcionalidad de la función HAL_SPI_TransmitReceive . No transmite primero el búfer tx y luego recibe el búfer de rx. Hace ambas cosas al mismo tiempo. Después de todo SPI es un protocolo dúplex completo. Puede transmitir (desde MOSI) y recibir (MISO) al mismo tiempo.

Para lograr lo que desea en una llamada a una sola función, debe usar buffers de tamaño 2 . Así:

    HAL_SPI_TransmitReceive(&hspi1, &tx, &rx, 2, 10000);

No importa lo que haya en el segundo byte del búfer de TX (tx [1]) o lo que lea en el primer byte del búfer RX (rx [0]). Solo asegúrese de poner los datos correctos en tx [0] y tome los datos recibidos de rx [1] e ignore el resto.

PD: no he comprobado la hoja de datos del dispositivo esclavo que mencionaste. Algunos dispositivos comienzan a enviar datos en el primer ciclo de reloj. Asegúrate de que entiendes el protocolo correctamente.

    
respondido por el HeyYO
3

Es estándar que el SCLK se detenga cuando un dispositivo no está transmitiendo, porque SCLK generalmente fuerza la comunicación en ambas direcciones. En este caso, el ADC solo tiene comunicación en una dirección a la vez, ya sea que el dispositivo recibió un comando o envía datos, y lo ilustraron de manera deficiente.

Debe enviar algunos datos nulos después de su comando para forzar la activación del reloj. Parece que la hoja de datos recomienda enviar 0, pero no está claro si el dispositivo presta atención a los datos.

Si el ADC desea un tiempo específico entre sus bytes de comando y los datos, es posible que deba tomar el control manual de la línea CS para que pueda mantenerlo bajo mientras se demora.

    
respondido por el pscheidler

Lea otras preguntas en las etiquetas