Mostrando postagens com marcador 8051. Mostrar todas as postagens
Mostrando postagens com marcador 8051. Mostrar todas as postagens

quarta-feira, 12 de maio de 2021

80C32 + EPROM - Como Apagar e Gravar a Memória EPROM 27C512

 Aprenda a trabalhar com as memórias EPROM do tipo UVPROM, que necessitam da Luz Ultravioleta para serem apagadas.

Neste artigo você vai aprender como apagar uma memória EPROM 27C512 com luz Ultravioleta UV e fazer a gravação de um novo programa com o programador de memórias Minipro / TL866 II plus.

Escolhemos uma placa de sucata de impressora antiga para o nosso aprendizado. 


Figura 1 - Placa de sucata com o microcontrolador 80C32 e memória EPROM 27C512.



Figura 2 - Memória EPROM 27C512 de 64 kB com a janela de quartzo sem o selo.


Figura 3 - Pinos da memória EPROM 27C512. Fonte: datasheet da ST.



Figura 4 - Exemplo de diagrama de um circuito com uma memória EPROM.



Figura 5 - Equipamentos para trabalhar com as memórias EPROM.


Vejamos o que dizem os datasheets das memórias EPROMs com relação a forma de apagá-las.


Fonte: datasheet da EPROM M27C512 da ST.

Fonte: datasheet da EPROM TMS27C512 da TI.

Resumindo tudo: para apagarmos o conteúdo da memória temos que utilizar um apagador de EPROM, que possui uma lâmpada Ultravioleta, e deixar nosso chip lá dentro durante 20 minutos com a janela de quartzo exposta a luz UV!   Simples assim né!  :)

Figura 6 - Memória pronta para ser limpa com o Apagador de EPROM.



Figura 7 - Memória EPROM sendo apagada com Luz Ultravioleta.


Depois de apagar a memória EPROM todos os bits passam para o nível lógico 1 (bytes com valor  FF em hexadecimal).
Dizemos que a memória está limpa, ou em branco, e pode ser gravada com um novo programa.

Existem diversos modelos de programadores no mercado. Neste post vamos utilizar o programador de memórias Minipro / TL866 II plus da XGecu.

Figura 8 - Memória encaixada no soquete ZIF do programador Minipro / TL866 II plus.


Figura 9 - Software XGpro para programação de memórias.




Figura 10 - Programa .HEX ou .BIN aberto no programador.


Figura 11 - Processo de programação e verificação do programa na memória EPROM.

Devemos proteger novamente a janela de quartzo do chip com um selo para evitar que o programa seja apagado parcialmente ao ser exposto a luz solar ou lâmpadas fluorescente.

Figura 12 - Memória EPROM já programada, montada na placa e com o selo na janela de quartzo.


Acompanhe no vídeo todo o processo passo-a-passo para Apagar e Programar uma memória EPROM 27C512!

Vídeo 1 - 80C32 + EPROM - Como Apagar e Gravar a Memória EPROM 27C512


terça-feira, 20 de abril de 2021

80C32 + EPROM 27C512 - O primeiro projeto 8051 Pisca LED 1 Hz

 Transformando uma placa de sucata  em um Kit de Desenvolvimento 8051: Microcontrolador 80C32 com memória de programa externa EPROM 27C512.


Projeto 8051 Pisca LED a 1 Hz no Port P1.4.

Você vai aprender a trabalhar com a memória EPROM 27C512, como fazer o apagamento da memória com luz Ultra Violeta e fazer a gravação com o programador Minipro / TL866 II plus.

Figura 1 - Diagrama do circuito com o Microcontrolador 80C32 e memória externa EPROM 27C512.


Figura 2 - Placa de sucata com o Microcontrolador 80C32 e memória externa EPROM 27C512.


Figura 3 - Ferramentas utilizadas.


Código para o primeiro projeto 8051 Pisca LED 1 Hz.



 ;############ PISCA LED 1 HZ ###############

; MICROCONTROLADOR 8051 
; COMPILADOR ASM51 ou Keil
; MAIO/2013  M.R.G. original placa desenvolvimento  aT89s82
; MARC/2021  M.R.G. adaptado para placa 80c32 + EPROM 27C512
; PINO 5, P1.4 = LED


$MOD51

; *************** DEFINE CONSTANTES   ************** 
		TEMPO10MS			EQU 	9210
		LED				EQU	P1.4
		ENABLE_INPUT_DRIVE_MTA011	EQU	P3.5
		
;*************** VETOR DE RESET ****************************************

		ORG	000H

		LJMP INICIO

;************************** MAIN ***************************************
		ORG	100H

INICIO:	

;CONFIGURA TIMER0

		MOV	TMOD,#00000001B				;TIMER 0 MODO 1 - 16 BITS



