ESTUDOS 16F628/88

PARTE-2

agosto 2005 por alvaro luiz
"QUANDO UM POVO É EDUCADO AS DIFERENÇAS ENTRE AS CLASSES DESAPARECEM". (Confúcio)

Estudos feitos com o 16F628, Soft varrendo display, leds, saidas digitais e teclas, tudo multiplexado,tudo ocorrendo no software ISR. ; Esta discussão é parte de um projeto, onde foi utilizado o 12F675, houve economia em pinos (ports), assim acabou utilizando somente 3 pinos para atender as funções de: varrer 3 dígitos de 7 segmentos, 3 LEDs, 4 sadias digitais e ler 3 teclas. Analisando a complexidade e as soluções encontradas cheguei a conclusão que seria muito bom vermos este software, acredito que todos nós aprendemos um pouco mais, aqui vamos encontrar um pedaço de software Assembler em um nível complexo e com suas soluções. Aqui vamos aprender a usar as valiosas instrução que envolvem o registro Indexador "FSR" e o "RETLW xx" ; ============================================================================ Tomarei como base o circuito a seguir: ; ; Parte do Circuito do meu antigo projeto ============================================================================ ; Analise do Circuito: Temos 2 Circuitos tipo TTL 74HC595 deo 8 bits com entrada serial e saída Paralela, onde estão ligados em cascata, saída do CI-1 (9) ligado a entrada do CI-2 (14), então temos registros de saída paralela de 16 bits. Os três pinos da PORTB (RB6, 5 e 4) fazem toda a comunicação serial com estes dois CIs e pega dados sobre as 3 teclas K0,1,2. ; RB5, bidirecional como saída envia dados (D) para o CI-1 e como entrada recebe dados das teclas K0,1,2. RB6, como saída de clock (CLK), fazendo os dois CIs shift simultaneamente na subida do pulso clock. RB4, como LATCH nos CIs dois registros de 8 bits em cada um ; Os CIs tem 2 registros de 8 bits cada sendo um deles de deslocamento e o outro LATCH, que segura os dados quando houver subida do pulso LT e apresenta-os nas 8 saídas, tendo assim as 16 saídas. Eles tem que ser 74HC porque tipo LS ou outros não servirão por causa da impedância de entrada. ; ; Se quiser mais informação sobre o 74HC595 pegue o Manual aqui ; ; Então forneceremos a informação serial de 16 bits, o que comporta os dois chips seriais. Olhando o circuito vemos que os dados entram no pino 14 do CI-1, adotei o primeiro a entrar a saída "S3" e o último o segmento "a", entrarão nesta ordem com seus respectivos CLKs: ; CI-1 <-S3<-S2<-S1<-S0<-LED<-DY2<-DY1<-DY0<-pt<-g<-f<-e<-d<-c<-b<-a (direita/esquerda) ; Quando todos os bits entrarem nos CIs com seus respectivo CLKs, sendo o último (a), os CIs estarão ; prontos para receberem o pulso LT (LATCH), transferir para seus respectivos registros que terão acesso a ; saída Paralela. Os pinos 10 e 13 dos CIs são inibidores que no nosso projeto não são utilizados, então ; são habilitados com VCC e GND. ; A varredura dos displays e LEDS ocorrem no CI-1 e mais a metade baixa do ; CI-2, porque as sadias S0,1,2 e 3 são fixas, saídas digitais, não podem variar porque espera-se ligar ; amplificadores que irão até reles. ; O Display é formado de diodos tipo LED de cátodo comum e seus segmentos ; correspondem aos seus ânodos. Então aplicando V+ no segmento e GND no cátodo o segmento LED acenderá. ; Só precisamos limitar a corrente, quem faz isto são os 8 resistores, cujo valor poderá ser de 470R ; até 1K de 1/8, 1/16 Watts ou SMD, obtendo o máximo e mínimo brilho. Utilizei no meu projeto resistores de ; 1K e obtive bons resultados com brilho fraco mas satisfatório e menor consumo de corrente com menor ; aquecimento do regulador de 5VCC e dos CIs HC595. ; A leitura das teclas envolve um algoritmo, ou seja, ; uma técnica especifica ou uma ação dedicada, adotou-se: quando for a vez de varrer o DY0 antes vai ler a ; tecla K0, DY1 ler K1, DY2 ler K2 e LED ler K3, mas esta não foi usada. Procede-se da seguinte forma: ; faz-se uma carga serial, mas carregando 8 zeros para o CI-1 de segmentos e o novo valor do MUX para o ; CI-2. Isto porque na hora de ler a tecla não deverá haver nenhum segmento aceso senão a linha DYx ; não estará no ZERO ou GND mas sim acima de 1V o que causaria leitura errada de tecla e também deve-se ; fazer a inversão do sentido de RB5, estava como saída agora será entrada. Assim com o display apagado ; pode-se ler através de RB5 se a tecla foi acionada, Para quem está aprendendo será ótimo, para quem já ; sabe poderá servir para sua analise. Espero que tenha comentários a respeito de nosso trabalho. ; ; por exemplo: quando DY0=0 leva o GND pelo diodo D1 até um lado esquerdo tecla K0, se a tecla foi acionada ; a tensão do lado direito será zero que poderá ser sentida pela entrada RB5, caso não seja acionada o resistor ; R1 leva 5V até RB5. O Resistor R2 é para elevar a impedância deste ponto não causando curto, corrente ; desnecessária entre DYx e RB5, quando este for saída. Os diodos D1,2 e 3 asseguram que não ocorrerá retorno ; caso acione mais de uma tecla, ou seja, o curto entre DY0, DY1 e DY2. Quando acabar de fazer a leitura, ; colocar RB5 como saída novamente, e fazer nova carga nos dois CIs, agora com o valor dos segmentos ; correspondente ao digito a ser varrido. A mesma coisa quando for varrer o DY1 ler K1 e DY2 ler K2. Admitiria ; uma Quarta tecla, mas para este projeto não foi necessária. ; ============================================================================= ; Inicio da Construção do Software: ; Vamos utilizar o mesmo software Assembler já feito na PARTE-1, lá no inicio deste onde está sendo definidas ; a variáveis do sistema na RAM, vem os registros: ; cdig, dg0, dg1, dg2, led, rele ; CDIG = contador de dígitos de 0 a 3, valores 0=DY0, 1=DY1, 2=DY2, 3=LED ; DGx = Segmentos do correspondente digito DY0, 1, 2 ; LED = bits 0, 1 e 2 corresponde aos LEDs La,b e c. Poderia ser até 8 LEDs. ; Ainda no inicio do programa colocamos a TABUA de POSIÇÃO dos dígitos "tabpos". ; Como foi dito,para acender um segmento do display aplicamos V+ no segmento e GND no cátodo comum a todos segmentos, ; então é o que faremos aqui. O segmento serão os 3 registros "dg0, 1 e 2" onde cada ; bit deste corresponde a um segmento, na ordem adotei: ; 7 6 5 4 3 2 1 0 pt g f e d c b a ; e a "tabpos" corresponde a qual display deverá acender seus dígitos. ; 7___6___5___4___3___2___1___0__ = BITS S3__S2__S1__S0_LED_DY2_DY1_DY0 = sendo S3,2,1,0 = 0000 ; Para acender o DY0, aplica-se somente no cátodo dele GND (0V), veja "tabpos" abaixo quando "cdig=0", para DY1 quando "cdig=1", para DY2 quando "cdig=2" e para LED quando "cdig=3". ; ; ===================================== org 0 goto inicio ; start org 4 goto int_timer0 ; ; ================================================= ;a próxima instrução "call tabpos" faz o salto direto para a ; ; tabpos: andlw 0x03 ; por proteção só os 2 primeiros bits valem addwf PCL,F ; salte imediatamente para a próxima posição+W retlw b'00001110' ; dy0, W = cdig = 0 retlw b'00001101' ; dy1, W = cdig = 1 retlw b'00001011' ; dy2, W = cdig = 2 retlw b'00000111' ; LED, W = cdig = 3 ; ; ; O valor de W será somado ao PC e ocorrerá um salto imediato para a nova posição, se W=0 não haverá salto, W=1 salta 1 pos, W2=2 salta 2 pos e W=3 salta 3 pos, a Instrução RETLW, faz com que os 8 bits baixos da instrução retorne em W. A instrução RETLW de 14 bits -[11 01xx byte] o valor byte retorna em W. Lembra que foi chamada por "CALL tabpos", logo a posição que estava+1 do PC foi guardada no SP, agora com RETLW esta posição é restabelecida e ocorre o retorno imediato para uma posição após a da chamada, mas com o valor adquirido em W. Para mais detalhes veja o manual pagina 117, a instrução RETLW

