ESTUDOS 16F628/88 PARTE-1

junho 2005 por alvaro luiz - INDICE GERAL Fevereiro 2010 atualizado
"EM TODA CRIATURA TERRESTRE HÁ LUZ E SOMBRA. DESTAQUE SUA NOBREZA, PARA QUE A NOBREZA DO PRÓXIMO VENHA AO SEU ENCONTRO".


O objetivo deste trabalho é de facilitar a realizações de seus projetos. Acredito que seguindo este artigo tem-se uma boa idéia de como se fazer um programa organizando-o da melhor forma possível. Informo que operamos aqui em ASSEMBLER PURO, onde se observa o máximo em conceitos lógicos e economia de memória.Estou as suas ordens no email acima para dúvida referente a esteeste artigo ou erros e enganos aqui encontrados. Boa leitura e aprendizado!
Primeiro apresento meu gravador e testes para desenvolvimento, bonito não é, mas funciona e quando ocorre problemas sei onde é, e arrumo rápido, poís fui eu quem montou!

Apresento minha simples e funcional Plataforma, onde edito, compilo e emulo no MPLAB, gravo pelo software da OSHON via paralela DB25 com meu circuito gravador e monitoro, altero e testo on-line via Serial DB9 COM1 com meu software PSER.EXE. Tudo que preciso faço aqui a um custo muito baixo.

Montei um gravador para o DB25 e vai com cabo de 6 vias até a placa onde está o 16F628 (à esquerda) ou para a outra placa 16F88 (à direita) que chamei-as e BD628 e BD88. As duas proporcionam acesso a todos os pinos para serem emulados na protoboard. Elas também oferecem colocar cristal e comunicação serial em cima a esquerda em cada placa direto ao 16Fxxx com conector de 4 pinos (rx,gnd,tx,vcc). No cabo Db9 temos um pequeno circuito 2 transistores que fazem o RS232 para o PC em COM1 com o software [pser.exe]. Também temos uma pequena fonte 5VCC regulado e 12VCC.. Circuito RS232C no db9


O circuito do gravador é oferecido pela OSHON, fiz algumas modificações mas nada significativo, do lado vê-se o SET do software no gravador que eu adotei.
Onde pegar o PSER.EXE: PSER.EXE para PC se comunicar com o Procolo LSX, aqui Aqui temos a foto do PSER.EXE sendo rodado. O nome dele mesmo é: LSX2-COM1 - 9600_8N1 = Protocolo tipo LSX, verSão 2, só opera em COM1, opera com 9600bps, 8 bits, Não paridade e 1 Stop bit. A esquerda temos o endereço em HEX de $0000->$FFFF, o valor em hex deste endereço, depois o valor que desejo gravar em HEX, tudo a comando das 4 teclas abaixo, sendo + e - proximo e anterior endereços, rd- ler e wr gravar. O valor lido, poderá aparecer no meio para direita em decimal, binário e hexadecimal. O binário proporciona, alterar bit a bit, bastando clicar o mouse no bit. Click =1 outro click =0 o seu valor será ajustado em todos displays e automaticamente gravado no endereço selecionado. Mais abaixo, temos +data , -data e clr que proporcionam somar um ou subtrair e fazer zero o display binário, tudo será gravado imediatamente. Temos as teclas repetir, ficará lendo uma vez por segundo, ou UP/DOWN soma ou subtrai uma unidade 1 vez por segundo automaticamente. Precisa ver nesta última opção se seu software admite tantas gravações em curto intervalo de tempo, principalmente em EEPROM ocorrerá problemas com certeza, mas devemos lembrar que este software é uma ferramenta que virá ajudar nosso trabalho. ================================================================================================ Gravador OSHON MPLAB v7.11 Manual do 16F628 MercadoLivre, ou na Farnell Livro do 16F84 está em Portugues de Portugal - ajuda a iniciar Local dos apontamentos da Microchip - MUITO BOM

Acredito que já temos as ferramentas para iniciar nossos estudos e ensaios. Vamos lá: Vou tomar como base parte de um projeto que fiz de um controlador de temperatura, o mesmo poderá ser visto aqui


