Ir ao conteúdo
  • Cadastre-se
Entre para seguir isso  
Lipextreme

[Resolvido] Contador com display 7 segmentos Assembly

Recommended Posts

Boa noite pessoal, sou novo no fórum e preciso de uma ajuda se possível, é quanto a um programa que estou montando em Assembly, utilizando um PIC16F877A o mesmo se refere a um contador com um botão de incremento e outro botão de decremento, este contador vai de 0 a 9999, ou seja utiliza 4 displays sete segmentos, eu criei o programa e está funcionando normalmente, tanto o incremento quanto o decremento, porém a contagem só vai até 255 e depois volta ao zero, como faço para que ele prossiga a contagem? Tem algo a ver com o estouro de registrador? O pic tem algum limite para contagem?

Desde já agradeço a atenção!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Poste o código,mas provavelmente voce deve saber que qualquer micro de 8 bits,geralmente,tem registradores de uso geral em 8 bits(255).

Neste caso voce terá que montar uma rotina para usar dois registradores.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

porém a contagem só vai até 255 e depois volta ao zero,

O registrador chegou ao limite e reiniciou a contagem.

como citado acima, um registrador de 8 bits somente armazena valores de 0 a 255, no caso 2^8 = 256. Uma solução seria usar um registrador para os dois primeiros digitos e um outro para os dois ultimos digitos, fazendo-os contar até 99 cada um dos registradores.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa noite vtrx, obrigado pela informação realmente eu não sabia que os registradores de 8 bits eram de 255, agradeço muito a ajuda!:)

Poste o código....

vtrx segue código utilizado! Após incremento e decremento dos botões é "chamado" as rotinas abaixo:



radix dec

variable RAM_MAIN = 0x20
variable RAM_INCLUDE = 0x1A0 ; direcionando para o banco 3
; as variáveis das bibliotecas
variable RAM_TRANSF = 0x70 ; área de transferência
; 0x70 ~ 0x7F todos os bancos
variable v_spbrg

#define max_bank 0x1EF; colocado o máximo valor do banco
; escolhido para RAM_INCLUDE
; no caso foi escolhido o banco 3 (0x120~0x16F)

#include <p16f877a.inc>

#define FOSC 20000000

#ifndef FOSC; ifndef é igual se não definido !
error "FOSC não definido!!"
#endif

#if FOSC <= 4000000
#define XTAL _XT_OSC
#endif

#if FOSC > 4000000
#define XTAL _HS_OSC
#endif

#if FOSC > 20000000
error "oscilador definido fora da faixa"
#endif

cblock RAM_MAIN

ponteiro_ ;0X20
contador:1 ;0X21com apenas 1 byte
unidade ;0X22
dezena ;0X23
centena
milhar
quantidade ;0X24
STACKPOINTER;0X25
endc

RAM_MAIN = RAM_MAIN + .2

#if RAM_MAIN > 0x6F
#error " Você está escrevendo em local proibido de RAM "
#endif

cblock RAM_TRANSF
pclath_temp
w_temp
status_temp
fsr_temp
endc
RAM_TRANSF = RAM_TRANSF + .4

#if RAM_TRANSF > 0x7F
#error " Você está escrevendo em local proibido de RAM "
#endif

;__fuses
__config _CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _PWRTE_ON & _WDT_OFF & XTAL

org 0x0000 ;início do programa
goto configura


org 0x0004 ;atendimento de interrupções
retfie

configura

banksel 0x80 ; mesmo que bank1
movlw 0x0f ; movlw b'00001111' movlw .15
movwf TRISA
clrf TRISB
movlw b'00000000'
movwf TRISC ;
clrf TRISD
clrf TRISE

movlw 0x07
movwf ADCON1; PORTA e PORTE como digital




banksel 0x05 ; mesmo que bank0
movlw 0xA0
movwf STACKPOINTER ; inicializando o STACKPOINTER
; no banco 1 valores entre 0xA0 e 0xEF
clrf PORTA
clrf PORTB
clrf PORTC
clrf PORTD
clrf PORTE
clrf contador
clrf unidade
clrf dezena
clrf centena
clrf milhar
clrf quantidade