No área da ISR de timer0, coloca-se a chamada para subrotina que irá varrer o display e ler teclado que se chama dislay:

call display ;coloque está linha dentro do ISR na PARTE-1

ou mesmo com um voltímetro analógico lembrando que Vmax=5V aplicando regra de três: (% a saber) = 20(V lido) poderá ser ensaiado usando o PWM da Parte-1 que continua instalado aqui, colocar o multímetros com FS (fundo de escala) maior que 5VCC no pino RB3 (saida PWM) e variar via SCI o valor do registro 0x15 reg func CCPR1L. O Multimetro Analógico tem comportamento de ler a média como fica PWM pulsos de 5VCC durante um mesmo intervalo de tempo o ponteiro pega a média devia sua inércia. Conclui- se que o sistema PWM é linear, caso contrário não poderia utilizar regra de três.

========================================================================================================

Agora passaremos a descrever a rotina de varredura dos displays e leds e leitura de teclas, mas antes vamos acertar a freqüência de varredura para que não ocorra o fenômeno da cintilação, pois a multiplexação do display fará este acender e apagar, precisamos achar uma freqüência conveniente de forma que o olho humano não perceba.

Quando olhamos para uma figura, o olho capta a imagem que é levada até o cérebro. Cada imagem fica retida em nossa retina (olho) por um intervalo de 1/16 segundos. Por isso, ao multiplexarmos os dígitos rapidamente, antes de que a imagem anterior suma de nossa retina, vemos o display sem piscar. As imagens ficam sobrepostas em nosso cérebro, dando a impressão de não picar.

