Página 1 de 1
Ajuda assembly

Enviado:
20 Nov 2006 20:32
por alex_david_lima
Ola, a todos aestou trabanhando em um pequeno projeto, por titulo de curiosidade, estou fazendo um oscilador de audio com frequencia variavel gostaria da ajuda dos colegas do forum.
objetivo do projeto é gerar fequencias de audio, ajustaveis atravez dos botões de + e - , gostaria que sua frequencia variase entra 10hz ate o maximo que conseguir, o codifgo fonte que coloque esta variando mais não esta linear, gostaria de um help do pessoal ai do forum
aqui esta o circuito

aqui esta o codigo fonte
- Código: Selecionar todos
#include <p16f628a.inc>
__CONFIG _BODEN_ON & _CP_OFF & _WDT_OFF & _LVP_OFF
& _MCLRE_OFF & _XT_OSC
errorlevel -302
errorlevel -305
; CONFIGURAÇÕES DOS BANCOS
; RP0 | RP1
; 0 | 0 => BANK0
; 0 | 1 => BANK1
; 1 | 0 => BANK2
; 1 | 1 => BANK3
; DEFINIÇÃO DOS BANCOS
#DEFINE BANK0 BCF STATUS, RP0
#DEFINE BANK1 BSF STATUS, RP0
; ESPAÇO RESERVADO PARA OS REGISTRADORES
; CBLOCK 0x20
VARIAVEL1 ORG 0X20
VARIAVEL2 ORG 0X21
CONT_AUX1 ORG 0X22
CONT_AUX2 ORG 0X23
TEMPO1 ORG 0X24
TEMPO0 ORG 0X25
FILTRO_BOTOES ORG 0X26 ; FILTRO PARA RUIDOS
; ENDC
; VETOR
ORG 0x00 ; ENDEREÇO DE INICIO
GOTO CONFIGURA
ORG 0x04 ; ENDEREÇO DE INTERUPÇÃO
GOTO LOOP
delayTmr0:
btfss INTCON,T0IF
goto $-1
MOVFW VARIAVEL1
movwf TMR0
bcf INTCON,T0IF
RETURN
INCRE:
CALL DELAY_150MS
DECFSZ FILTRO_BOTOES,1
GOTO INCRE
INCF VARIAVEL1,F
MOVLW D'10'
MOVWF FILTRO_BOTOES
RETURN
DECREM:
CALL DELAY_150MS
DECFSZ FILTRO_BOTOES,1
GOTO DECREM
DECF VARIAVEL1,F
MOVLW D'10'
MOVWF FILTRO_BOTOES
RETURN
CONFIGURA
BANK0 ; MUDA PARA O BANK0, ONDE ESTÃO OS PORTS
MOVLW B'00000111'
MOVWF CMCON
BCF RCSTA,SPEN
BANK1 ; MUDA PARA O BANK1, ONDE ESTÃO OS TRIS
MOVLW B'11111111' ; SETA O TRISB COMO SAÍDA
MOVWF TRISB ; MOVE DO WORK PARA FILE TRISB
MOVLW B'00000000'
MOVWF TRISA
MOVLW B'00000000'
MOVWF OPTION_REG
BANK0 ; MUDA PARA O BANK0, ONDE ESTÃO OS PORTS
INICIO:
CLRF PORTB
CLRF PORTA
MOVLW D'255'
MOVWF VARIAVEL1
MOVLW D'10'
MOVWF FILTRO_BOTOES
LOOP:
BSF PORTA,0
CALL delayTmr0
BCF PORTA,0
CALL delayTmr0
BTFSS PORTB,0
CALL INCRE
BTFSS PORTB,1
CALL DECREM
GOTO LOOP
DELAY_150MS:
MOVLW .50
MOVWF CONT_AUX1
LODOP:
CALL DELAY_1MS
DECFSZ CONT_AUX1
GOTO LODOP
RETURN
DELAY_1MS:
MOVLW .248
MOVWF CONT_AUX2
LOOP2:
NOP ; NÃO OPERA, NÃO FAZ NADA, SÓ PERDE O TEMPO DE 1MS
DECFSZ CONT_AUX2
GOTO LOOP2
RETURN
END