zero
movlw .0 ;Faz aparecer o numero 0 como numero inical
movwf contador
call quantidade_bcd
call atualiza_display

main

btfss PORTA, 2
goto zero
btfsc PORTA,0
goto decremento
call quantidade_bcd
call atualiza_display
btfsc PORTA,0
goto main
incf contador,F
call quantidade_bcd
call atualiza_display

volta_01

call quantidade_bcd
call atualiza_display
btfss PORTA,0
goto $-5
goto main

decremento

btfsc PORTA,1
goto atual_0
call quantidade_bcd
call atualiza_display
btfsc PORTA,1
goto main
decf contador,F
call quantidade_bcd
call atualiza_display

volta_02

call quantidade_bcd
call atualiza_display
btfss PORTA,1
goto $-5
goto main

atual_0 ;Subrotina onde não é realizado o incrmento, apenas mantem o valor atual

call quantidade_bcd
call atualiza_display
goto main

quantidade_bcd
clrf unidade
clrf dezena
clrf centena ;NEW
clrf milhar ;NEW
movf contador,W
movwf quantidade; indiretamente quantidade <-- contador
volta
movf quantidade,F
btfsc STATUS,Z
return

decf quantidade,F
incf unidade,F

movf unidade,W ; comparando com .10
sublw .10
btfss STATUS,Z
goto volta

clrf unidade
incf dezena,F

movf dezena,W
sublw .10
btfss STATUS,Z
goto volta

clrf dezena
incf centena,F

movf centena,W
sublw .100
btfss STATUS,Z
goto volta

clrf centena
incf milhar,F

movf milhar,W
sublw .1000
btfss STATUS,Z
goto volta

return


;inicio atualiza_display
atualiza_display

movf milhar,W
lcall tabela
pagesel atualiza_display
banksel PORTB
movwf PORTB
bsf PORTC,4
movlw .8 ;milhar
call delay_ms
bcf PORTC,4
movlw .1
call delay_ms

movf centena,W
lcall tabela
pagesel atualiza_display
banksel PORTB
movwf PORTB
bsf PORTC,5
movlw .8 ;centena
call delay_ms
bcf PORTC,5
movlw .1
call delay_ms

movf dezena,W
lcall tabela
pagesel atualiza_display
banksel PORTB
movwf PORTB
bsf PORTC,6 ;dezena
movlw .8
call delay_ms
bcf PORTC,6
movlw .1
call delay_ms

movf unidade,W
lcall tabela
pagesel atualiza_display
banksel PORTB
movwf PORTB ;unidade
bsf PORTC,7
movlw .8
call delay_ms
bcf PORTC,7
movlw .1
call delay_ms

org 0x1200

pagesel tabela

tabela

movwf ponteiro_
movlw high tabela_conv
movwf PCLATH
movf ponteiro_,W
andlw b'00001111'
movwf ponteiro_
movlw low tabela_conv
addwf ponteiro_,W
btfsc STATUS,C
incf PCLATH,F
movwf PCL

tabela_conv

;hgfedcba
retlw b'00111111' ; '0'
retlw b'00000110' ; '1'
retlw b'01011011' ; '2'
retlw b'01001111' ; '3'
retlw b'01100110' ; '4'
retlw b'01101101' ; '5'
retlw b'01111101' ; '6'
retlw b'00000111' ; '7'
retlw b'01111111' ; '8'
retlw b'01101111' ; '9'
retlw b'00000000' ; ' '
retlw b'00000000' ; ' '
retlw b'00000000' ; ' '
retlw b'00000000' ; ' '
retlw b'00000000' ; ' '
retlw b'00000000' ; ' '

end
processor PIC16F877A; 

Uma solução seria usar um registrador para os dois primeiros digitos e um outro para os dois ultimos digitos, fazendo-os contar até 99 cada um dos registradores.

