¿Por qué no funciona mi implementación VGA con un microcontrolador AVR?

5

Problema

Estoy intentando generar la salida de señal adecuada para conectar un microcontrolador AVR ATmega328P con un monitor LCD, a través de la especificación VGA. La especificación VGA que trato de cumplir es el estándar de la industria 640 * 480 con una frecuencia de actualización de cuadros de 60 Hz (1).

Información de fondo

El AVR funciona a una frecuencia de 20 MHz , que es inferior a la frecuencia del reloj de píxeles VGA de 25.175 MHz . Sin embargo, creía, habiendo considerado proyectos similares en línea (2), que a través de una manipulación del número de relojes por región, podía cumplir con los tiempos estipulados en la especificación VGA. Los horarios ajustados tanto para la especificación vertical como para la horizontal se pueden encontrar a continuación:

Cronometraje vertical (cuadro)

Área visible: 15.24 ms, 480 líneas (304800 clk ciclos a 20 MHz)
Porche delantero: 0,3175 ms, 10 líneas (6350 clk ciclos a 20 MHz)
Pulso de sincronización: 0.0635 ms, 2 líneas (1270 clk ciclos a 20 MHz)
Porche trasero: 1.04775 ms, 33 líneas (20955 ciclos de clk a 20 MHz)
Cuadro completo: 16.66875 ms, 525 líneas (333375 ciclos a 20 MHz)

Temporización horizontal (línea)

Área visible: 25.45 us, 508 píxeles (508 clk ciclos a 20 MHz)
Porche delantero: 0.65 us, 13 píxeles (13 clk ciclos a 20 MHz)
Pulso de sincronización: 3.8 us, 76 píxeles (76 ciclos de clk a 20 MHz)
Porche trasero: 1.9 us, 38 píxeles (38 clk ciclos a 20 MHz)
Línea completa: 31.75 us, 635 píxeles (635 ciclos de clk a 20 MHz)

Según estos tiempos, la frecuencia de actualización del marco es 59.9925 Hz . La región visible en la pantalla tiene una resolución de 508 * 480 en contraste con los 640 * 480 de la especificación.

Soy consciente de que a una frecuencia de reloj de 20 MHz los tiempos no se pueden cumplir con precisión, pero si comparas mis tiempos con la especificación real (3), los tiempos están muy cerca.
El software que escribí para generar estas salidas se ha escrito en el ensamblador AVR, esto me permite contar el número de ciclos de reloj para cada región, y se puede encontrar justo debajo de este párrafo. El software emitirá indefinidamente un marco rojo en la pantalla.
Una imagen del esquema para la implementación del hardware se puede encontrar debajo del código.

;
; VGA_INTERFACE.asm
;
; Outputs the required signals with the correct timings for VGA output to a monitor.
;
;
;
; Created: 13/02/2018 
; Author : Tom
;









; COMPILER SETTINGS
.INCLUDE "M328pDEF.INC"


; INTERRUPT VECTORS
.org 0      ; defines absolute address for interrupt vector




; ****************************************************************************************
; **** IO PORT D SETUP
; ****************************************************************************************

    ; ddrd pin I/O direction configured

    sbi ddrd,0  ; RED BIT 0             
    sbi ddrd,1  ; RED BIT 1             
    sbi ddrd,2  ; GRN BIT 0
    sbi ddrd,3  ; GRN BIT 1
    sbi ddrd,4  ; BLU BIT 0
    sbi ddrd,5  ; BLU BIT 1
    sbi ddrd,6  ; HORIZONTAL SYNC       
    sbi ddrd,7  ; VERTICAL SYNC          



    ldi r20, 0xC0
    out portd, r20      ; clears the RGB bits and sets the sync pulses high





; ****************************************************************************************
; **** STARTUP SEQUENCE
; ****************************************************************************************

; INITIALIZE STACK POINTER

    ldi r16,low(ramend)     ; loads the lower byte of top stack address into register 16 
    out spl,r16             ; stack pointer lower byte is set to lower byte of the top 
                            ; stack address stored in register 16

    ldi r16,high(ramend)    ; loads the upper byte of top stack address into register 16
    out sph,r16             ; stack pointer upper byte is set to upper byte of the top 
                            ; stack address stored in register 16






; main program loop
main:



V_LOOP:

; ****************************************************************************************
; **** VERTICAL LOOP - BEGIN
; ****************************************************************************************


; **** V-SYNC DRIVE LOW (2 lines, 1,270 cycles)




    cbi portd,7     ;2 drives v-sync active low 


; ========================================================================================
    ; Delay 1268 cycles
    ldi  r18, 2
    ldi  r19, 165
L1: dec  r19
    brne L1
    dec  r18
    brne L1
; ========================================================================================


    sbi portd,7     ;2 drives v-sync high 