Iremos realizar estudos como: · Inicializar o 16F628 com suas funções periféricas, · divisão do software em Iniciar, Operacional e ISR, · Como atender uma chamada ISR sem perder o que estava fazendo, · Comunicação Serial com o PC com um simples protocolo, · PWM com 8 bits com saída em RB3, · Interrupt Service Request (ISR) por TIMER0, · Como fazer o CONFIG, · As linhas do Assembler com comentários, · Como trabalha o Indexador FSR com o INDF, · Fazer tábuas na Memória e como acessá-las por RETLW, · Subrotinas, Chamadas CALL e Retornos, · STACK POINT contador em anel de 8 posições tipo LIFO, · Como Multitlexar (MUX) um display de 3 dígtos, 8 Leds, 4 saídas digitais e ler até 4 teclas tudo com comunicação serial a 3 fios somente, · Etc ...


Comunicação serial tipo RS232 com 9600bps somente em COM1. O pacote serial está no LABEL "SCI", as características do protocolo que são bem simples só opera com as letras S, L e X totalmente ASCII, foi feito em 1992 para operar com família HC11 da Motorola, agora modificado para atender o PIC, funciona bem. No seu PC rode o software "pser.exe" que foi feito em linguagem C++ e atende este protocolo, quando este rodar pela primeira vez pedirá o bps, coloque 9600, o endereço preferencial (coloque o que quiser, por exemplo 0x20), antes e depois coloque 0 e 0 (zeros). Para opera-lo é fácil na própria tela azul tem- se: (m) acessar novo endereço , (s/r) set/reset em bit 0...7,(+/-) incremente/decrementa valor do byte em destaque,(q) fim,(?/$) conversor BcdToHex e HexToBcd, qualquer numero BYTE HEX digitado (00...FF) será enviado para o 16F628 no endereço indicado e imediatamente pega o conteúdo deste endereço. Estudar desta forma é muito bom, evita gastos, displays, etc, vê-se o resultado na tela de imediato, altera-se on-line todos os registros RAM/Funções. Lembrar que só funciona na COM1 do seu PC, talvez seja necessário mudar seu mouse para o COM2 assim COM1 fica livre.


PWM com 8 bits saída RB3, temos sua inicialização : inicializando PWM, fazendo PWM com xtal interno de 4MHz, a freqüência será = (4MHz/4)/256 ~ 4K HZ com timer2 prescaler=1 exemplo reconstruído com algumas alterações do manual do 16F628 pagina 65 código DS40300C e do PICMICRO exemple 14.5 PWM INITIALIZATION CODE DS31014A PAGE 14-14 PWM de 8 bits carga no registro 0x15 neste local registro de FUNTION CCPR1L, temos os 8 bits que fazem a duração do pulso nível alto PWM que pode variar de 0% = 0x00 até 100% = 0xff, poderá ser alterado o registro 0x15 via comunicação serial. Se desejar fazer experiência em um pequeno motor DC em um único sentido, poderá usar o circuito abaixo que poderá chegar 12VCC/2A. Caso deseje 2 sentidos, necessitará de um driver mais complexo.


ISR (INTERRUPT SERVICE REQUEST) Aqui deve ser colocado o serviço de INTERRUPT, que não deverá ser grande, ou seja, gastar no máximo 50% do tempo entre chamadas de ISR, no nosso caso tempo vale 4MHz/4=1MHz/16*256 = 244Hz então a cada aproximadamente 4ms ocorrerá um ISR chamado pelo OVERFLOW de TIMER0. Para monitorar o tempo de ISR utilizei o RB0 como saída que poderá ser lido em um osciloscópio, ou mesmo com um voltímetro analógico lembrando que Vmax=5V aplicando regra de três: (% a saber) = 20(Tensão Lida)

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 e 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.

No Inicio habilitamos a INTERRUPT para TIMER0: ; ------------------------------ ; set timer-0 ; ------------------------------ bsf status,RP0 ;bank1 movlw b'00000011' ;escrevendo em binário o valor 0x03 movwf OPTION_REG ;que fará prescaler igual a 16 ; ---------------------------------- ; habilitando interrupt para timer0 ; ---------------------------------- movlw b'10100000' movwf INTCON ;hab interrupt timer0 ;

