ADS1234 y STM32L

Estoy intentando usar el periférico SPI2 en el microcontrolador STM32L471RG para comunicarme con el ADS1234 y quería compartir mis pensamientos con algunos de ustedes, desarrolladores de firmware más experimentados.

En este momento estoy usando el reloj interno del ADC, por lo que necesito concentrarme principalmente en los pines DRDY/DOUT y SCLK. Voy a tener una función de inicialización que configura los otros pines ADC.

El manual de referencia del STM32L habla sobre los diferentes modos de SPI que son posibles, lo que lleva a mi(s) pregunta(s):

  1. Estoy planeando usar la recepción símplex con SPI2. ¿Este modo suena razonable según las formas de onda de la interfaz ADS1234?
  2. El ADS1234 es de 24 bits y el STM32L solo sube a 16 bits en el búfer. Mi idea es configurarlo para 12 bits y hacer dos transferencias, aunque no estoy seguro de si esto entrará en conflicto con algo.
  3. Dado que el uso de la función DRDY no es completamente una parte del protocolo SPI, me pregunto cómo hacer que esto active una transferencia de datos. Si el estado del pin DRDY/DOUT va de alto a bajo (lo que indica que los datos están listos), ¿debo configurarlo para un evento de interrupción en el cambio (IOC) y luego completar una transferencia?

A continuación se muestra la forma de onda de recuperación de datos del ADS1234.

Recuperación de datos ADS1234

Gracias por cualquier ayuda. Me preocupa principalmente la logística de todo.

Respuestas (3)

Yo lo haría completamente de otra manera.

  1. Configure el pin SPI2 MISO como entrada GPIO. Configure la interrupción EXTI (flanco descendente) en este pin
  2. En la interrupción EXTI: deshabilite EXTI, cambie este pin a MISO AF e inicie la transacción DMA de 3 bytes (envíe 3 bytes ficticios según sea necesario para generar el reloj para el ADS).
  3. En la transferencia DMA, cambie el pin de interrupción completa a la entrada GPIO. Habilitar EXTI

Los pasos 2 y 3 se repetirán automáticamente en cada conversión.

Disculpe mi ignorancia: ¿cuál es el acrónimo de AF?
F unción alternativa : es decir, este puerto actúa como SPI2 MISO. se configura configurando el registro GPIOx MODER en modo alternativo y configurando los registros AF
Ah, entendido.
Solo debería necesitar DMA para TX, ¿correcto? ¿O debería hacer SPI full-duplex con DMA1 y dos canales para RX y TX?
@Biff: DMA para RX, TX, puede hacer DMA o no.
No tengo claro por qué se necesita TX: STM32 generará SCLK ya que está en modo RX maestro semidúplex.
La interfaz SPI solo genera el reloj cuando se envían los datos. Entonces, como maestro, debe enviar los datos ficticios para recibir algo
¿Generar SCLK en modo maestro no es algo específico de STM32? De acuerdo con esto, el maestro genera SCLK (desplazamiento a lectura única semidúplex).
Más investigación, de 36.1 (pág. 1210) del manual de referencia STM32: La interfaz se puede configurar como maestra y en este caso proporciona el reloj de comunicación (SCK) al dispositivo esclavo externo.
@Biff Me disculpo de antemano por las cosas que escribiré ahora. Me temo que no entiende los documentos que lee. Y por los puestos no tienes demasiada experiencia. Pero si sabe mejor cómo funciona la interfaz SPI, digo que pase, no más ayuda de mi parte.
Gracias por su ayuda hasta ahora, me doy cuenta de mi inexperiencia y estoy tratando de entender. Estoy de acuerdo con tus declaraciones. :)

Estoy planeando usar la recepción símplex con SPI2. ¿Este modo suena razonable según las formas de onda de la interfaz ADS1234?

Sí, debería poder usar un puerto SPI de hardware en el STM32 para comunicarse con el ADS1234

El ADS1234 es de 24 bits y el STM32L solo sube a 16 bits en el búfer. Mi idea es configurarlo para 12 bits y hacer dos transferencias, aunque no estoy seguro de si esto entrará en conflicto con algo.

Eso funcionará, también puede configurar el búfer para 8 bytes también. Al final de la transferencia, el búfer se llenará y generará una interrupción (si lo configura de esa manera) que deberá copiar los datos del búfer antes de iniciar otra transferencia.

Dado que el uso de la función DRDY no es completamente una parte del protocolo SPI, me pregunto cómo hacer que esto active una transferencia de datos. Si el estado del pin DRDY/DOUT va de alto a bajo (lo que indica que los datos están listos), ¿debo configurarlo para un evento de interrupción en el cambio (IOC) y luego completar una transferencia?

Hay dos formas de ejecutar el muestreo del ADC1234:

1) inicie una muestra de ADC y luego espere de manera determinista con un temporizador o retrase la transferencia de datos hasta que sepa que DRDY se ha reducido, luego inicie una transferencia.

2) Haga lo que sugiere y espere a que DRDY baje con un puerto GPIO usando EXTI en el STM32 y luego inicie una transferencia.

Si espero que DRDY baje con un puerto EXTI, estaría usando dos pines, ¿correcto? ¿Uno para DOUT y otro esencialmente para DRDY con EXTI, ambos en paralelo?
@ laptop2d EXTI port on the STM32 (not all GPIOS support this)¿cuál no? EXTI en flanco descendente (no nivel bajo)
Sí, uno para DOUT y otro para DRDY. En realidad revisé dos veces la declaración EXTI y estaba equivocado, pido disculpas, corregiré la respuesta

Tengo un ADC AD4115 que tiene el mismo esquema para notificar al host uC que tiene datos listos: trae MISO/DOUT/~RDY bajo. Pude hacer que el STM32 cambiara el pin entre el comportamiento SPI y GPIO.

void PA6_to_SPI1(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void PA6_to_EXTI(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

Después de inicializar un poco para configurar los registros AD4115 donde main()necesito usar el pin como una línea MISO, lo cambio al modo EXTI. En el siguiente flanco descendente, se llamará al ISR

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin != GPIO_PIN_6) return;

    /* turn PA6 back into a MOSI line */
    PA6_to_SPI1();
    adc_data = ad4115_read_reg(&hspi1, 4, 4);

    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

    /* PA6 leaves SPI mode and becomes EXTI source */
    PA6_to_EXTI();

}

El ISR vuelve a convertir el pin en su propio SPI, lee el registro de 32 bits, borra cualquier interrupción pendiente (en realidad no puedo entender por qué necesito hacer esto, pero el ISR seguía activándose si no lo hacía). lo), luego cambia de nuevo a EXTI.

Todo esto utiliza E/S programadas directamente, por lo que es tan básico como parece. Solo estoy leyendo a 1 kHz, por lo que actualmente la sobrecarga es aceptable.