; **** VERTICAL BACK PORCH (33 lines, 20955 cycles)

    ; **NOTE: Only 20951 cycles required to be wasted as 4 cycles are used by Horizontal 
    ; loop. 2 are used when setting max loop value in r16 and r17. A further 2 are used 
    ; setting horizontal sync active low.


; ========================================================================================
    ; Delay 20951 cycles
    ldi  r18, 28
    ldi  r19, 52
L2: dec  r19
    brne L2
    dec  r18
    brne L2
    rjmp PC+1
; ========================================================================================









; ****************************************************************************************
; **** HORIZONTAL LOOP - BEGIN (LOOPS 480 times)
; ****************************************************************************************


    ldi r16,low(480)        ;1 holds LSB of loop value
    ldi r17,high(480)       ;1 hold MSB of loop value




H_LOOP:


; **** H-SYNC DRIVE LOW (76 cycles)


    cbi portd,6     ;2 drives h-sync active low 

; ========================================================================================
    ; Delay 74 cycles
    ldi  r18, 24
L3: dec  r18
    brne L3
    rjmp PC+1
; ========================================================================================


    sbi portd,6     ;2 drives h-sync high









; **** HORIZONTAL BACK PORCH (38 cycles)


    ; **NOTE: Only 36 cycles required to be wasted as 2 cycles are used by RGB for setting
    ; the red bit 0 high.



; ========================================================================================
    ; Delay 36 cycles
    ldi  r18, 12
L4: dec  r18
    brne L4
; ========================================================================================









; **** RGB (508 cycles)

    ldi r20, 0xC1       ;1
    out portd, r20      ;1 sets red bit 0 high, all other RGB low, sync pulses high 


; ========================================================================================  
    ; Delay 506 cycles
    ldi  r18, 168
L5: dec  r18
    brne L5
    rjmp PC+1
; ========================================================================================


    ldi r20, 0xC0       ;1
    out portd, r20      ;1 sets the RGB outputs low, sync pulses high 









; **** HORIZONTAL FRONT PORCH (13 cycles)


    ; **NOTE: Only 5 cycles required to be wasted as 8 cycles are used up already. 4 are    
    ; are used for subtracting one from the loop counter. A further 4 are used for 
    ; jumping to start of horizontal loop and setting the Horizontal sync active low.


; ========================================================================================
    ; Delay 5 cycles
    lpm
    rjmp PC+1
; ========================================================================================


    ldi r18, low(1)     ;1
    ldi r19, high(1)    ;1


    sub r16,r18         ;1
    sbc r17,r19         ;1  


    brne H_LOOP     ; 2 cycles if true, 1 if false  









; ****************************************************************************************
; **** HORIZONTAL LOOP - END
; ****************************************************************************************











; **** VERTICAL FRONT PORCH (10 lines, 6350 cycles)

    ; **NOTE: Only 10 cycles have been used up for the Horizontal front porch, as a result a  
    ; further 3 must be added to the vertical front porch. 
    ; However 4 cycles are already being used, 2 to jump to start of vertical loop and a 
    ; further 2 to drive horizontal sync active low.
    ; As a result taking these two factors into account, the delay needs to be 6350+3-4 =
    ; 6349  cycles long.


; ========================================================================================
    ; Delay 6349 cycles
    ldi  r18, 9
    ldi  r19, 62
L6: dec  r19
    brne L6
    dec  r18
    brne L6
; ========================================================================================


    rjmp V_LOOP     ;2  relative jump to start of vertical loop









; ****************************************************************************************
; **** VERTICAL LOOP - END
; ****************************************************************************************

Resultados

Despuésdehaberprobadolaimplementacióndehardwareysoftware,encontréquefuncionabienenlainterfazVGAdemitelevisordelasaladeestar,peronofuncionaenningúnotromonitorotelevisorquehayaprobado.Descubríquefuncionaenunmonitordeamigos,mostraráunapantallarojaperoconparchesnegrosalazaryperderálaseñalperiódicamente.Losotrosmonitoresqueheprobadodetectanlaentrada,perosimplementenopuedenmostrarnadaenlapantalla.

Creoquelarazónporlaquefuncionaenalgunaspantallasynoenotras,essimplementedebidoalastoleranciasquelosfabricanteshanestipuladoensusdispositivos.

Solucionespotenciales

Heintentadonumerososajustesenelcódigo,estoimplicóprincipalmentecambiarelnúmerodeciclosderelojencadaregión,peroestonoprodujoningúnresultadopositivo.Estomellevaacreerenunadedossituacionesposibles:

1)(MÁSFÁCILMENTE)Heimplementadoelsoftwareohardwareincorrectamente,loquehacequelostiemposesténligeramentefueradetiempo.