; HABILITA ENTRADAS DO DRIVE MTA011 - TEM PORTA INVERSORA LS05 ENTRE 80C32 E MTA011
               CLR ENABLE_INPUT_DRIVE_MTA011	                ;QUANDO EM ZERO HABILITA DRIVE



LOOP:
		MOV R0, #50D			                ;50 X 10 MS = 500 MS
DELAY10MS:							  	
		MOV TL0, #LOW (65535-TEMPO10MS)	                ;CARREGA VALOR PARA TIMER 0
		MOV TH0, #HIGH(65535-TEMPO10MS)
		SETB TR0					;LIGA TIMER 0
		JNB TF0, $					;AGUARDA FIM DA CONTAGEM
		CLR TR0						;LIMPA FLAG
		CLR TF0
		DJNZ R0, DELAY10MS				;DECREMENTA E VERIFICA SE TERMINOU OS 50 LOOPS

		CPL LED						;INVERTE SAIDA PARA O LED
		LJMP LOOP

		
	END	

Figura 4 - Código em Assembly do programa 8051 Pisca LED 1Hz.



Figura 5 - Apagando a memória EPROM com Luz Ultravioleta.


Figura 6 - Programando a memória EPROM com Minipro TL866 II plus.


Figura 7 - Placa 80C32 rodando o programa. LED piscando a 1 Hz




Assista ao vídeo para ver como ficou nosso projeto:

Vídeo 1 - 80C32 EPROM - O primeiro projeto 8051 Pisca LED 1 Hz.




Referência:

NICOLOSI, D. E. C.; Laboratório de Microcontroladores: Treino de instruções, hardware e software. São Paulo: Érica, 2002.




80C32 + EPROM 27C512 - Projeto Testando a Comunicação Serial do 8051

Transformando uma placa de sucata  em um Kit de Desenvolvimento 8051: Microcontrolador 80C32 com memória de programa externa EPROM 27C512. 


Projeto Teste da Comunicação Serial com o 8051: o programa inicia e envia algumas mensagens de texto para o computador pela comunicação serial. Depois passa a aguardar dados vindos pela serial e retorna os caracteres para o computador como uma função de echo. A cada dado recebido o 8051 inverte o status do LED ligado no Port P1.4. Trabalha com a Interrupção Serial.

Você vai aprender a trabalhar com a memória EPROM 27C512, como fazer o apagamento da memória com luz Ultra Violeta e fazer a gravação com o programador Minipro / TL866 II plus.


Figura 1 - Diagrama do circuito com o Microcontrolador 80C32 e memória externa EPROM 27C512.


Figura 2 - Placa de sucata com o Microcontrolador 80C32 e memória externa EPROM 27C512.



Figura 3 - Ferramentas utilizadas.



Código do projeto Testando a Comunicação Serial do 8051.


;############ PROGRAMA 8051 COM LED E SERIAL ###############

; ENVIA MENSAGENS INICIAIS PARA O COMPUTADOR
; DEVOLVE DADO RECEBIDO PARA O COMPUTADOR E INVERTE STATUS DO LED
; COMPILADOR ASM51 ou Keil

; V 1.1 ABRIL/2013  PLACA AT89S52
; V 1.2 MARÇO/2021  ADAPTADO PARA PLACA 80C32
; v 1.3		    CORRIGIDO BUG DA INTERRUPCAO SERIAL
; M.R.G.


; PINO 10, P3.0 = RX
; PINO 11, P3.1 = TX
; PINO  5, P1.4 = LED
; PINO 15, P3.5 = enable drive MTA011


$MOD51


; *************** DEFINE CONSTANTES   ************** 
		TEMPO		EQU 	60535
		TEMPO2		EQU	15535


		STRING01	EQU	0500h
		STRING02	EQU	0520h
		STRING03	EQU	0540h
		STRING04	EQU	0560h
		STRING05	EQU	0580h
		STRING06	EQU	0600h
		STRING07	EQU	0620h	
		STRING08	EQU	0640h	

		TRANSMIT	EQU	F0	;UTILIZANDO BIT DO PSW PARA FLAG DE TRANSMISSÃO


		LED				EQU	P1.4
		ENABLE_INPUT_DRIVE_MTA011	EQU	P3.5





; ******************** DECLARACAO DE VARIAVEIS DA RAM **********************



  
;*************** VETOR DE RESET **********************************************

		ORG	000H

		MOV	R0, #0FFH
		LJMP INICGERAL


;****************** TRATAMENTO DA INTERRUPÇÃO SERIAL ***************************
		ORG    023H
		LJMP INT_SERIAL


		ORG	100H
INT_SERIAL:
 		JNB RI, INT_TX 		;SEPARA POR SOFTWARE A INTERRUPCAO DA TRANSMISSAO E DA RECEPCAO