Lembrar que quando ocorrer interrupt o valor do contador de programa (PC) será guardado no stack point e salta para o endereço 0x0004, lá deverá estar o local de ISR. Falarei um pouco do método que utilizo. É como MULTITAREFAS, fazer um pouco de cada tarefa no tempo, assim atende-se quem chama sem prejudicar ninguem, todos serão atendidos, claro que não ao mesmo tempo. Mas como quem chama (ISR) obedece rigorosamente tempos, pois será chamada de TIMER0, assim todas temporizações deixo para o ISR fazer. As três tarefas que utilizo chamo de INICIALIZADOR, OPERACIONAL e ISR, a primeira executada logo após o RESET se ocupa em fazer o SET de toda area periférica e registros, a OPERACIONAL é para atender o projeto, é a operação normal, ou seja, o estado de repouso do micro (seu estado estável), o ISR é quem chamará no nosso, caso, em intervalos de tempos, para se fazer um rápido serviço e retornar. Este serviço pode ser normalmente aquisições de valores periféricos, ajustes de tempos, varrer display, ver teclado, etc, coisas correqueiras que devem ser feitas para ter-se as variavéis que OPERACIONAL precisará. Assim, no OPERACIONAL torna-se mais fácil poís basta ler, ou testar um registro para ter-se o o valor de uma variável, porque o ISR estará constantemente atualizando esta. No nosso caso ISR por TIMER-0, ocorrerá toda vez que o byte contador TIMER0 passar de FF->00, inicialmente salva o endereço corrente do OPERACIONA num dos 8 registros em anel STACK-POINT e depois salta para a posição 0x0004 da memória, onde lá estará o local onde deverá ir, no nosso caso "goto int_timer0". Aproveitando as 16 últimas posições da pagina1 dos registros da RAM (0x070 a 0x07f), que são comuns a todas as 4 paginas do 16F628 e 16F88, procurei dividir os necessários registros para atender as duas rotinas, a OPERACIONAL usa os registros ra, rb,... e a ISR usa ria, rib,.... wr, st, fsrr, assim não precisamos nos preocupar em salvar nem repor registros ao passar de uma rotina para outra, basta salvar somente três W, STATUS e FSR, agilizando satisfatóriamente os tempos de atendimento e retorno.

O STACK-POINT do 16F628 é composto de 8 registros de 14bits cada, de forma a guardar um endereço do PC (Contador de Programa), aqui eles estão em ANEL, ou seja, não tem começo nem fim, onde entrar está valendo, não precisa ser inicializado. Este registro atua como LIFO (Last In First Out, último a entrar primeiro a sair). Precisamos sempre lembrar que só tem 8 posições, se ultrapassar a posição nove entra em cima da numero 1, aí vai perder retorno, ou seja, não sabe mais de onde veio estará perdido. Nos micros PIC16xxx deve-se tomar cuidado, procure usar mínimo de subrotinas. No caso eu nunca uso mais de 2 ou 3 consecutivas em cada uma no OPERACIONAL e ISR, poque sempre lembro que se estiver usando 3 passos do anel e só com a chegado do ISR vai uma, só tem mais 4... assim o ISR também não deverá usar mais que 2 ou 3, assim no pior dos casos 3+1+3 sobra uma só como segurança. Devemos saber que ao chegar a primeira interrupção o Habilitador geral de interrupt GIE no reg INTCON vai para "0" desabilitando assim outros atendimentos, aqui vale fazer em trabalhar com outras ISRs, a coisa complica para falar sobre isto precisariamos um novo artigo só sobre isto, vamos ver talvez eu faça. Por enquanto vamos ficar só com a interrupt TIMER0.

org 0 goto start ; ======================== org 4 goto int_timer0 ;===========================

Aqui também aprendemos a salvar e repor os registros W, STATUS e FSR.

;===================================================== int_timer0: bsf PORTB,5 ; fazer monitoração da % do tempo gasto em ISR movwf wr ; salvar W sem alterar o STATUS swapf STATUS,W ; salvar STATUS sem alterar seu valor movwf st movf FSR,W ; agora salvar FSR movwf fsrr clrf STATUS ; passar para blok0 e iniciar ISR ; =================================================== ; ; ; colocar aqui o SERVIÇO de ISR ; ; ; =================================================== intf: movf fsrr,W ; repor todos os registros como estava antes da ISR movwf FSR ; primeiro FSR movwf st,W ; segundo W movwf STATUS swapf wr,F ; o último STATUS lembrar que foi salvo invertido, logo... swapf wr,W bcf PORTB,5 ; tirar a monitoração retfie ; repor em PC o endereço guardado no stack point e habilitar INTERRPT ; voltar a fazer o que estava fazendo antes da ISR ; ===================================================

