Se sabe que la familia de microcontroladores STM32F4xx, que tiene a bordo núcleos suficientemente productivos que son bastante adecuados para tareas "sin corte de carne", los DSP no tienen una interfaz de entrada de datos completa con el bus paralelo más simple en el modo "línea de tubería" (clk-data). Habiendo fumado dm00037051.pdf, encontré una opción adecuada no específica, pero a primera vista, la interfaz DCMI (interfaz de cámara digital).
Por supuesto, el uso de microcontroladores STM32 para un microcontrolador DSP clásico (FIR, IIR, FFT) cargado no es la mejor opción, pero si las tarjetas se despliegan repentinamente y las capacidades de este microcontrolador siguen siendo suficientes, además, necesita una cantidad suficiente de interfaces de baja velocidad. Sobre esto debajo del corte.
En uno de los proyectos con plazos y presupuestos "vigentes", era necesario implementar una "pieza de hierro" con unos óptimos: masa, dimensiones, consumo. Como función básica, se requería el procesamiento digital de la señal (filtrado y análisis estadístico), proveniente del ADC en modo suave en tiempo real. Para el procesamiento, quería tener un solo punto flotante de precisión. La señal del ADC se recibió a una frecuencia intermedia de 48 MHz. Banda de señal de 1 MHz. Para implementar la transferencia del espectro de la señal desde la frecuencia intermedia a cero, preferiblemente utilizando submuestreo del ADC de banda ancha. Además, era necesario recibir y transmitir información a través de Ethernet, SPI, UART, I2C y trabajar con interrupciones.
Los plazos de implementación y las funciones específicas de DSP no permitieron el uso de FPGA para estos fines. Con el conocido procesador de señales de la familia Blackfin, los conocidos Analog Devices no tenían experiencia en comunicación y no había herramientas de depuración y placas de demostración en el acceso cercano. Solo había una experiencia de comunicación cercana y prolongada con el costoso, una vez que el procesador DSP insignia ADSP-TS201 TigerSHARC. Además, Blackfin carece de una implementación de hardware de IEEE-754. Además, era necesario aceptar un bloque continuo de datos con un ADC de 128 KB, más 30 KB de sobrecarga de procesamiento y sin memoria externa, era difícil meter todo en algo menos presupuesto.
En general, solo había tableros STM32F407 (Discovery y personalizados de China) a la mano. Como sospecho, muchos de los que tratan temas relacionados ahora tienen esa ayuda universal a la mano. También había una placa ADS-HSMC de Terasic en la que se instaló el ADC de doble canal AD9228 (12 bits, Fd = 65 msps, ancho de banda = 315 MHz).
Una opción no específica pero bastante adecuada es la interfaz DCMI (interfaz de cámara digital), que es un hardware implementado en STM32F4.
El funcionamiento de esta interfaz se describe en RM0090, DocID018909, p. 454/1718. Las siguientes cuatro cifras se dan de este documento.
Entonces, la frecuencia de entrada reclamada es de hasta 54 MHz. Lo cual es suficiente: nuestra frecuencia de submuestreo es de 10 MHz. Aquí está el conjunto de señales de interfaz DCMI utilizadas:

Nota: D13, D14 solo están disponibles en paquetes de 144 pines. Tenemos 100 pines, pero no los necesitamos. (aunque los dispositivos analógicos tienen un ADC similar de 14 bits - AD9248).
Aquí hay un diagrama de tiempo generalizado de la interfaz:

Y este es el diagrama de tiempo de la interfaz en modo de formato de cuadro JPEG:

Utilizaremos este modo operativo como Él nos queda mejor.
En este modo, la señal VSYNC es llevada a la alimentación. Utilizaremos HSYNC como señal externa para permitir el inicio de la recepción de datos a través de la interfaz.
Utilizamos el microcontrolador STM32F407RGT6 en el paquete LQFP100.
El AD9238 ADC tiene una entrada para el modo de apagado (ahorro de energía) del canal correspondiente PDWN_A (B), y el permiso de salida es OEB_A (B). Es lógico obtenerlos de cualquier pin del controlador. Como resultado, el diagrama de conexión del pin se verá así:

