STM32 USART con DMA, ¿qué interrupciones usar?

4

Estoy trabajando en el firmware para un STM32F103 que se está comunicando a través de RS232 a 115200 baudios con un controlador de motor. El controlador del motor (un Copley Xenus XTL ) funciona en un "habla cuando hablado a "protocolo. Estoy usando la interfaz de programación ASCII en los documentos vinculados. El STM32 siempre envía el mismo comando ("g r0x18") para sondear un registro, y el controlador del motor responde con un número variable (~ 4-10 bytes) de caracteres terminados por un retorno de carro ("v 12345", donde número de dígitos es variable). Tengo un código para analizar la respuesta y extraer un valor numérico de ella. Una vez analizada la respuesta, el comando de sondeo de registro debe transmitirse nuevamente al controlador del motor. El STM32 también está leyendo un canal ADC sobre DMA en modo circular en segundo plano.

Me gustaría implementar esto usando el controlador DMA para hacer que todo sea lo más no bloqueable posible, pero estoy un poco confundido en cuanto a qué interrupciones debería usar y cuándo se activan. Sin utilizar el controlador DMA, el código de análisis reside actualmente en la interrupción USART RXNE. Supongamos que transmito un comando y el controlador del motor comienza a responder. Creo que la interrupción RXNE se activa para cada byte recibido, pero ¿qué pasa con la interrupción completa de la transferencia DMA? ¿Hay alguna diferencia funcional en este caso entre usar la interrupción DMA TC y la interrupción USART RXNE?

    
pregunta Joe Baker

2 respuestas

3

Puede configurar DMA para que funcione en modo cíclico, y con un búfer grande razonable puede extraer caracteres con la frecuencia que desee con la simple función poll . Solo almacene el índice del último carácter recuperado y use el registro DMA para verificar cuántos caracteres tiene que recibir hasta que se desplace (el registro AFAIR tiene NDTR en su nombre) y procesa los caracteres recibidos desde la última llamada, luego actualice el índice del último carácter recuperado .

El uso de DMA descrito hace que su poll sea independiente del contexto desde el que lo llame, siempre que evite la preferencia. Luego, puede usar la interrupción de RX para activar la (s) llamada (s) de encuesta, o puede hacerlo en otro contexto (por ejemplo, con algunos eventos periódicos).

Esto generalmente es eficiente si los marcos son lo suficientemente largos, la velocidad en baudios es grande y la latencia de interrupción es mayor que el tiempo de recepción de un solo carácter.

Pero si los datos se reciben con la suficiente lentitud, puede procesarlo de forma char por char actual y el uso de DMA puede ser excesivo.

Como señaló @Chris Stratton, también puede configurar DMA para una transmisión única y esperar el tiempo suficiente, cambiar el protocolo o usar otra señal como "fin de la transmisión", y luego procesar la trama en el búfer DMA.

    
respondido por el kwesolowski
1

Deberías usar interrupciones DMA. Estoy utilizando STM32F02 con las bibliotecas periféricas STM32 STL, pero la idea es bastante similar para F01:

  • Inicializa tu UART
  • Inicialice DMA (¡no olvide proporcionar la señal CLK para el periférico ANTES de llamar a DMA_Init!)
  • Configure las interrupciones de NVIC y DMA, y habilite DMA de la siguiente manera:
 NVIC_InitTypeDef NVIC_InitStructure;
 //Enable DMA1 channel IRQ Channel
 //Note: maybe in your implementation you don't have DMAx_Streamy, look for channel/ stream configurations in your microcontroller manual

 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream1_IRQn; // This could be different in your implementation

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);

 // Enable DMA1 Channel Transfer Complete interrupt
 DMA_ITConfig(DMA1_Stream1, DMA_IT_TC, ENABLE);

 USART_DMACmd(ACCESSORY_UART, USART_DMAReq_Rx, ENABLE);
 DMA_Cmd(DMA1_Stream1, ENABLE);

La función USART_DMACmd enlaza UART con DMA, y creo que esa es su respuesta. De esta manera, el DMA copiará un byte al puntero que proporcionó en la configuración cada vez que se desencadena un evento RXNE, pero se interrumpe SOLAMENTE cuando se activa un evento de transferencia completa (DMA_IT_TC), llamando a la función DMA correspondiente de acuerdo con el canal configurado / stream.

    
respondido por el Chewbacca

Lea otras preguntas en las etiquetas