INT_RX:
		MOV	A,SBUF		;MOVE DADO RECEBIDO DA SERIAL PARA R1
		MOV R1, A		;MOVE DADO DO ACUMULADOR PARA REGISTRADOR R1

		CALL TRANSMITE		;DEVOLVE DADO RECEBIDO PARA O COMPUTADOR                   			

		CPL 	LED		;INVERTE SAIDA DO LED
		CLR	RI		;LIMPA FLAG DE RECEPCAO SERIAL

INT_TX:					
    		CLR TI         		;LIMPA FLAG DE TRANSMISSAO SERIAL
		RETI



;************************** MAIN ***************************************
		

INICGERAL:
	
; HABILITA ENTRADAS DO DRIVE MTA011 - TEM PORTA INVERSORA LS05 ENTRE 80C32 E MTA011
               CLR ENABLE_INPUT_DRIVE_MTA011	;QUANDO EM ZERO HABILITA DRIVE



;CONFIGURA SERIAL

		MOV	TMOD,#00100001B	;TIMER 1 NO MODO2	TIMER 0 MODO 1
		MOV	TH1,#232D	;VALOR DA RECARGA AUTOMÁTICA PARA BAUD RATE = 2400 @11,0592 MHz
		SETB	TR1		;LIGO TIMER1
		MOV	A,PCON		
		SETB	ACC.7		;SETA BIT SMOD PARA TER BAUD RATE = 2400
		MOV PCON,A
		;MOV IE,#10010000B	;HABILITA INTERRUPÇÃO GERAL E SERIAL
		MOV SCON,#01000000B	;MODO 1 DA SERIAL, DESABILITA RECEPÇÃO

  


; ENVIA MENSAGENS INICIAIS PELA SERIAL - COM AS INTERRUPCOES DESABILITADAS

MENSAGEM7:	
		MOV DPTR, #STRING07	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO


MENSAGEM1:	
		MOV DPTR, #STRING01	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO


MENSAGEM2:	
		MOV DPTR, #STRING02	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO


MENSAGEM3:	
		MOV DPTR, #STRING03	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO

MENSAGEM4:	
		MOV DPTR, #STRING04	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO


MENSAGEM5:	
		MOV DPTR, #STRING05	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO

MENSAGEM6:	
		MOV DPTR, #STRING06	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ENVIA_ENTER
		LCALL ATRASO

MENSAGEM8:	
		MOV DPTR, #STRING08	;carrega endereço da string
		LCALL WRITESTRING
		LCALL ATRASO


; FIM DAS MENSAGENS NO DISPLAY - HABILITA COMUNICACAO SERIAL
		MOV IE,#10010000B	;HABILITA INTERRUPÇÃO GERAL E SERIAL
		MOV SCON,#01010000B	;MODO 1 DA SERIAL, HABILITA RECEPÇÃO

LOOP:

		LJMP LOOP





; ----------- SUB-ROTINAS DE ENVIO DE MENSAGENS ----------------



WRITESTRING:
		MOV A, #0
		MOVC A, @A + DPTR
		CJNE A, #'$', WRITE_NEXT
		SJMP FINIS_STRING
WRITE_NEXT:
		MOV R1, A		;MOVE DADO DO ACUMULADOR PARA REGISTRADOR R1
		LCALL TRANSMITE		;ENVIA CARACTERE PARA O COMPUTADOR
		INC DPTR
		SJMP WRITESTRING
FINIS_STRING:
		RET

ENVIA_ENTER:
		MOV A, #13		;CR (Carriage Return) = “\r” = (char) 13
		MOV R1, A		;MOVE DADO DO ACUMULADOR PARA REGISTRADOR R1
		LCALL TRANSMITE		;ENVIA CARACTERE PARA O COMPUTADOR
		RET



; *********** SUBROTINAS DE DELAY ****************************************

T5MS:
		MOV TL0, #LOW(TEMPO)
		MOV TH0, #HIGH(TEMPO)
		SETB TR0
		JNB TF0, $
		CLR TR0
		CLR TF0
		RET



ATRASO:
		MOV R2, #10D
DENOVO:
		MOV TL0, #LOW (TEMPO2)
		MOV TH0, #HIGH(TEMPO2)
		SETB TR0
		JNB TF0, $
		CLR TR0
		CLR TF0
		DJNZ R2, DENOVO
		RET


	

; *********** TRANSMISSAO SERIAL ****************************************
TRANSMITE:
	MOV	SBUF,R1		;TRANSMITE DADO QUE ESTÁ EM R1
ESPERA:
	JNB	TI, ESPERA	;ESPERA TRANSMISSAO
	CLR	TI
	RET

; MENSAGENS SALVAS NA FLASH - MEMORIA DE PROGRAMA

		ORG STRING01
		DB ' Microcontrolador$'

		ORG STRING02
		DB ' 80C32, LED e RS232$'

		ORG STRING03
		DB ' Freq 11.0592 MHz$'

		ORG STRING04
		DB ' 256 B RAM$'

		ORG STRING05
		DB ' 64 kB EPROM$'

		ORG STRING06
		DB ' 32 kB Ext RAM$'

		ORG STRING07
		DB 'Inicializando...$'

		ORG STRING08
		DB '8051 echo:>_ $'