Esse mesmo princípio, o da persistência visual, foi utilizado para a criação do cinema, a cada segundo são projetados 24 imagens que devido a persistência visual temos a impressão de se movimentarem.

Nossa multiplexação será de 3 dígitos mais o LED, assim com segurança poderia ser 30 amostragem por segundo, logo a freqüência mínima seria 30x4=120Hz.

Vamos ver se a freqüência de TIMER0 ajustada na PARTE-1 seria suficiente para atender nosso caso. Tempo entre chamadas de ISR, no caso este tempo vale 4MHz/4=1MHz/16*256 = 244Hz o que está bom, vamos deixar como está por enquanto.

Se você for ensaiar este software, para sua experiência mude o valor da freqüência, no prescaler de TIMER0 registro OPTION (0x81, poderá ser via SCI), passara a dividir por 256, assim a freqüência será: 1MHz/256*256=15,2 HZ

e veja o display piscar. Se quiser menor freqüência crie um delay. Crie uma variável (byte) por exemplo nome "atraso" que só ocorrerá o MUX quando "atraso=0", faça assim:

; decfsz atraso, ; decremente o reg atraso e deixe lá o resultado goto continue ; se o resultado for zero pule a próxima movlw 0x64 ; carregue o atraso para a prox varredura movwf atraso call display ; vá varrer o display ; continue: ;