Dado que este ADC no tiene una señal de reloj de salida, es necesario usar multiply (buffer de reloj). Usamos el LMK00101 de Texas Instruments: un buen valor por el precio, baja inestabilidad y, lo más importante, nuevamente, a la mano).
En el procesamiento, tenemos en cuenta que los datos en el bus paralelo ADC aparecen con un retraso de 7 ciclos de reloj en relación con la señal del reloj de entrada.
Recibiremos datos (por supuesto) a través de DMA. Aquí está el código fuente para inicializar DCMI y DMA.
Activamos la sincronización de los puertos que necesitamos, DCMI y DMA2
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD, ENABLE); RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_DCMI, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
Este pin (PA5) simulará la división en cuadros: HSYNC. Inicializar al salir
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_ResetBits(GPIOA, GPIO_Pin_5);
Configure los pines correspondientes en modo DCMI
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_DCMI); GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_DCMI);
Lo más interesante aquí es configurar DCMI en el modo correspondiente a los cuadros JPEG.
DCMI_InitStructure.DCMI_CaptureMode = DCMI_CaptureMode_Continuous; DCMI_InitStructure.DCMI_SynchroMode = DCMI_SynchroMode_Embedded; DCMI_InitStructure.DCMI_PCKPolarity = DCMI_PCKPolarity_Rising; DCMI_InitStructure.DCMI_VSPolarity = DCMI_VSPolarity_Low; DCMI_InitStructure.DCMI_HSPolarity = DCMI_HSPolarity_High; DCMI_InitStructure.DCMI_CaptureRate = DCMI_CaptureRate_All_Frame; DCMI_InitStructure.DCMI_ExtendedDataMode = DCMI_ExtendedDataMode_12b;
Configuración de DMA
DCMI_Init(&DCMI_InitStructure); DMA_InitStructure.DMA_Channel = DMA_Channel_1; DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDRESS;
Configuración de interrupciones al final de recibir datos del canal DMA correspondiente
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
El código de nuestro controlador, en el que desactivamos la recepción de datos DCMI y establece el indicador de datos listos.
void EXTI1_IRQHandler() { EXTI_ClearFlag(EXTI_Line1); DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1); DMA_Cmd(DMA2_Stream1, DISABLE); DCMI_Cmd(DISABLE); dma_recv_f = 1;
Todo está con la configuración. Ahora activamos nuestro canal DMA, el bloque DCMI, comenzamos a recibir datos DCMI en modo de cuadro JPEG.
/* Enable DMA transfer */ DMA_Cmd(DMA2_Stream1, ENABLE); /* Enable DCMI interface */ DCMI_Cmd(ENABLE); /* Start Image capture */ DCMI_CaptureCmd(ENABLE); DCMI_JPEGCmd(ENABLE);
El ciclo del programa principal. Aquí, sondear la bandera y reiniciar la recepción de datos.
uint8_t dma_recv_f = 0;
Nota: si necesita recibir y procesar datos en tiempo real con doble búfer, stm32f4 tiene un mecanismo de interrupción cuando la mitad del búfer está lleno. En la configuración de DMA, entonces es necesario establecer el modo cíclico continuo de recepción de datos. Por ejemplo:
En el controlador de interrupciones, entonces es necesario restablecer el bit final de DMA solo después de llenar todo el búfer, y el programa de usuario para indicar el número del búfer actual en el que ha finalizado la recepción de datos. Algo como esto:
if(DMA_GetITStatus(DMA2_Stream1,DMA_IT_TCIF1)){ DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF1); num_buf = 1; } else{ num_buf = 0; }
Eso es básicamente todo lo que se necesita para recibir datos de nuestro ADC a través de DCMI.
Desafortunadamente, por el momento no puedo demostrar todo este mecanismo en vivo. la pieza de hierro ya lleva unos 3 años en funcionamiento))). Solo puedo traer los datos de registro de prueba guardados de esos momentos.
Aquí hay una señal armónica del generador SMB100A a una frecuencia de 48.001 MHz, igual a nuestro IF con un desplazamiento de 1 KHz:

Y este es su espectro:

Para verificar el rendimiento máximo en los cables de placa estándar con una longitud de aproximadamente 200 mm, con los que se conectaron el ADA-HSMC y STM32F4 Discovery, se recibieron los datos correctos a una frecuencia de reloj de 40 MHz.
En una placa "nativa" fabricada para esta tarea, a través de un cable plano de 100 mm de largo, a temperatura ambiente, resultó elevar la frecuencia de muestreo a un máximo de 54 MHz.
A la frecuencia de muestreo deseada de 10 MHz, el rendimiento se probó en el rango industrial: de -40 a +60.
En realidad todo. Gracias por su atencion!