Moley muito obrigado pela ajuda também, a ideia foi perfeita quanto a realizar a contagem através de dois registradores, vou realizar os testes aqui e logo mais eu posto o resultado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa noite Moley tentei seguir as suas dicas, 2 displays eu armazeno a contagem até 99 com um registrador PCL, porém os outros dois eu não sei em qual registrador armazenar a contagem.

Obrigado Moley e vtrx.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você complicou demais a situação, os registradores para uso dessa aplicação são os da memoria de uso geral.

veja esse exemplo:


;******************************************************************************
; CONTADOR UP DOWN COM RESET
; COMPILADO EM 14/08/2013
;******************************************************************************


list p=16f877A
#INCLUDE <p16f877A.inc>

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _LVP_OFF & _CPD_OFF & _DEBUG_OFF
ERRORLEVEL -302

;******************************************************************************
;************************MACROS PARA MUDANÇA DE BANCOS*************************
;******************************************************************************

BANK0 MACRO ; macro para selecionar banco 0
BCF STATUS,RP0 ; clear rp0
BCF STATUS,RP1 ; clear rp1
ENDM
BANK1 MACRO ; macro para selecionar banco 1
BSF STATUS,RP0 ; set rp0
BCF STATUS,RP1 ; clear rp1
ENDM
;******************************************************************************
;***************NOMEIA ENTRADAS E SAIDAS PARA SIMPLIFICAR**********************
;******************************************************************************


#DEFINE DSP_4 PORTC,4 ;DISPLAY 4
#DEFINE DSP_3 PORTC,5 ;DISPLAY 3
#DEFINE DSP_2 PORTC,6 ;DISPLAY 2
#DEFINE DSP_1 PORTC,7 ;DISPLAY 1
#DEFINE DADOS_DSP PORTB ;DADOS DOS DISPLAYS
#DEFINE BT_INCREMENTA PORTA,0 ;BOTAO INCREMENTA
#DEFINE BT_DECREMENTA PORTA,1 ;BOTAO DECREMENTA
#DEFINE BT_RST_CONTAGEM PORTA,2 ;BOTAO RESET

;******************************************************************************
;***************************DEFINE AS VARIAVEIS NA RAM*************************
;******************************************************************************

CBLOCK H'20'
W_TEMP
STATUS_TEMP
PCLATH_TEMP
TEMP_FSR
UNIDADE
UNIDADE_
DEZENA
DEZENA_
CENTENA
CENTENA_
MILHAR
MILHAR_
DISPLAY
ENDC

;******************************************************************************
;*********************************RESET****************************************
;******************************************************************************

ORG 0x0000
GOTO START

;******************************************************************************
;*********************************INTERRUPCAO**********************************
;******************************************************************************

ORG 0x0004
MOVWF W_TEMP
MOVF STATUS,W
MOVWF STATUS_TEMP
MOVF PCLATH,W
MOVWF PCLATH_TEMP

BTFSS INTCON,T0IF
GOTO SAIR
BCF INTCON,T0IF
MOVLW .132
MOVWF TMR0
CLRF PORTC
INCF DISPLAY,F
MOVF DISPLAY,W
ADDWF PCL,F
NOP
GOTO MOSTRA_UNIDADE
GOTO MOSTRA_DEZENA
GOTO MOSTRA_CENTENA
CLRF DISPLAY
GOTO MOSTRA_MILHAR

SAIR

MOVF PCLATH_TEMP,W
MOVWF PCLATH
MOVF STATUS_TEMP,W
MOVWF STATUS
MOVF W_TEMP,W
RETFIE


;******************************************************************************
;**************************PROGRAMA PRINCIPAL**********************************
;******************************************************************************

START
CALL CONFIG_HARD_SOFT
CALL INICIALIZA_VARIAVEIS
CALL CHECA_BOTOES
GOTO $-1

;******************************************************************************
;***********ROTINA PARA CONFIGURAR ENTRADAS E SAIDAS E INTERRUPCOES************
;******************************************************************************