Enviado:
20 Nov 2006 22:44
por proex
Perguntinha básica: Que compilador esquisito é esse que vc esta usando?

Enviado:
20 Nov 2006 23:22
por alex_david_lima
Ola, proex
Estou utilizando o MPLAB, assembly
Abraços, Alex David

Enviado:
21 Nov 2006 07:35
por proex
Mplab? ok!
Então é a forma que vc escreve o programa, o que me parece esquisito.
No Mplab vc nao precisa definir o bits de mudança de banco de registradores, como fez em
- Código: Selecionar todos
; DEFINIÇÃO DOS BANCOS
#DEFINE BANK0 BCF STATUS, RP0
#DEFINE BANK1 BSF STATUS, RP0
Isso já esta feito no arquivo p16f628a.inc.
Em vez disso, sempre que precisar mudar a pagina de registradores em seu programa, use o comando BANKSEL.
Exemplo:
Em vez disso:
- Código: Selecionar todos
BANK1 ; MUDA PARA O BANK1, ONDE ESTÃO OS TRIS
MOVLW B'11111111' ; SETA O TRISB COMO SAÍDA
MOVWF TRISB ; MOVE DO WORK PARA FILE TRISB
Vc pode fazer isso:
- Código: Selecionar todos
BANKSEL TRISB ; MUDA PARA O BANK1, ONDE ESTÃO OS TRIS
MOVLW B'11111111' ; SETA O TRISB COMO SAÍDA
MOVWF TRISB ; MOVE DO WORK PARA FILE TRISB
Na definiçao dos registradores, vc usou um virgula antes da diretiva CBLOCK e ENDC, O que invalidou essas diretivas.
O modo correto de fazer essas definiçoes é assim:
- Código: Selecionar todos
; ESPAÇO RESERVADO PARA OS REGISTRADORES
CBLOCK 0x20
VARIAVEL1
VARIAVEL2
CONT_AUX1
CONT_AUX2
TEMPO1
TEMPO0
FILTRO_BOTOES
ENDC
A diretiva CBLOCK já instrui o compilador onde estao os registradores que vc usará.
No caso acima, o comando CBLOCK vai dizer ao compilador que os registradores especificados estao na posiçao 0X20, 0X21, 0X22, ......até encontrar a diretiva ENDC.
Se vc esta testando esse programa no PROTEUS, tenha cuidado. O Proteus muitas vezes dá algumas mancadas na simulaçao do programa ou do circuito.
Já simulei algums programas que ja funcionavam perfeitamente numa placa mas que ficavam esquisitos na simulaçao com o Proteus.

Enviado:
21 Nov 2006 09:36
por zielpunkt
Então, mesmo que não utilizasse CBLOCK e ENDC, vc está utilizando a diretiva ORG (?!??!!?) para declarar os registradores. A função do ORG não é essa e sim para indicar ao compilador o local do início de determinado bloco do programa. Vc deveria ter usado a diretiva EQU nesse caso.
A questão de não linearidade pode estar ligada a isso, mas eu nem sei se o programa compilaria ou funcionaria do jeito que está escrito. Como o Proex perguntou, e se compilou, pq vc disse que já testou alguma coisa, vc está simulando ou na real?

Enviado:
21 Nov 2006 10:42
por renatokodaira
Oi Alex !
Seu gerador nao aumenta ou diminui linearmente a frequencia do sinal gerado porque a frequencia é inversamente proporcional ao periodo. Entao um pequeno step no periodo pode gerar uma grande variaçao na frequencia dependendo em que ponto estiver.
Por exemplo voce usou o TIMER0 para contar os periodos "on" e "off". Se o timer0 contar somente 2 para cada periodo (digamos p/ simplificar que 2 = 2ms e que cada passo seja de 1ms), a frequencia (nao levando em conta as instruçoes que se seguem para processar os botoes) seria de 1/(2+2) = 1/4ms = 250Hz
Se voce aumentar o periodo (e consequentemente diminua a frequencia) para 3ms on e 3 ms off teria : 1/6ms = 166Hz. Veja que o proximo passo seria de 4ms, e a frequencia seria: 1/ 8ms = 125 Hz. Ou seja dessa forma variando a contagem de estouro do TMR0 a variaçao de frequencia nao será mesmo linear (mas inversamente proporcional). Alem disso precisa levar em conta que o sinal no PORTA.0 vai ficar um tempinho a mais em nivel 0 (por causa do processamento dos botoes e que é praticamente fixo).

