Ajuda assembly

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Ajuda assembly

Mensagempor alex_david_lima » 20 Nov 2006 20:32

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

Imagem

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
alex_david_lima
Bit
 
Mensagens: 35
Registrado em: 04 Nov 2006 07:46

Mensagempor proex » 20 Nov 2006 22:44

Perguntinha básica: Que compilador esquisito é esse que vc esta usando?
proex
Dword
 
Mensagens: 2101
Registrado em: 11 Out 2006 14:05
Localização: São Paulo

Mensagempor alex_david_lima » 20 Nov 2006 23:22

Ola, proex

Estou utilizando o MPLAB, assembly

Abraços, Alex David
alex_david_lima
Bit
 
Mensagens: 35
Registrado em: 04 Nov 2006 07:46

Mensagempor proex » 21 Nov 2006 07:35

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.
Editado pela última vez por proex em 21 Nov 2006 10:03, em um total de 1 vez.
proex
Dword
 
Mensagens: 2101
Registrado em: 11 Out 2006 14:05
Localização: São Paulo

Mensagempor zielpunkt » 21 Nov 2006 09:36

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?
"Talento é mais barato que sal. O que separa a pessoa talentosa da bem-sucedida é muito trabalho duro." [ Stephen King ]
zielpunkt
Byte
 
Mensagens: 376
Registrado em: 12 Out 2006 11:36
Localização: Sao Paulo - SP

Mensagempor renatokodaira » 21 Nov 2006 10:42

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).
renatokodaira
Byte
 
Mensagens: 402
Registrado em: 11 Out 2006 15:15

Mensagempor brasilma » 21 Nov 2006 11:18

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.
" A Teoria orienta e a Prática decide" ;-)
Avatar do usuário
brasilma
Dword
 
Mensagens: 3621
Registrado em: 11 Out 2006 15:39
Localização: Planeta Terra

Mensagempor alex_david_lima » 21 Nov 2006 11:23

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. :lol:



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).
alex_david_lima
Bit
 
Mensagens: 35
Registrado em: 04 Nov 2006 07:46

Mensagempor renatokodaira » 21 Nov 2006 13:10

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.
renatokodaira
Byte
 
Mensagens: 402
Registrado em: 11 Out 2006 15:15

Mensagempor alex_david_lima » 21 Nov 2006 19:50

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.
alex_david_lima
Bit
 
Mensagens: 35
Registrado em: 04 Nov 2006 07:46

Mensagempor renatokodaira » 22 Nov 2006 08:08

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.
renatokodaira
Byte
 
Mensagens: 402
Registrado em: 11 Out 2006 15:15

Mensagempor alex_david_lima » 22 Nov 2006 19:18

Ola Renato posta ai , pra eu ver



Obrigado, Alex David
alex_david_lima
Bit
 
Mensagens: 35
Registrado em: 04 Nov 2006 07:46


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x