Quero Aprendendo mais ... , Como construir MACROS, tornando mais resumida a forma de escrever o programa. Fazendo comparações de um reg com um byte "cpi" dizendo se é Maior/Menor/Igual. alto condicionais se Maior/Menor?Igual. Mover de um reg para outro. Fazer lógica AND/OR/EXCLUSIVE OR. Fazer Adição/Subtração de reg para reg e de reg com byte, etc. Tente entender cada MACRO descobrindo como foi feita, nada difícil experimente.

Como organizar os registros no inicio do programa, as duas formas: cblock 0x20 ... endc ou equ 0x33, nolist/list = para não sair e sair no (pwm_628.lst)

__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _LVP_OFF

;(0x3F70 no local 0x2007) pagina 92 do Manual do 16F628

Lembrar que para conservar a integridade dos registros operacionais quando ocorrer a ISR, foi salto W, STATUS e FSR em wr, st e fsrr. E também foi criado registros para operações fora e dentro da interrupt, desta forma separando os trabalhos e dados para a parte OPERACIONAL ra,rb... e para ISR ria, rib ...

Gostaria de mostrar algumas operações que trazem dificuldades em sua elaboração, pois o núcleo de instruções do PIC não traz muitos recursos. Um deles é a operação de comparação: Temos um só caminho para fazer as comparações é com a subtração:

movf ra,W ; comparação é feita pela subtração sublw 0x64 ; operação (0x64 - ra) altera C e Z de STATUS

Toda vez que fazemos "sublw" vale a tabela abaixo:

-------------------- resultado C Z ------------------- ra igual 0x64 1 1 ra maior 0x64 0 0 ra menor 0x64 1 0 ---------------------

Vamos comparar dois bytes, dois registros:

cp2: movf ra,W subwf rb,W

A mesma coisa vale para comparar 2 ou mais registros, sempre começa-se comparando as partes mais altas dos registros, poís se a parte mais alta for maior (CZ=00) ou menor (CZ=10), a comparação já estará feita, pois a menor não afetará esta decisão, mas se as partes altas forem iguais (Z=1) temos que ver as baixas. Veja comparando dois registros ra/rb com rc/rd sendo ra e rc partes altas e rb e rd partes baixas:

comp2: movf ra,w subwf rc,w btfss STATUS,Z ;se Z=0 retorno com C=0 rab maior que rcd, ou C=1 rab ;menor que rcd return

movf b,w subwf rd,w ;como as partes altas foram iguais Z=1 então return ;como resposta vale só parte baixa

exemplo: deseja-se comparar o valor que está nos regs vh e vl, parte alta(h) e baixa (l), com o valor 10000 decimal ou 0x2710 em Hex e tome as 3 possíveis decisão se igual, maior ou menor:

movf vh,w ;primeiro carregar os registros comparadores movwf ra movf vl,w movwf rb

movlw low(.10000) ;aqui aprendemos como escrever um número em decimal movwf rc ;esperando que o MPLAB passe-o para Hex movlw high(.10000);veja que 10.000 espera-se uma word=2bytes movwf rd ;e byte alta=high, e baixo=low

call comp2 ;fazer a comparação

btfsc status,z ;teste bit z goto v_igual_10000 ;z=1 v=10.000

btfsc status,c ;teste bit c goto v_menor_que_10000 ;c=1 logo v < c="0"> 10.000

========================================================================================================== Passamos a descrever uma programa passo a passo com comentários ;==================================================

; ; ESTUDOS DO 16F628 E DO 16F88 ; por alvaroluiz@click21.com. ; ;==================================

nolist ;pare de lista não que quero de saia no arquivo.lst

#include "p16f628.inc" ;este arquivo tem endereços funções, está no MPLAB /MCHIP_Tools, faça cópia

list ;agora pode copiar aparecerá no arquivo.lst

; No nosso caso será gravado no CONFIG 0x3F70 na posição 0x2007, se examinarmos a ;sentença do ; CONFIG abaixo que o MPLAB irá compilar e a comparamos com o P16F628.INC, temos: ; 0x3FFF and 0x3FF7 and 0x3FFB and 0x3FFC and 0x3F7F = 0x3F70 valor que será ; gravado no endereço 0x2007 local do CONFIG