2)Esmuydifícil/imposibleimplementarlaespecificaciónVGAconunrendimientoconstanteentodoslosdispositivosconcapacidadVGAqueutilizanelATmega328Pquefuncionaa20MHz.

Comoresultadodeesto,estoyplaneandooverclockeareldispositivoAtmegaconuncristalde25.175MHzparaasegurarquesepuedancumplirlostiemposovoyausarunmicrocontroladormáscapazconmayorcapacidaddeprocesamiento,algocomounPIC24EP128MC202.

Sialguientienealgunaideadeporquémiimplementaciónactualnofuncionaycómopodríarectificaresto,¡seríamuyapreciado!

Sihaslogradoleerhastaaquí,graciasdetodosmodos!:)

Referencias

(1)(3)SeñalVGA640x480@60HzTemporizaciónestándardelaindustria- enlace

(2) Lucid Science VGA Video Generator (desafortunadamente el sitio ya se cerró) enlace

    
pregunta Tom Finch

1 respuesta

2

Primero, no debería haber ningún problema al generar VGA utilizando un ATMega328. Puede generar trabajos VGA con todo, desde antiguos CRT, pequeños módulos LCD misteriosos fuera de Aliexpress o un LCD moderno. Nunca he oído hablar realmente de problemas de compatibilidad con VGA, especialmente no relacionados con la sincronización.

Hay docenas de proyectos que producen con éxito al menos 640x480 VGA monocromáticos (en paralelo a las líneas RGB) usando mucho menos que un ATMega, y ni siquiera necesita un reloj de 20MHz; varios proyectos se administran con un reloj de 16MHz. Y si está de acuerdo con menos de 640x480, este proyecto genera un VGA válido con un ATTiny15 en ejecución a 1.6MHz.

Ahora, no he revisado dos veces el ensamblaje, por lo que podría estar equivocado, pero parece poco probable que el tiempo funcione bien en una pantalla pero no en otras. No, creo que esto es simplemente un problema de atenuación de la señal debido a la falta de coincidencia de impedancia.

Las 3 líneas de color esperan de 0 a 0.7V. Y veo que ha dimensionado sus resistencias de tal manera que, con una impedancia de 75Ω, resultará en 0.696V o .348V.

Sé que probablemente parece una solución muy agradable y elegante para obtener negro + dos tonos, pero me temo que no funcionará muy bien. Sus resistencias son demasiado grandes y esto está causando un mal caso de desajuste de impedancia. Y es probable que experimente los problemas exactos que describe: algunas pantallas (una pequeña minoría que esperaría con resistencias tan grandes) podrían usar la señal, pero la mayoría no lo haría, o solo leería los píxeles de forma intermitente por cada fotograma.

Si desea controlar correctamente una impedancia de 75Ω mientras reduce un voltaje más alto al rango de voltaje correcto, necesita usar una red de adaptación de impedancia, como un divisor L-pad.

Discutir la teoría detrás de los divisores L-pad está más allá del alcance de esta pregunta, pero sería bueno usar transistores para establecer correctamente los niveles de voltaje sin tener la alta impedancia de un divisor.

Aquí, solo para hacer una verificación de cordura y ver si mi suposición es correcta, abandone la segunda línea IO en las 3 entradas de color. No se puede manejar correctamente una entrada VGA usando los 75 ohmios como participante en un divisor de voltaje de todos modos, así que tendré que abandonar esa idea por completo, me temo. Puede salirse con la suya utilizando una escalera de estilo DAC adecuada, pero incluso en ese caso, todas las resistencias tendrán un orden de magnitud menor que 1K y 2K.

Solo use un pin de E / S, y me di cuenta de que esto probablemente excede la corriente de un solo pin ... 50mA, creo? Pero el pad-l ideal para 75Ω que atenúa 5V a 0.7V sería una resistencia de 64Ω y 12Ω en serie a tierra, con la señal en la pantalla siendo el toque entre los dos.

La magia aquí es que, si eliminas mis errores de redondeo, esto resulta en una resistencia de 75Ω. Eso es lo que significa impedancia emparejada. Que cada extremo tiene el equivalente a 75Ω desde el pin de señal a tierra.

Básicamente, los pines de su atmega no son lo suficientemente fuertes para impulsar una impedancia de 75Ω a plena potencia cuando se ejecuta desde 5V, ya que consumirían más de 50mA. En su lugar, solo use una escalera con una proporción similar, pero no tan grande. Pruebe 220Ω y 56Ω, y eso debería resolver sus problemas de señal y reducir el voltaje de la señal a 0.7 V SIN tener una impedancia tan grande que la mayoría de las pantallas ni siquiera funcionan correctamente.

    
respondido por el metacollin

Lea otras preguntas en las etiquetas