CONFIG_HARD_SOFT
BANK1
MOVLW b'11111111'
MOVWF TRISA ; SETA PORTA COMO ENTRADA
MOVLW b'00000000'
MOVWF TRISB ; SETA PORTB COMO SAIDA
MOVLW b'00000000'
MOVWF TRISC ; SETA PORTC COMO SAIDA
MOVLW b'00000000'
MOVWF TRISD ; SETA PORTD COMO SAIDA
MOVLW b'00000000'
MOVWF TRISE ; SETA PORTE COMO SAIDA
MOVLW b'10000111'
MOVWF OPTION_REG ; PULL UP DESABILITADOS E TMR0 1:256
MOVLW b'11100000'
MOVWF INTCON ;INTERRUPÇÃO TIMER0 HABILITADA
MOVLW b'00000110'
MOVWF ADCON1
BANK0
RETURN

;******************************************************************************
;*************************ROTINA PARA INICIAR VARIAVEIS************************
;******************************************************************************

INICIALIZA_VARIAVEIS ; INICIA VARIAVEIS
CLRF DISPLAY
CLRF UNIDADE
CLRF CENTENA
CLRF DEZENA
CLRF MILHAR
CLRF UNIDADE_
CLRF DEZENA_
CLRF CENTENA
CLRF MILHAR_
MOVLW .132 ; INICIA TIMER 0
MOVWF TMR0
RETURN

;******************************************************************************
;***************CHECA SE ALGUM BOTAO FOI PRECIONADO****************************
;******************************************************************************

CHECA_BOTOES
BTFSS BT_INCREMENTA ;CHECA BOTAO DE INCREMENTA
CALL INCREMENTA
BTFSS BT_DECREMENTA ; CHECA BOTAO DE DECREMENTA
CALL DECREMENTA
BTFSS BT_RST_CONTAGEM ;CHECA BOTAO DE RESET
CALL RESET_CONTAGEM
CALL ATUALIZA_DSP ; ATUALIZA E CONVERTE PARA 7 SEGMENTOS
RETURN

;******************************************************************************
;**********************ROTINA PARA INCREMENTAR VALORES*************************
;******************************************************************************

INCREMENTA
BTFSS BT_INCREMENTA
GOTO $-1
INCF UNIDADE,F
MOVLW .10
XORWF UNIDADE,W
BTFSS STATUS,Z ;SE ATINGIU 10, ZERA REGISTRADOR E INCREMENTA 1 NA DEZENA
RETURN
CLRF UNIDADE
INCF DEZENA,F
MOVLW .10
XORWF DEZENA,W
BTFSS STATUS,Z ;SE ATINGIU 10, ZERA REGISTRADOR E INCREMENTA 1 NA CENTENA
RETURN
CLRF DEZENA
INCF CENTENA,F
MOVLW .10
XORWF CENTENA,W
BTFSS STATUS,Z ;SE ATINGIU 10, ZERA REGISTRADOR E INCREMENTA 1 NA MILHAR
RETURN
CLRF CENTENA
INCF MILHAR,F
MOVLW .10
XORWF MILHAR,W
BTFSS STATUS,Z
RETURN
CLRF MILHAR
RETURN

;******************************************************************************
;**********************ROTINA PARA DECREMENTAR VALORES*************************
;******************************************************************************


DECREMENTA
BTFSS BT_DECREMENTA
GOTO $-1
DECF UNIDADE,F
MOVLW .255
XORWF UNIDADE,W
BTFSS STATUS,Z ;SE ATINGIU 255, COLOCA 9 NO REGISTRADOR E DECREMENTA 1 NA DEZENA
RETURN
MOVLW .9
MOVWF UNIDADE
DECF DEZENA,F
MOVLW .255
XORWF DEZENA,W
BTFSS STATUS,Z ;SE ATINGIU 255, COLOCA 9 NO REGISTRADOR E DECREMENTA 1 NA CENTENA
RETURN
MOVLW .9
MOVWF DEZENA
DECF CENTENA,F
MOVLW .255
XORWF CENTENA,W
BTFSS STATUS,Z ;SE ATINGIU 255, COLOCA 9 NO REGISTRADOR E DECREMENTA 1 NA MILHAR
RETURN
MOVLW .9
MOVWF CENTENA
DECF MILHAR,F
MOVLW .255
XORWF MILHAR,W
BTFSS STATUS,Z
RETURN
MOVLW .9
MOVWF MILHAR
RETURN