No caso acima se aplicarmos a anterior freqüência de 15,2Hz teremos 15,2/100=0,15 Hz, vai perceber lentamente varrendo todos os dígitos, aproximadamente 6,6Seg/digito.

=============================================================================== Agora passamos a estudar o SOFT VARREDURA que vem a seguir, poderá ser colocado em qualquer local da memória, mas eu prefiro no fim do programa, assim eu divido: 1-INICIALIZAÇÕES e TABUAS 2-OPERACIONAL e a seguir suas SUOTINAS 3-ISR e a seguir suas SUOTINAS

Todo trabalho de Multeplexação dos displays e leitura de teclas serão feito dentro ISR, onde o OPERACIONAL não toma parte isto será muito confortável, porque lá no programa OPERACIONAL desejando saber se alguma tecla foi acionada, por exemplo se tecla K1 acenda o segmento b do digito 2 e se a tecla Ko for acionada acenda o LEDc:

; btfsc rkey,1 ; teste a posição da tecla K1 goto func4 ; Deseja-se acender somente segmento b de DY2: ; clrf dg2 ; fazendo os 7 ESG + o to apagados bsf dg2,1 ; acender somente o Seg b ;

Se a tecla K0 for acionada acender LEDc, caso contrário apagar LEDc ; btfsc rkey,0 goto ali1 ; tecla acionada ; bcf LED,2 ; apagar LEDc goto ali2 ; ali1: bsf LED,2 ; acender LEDc ; ali2: ; ; É preciso lembrar que as subrotinas de ISR não poderão ser usadas pelo OPERACIONAL, caso contrário os dados entrarão em conflito com perdas dos mesmos, pois usarão os mesmos registros sem nenhuma ordem. Por este motivo que criei registros para o OPERACIONAL (ra, rb...) e para o ISR (ria, rib...). ; ; ; ;================================================================ ; INICIAMOS AQUI O ESTUDO DETALHADO DO PROPOSTO ACIMA: ;================================================================ ; primeiro tem-se certeza que esta na pagina 0 ou seja RP1 e RP0 = 0 ; display: incf cdig,F ; ver o contador de dígitos cpi cdig,3 ; compare com o número 3 brcs disp1 ; se for menor ou igual a 3 pule a próxima clrf cdig ; se for maior que 3 faça cdig=0 ; disp1: movf cdig,w ; pegar mux bit position ; call tabpos ; veja em tabpos ret com valor MUX em W ; iorwf rele,W ; rele b7,6,5,4 os 4 bits altos, W=valor do CI2 movwf rid ; salve o valor do CI2 no rid para a Segunda carga movwf rib ; salve rib para primeira carga clrf ria ; faça conforme descrito não acenda nenhum segmento. ; ; transferencia spi será = 16x[ria->rib->CI1->CI2] ; ; CI2<-CI1<-(rib=rele+MUX)<-(ria=00) ; call spi ; ; ============= T E C L A D O ======================= ; aqui foram suprimidos os diodos e resistores R1 e R2 ; porque não interessam na analise do software ; quanto a funcionalidade de circuito já foi visto ; ; _|_ ; led-o o-------------o----RB5 ; | ; _|_ | ; dy2--o o-------------o ; | ; _|_ | ; dy1---o o------------o ; | ; _|_ | ; dy0-----o o----------o ; ; ; key: bsf status,RP0 ;passar para a pagina1 bsf TRISB,5 ; RB5 como input clrf status ; retornando pagina 0 ; ; a leitura da tecla envolve antes achar sua posição que coincide com o ; inverso lógico da posição do MUX. Importante notar que este leitor faz ; 4 teclas, embora a posição LED está sem tecla, ; mas poderá ser colocada mais uma tecla ou até um jump ; movf rid,w ;pegue somente a posição MULTIPLEX xorlw 0x0F ; pegue o inverso addlw 0x01 ; adione 1 para sair do 0x00 andlw 0x0f ; só termos valores 0x01, 0x02, 0x04, 0x08 ; ; agora vamos ver a tem tecla ; btfss PORTB,5 ;ver estado de RB5 goto key1 ;se for 0 goto key1 tem tecla ; ; tecla não acionada logo deverá ser colocado 0 na devida posição ; então como os valores são 1,2,4,8 com o ou exclusivo ficará, ; 0xFE, 0xFD, 0xFB, 0xF7, que proporciona fazer um AND com o registro rkey. ; xorlw 0xff andwf rkey,F goto keyf ; ; aqui temos a tecla acionada, então basta fazer um OU com rkey ; key1: iorwf rkey,F keyf: ; ; fez a leitura da tecla continuar o MUX, fazer a 2a carga ; ============================================================ ; aplicar o Segunda carga mas agora com os valores dos segmentos ; movf rid,W ; recarregar rib com o MUX movwf rib ; e rib = valor do CI2 (MUX + SaidaDigital) ; ; aqui vamos pegar o valor dos segmentos do MUX corrente, para utilizaremos ; a instrução INDEXADORA FSR, merece toda a atenção. Quem não conhece veja o ; Manual pagina 25 tem um capitulo só para ela. Mas em resumo é assim: ; indexa-se qualquer posição da memória de 0x00 até 0xFF se IRP =0 em STATUS ou ; de 0x100 até 0x1FF se IRP=1. A função de FSR é só apontar para que se possa ; fazer qualquer operação com o registro que FSR aponta, mas para isto devo ; fazer a operação com o registro 0x00 ou INDF. Figuramente, pense assim: ; "a posição da memória RAM 0x00 é um BURACO que sair onde FSR aponta" ; movlw dg0 ; pegar o endereço do dg0 movwf FSR ; FSR = endereço de dg0 movf cdig,W ; pegar o contador cdig pode ser 0,1,2,3 addwf FSR,F ; fazer o Indexador FSR apontar para o DIGITO CORRENTE movf INDF,W ; W = segmentos do DIGITO CORRENTE movwf ria ; mover este valor para ria ; ; Para se economizar passos de memória de programa imbutiu-se aqui duas chamada ; a sub rotina SPI, a primeira antes da SUB TECLADO uma chamada normal como ; "CALL SPI", no retorno volta para fazer a SUB TECLADO, mas aqui é diferente ; porque entra em SPI sem chama-lo, quando encontrar o RETURN para onde irá? ; Voltará para a posição anterior que deve estar no SP, que é o primeiro ; chamado que ocorreu lá na ISR do pwm628.asm quando chamou o "CALL DISPLAY" ; lema? Isto porque agora serviço aqui acabou. ; ; SPI = 16x[ria->rib->CI1->CI2] spi: movlw .16 ; são 16 shifts movwf ric ; ric será o contador ; ; aqui inicia os 16 shifts ; spi1: bcf PORTB,5 ; inicializar o D com 0 rrf ria,F rrf rib,F ; rodar para direita ria->rib->C btfsc STATUS,C ; b0 de rib vai p/ C de STATUS se C=0 pule próxima bsf PORTB,5 ; se for C=1 faça RB5=1 ; ; caso contrário já fez RB5=0 ; bsf PORTB,6 ; fazer CLK=1 ; nop ; se precisar fazer um delay 1us/NOP bcf GPIO,4 ; CLK=1 ; decfsz ric,f ; faça isto 16 vezes goto spi1 ; bsf PORTB,4 ; LT=1 fazer LATCH (segurar) ; nop ; se precisar fazer um delay 1us/NOP bcf PORTB,4 ; LT=0 16 bits já foram transferido para saida. ; return ============================================================= ; ; ; ;;


Abraços alvaroluiz@click21.com.br P R I N C I P A L