__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT &amp;amp;amp;amp;amp; _LVP_OFF ;

;==================================================

cblock 0x20 ;local de inicio dos registros temp,rsl,rsh,down1 ;o MPLAB coloca na seqüência atraso,vh,vl endc ;esta forma mais fácil escrever mas saber o

; a seguir outra forma de declarar variáveis na RAM ; -------------------------------------------------

cdig equ 0x30 ;esta outra a seqüência e minha, mais difícil dg0 equ 0x31 ;escrever mas é mais fácil saber o endereço dg1 equ 0x32 dg2 equ 0x33 led equ 0x34 rele equ 0x35

; aqui os 16 registros RAM comum as 4 paginas ; -------------------------------------------

cblock 0x70 ra,rb,rc,rd,re,rf,rg ; lembrando que este 16 regs comuns as 4 paginas ria,rib,ric,rid,rie,wr,st,fsrr ; escolhi este local para colocar regs de operação endc ; ; algumas palavras que definem bit/bites ; --------------------------------------

status equ STATUS c equ C z equ Z

; ======= I N I C I O D A S M A C R O S ========== ; ; estas MACROS agem como carimbo, onde são chamadas o MPLAB coloca no lugar o que está aqui ; exatamente como foi editada, simplesmente fica mais fácil entender o prog .ASM

; esta macro associada a breq, brne, brcc e brcs para comparações e saltos ; comparando um registro "R1" com um byte ; C Z ; R1 igual byte 1 1 ; R1 maior byte 0 0 ; R1 menor byte 1 0 ;=============================== ; cpi macro r1,valor ;=============================== cpi macro r1,valor movf r1,W ;comparação é feita pela subtração sublw valor endm ;=============================== ; cp reg1,reg2 (reg1:reg2) ;=============================== cp macro reg1,reg2 movf reg1,W subwf reg2,W endm ;=============================== ; breq label se z=1 salte para label ;=============================== breq macro label btfsc STATUS,Z goto label endm ;=============================== ; brne label se z=0 salte para label ;=============================== brne macro label btfss STATUS,Z goto label endm ;=============================== ; brcs label se C=1 (menor ou igual) salte p/ label ;=============================== brcs macro label btfsc STATUS,C goto label endm ;=============================== ; brcc label se C=0 (maior) salte p/ label ;=============================== brcc macro label btfss STATUS,C goto label endm ;=============================== ; mov reg1,reg2 (reg1=reg2) ;=============================== mov macro r1,r2 movf r2,W movwf r1 endm ;=============================== ; andi r1,value (r1=r1 & value) ;=============================== andi macro r1,value movlw value andwf reg1,F endm ;=============================== ; addi reg,value (reg=reg+value) ;=============================== addi macro reg,value movf reg,W addlw value movwf reg endm ;=============================== ; add r1,r2 (r1=r1+r2) ;=============================== add macro reg1,reg2 movf reg2,W addwf reg1,F endm ;=============================== ; subi r1,value (r1=r1-value) ;=============================== subi macro reg1,value movlw value subwf reg1,F endm ;=============================== ; TROCA RA,RB COM RC,RD, usa re ;=============================== rabXrcd macro mov re,ra mov ra,rc mov rc,re mov re,rb mov rb,rd mov rd,re endm ;=============================== ; soma 16 bits rab=rab+rcd AN526 ;=============================== add16 macro add rb,rd btfsc STATUS,C incf ra,F add ra,rc endm ;=============================== ; sub 16 bits rab=rab-rcd ;=============================== sub16 macro comf rd,F incf rd,F btfsc STATUS,Z decf rc,F comf rc,F add16 endm

; ======= F I M D A S M A C R O S ============== ; ====================================================