;ENTER
;CR (Carriage Return) = “\r” = (char) 13
;LF (Line Feed) = “\n” = (char) 10

		
	END	

Figura 4 - Código em Assembly do programa 8051 Teste Serial.


Figura 5 - Apagando a memória EPROM com Luz Ultravioleta.


Figura 6 - Programando a memória EPROM com Minipro TL866 II plus.


Figura 7 - Placa 80C32 conectada ao computador pela porta serial.


Figura 8 - Mensagens iniciais enviadas do 80C32 para o computador.


Figura 9 - Frame da comunicação serial de 1 caractere medida com o osciloscópio.


Assista ao vídeo para ver como ficou nosso projeto:

Vídeo 1 - 80C32 EPROM - Projeto Teste Comunicação Serial com o 8051.





Referência:

NICOLOSI, D. E. C.; Laboratório de Microcontroladores: Treino de instruções, hardware e software. São Paulo: Érica, 2002.


quinta-feira, 4 de junho de 2015

Relógio Digital com o 8051

Que tal montar seu próprio Relógio Digital com um 8051?


Este artigo mostra o projeto de um Relógio Digital simples com 4 displays do tipo 7 Segmentos para fins didáticos.



Para a montagem é utilizada a lista de componentes:

- 1 microcontrolador da família 8051 (Atmel AT89S52);
- 4 displays 7 segmentos catodo comum (-);
- 4 transistores NPN BC337 para drive dos displays.
- 8 transistores PNP BC327 para drive dos segmentos.
- 2 botões para ajustes de hora e minuto;
- 1 cristal de 11,0592 MHz
- 2 capacitores de 33 pF para o cristal.
- 8 resistores de 330 ohms para os segmentos do display;
- 2 resistores de 10 kohms para pullup dos botões;
- 12 resistores de 10 kohms para acionamento dos transistores.

O circuito é alimentado com 5 Vcc.

O diagrama de interligação é mostrado na Figura 1.
 
Figura 1 - Diagrama do Relógio Digital.

A montagem pode ser feita em Matriz de Contatos. Veja a Figura 2.
 
Figura 2 - Montagem do Circuito em Matriz de Contatos.


O Vídeo a seguir mostra o Relógio Digital funcionando e a Simulação do circuito no Proteus.

 Vídeo 1 - Nosso Relógio Digital com o 8051 funcionando.


O programa do 8051

O programa do Relógio Digital foi escrito em Linguagem Assembly e pode ser compilado com os Compiladores ASM51 ou Keil. No Anexo 1 você encontra o código fonte.

A interrupção do Timer1 é utilizada como base de tempo para o relógio (clock).

O programa inicia no endereço 100H.

Após a inicialização algumas variáveis são carregadas com seus valores iniciais. 


O temporizador Timer1 é configurado para operar no modo 2: 8-bit com recarga automática. 

Os registros TL1 e TH1, carga e recarga do Timer1, são setados com valor (255 - 225).

No final das configurações são habilitadas as interrupções do Timer1 e global.

O Timer1 é inicializado.

O programa passa a rodar em um loop infinito verificando se os botões de ajustes de hora e minuto foram pressionados e atualizando o display.

A rotina de interrupção do Timer1 é chamada a cada 244,140625 us.
 
Os cálculos para definir a carga do Timer1 com valor (255 - 225) estão disponíveis no Quadro 1:


; CLOCK DO RELOGIO BASEADO NA INTERRUPCAO DO TIMER 1 
; OPERANDO NO MODO 1 - 8 BITS COM RECARGA AUTOMATICA
;
; CALCULOS
; FREQUENCIA DO CRISTAL f = 11.059.200 MHz
; PERIODO DO CRISTAL T = 1/f  =  9,04224537037037...e-8     s
; PERIODO DE UMA INSTRUCAO     = T * 12 =     1,085069444...e-6  s
; NUMERO DE INSTRUCOES EM 1 SEGUNDO = 921.600 IPS
; CARREGAMENTO DO TIMER 1 = 921.000 / 4096 = 225
; 4096 DECIMAL = 1000 HEXADECIMAL = 1 0000 0000 0000 BINARIO

Quadro 1 - Cálculos para definir o tempo da interrupção do Timer1.

As variáveis CONTADOR_L e CONTADOR_H armazenam o número de interrupções.

A cada 4096 interrupções (1000H em hexadecimal) é completado 1 segundo. A variável SEGUNDO é incrementada em 1 unidade e quando necessário as demais variáveis são incrementadas: 

- UNIDADE, para a unidade dos minutos do relógio;
- DEZENA, para dezena dos minutos do relógio;
- CENTENA, para a unidade das horas do relógio;
- MILHAR, para dezena das horas do relógio.