;******************************************************************************
;************************* ROTINA PARA ZERAR O CONTADOR************************
;******************************************************************************


RESET_CONTAGEM
BTFSS BT_RST_CONTAGEM
GOTO $-1
CLRF UNIDADE
CLRF DEZENA
CLRF CENTENA
CLRF MILHAR
RETURN

;******************************************************************************
;*********ROTINA PARA MOSTRAR VALORES NOS RESPECTIVOS DISPLAYS*****************
;******************************************************************************


MOSTRA_UNIDADE
MOVF UNIDADE_,W
MOVWF PORTB
BSF DSP_1
GOTO SAIR
MOSTRA_DEZENA
MOVF DEZENA_,W
MOVWF PORTB
BSF DSP_2
GOTO SAIR
MOSTRA_CENTENA
MOVF CENTENA_,W
MOVWF PORTB
BSF DSP_3
GOTO SAIR
MOSTRA_MILHAR
MOVF MILHAR_,W
MOVWF PORTB
BSF DSP_4
GOTO SAIR

;******************************************************************************
;*********ESTA ROTINA RECEBE VALORES CONVERTIDOS JA EM 7 SEGMENTOS*************
;******************************************************************************

ATUALIZA_DSP
MOVF UNIDADE,W
CALL CONVERTE
MOVWF UNIDADE_
MOVF DEZENA,W
CALL CONVERTE
MOVWF DEZENA_
MOVF CENTENA,W
CALL CONVERTE
MOVWF CENTENA_
MOVF MILHAR,W
CALL CONVERTE
MOVWF MILHAR_
RETURN
;******************************************************************************
;***************ESTA ROTINA CONVERTE DE DECIMAL PARA 7 SEGMENTOS***************
;******************************************************************************

CONVERTE
ADDWF PCL,F
RETLW B'00111111'
RETLW B'00000110'
RETLW B'01011011'
RETLW B'01001111'
RETLW B'01100110'
RETLW B'01101101'
RETLW B'01111101'
RETLW B'00000111'
RETLW B'01111111'
RETLW B'01100111'
RETLW B'00111111'
RETLW B'00000000'
RETLW B'00000000'
RETLW B'00000000'


END

Compartilhar este post


Link para o post
Compartilhar em outros sites
Você complicou demais a situação, os registradores para uso dessa aplicação são os da memoria de uso geral.

Boa noite Moley realmente o programa ficou muito mais organizado e de fácil entendimento agora, consegui entender com muito mais clareza a aplicação dos registradores nesse código, também achei perfeita a utilização do TIMER 0 para auxiliar na atualização dos displays, vou realizar os testes necessários e logo posto os resultados, muito obrigado novamente!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Moley muito obrigado pela ajuda, funcionou perfeitamente o código, a partir de agora vou estruturar todos os meus programas com base no na sua organização, pois o entendimento se torna muito mais fácil, fico muito agradecido pelo auxilio!

vtrx obrigado também pela ajuda a respeito do estouro do registrador!

Antes de fechar o tópico: Moley se não for incomodo você poderia me tirar uma última dúvida, no trecho do programa abaixo onde você utilizou o TIMER 0 eu consegui entender perfeitamente a utilização do mesmo a ligação dos pinos GIE, T0IF... porém o que eu fiquei em duvida foi a respeito do ponto em destaque .132 acredito eu que seja o tempo, porém como o mesmo foi definido? através de cálculos? ou você determinou que seria .132 por intuição?

BTFSS INTCON,T0IF ;VERIFICA SE TIMER ESTOUROU 255?

GOTO SAIR