; ======================================= ; ==== I N I C I A L I Z A T I O N ====== ; ======================================= ; org 0 ;quando ocorre RST salta para este endereço goto start ; ======================================================================= org 4 ;quando ocorre qualquer INTERRUPT HABILITADA guarda goto int_timer0 ;o endereço do PC no STACK POINT e salta para cá ; ======================================================================= start: movlw 0 ;inciliazando PORTA/B conforme manual pagina 15 movwf PORTA ;somente RA0,1,2,3 são incializadas em "0" ; movlw b'00000100' ;forma de escrever em binário valor 0x02 movwf PORTB ;RB2=Tx e RB1=Rx ; movlw 0x07 ;é obrigado desativar o comparador analógico movwf CMCON ;caso contrário cria saídas PORTA indesejáveis; ; bsf STATUS,RP0 ;bank1 passando para a página 1 (de 0x80-0xFF) ; movlw 0xff movwf TRISA ;todos pinos inp ; movlw b'01011011' ;0x5B movwf TRISB ;RB0,1,3,4,6 inp RB1(rx) ; ; ------------------------------ ; set timer-0 ; ------------------------------ movlw b'00000011' ;consulte OPTION pagina 20 movwf OPTION_REG ;tm0=1MHz/(16*256)=~244Hz. 16 é o prescaler e 256 o OVERFLOW TIMER0 ; ; ------------------------ ; Set baud rate = 9600, no parity, 1 stop bit ; 4MHz usando interno RC oscilador ; ------------------------ movlw 0x19 ;com osc interno de ~4MHz vide pag.72 do movwf SPBRG ;manual assíncrono GH=1 erro de 0,16% ; movlw 0x24 ;habilitando TX movwf TXSTA ; clrf STATUS ;STATUS=0 ir para pagina 0 e fazer bits Z=C=0 ; movlw 0x90 ;habilitando RX movwf RCSTA ; ; ------------------------------------------------------- ; inicializando PWM fazendo PWM com oscilador interno de 4MHz ; a freq será = (4MHz/4)/63~15K87 HZ com timer2 prescaler=1 ; exemplo reconstruido0 com algumas alterações do manual do ; 16F628 page 65 code DS40300C e do PICmicro example 14.5 PWM ; Initialization code DS31014A page 14-14 ; a frequencia do PWM = (4MHz/4)/timer2*prescaler=3K9Hz ~ 4KHz ; --------------------------------------------------------- clrf status ;bank0 clrf CCP1CON ;CCP module is OFF clrf TMR2 ;clear timer2 ; movlw 0x3f movwf PR2 ;fazendo periodo do PWM clrf CCPR1L ;iniciar ativo PWM = 0% ; clrf INTCON ;para prog daqui em diante sem interrupts bsf status,RP0 ;bank1 bcf TRISB,3 ;fazendo RB3 out PWM ; clrf PIE1 ;desabilitando periférico interrupts clrf status ;bank0 ; clrf PIR1 ;clear periférico flags interrupts ; movlw 0x2c ;mode PWM movwf CCP1CON ; clrf T2CON ;prescaler 0000 = 1:1 bsf T2CON,TMR2ON ;start timer2 and PWM ; ; ; ; ============================================================ ; habilitando interrupt para timer0 ; ============================================================ movlw b'10100000' ;habilita global interrupt + movwf INTCON ;habilita interrupt timer0 pagina 21 manual ;============================================================ ; ; ; ================================ ; ==== O P E R A C O N A L ====== ; ================================ ; ; aqui deverá ser colocado o seu programa operacional ; ; st1: call sci ;deverá sempre ser visto se tem dados pendentes ; ; ; call resolver_problema_proposto ; ; ; goto st1 ; ; ; =========================================== ; ==== F I M O P E R A C O N A L ====== ; =========================================== ; ; ; ; ================================ ; =========== I S R ============== ; ================================ ; ; aqui tem o inicio do atendimento de ISR vindo do endereço 0x0004 ; primeiro vou salvar registros para não perder a ; integridade das operações, ; ou seja, quando voltar o software operacional ; nem deve saber que ocorreu atendimento ; do software ISR devemos ter em mãos tabela com as 35 instruções e veremos ; que somente para transportes as instruções ; MOVWF e SWAPF não alteram STATUS, devemos usa-las ; na confiança de alterar ; os dados que estão no STATUS ; ========================================================================= ; para efeito de monitoração do tempo gasto em ISR, fiz RB0 como ; saída e ponho logo no inicio antes de salvar os registros de operação ; porque sei que a instrução BSF não afeta nenhum dos registros operacionais ; ========================================================================= int_timer0: ; bsf PORTB,0 ;iniciar a monitoração de RP0 _____ movwf wr ;salvar o reg W swapf STATUS,W ;preservando de STATUS, pegamos este invertido movwf st ;e o salvamos invertido clrf STATUS ;aqui salvamos wr,status e FSR movf FSR,W ;esta instrução altera STATUS, mas este já foi salvo movwf fsrr ;podemos salvar FSR, e deixa-lo livre para ISR usa-lo ; bcf INTCON,T0IF ;tirando requisição ISR,do contrário não sai mais daqui ; ; ============================================================================= ; ISR (aqui Interrupt Service Request) aqui deve ser ; colocado o serviço de interrupt, que não pode ser grande, ; ou seja, levar mais que 20% do ; tempo entre chamadas de ; ISR, no caso este tempo vale 4MHz/4=1MHz/16*256 = 244Hz, ; então a cada aprox. 4,1ms ocorrerá um ISR chamado pelo ; overflow de timer0 RB0 está sendo usado como monitoração ; para tempo, poderá ser visto em um osciloscópio. ; ============================================================================= ; movf down1,f ;vendo se donw1 é dif de zero com Z, é um modo rápido de ; ;ver se um reg é zero movendo ele para ele mesmo. btfsc status,z ;depois o BIT Z/STATUS a instrução SKIP NEXT ADDRESS goto int1 ;if not equ 0, então conclui-se que down1=0 e nada a fazer ; decf down1,f ;else -> donw1 dif de zero decrementar este ; goto int2 int1: ; int2: ; ; ; AQUI SERVIÇO ISR ; ; call display ;varrer display e teclado ; ; call outros_services_ISR ; ; ===================================================================== ; fim do ISR reponha todos registros ; intf: movf fsrr,W ;repor FSR movwf FSR swapf st,W ;como o salvamos invertido agora o reavemos movwf STATUS ;invertido também logo nada mudou swapf wr,F ;e o último a ser reposto é o reg W. swapf wr,W ;está tudo reposto ; bcf PORTB,0 ;tirar RP0 _____""""""___ ton prox. 12% de 4ms ; ; ;deu para observar no osciloscópio freq=255Hz ton~12% até prox pulso ; retfie ;retorne pegando o endereço do STACK POINT ; ; ; ====================================== ; ====== F I M DE I S R ============== ; ====================================== ; ; ; ; A ROTINA SCI A SEGUIR PERTENCE A PARTE OPERACIONAL FOI COLOCADA AQUI ; SOMENTE POR QUESTÕES DIDATICAS ; ========================================================================== ; Serial com 16F628 ; alvaro luiz julho 2004 ; alvaroluiz@click21.com. ; =========================================================================== ; Aqui temos um estudo com comunicação serial tipo RS232 ou TTL com 9600bps ; O pacote serial está aqui no LABEL "SCI", no inicio temos as características ; do protocolo deste, que é bem simples só opera com as letras S/L/X, fiz este ; em 1992 para operar com família HC11 da Motorola, agora modificado para ; atender o PIC. Para seu PC rodar o software "pser.exe" que foi feito em ; linguagem C++ e atende este protocolo, seu PC deverá estar com COM1 livre. ; Esta maneira de estudar é muito boa, porque ano dizer, ótima, evita displays, ; etc, vê-se o resultado na tela de imediato. ; ; Se deseja a tabela ASCII tecle aqui ; ============================================================================ ; Este programa opera todo sem interrupt, deverá ser chamado contentemente por call sci ; ; Protocolo X,S,L não tem check sum todo em ASCII bem simples ; ; do PC para PIC16F628 ; S 30 30 30 41..........byte(ASCII) Pc pergunta data no address $000a ; PIC responde com o valor do address ; o address é armazenado em rs para futuro ; ; L 31 42...............Armazenar o valor $1b no address indicado em rs ; ; X.....................Pergunta qual o valor no address rs ; ; Este Software não tem acesso a EEPROM ; sci: btfss PIR1,RCIF ;ver se tem dado recebido por Rx return ; não tem retorne ; movf RCREG,W ;sim pegue-o movwf ra ;ra = RCREG ; movf rsl,W ;aponte para rsl movwf FSR ;FSR = rsl ; cpi ra,'S' ;compare de veja se é igual a X, S ou L breq sci_S; ; cpi ra,'X' breq sci_X ; = X ; cpi ra,'L' breq sci_L ; = L ; return ;desconhecido retorne sem nada fazer ; ; sci_S: call address ;espere os prox 4 bytes e monte endereço e faça FSR=rsl sci_X: mov ra,INDF ;pegue dado onde rsl aponta scib1: mov rb,ra ;salve dado swapf ra,F ;transmita primeiro parte alta em ASCII call saia mov ra,rb call saia ;agora transmita parte baixa em ASCII return ;acabou retorne sci_L: call pga1 ;pegue o byte mov INDF,ra ;armazene na memória endereço indicado em rsl goto sci_X ;agora transmita este, faça eco ; ; ======================================================================= ; vai transmitir somente a parte baixa do byte "ra" saia: andi ra,0x0f ;por segurança faça parte alta 0 addi ra,0x30 ;some 0x30 começar por '0' ASCII cpi ra,0x39 ;será maior de '9' em ASCII brcs sai ;não é esta dentro de '0...9' pode transmitir addi ra,0x07 ;é > some 7 para atingir de 0x41 a 0x46 (A a F) sai: btfss PIR1,TXIF ;veja se TX está ocupado transmitindo goto sai ;sim está espere mov TXREG,ra ;transmita return ; ;====================================================================== ; pegar 2 bytes ASCII e passar 1 byte bin resposta em dado ; é conversor AscToBin pga1: call capta ;pegar 1o byte ASCII call conv ;conv para bin mov rb,ra ;guardar swapf rb,F ;inverter e deixar em W ; call capta ;pegar 2o bytes asc call conv ;conv bin add ra,rb ;monte o byte BIN return ; ;====================================================================== ; converter de ASCII para BIN conv: subi ra,0x30 ;subtraia 0x30 cpi ra,0x10 ;será maior que 0x10 se for é letra de A..F brcs conv1 ;esta é uma MACRO, testa bit C e se C=0 que >ou= subi ra,0x07 ;subtrai 0x07 caso contrario pula esta subi que também é uma MACRO conv1: andi ra,0x0f ;MACRO como segurança só vale a parte baixa return ; ;======================= ;esperar e receber um byte capta: btfss PIR1,RCIF ;já chegou o byte em Rx goto capta ;ainda não espere ; mov ra,RCREG ;chegou, pegue e retorne return ; ;=========================================================================== ; pegar o endereço para rs (Rsh+Rsl) receber 4 bytes ASCII converte-los ; em 2 bytes BIN 0x0000 address: call pga1 ;pegar 1o byte BIN = 2bytes ASCII mov rsh,ra ;byte alto armazenar em rsh ; call pga1 ;pega 2o byte BIN = 2bytes ASCII mov rsl,ra ;byte baixo armazenar em rsl ; clrf rsh ;desconsiderar rsh, faça sempre =0 mov FSR,rsl ;FSR = rsl prepare o INDEX FSR return ;=========================================================================== ; end ; ; ; ;