Este relógio possui o formato de 24 horas.

O acionamento do display é feito por multiplexação. Cada dígito fica ligado por um tempo de 1 ms. Pela cintilação do olho humano enxergamos os 4 displays acesos, mas na verdade apenas um se mantém ligado!

O horário do relógio é atualizado.

A cada 500 ms o "ponto" do relógio é invertido de status, para "piscar" a cada segundo.

Os "2 pontos" do relógio são formados invertendo-se a montagem do terceiro display de 7 segmentos em 180°.

Após compilar o seu projeto com o ASM51 ou Keil você deve programar o microcontrolador 8051 com o arquivo .hex. O vídeo 8051 - O primeiro projeto - Pisca LED - Compilação e Gravação do AT89S52  mostra um exemplo de como programar o AT89S52.



Você agora pode implementar o código e criar um horário de alarme para adicionar a função de despertador para o seu Relógio Digital!



Obs: 

Este é um circuito didático para ensinar o princípio de funcionamento de um relógio digital.


Para melhor precisão no relógio deve-se utilzar um Relógio de Tempo Real (Real Time Clock - RTC), como por exemplo o DS1302  com cristal de 32,768 kHz ou um microcontrolador com o módulo RTC interno.

Exemplos de circuitos com RTCC:
https://www.youtube.com/watch?v=zR0KW0H_dD4
https://www.youtube.com/watch?v=k_SVMvWyYak


O circuito também não pode ser desligado da alimentação, senão perde a hora, pois não tem bateria de backup.


Referência:

NICOLOSI, D. E. C.; Laboratório de Microcontroladores: Treino de instruções, hardware e software. São Paulo: Érica, 2002.



Anexo 1 - Código fonte do Relógio Digital com o 8051 em Assembly 

; ############ RELOGIO DIGITAL COM 4 DISPLAYS DE 7 SEGMENTOS ########################

; RELOGIO DIGITAL COM HORA MINUTO E 2 PONTOS
; AJUSTE DE HORA E MINUTO ATRAVES DE 2 TECLAS

; MICROCONTROLADOR 8051 - AT89S52
; COMPILADOR ASM51 ou Keil
; JUNHO/2013  M.R.G.

; SEGMENTOS DO DISPLAY NO PORT 3
; DISPLAY CATODO COMUM (-) 
; SEGMENTO ATIVO COM LOGICA NIVEL BAIXO (TRANSISTOR PNP PARA CADA SEGMENTO)

; DISPLAY UNIDADE P2.0
; DISPLAY DEZENA  P2.1
; DISPLAY CENTENA P2.2
; DISLAY MILHAR   P2.3

; BOTAO 1 P2.4
; BOTAO 2 P2.5

; CLOCK DO RELOGIO BASEADO NA INTERRUPCAO DO TIMER 1 
; OPERANDO NO MODO 1 - 8 BITS COM RECARGA AUTOMATICA
; CALCULOS
; FREQUENCIA DO CRISTAL f = 11.059.200 MHz
; PERIODO DO CRISTAL T = 1/f  =  9,04224537037037...e-8     s
; PERIODO DE UMA INSTRUCAO     = T * 12 =     1,085069444...e-6  s
; NUMERO DE INSTRUCOES EM 1 SEGUNDO = 921.600 IPS
; CARREGAMENTO DO TIMER 1 = 921.000 / 4096 = 225
; 4096 DECIMAL = 1000 HEXADECIMAL = 1 0000 0000 0000 BINARIO


$MOD51

; *************** DEFINE CONSTANTES   ********************************** 
        TEMPO10MS      EQU      9210
        TEMPO1MS       EQU      921
        DISPU          EQU      P2.0
        DISPD          EQU      P2.1
        DISPC          EQU      P2.2
        DISPM          EQU      P2.3
        BOTAO1         EQU      P2.4
        BOTAO2         EQU      P2.5

; ******************** DECLARACAO DE VARIAVEIS DA RAM ******************

        UNIDADE        EQU 60H       ;NUMERO
        DEZENA         EQU 61H       ;NUMERO
        CENTENA        EQU 62H       ;NUMERO
        MILHAR         EQU 63H       ;NUMERO
        UNIDADE7SEG    EQU 64H       ;CARACTERE
        DEZENA7SEG     EQU 65H       ;CARACTERE
        CENTENA7SEG    EQU 66H       ;CARACTERE
        MILHAR7SEG     EQU 67H       ;CARACTERE
        CONTADOR_L     EQU 68H       ;LSB CONTADOR INTERRUPCOES T1
        CONTADOR_H     EQU 69H       ;MSB CONTADOR INTERRUPCOES T1
        SEGUNDO        EQU 6AH       ;ARMAZENA OS SEGUNDOS
        PONTO          EQU 00H       ;BIT UTILIZADO PARA PISCAR 2 PONTOS