Enviado:
21 Nov 2006 11:18
por brasilma
Nem me lembrem desse tema, tive de fazer no passado um oscilador onde era necessário variar a frequencia e o periodo de forma independente, tudo no braço, sem recurso PWM nem nada.
Duas rotinas de interrupção e muito calculo, porem a maxima frequencia era 2KHz.

Enviado:
21 Nov 2006 11:23
por alex_david_lima
Ola, renatokodaira
É isso memo que acontece, vc tem alguma ideia de como posso fazer?
Gostaria de lembrar aos meu colegas, que não tenho muita experiencia em assembly e que me perdoe as falas do meu codigo.
Abraços, Alex David
renatokodaira escreveu:Oi Alex !
Seu gerador nao aumenta ou diminui linearmente a frequencia do sinal gerado porque a frequencia é inversamente proporcional ao periodo. Entao um pequeno step no periodo pode gerar uma grande variaçao na frequencia dependendo em que ponto estiver.
Por exemplo voce usou o TIMER0 para contar os periodos "on" e "off". Se o timer0 contar somente 2 para cada periodo (digamos p/ simplificar que 2 = 2ms e que cada passo seja de 1ms), a frequencia (nao levando em conta as instruçoes que se seguem para processar os botoes) seria de 1/(2+2) = 1/4ms = 250Hz
Se voce aumentar o periodo (e consequentemente diminua a frequencia) para 3ms on e 3 ms off teria : 1/6ms = 166Hz. Veja que o proximo passo seria de 4ms, e a frequencia seria: 1/ 8ms = 125 Hz. Ou seja dessa forma variando a contagem de estouro do TMR0 a variaçao de frequencia nao será mesmo linear (mas inversamente proporcional). Alem disso precisa levar em conta que o sinal no PORTA.0 vai ficar um tempinho a mais em nivel 0 (por causa do processamento dos botoes e que é praticamente fixo).

Enviado:
21 Nov 2006 13:10
por renatokodaira
Oi Alex !
Primeiro vamos admitir que voce queira começar com 10Hz (apesar de que 10Hz nao é frequencia de audio) e cada passo seja de 1Hz.
10 Hz = periodo de 0,1 s = 50 ms on e 50 ms off
11 Hz = 0,090909 s = 45,4 ms on e 45,4 ms off
12 Hz = 0,083333 s = 41,6 ms on e 41,6 ms off
...
20 Hz = 0,05 s = 25 ms on e 25 ms off
e assim por diante.
O negocio é calcular os tempos que serao necessarios para o TMR0 estourar. è o contrario do que voce faz, que modifica linearmente o TMR0 e depois vê o que é que sai de frequencia.
Como para fazer essa variaçao linear precisa de muito calculo, e o PIC nao é lá grande coisa nisso, é melhor voce montar uma tabela de busca de frequencias x valores a serem postos no TMR0 e colocar isso na memoria (usando MOVLW frequencia; ADDFW PCL e RETLW valor TMR0).
Ex:
oscilador = 4,096MHz
prescaler TMR0 = 256
periodo de cada contagem do TMR0 = 250us
Para 10Hz, voce precisa de Ton = 50ms = 50ms / 250us = 200 contagens
voce usa o valor de 255 - 200 = 55 no TMR0
Para 11 Hz, voce precisa de Ton = 45,4ms = 45,45 / 250us = 181,8 = 182 contagens, voce coloca 255 - 182 = 73 no TMR0
Para 12 Hz, voce precisa de Ton = 41,66 ms = 41,66 / 250us = 166,7 contagens, vc coloca 255 - 167 = 88 no TMR0
....
Para 20 Hz; 25 ms / 250us = 100, TMR0 = 255 - 100 = 155
....
Para 50 Hz, 10 ms / 250us = 40, TMR0 = 255 - 40 = 215
....
Para 100 Hz, 5ms / 250us = 20, TMR0 = 255 - 20 = 235
Para 101 Hz, 4,95 ms/ 250 us = 19,8 veja que nesse caso, ou voce usa 20 ou 19 (235 ou 236 no TMR0), portanto vai perder a frequencia de 101 Hz com precisao por causa da resoluçao
Para melhorar a resoluçao, talvez seja melhor usar o TMR1 que possui mais estagios e uma frequencia maior de clock, Assim voce obtem mais passos e maior resoluçao.
Enquanto as frequencias estiverem baixas, até que dá pra conseguir os valores com certa precisao, mas a medida que vai aumentando haverá o problema de resoluçao.