Podemos também utilizar a saída PWM de PB3 para termos uma saída analógica utilizando para isto um um Filtro Passa Baixas (FPB) com 1 polos com frequência de corte fo em torno de 40Hz que é 2 decadas abaixo da frequencia PWM aqui dita de 4KHz. Com isto temos atenuação -20dB/dec em 4KHz seria 2 decadas acima de fo teriamos -40dB (1/100), na saída do filtro seria tensão DC mas a resposta de frequencia deste conversor D/A seria menor que 10Hz. Uma forma de se medir resposta de um circuito rapidamente, não é precisa mas tem-se boa aproximação é RiseTime.


Poderia ser usado também um Filtro Passa Baixas ativo com circuito operacional do tipo Butterworth, ou equivalente, assim poderiamos ter até -40 ou -60db/dec e baixa impedância de saída. Poderá ser visto na internet ou em qualquer livro de estudos sobre operacional circuits. Para efeito ilustrativo apresento a seguir um circuito que utiliza o PWM com um FBP duplo polos, para saber a tensão do potenciometro e assim saber a posição que está o step motor, vamos mais tarde voltar a ver e estudar este circuito.


Tudo que escrevo aqui é resultado de meus estudos o software e projeto fiz com meus proprio trabalho, dou permissão para estudar e copiar, mas não esqueça de citar meu email. até a próxima Abraços alvaroluiz@click21.com.br
alvaro luiz - INDICE GERAL