;*************** VETOR DE RESET ****************************************

        ORG    000H

        NOP
        NOP
        LJMP INICIO

;************ VETOR DE INTERRUPCAO DO TIMER    1***************************

        ORG  01BH

        LJMP INT_TIMER1

;************************** MAIN ***************************************
        ORG    100H

INICIO:    
        MOV SP, #30H    ;ALTERA ENDERECO DA BASE DA PILHA

;DESLIGA DISPLAYS
        MOV P3, #0FFH    ;DESATIVA TODOS OS SEGMENTOS
        CLR DISPU         ;DESATIVA TODOS OS DISPLAY
        CLR DISPD
        CLR DISPC
        CLR DISPM


;INICIALIZA VARIAVEIS DA RAM
        MOV        UNIDADE, #0        
        MOV        DEZENA, #0        
        MOV        CENTENA, #0        
        MOV        MILHAR, #0        
        MOV        CONTADOR_L, #0    
        MOV        CONTADOR_H, #0    
        MOV        SEGUNDO, #0
        CLR        PONTO        


;CONFIGURA TIMERS

        MOV    TMOD,#00100001B   ;TIMER 0 MODO 1 - 16 BITS
                                 ;TIMER 1 MODO 2 - 8 BITS COM RECARGA AUTOMATICA
        MOV TL1, #(255 - 225)    ;CARGA DO TIMER 1
        MOV TH1, #(255 - 225)    ;RECARGA DO TIMER 1


        LCALL ESCREVE7SEG        ;TESTE DISPLAYS


        SETB EA                 ;HABILITA FLAG DE INTERRUPCAO GERAL
        SETB ET1                ;HABILITA FLAG DE INTERRUPCAO DO TIMER 1
        
        SETB TR1                ;INICIA TEMPORIZADOR TIMER1



LOOP:
        JB BOTAO1, TESTA_BT2        ;SE TECLA NAO PRESSIONADA(1) DESVIA
        LCALL ACERTA_MINUTO
TESTA_BT2:
        JB BOTAO2, ACIONA_DISPLAY   ;SE TECLA NAO PRESSIONADA(1) DESVIA
        LCALL ACERTA_HORA
ACIONA_DISPLAY:
        LCALL ATUALIZA_DISPLAY

        LJMP LOOP





;AJUSTE MANUAL DO MINUTO PELO BOTAO 1
ACERTA_MINUTO:
        INC UNIDADE
        MOV A, UNIDADE
        CJNE A, #10D, INCREMENTO_MIN_FIM
ACERTA_DEZ_MINUTO:
        MOV UNIDADE, #0
        INC DEZENA
        MOV A, DEZENA
        CJNE A, #06D, INCREMENTO_MIN_FIM
        MOV DEZENA, #0
INCREMENTO_MIN_FIM:
        RET


;AJUSTE MANUAL DA HORA PELO BOTAO 2
ACERTA_HORA:
        INC CENTENA
        MOV A, CENTENA
        CJNE A, #04D, ACERTA_DEZ_HORA        ;VERIFICA SE COMPLETOU 24 HORAS
        MOV A, MILHAR
        CJNE A, #02D, INCREMENTO_HORA_FIM
        MOV CENTENA, #0                      ;COMPLETOU 24 HORAS ZERA O RELOGIO
        MOV    MILHAR, #0
        AJMP INCREMENTO_HORA_FIM
ACERTA_DEZ_HORA:
        CJNE A, #10D, INCREMENTO_HORA_FIM
        MOV CENTENA, #0
        INC MILHAR
INCREMENTO_HORA_FIM:
        RET





;SUBROTINA PARA ESCRITA NOS DISPLAY
ESCREVE7SEG:
        MOV P3, #00000000B    ;ACENDE TODOS OS SEGMENTOS
        LCALL MUX7SEG

;SUBROTINA MULTIPLEXA NUMERO NO DISPLAY    - VISUALIZA 1 DISPLAY ACESO POR VEZ
MUX7SEG:
          CLR DISPU           ;DESATIVA TODOS OS DISPLAY
        CLR DISPD
        CLR DISPC
        CLR DISPM

        SETB DISPU            ;LIGA DISPLAY DA UNIDADE
        LCALL DELAY500MS      ;DELAY
        CLR DISPU             ;DESLIGA DISPLAY DA UNIDADE
        NOP

        SETB DISPD            ;LIGA DISPLAY DA DEZENA
        LCALL DELAY500MS      ;DELAY
        CLR DISPD             ;DESLIGA DISPLAY DA DEZENA
        NOP

        SETB DISPC            ;LIGA DISPLAY DA CENTENA
        LCALL DELAY500MS      ;DELAY
        CLR DISPC             ;DESLIGA DISPLAY DA CENTENA
        NOP

        SETB DISPM            ;LIGA DISPLAY DO MILHAR
        LCALL DELAY500MS      ;DELAY
        CLR DISPM             ;DESLIGA DISPLAY DO MILHAR
        NOP

          RET


