# Mini piano en PIC16F84A. Programa en ensamblador (MPLAB)



## Dakira (Feb 24, 2013)

Bueno, lo que pasa es que tengo este programa que usa las frecuencias de las notas musicales para simular un piano. Tiene 8 botones que van al puertoB. Las resistencias PULL-UP estan habilitadas en el codigo. La salida es el pin RA0. Se compila bien y todo, pero al simularlo en PROTEUS dice que hay STACK OVERFLOW. Segun lei, es porque hay muchos CALL. Si lo programo en el PIC16F84A asi como esta, puede resultar dañado? O que puedo hacer para modificarlo?

*los puntos no estan en el codigo (obviamente), es solo para que se visualice mejor aqui*


```
;Configuracion del MPLABX
.........__CONFIG.........._CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
.........LIST ................P=16F84A
........INCLUDE.............<P16F84A.INC> ;LIBRERIA

........CBLOCK  0x0c
........ENDC
#define Salida........PORTA,0
;------------------------------------------------------------------
;Configuracion del microcontrolador
........ORG........0                    ;Inicia en direccion 0
Inicio                                  ;etiquetas comienza con mayuscula
........bsf........STATUS,RP0              ;Accesar al Banco 1
........bcf........Salida                  ;PORTA como salida
........movlw........0xFF                    ;carga unos a w
 ........movwf........PORTB                   ;pone RB como entrada
........bcf ........OPTION_REG,7            ;activa resistencias pull up de RB
........bcf........ STATUS,RP0              ;Acceso al banco 0
;------------------------------------------------------------------------------
;Programa principal
Main    

Do
........ btfsc........PORTB,0         ;esta pulsado?
........goto........Re              ;espera a que este pulsado
........ call........Retardo_20ms    ;espera que se estabilicen niveles de tension
........btfsc........PORTB,0         ;comprueba si es rebote
........goto........Re              ;si era rebote, se sale
 ........call........Nota_do
Re
........btfsc........PORTB,1         ;esta pulsado?
........goto........Mi             ;espera a que este pulsado
........call........Retardo_20ms    ;espera que se estabilicen niveles de tension
........btfsc........PORTB,1        ;comprueba si es rebote
........ goto........Mi             ;si era rebote, se sale
........call........Nota_re
Mi
........btfsc........PORTB,2         ;esta pulsado?
........goto........Fa             ;espera a que este pulsado
........call........Retardo_20ms    ;espera que se estabilicen niveles de tension
........btfsc........PORTB,2         ;comprueba si es rebote
........goto........Fa             ;si era rebote, se sale
........call........Nota_mi
Fa
........ btfsc........PORTB,3         ;esta pulsado?
........goto........Sol             ;espera a que este pulsado
........call ........Retardo_20ms    ;espera que se estabilicen niveles de tension
........btfsc........PORTB,3         ;comprueba si es rebote
........goto........Sol             ;si era rebote, se sale
........call........Nota_fa
Sol
........btfsc........PORTB,4         ;esta pulsado?
........ goto........La             ;espera a que este pulsado
........call ........Retardo_20ms    ;espera que se estabilicen niveles de tension
........ btfsc........PORTB,4         ;comprueba si es rebote
........goto........La             ;si era rebote, se sale
........call ........Nota_sol
La
........btfsc........PORTB,5         ;esta pulsado?
 ........ goto........Si             ;espera a que este pulsado
........call........Retardo_20ms    ;espera que se estabilicen niveles de tension
........btfsc........PORTB,5         ;comprueba si es rebote
........goto........Si             ;si era rebote, se sale
........call........Nota_la
Si
........btfsc........PORTB,6         ;esta pulsado?
........goto........Do8             ;espera a que este pulsado
........call........Retardo_20ms    ;espera que se estabilicen niveles de tension
  ........ btfsc........PORTB,6         ;comprueba si es rebote
........goto........Do8             ;si era rebote, se sale
        call........Nota_si
Do8
........ btfsc........PORTB,7         ;esta pulsado?
........goto........Main             ;espera a que este pulsado
........call........Retardo_20ms    ;espera que se estabilicen niveles de tension
........btfsc........PORTB,7         ;comprueba si es rebote
........ goto........Main            ;si era rebote, se sale
 ........call ........Nota_do8

;-------------------------------------------------------------------------------
;subrutinas
Nota_do
........bsf........Salida
........ call........Retardo_do
........bcf........Salida
........call ........Retardo_do
........btfss........PORTB,0
........goto........Nota_do
 ........goto........Main
Nota_re
........ bsf........Salida
........cal........Retardo_re
........bcf........Salida
........call........Retardo_re
........btfss........PORTB,1
........goto........Nota_re
........goto........Main
Nota_mi
........bsf ........Salida
........call........Retardo_mi
........ bcf........Salida
........call........Retardo_mi
........btfss........PORTB,2
........ goto........Nota_mi
........goto........Main
Nota_fa
........ bsf........Salida
........call ........Retardo_fa
........ bcf........Salida
........call........Retardo_fa
........btfss........PORTB,3
........goto........Nota_fa
........goto........Main
Nota_sol
........bs........Salida
........call........Retardo_sol
........bcf........Salida
........call........Retardo_sol
........btfss........PORTB,4
........goto........ Nota_sol
........goto........Main
Nota_la
........bsf........Salida
........call........Retardo_la
........bcf........Salida
........ call    Retardo_la
........btfss   PORTB,5
........goto........Nota_la
........goto........Main
Nota_si
........bsf........Salida
........call........Retardo_si
........bcf ........Salida
........call........Retardo_si
........btfss........PORTB,6
........goto........Nota_si
........goto........Main
Nota_do8
........bsf ........Salida
 ........call........Retardo_do8
........bcf........Salida
........ call........Retardo_do8
........btfss........PORTB,7
........goto ........Nota_do8
........goto........Main
;-------------------------------------------------------------------------------
;libreria
        INCLUDE<retardos_p.inc>
        END
;-------------------------------------

Estos son algunos de los retardos:
........cblock
	d1
	d2
........endc
; Delay = 0.000956 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.000956 seconds = 956 cycles
; Error = 0 %
Retardo_do
			;948 cycles
........movlw........0xBD
........movwf........d1
........movlw........0x01
........movwf........d2
Delay_do
........decfsz........d1, f
........goto........$+2
........decfsz........d2, f
........goto	Delay_do

			;4 cycles
........goto	$+1
........goto	$+1

			;4 cycles (including call)
........return
;-----------------------------------------------------------------------------
; Delay = 0.000851 seconds
; Clock frequency = 4 MHz

; Actual delay = 0.000851 seconds = 851 cycles
; Error = 0 %
Retardo_re
			;843 cycles
........movlw........0xA8
........movwf........d1
........movlw........0x01
........movwf........d2
Retardo_re_0
........decfsz........d1, f
........goto	$+2
........decfsz........d2, f
........goto........Retardo_re_0

			;4 cycles
........goto	$+1
........goto	$+1

			;4 cycles (including call)
........return
```