Enviado:
21 Nov 2006 19:50
por alex_david_lima
Ola, renatokodaira
Gostei muito da sua teoria mais, não estou conseguindo utilizar na pratica vc, por favor vc poderia me ajudar !
vc não teria um exemplo ai ,
flau mesno pela ajuda, obrigo ate mais
Alex David
renatokodaira escreveu:Oi Alex !
Primeiro vamos admitir que voce queira começar com 10Hz (apesar de que 10Hz nao é frequencia de audio) e cada passo seja de 1Hz.
10 Hz = periodo de 0,1 s = 50 ms on e 50 ms off
11 Hz = 0,090909 s = 45,4 ms on e 45,4 ms off
12 Hz = 0,083333 s = 41,6 ms on e 41,6 ms off
...
20 Hz = 0,05 s = 25 ms on e 25 ms off
e assim por diante.
O negocio é calcular os tempos que serao necessarios para o TMR0 estourar. è o contrario do que voce faz, que modifica linearmente o TMR0 e depois vê o que é que sai de frequencia.
Como para fazer essa variaçao linear precisa de muito calculo, e o PIC nao é lá grande coisa nisso, é melhor voce montar uma tabela de busca de frequencias x valores a serem postos no TMR0 e colocar isso na memoria (usando MOVLW frequencia; ADDFW PCL e RETLW valor TMR0).
Ex:
oscilador = 4,096MHz
prescaler TMR0 = 256
periodo de cada contagem do TMR0 = 250us
Para 10Hz, voce precisa de Ton = 50ms = 50ms / 250us = 200 contagens
voce usa o valor de 255 - 200 = 55 no TMR0
Para 11 Hz, voce precisa de Ton = 45,4ms = 45,45 / 250us = 181,8 = 182 contagens, voce coloca 255 - 182 = 73 no TMR0
Para 12 Hz, voce precisa de Ton = 41,66 ms = 41,66 / 250us = 166,7 contagens, vc coloca 255 - 167 = 88 no TMR0
....
Para 20 Hz; 25 ms / 250us = 100, TMR0 = 255 - 100 = 155
....
Para 50 Hz, 10 ms / 250us = 40, TMR0 = 255 - 40 = 215
....
Para 100 Hz, 5ms / 250us = 20, TMR0 = 255 - 20 = 235
Para 101 Hz, 4,95 ms/ 250 us = 19,8 veja que nesse caso, ou voce usa 20 ou 19 (235 ou 236 no TMR0), portanto vai perder a frequencia de 101 Hz com precisao por causa da resoluçao
Para melhorar a resoluçao, talvez seja melhor usar o TMR1 que possui mais estagios e uma frequencia maior de clock, Assim voce obtem mais passos e maior resoluçao.
Enquanto as frequencias estiverem baixas, até que dá pra conseguir os valores com certa precisao, mas a medida que vai aumentando haverá o problema de resoluçao.

Enviado:
22 Nov 2006 08:08
por renatokodaira
Oi Alex !
Eu tenho um exemplo parecido para 12F629, mas está em basic e nao usava timers para a temporizaçao, apenas delays e usa alguns calculos em ponto flutuante para calcular os periodos on e off. E tambem só funciona para frequencias baixas.

Enviado:
22 Nov 2006 19:18
por alex_david_lima
Ola Renato posta ai , pra eu ver
Obrigado, Alex David