; ############## ATUALIZA DISPLAY 7 SEGMENTOS ##########################
ATUALIZA_DISPLAY:

    
        LCALL CONVERTE            ;CONVERTE NUMERO NO CARACTER CORRESPONDENTE 
                                  ;PARA O DISPLAY 7 SEGMENTOS

           MOV R3, #50D           ;4 X 50 X 1ms  = 200 ms

;FAZ A MULTIPLEXACAO DOS 4 DISPLAYS DE 7 SEGMENTOS
LOOP_DISPLAY_CONT2:
        MOV P3, UNIDADE7SEG    ;MOVE CARACTER DA UNIDADE PARA DISPLAY
        NOP
        NOP
        SETB DISPU            ;LIGA DISPLAY DA UNIDADE
        LCALL DELAY1MS        ;DELAY
        CLR DISPU             ;DESLIGA DISPLAY DA UNIDADE
        NOP
        NOP

        MOV A, DEZENA7SEG    ;MOVE CARACTER DA DEZENA PARA ACC
        MOV C, PONTO         ;MOVE VALOR DO PONTO DECIMAL
        MOV ACC.7, C
        MOV P3, A            ;MOVE CARACTER DA DEZENA PARA DISPLAY COM PONTO
        NOP
        NOP
        SETB DISPD            ;LIGA DISPLAY DA DEZENA
        LCALL DELAY1MS        ;DELAY
        CLR DISPD             ;DESLIGA DISPLAY DA DEZENA
        NOP
        NOP

        MOV A, CENTENA7SEG    ;MOVE CARACTER DA CENTENA PARA ACC
        MOV C, PONTO          ;MOVE VALOR DO PONTO DECIMAL
        MOV ACC.7, C
        MOV P3, A             ;MOVE CARACTER DA CENTENA PARA DISPLAY COM PONTO
        NOP 
        NOP
        SETB DISPC            ;LIGA DISPLAY DA CENTENA
        LCALL DELAY1MS        ;DELAY
        CLR DISPC             ;DESLIGA DISPLAY DA CENTENA
        NOP
        NOP

        MOV P3, MILHAR7SEG    ;MOVE CARACTER DO MILHAR PARA DISPLAY
        NOP
        NOP
        SETB DISPM            ;LIGA DISPLAY DO MILHAR
        LCALL DELAY1MS        ;DELAY
        CLR DISPM             ;DESLIGA DISPLAY DO MILHAR
        NOP
        NOP

        DJNZ R3, LOOP_DISPLAY_CONT2    ;DECREMENTA E VERIFICA SE TERMINOU OS 50 LOOPS

        RET


;  ---------------------------------------------------------

;CONVERTE NUMERO NO CARACTER CORRESPONDENTE 
CONVERTE:
        MOV A, UNIDADE
        LCALL COMPARA
        MOV UNIDADE7SEG, A

        MOV A, DEZENA
        LCALL COMPARA
        MOV DEZENA7SEG, A

        MOV A, CENTENA
        LCALL COMPARA
        MOV CENTENA7SEG, A
        
        MOV A, MILHAR
        LCALL COMPARA
        MOV MILHAR7SEG, A

        RET



;COMPARA E CARREGA ACC COM VALOR DO CARACTER 7 SEGMENTO
;CORRESPONDENTE AO ALGARISMO DECIMAL 
COMPARA:
       CJNE A, #0D, COMPARA1
       MOV A, #11000000B    ;CARACTER 0
       RET
COMPARA1:
       CJNE A, #1D, COMPARA2
       MOV A, #11111001B    ;CARACTER 1
       RET
COMPARA2:
       CJNE A, #2D, COMPARA3
       MOV A, #10100100B    ;CARACTER 2
       RET
COMPARA3:
       CJNE A, #3D, COMPARA4
       MOV A, #10110000B    ;CARACTER 3
       RET
COMPARA4:
       CJNE A, #4D, COMPARA5
       MOV A, #10011001B    ;CARACTER 4
       RET
COMPARA5:
       CJNE A, #5D, COMPARA6
       MOV A, #10010010B    ;CARACTER 5
       RET
COMPARA6:
       CJNE A, #6D, COMPARA7
       MOV A, #10000010B    ;CARACTER 6
       RET
COMPARA7:
       CJNE A, #7D, COMPARA8
       MOV A, #11111000B    ;CARACTER 7
       RET
COMPARA8:
       CJNE A, #8D, COMPARA9
       MOV A, #10000000B    ;CARACTER 8
       RET
COMPARA9:
       CJNE A, #9D, COMPARA_ERRO
       MOV A, #10010000B    ;CARACTER 9
       RET
COMPARA_ERRO:                ;ERRO - NAO E ALGARISMO DECIMAL 0 A 9
       MOV A, #0000000B      ;ACENDE TODOS SEGMENTOS
       RET