BCF INTCON,T0IF ;SE SIM, DESLIGA T0IF E MOVE .132 PARA TMR0

MOVLW .132

MOVWF TMR0

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
porém o que eu fiquei em duvida foi a respeito do ponto em destaque .132 acredito eu que seja o tempo, porém como o mesmo foi definido? através de cálculos? ou você determinou que seria .132 por intuição?

BTFSS INTCON,T0IF ;VERIFICA SE TIMER ESTOUROU 255?

GOTO SAIR

BCF INTCON,T0IF ;SE SIM, DESLIGA T0IF E MOVE .132 PARA TMR0

MOVLW .132

MOVWF TMR0

Veja bem:


BTFSS INTCON,T0IF ; Checa se a interrupção foi gerada pelo timer0
GOTO SAIR ; se não foi gerada por timer0, sai da interrupção
BCF INTCON,T0IF ; se foi gerada por timer0 limpa o bit que sinaliza interrupção de timer0 para poder habilitar a próxima interrupção
MOVLW .132
MOVWF TMR0 ; carrega 132 em decimal no timer0, o timer incrementará 1 no registrador a cada 256 ciclos de máquina, pois:

MOVLW b'10000111'
MOVWF OPTION_REG ; prescaler associado a timer0 e prescaler 1:256

;1 ciclo de máquina na família 16F é igual a o período da frequência multiplicado por 4, portanto: 1/20Mhz = período = 50nS = 0,00000005S multiplicado por 4 que é 1 ciclo de máquina, 0,00000005*4 = 0,0000002S = 200nS.
Bem, (1ciclo * prescaler * restante para estouro do timer) = periodo para interrupção do timer0
0,0000002*256*(256-132) = 6,35mS
1/6,35mS = 157,5Hz/4 displays = 39,38Hz (essa é a taxa de atualização dos 4 displays)

obs1: caso você observe os displays a piscar, poderá aumentar esse valor:
MOVLW .132 <-----
MOVWF TMR0

obs2: (256-132) = quantidade restante para estouro do timer. 256 = registrador de 8 bits

obs3: 1/6,35mS = com o inverso do período encontramos a frequência

Compartilhar este post


Link para o post
Compartilhar em outros sites
Veja bem:


BTFSS INTCON,T0IF ; Checa se a interrupção foi gerada pelo timer0
GOTO SAIR ; se não foi gerada por timer0, sai da interrupção
BCF INTCON,T0IF ; se foi gerada por timer0 limpa o bit que sinaliza interrupção de timer0 para poder habilitar a próxima interrupção
MOVLW .132
MOVWF TMR0 ; carrega 132 em decimal no timer0, o timer incrementará 1 no registrador a cada 256 ciclos de máquina, pois:

MOVLW b'10000111'
MOVWF OPTION_REG ; prescaler associado a timer0 e prescaler 1:256

;1 ciclo de máquina na família 16F é igual a o período da frequência multiplicado por 4, portanto: 1/20Mhz = período = 50nS = 0,00000005S multiplicado por 4 que é 1 ciclo de máquina, 0,00000005*4 = 0,0000002S = 200nS.
Bem, (1ciclo * prescaler * restante para estouro do timer) = periodo para interrupção do timer0
0,0000002*256*(256-132) = 6,35mS
1/6,35mS = 157,5Hz/4 displays = 39,38Hz (essa é a taxa de atualização dos 4 displays)

obs1: caso você observe os displays a piscar, poderá aumentar esse valor:
MOVLW .132 <-----
MOVWF TMR0

obs2: (256-132) = quantidade restante para estouro do timer. 256 = registrador de 8 bits

obs3: 1/6,35mS = com o inverso do período encontramos a frequência

Moley, novamente muito obrigado, excepcional a explicação referente ao TIMER0, agradeço muito a colaboração! o problema está resolvido!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Caso o autor do tópico necessite, o mesmo será reaberto, para isso deverá entrar em contato com a moderação solicitando o desbloqueio.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Visitante
Este tópico está impedido de receber novos posts.
Entre para seguir isso  





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×