Y pues esto es lo que tengo


----------



## Melghost (Feb 24, 2013)

Tranquilo, no dañas nada. Lo que pasa es que no te va a funcionar.

El error está claro. Fíjate que estás llamando a las subrutinas Nota_XX con la instrucción CALL, pero estás volviendo a la detección de pulsadores con GOTO, con lo cual el stack se va llenando con las direcciones de retorno y no se vacían nunca.

Siempre que llames a una subrutina con la instrucción CALL tienes que salir de ellas con la instrucción RETURN.

Me has recordado uno de los primeros programas que hice, hace ya casi 30 años, cuando tenía 12 años de edad. Hice sonar en mi ZX Spectrum la canción de los "pajaritos", con una instrucción para cada nota musical... ¡Qué tiempos! 

Es un buen intento, pero en el futuro plantéate los cambios que te voy a recomendar (sólo si quieres hacer un super-piano):

        1- Guarda los valores de retardos en una tabla.
        2- Haz una matriz de pulsadores para las teclas: Mandas 4 salidas a un decodificador y obtienes 16 comunes para cada 4 pulsadores, obteniendo en total 64 teclas, o sea, 5 octavas con sus bemoles y todo.

        Bueno, se me ocurren varias cosas más, como incluir algún chip generador de tonos con polifonía y así, pero bueno, supongo que no era tu intención inicial.


----------



## Dakira (Feb 24, 2013)

Wow, esta bien. Muchas gracias, si me ayudo. Ya esta sin problema.
Me sorprende que desde pequenio ya le sabias a estas cosas


----------