;SUBROTINA DE DELAY
DELAY500MS:
        MOV R0, #50D                        ;50 X 10 MS = 500 MS
DELAY10MS:                                  
        MOV TL0, #LOW (65535-TEMPO10MS)     ;CARREGA VALOR PARA TIMER 0
        MOV TH0, #HIGH(65535-TEMPO10MS)
        SETB TR0                           ;LIGA TIMER 0
        JNB TF0, $                         ;AGUARDA FIM DA CONTAGEM
        CLR TR0                            ;LIMPA FLAG
        CLR TF0
        DJNZ R0, DELAY10MS                 ;DECREMENTA E VERIFICA SE TERMINOU OS 50 LOOPS
        RET



;DELAY UNICO 1 MS
DELAY1MS:                                  
        MOV TL0, #LOW (65535-TEMPO1MS)   ;CARREGA VALOR PARA TIMER 0
        MOV TH0, #HIGH(65535-TEMPO1MS)
        SETB TR0                         ;LIGA TIMER 0
        JNB TF0, $                       ;AGUARDA FIM DA CONTAGEM
        CLR TR0                          ;LIMPA FLAG
        CLR TF0
        RET


DELAY20CICLO:
        MOV R4, #20
        DJNZ R4, $                        ;DELAY 
        RET


; ############# SUBROTINA DE TRATAMENTO DE INTERRUPCAO DO TIMER 1 ###########
INT_TIMER1:
        PUSH PSW                 ;ARMAZENA VALORES DOS REGISTROS PRINCIPAIS
        PUSH ACC

        MOV A, CONTADOR_L        ;MOVE BYTE LSB DO CONTADOR PARA ACC
        ADD A, #1D               ;INCREMENTA UMA UNIDADE
        JNC    COMPARA_CONT_L    ;DESVIA SE CARRY = 0 - VERIFICA OVERFLOW
        CLR A                    ;ZERA BYTE LSB SE MAIOR QUE 255
        INC CONTADOR_H           ;INCREMENTA CONTADOR H

; COMPARA SE COMPLETOU MEIO SEGUNDO = 0800H OU 1 SEGUNDO = 1000H
COMPARA_CONT_L:
        MOV CONTADOR_L, A        ;RETORNA VALOR DE ACC PARA CONTADOR

        CJNE A, #00D , INT_FIM   ; SE NAO COMPLETOU TEMPO SAI DA INTERRUPCAO

COMPARA_CONT_H:        
        MOV A, CONTADOR_H         ; MOVE BYTE MSB DO CONTADOR PARA ACC
        CJNE A, #08H , COMPARA_1SEG  ; SE NAO COMPLETOU MEIO SEGUNDO DESVIA
        CPL    PONTO                ; COMPLETOU MEIO SEGUNDO INVERTE 2 PONTOS
COMPARA_1SEG:
         CJNE A, #10H , INT_FIM  ; SE NAO COMPLETOU 1 SEGUNDO SAI DA INTERRUPCAO

        MOV CONTADOR_H, #0       ;LIMPA CONTADOR
INCREMENTA_1SEG:
        INC SEGUNDO              ;INCREMENTA SEGUNDO
        CPL PONTO                ; COMPLETOU MEIO SEGUNDO INVERTE 2 PONTOS
        MOV A, SEGUNDO
        CJNE A, #60D, INCREMENTO_FIM  ;VERIFICA SE COMPLETOU 1 MINUTO

INC_UNI_MINUTO:
        MOV SEGUNDO, #0
        INC UNIDADE
        MOV A, UNIDADE
        CJNE A, #10D, INCREMENTO_FIM
INC_DEZ_MINUTO:
        MOV UNIDADE, #0
        INC DEZENA
        MOV A, DEZENA
        CJNE A, #06D, INCREMENTO_FIM
INC_UNI_HORA:
        MOV DEZENA, #0
        INC CENTENA
        MOV A, CENTENA
        CJNE A, #04D, INC_DEZ_HORA            ;VERIFICA SE COMPLETOU 24 HORAS
        MOV A, MILHAR
        CJNE A, #02D, INCREMENTO_FIM
        MOV CENTENA, #0                       ;COMPLETOU 24 HORAS ZERA O RELOGIO
        MOV    MILHAR, #0
        AJMP INCREMENTO_FIM
INC_DEZ_HORA:
        CJNE A, #10D, INCREMENTO_FIM
        MOV CENTENA, #0
        INC MILHAR



INCREMENTO_FIM:        


INT_FIM:
        CLR TF1            ;LIMPA FLAG DE INTERRUPCAO DO TIMER 1

        POP ACC            ;RESTAURA VALORES DOS REGISTROS PRINCIPAIS
        POP PSW

        RETI               ;RETORNA DA INTERRUPCAO
        
        END