EJEMPLO 3Bueno ya sabemos manejar los puertos como entrada y salida, esta es una aplicación para tener siempre en cuenta los efectos de los pulsadores, cuando éstos no solo hagan una sola cosa como en el anterior ejemplo.
El tercer ejemplo consiste en un conmutador, es decir se enciende y se apaga un led mediante un mismo pulsador, tengo tres pulsadores instaladas, todos con las mismas funciones. Acá se ve el efecto que se hace para evitar el rebote de contactos, lo combatimos mediante software con retardos.
Este rebote de contactos, como el pulsador tendrá dos funciones, de encender y apagar hace funcionar inadecuadamente al circuito si no se controla adecuadamente.
Existe también el combate a los rebotes mediante hardware, pero como ya no quiero aumentarle más componentes prefiero hacerlo solamente por soft, en la web seguramente encontrarán esquemas muy buenos para pelear contra el ruido de los rebotes por hardware, y la combinación de la lucha por soft y hard seguramente nos dará un equipo más seguro, ya son cuestiones de necesidad, aplicación, etc.
Nuestra código anti-rebote es el siguiente:
toggle:
rcall delay20m ;retardo antirrebote
in r16,pind ;leer puertoD
andi r16,$07 ;AND con 7 que son los pines habilitados como entradas
cpi r16,0 ;comparar con cero, para asegurar que se solto el pulsador
brne toggle ;si no se solto seguimos con el retardo
también puede haber otra forma de hacerlo, como en programación no todos pensamos igual, esta es la que yo aprendí.
Acá tenemos el código del programa:
;--------------------------------------------------------------------------------
; Programa: Led on/off con el mismo Pulsador On/Off, conmutación 3 puntos
; Version: 0.0
;
; Dispositivo: ATmega8 Compilador: AVRASM2
; Entorno IDE: AVR Studio4.15 Simulador: Proteus 7.5sp3
;
; Notas: Este programa enciende un Led con un Pulsador, y lo apaga
; con el mismo pulsador, desde 3 puntos.
;
; Registros: r16 para almacenar la lectura del puertoD, r19 y r20 para
; el XOR, r17 y r18 para el retardo de 25ms antirrebote
;
; Conexiones: B1 -> Led
; D0 -> Pulsador1
; D1 -> Pulsador2
; D2 -> Pulsador3
;--------------------------------------------------------------------------------
;DIRECTIVAS EN ENSAMBLADOR
.include "m8def.inc" ;ATmega8
;reset-vector address $0000
.org $0000
rjmp main ;ve al main
;PROGRAMA PRINCIPAL
main:
ldi r16,$04 ;Configuracion de...
out sph,r16
ldi r16,$5F
out spl,r16 ;...la pila: Stack: $045F=RAMEND
ser r16 ;r16 <- $FF
out ddrb,r16 ;portB salida
clr r16 ;r16 <- $00
out ddrd,r16 ;portD entradas
ldi r19,2 ;cargar el valor para toggle
loop:
in r16,pind ;leer puertoD
sbrc r16,0 ;si el pin D0 es cero saltamos una instrucción
rcall toggle ;cambiamos estado del pin
sbrc r16,1 ;si el pin D1 es cero saltamos una instrucción
rcall toggle ;cambiamos estado del pin
sbrc r16,2 ;si el pin D2 es cero saltamos una instrucción
rcall toggle ;cambiamos estado del pin
rjmp loop ;bucle infinito
toggle:
rcall delay20m ;retardo antirrebote
in r16,pind ;leer puertoD
andi r16,$07 ;AND con 7 que son los pines habilitados como entradas
cpi r16,0 ;comparar con cero, para asegurar que se solto el pulsador
brne toggle ;si no se solto seguimos con el retardo
eor r20,r19 ;xor
out portb,r20 ;salida al puertob
ret ;retorno de subrutina
; =============================
; delay loop generator
; 80000 cycles:
; -----------------------------
; delaying 79998 cycles:
delay20m:
ldi R17, $86
WGLOOP0: ldi R18, $C6
WGLOOP1: dec R18
brne WGLOOP1
dec R17
brne WGLOOP0
; -----------------------------
; delaying 2 cycles:
nop
nop
ret
; =============================
El esquema del circuito:
La foto del circuito montado:
Y el video del circuito funcionando:
Hay un pequeño problema parece que se debe tener presionado bastante tiempo el pulsador y recién se ejecuta la orden, en simulación si funciona muy bien, pero en el circuito armado pasa el problema que mencioné, estaré revisando el código y lo actualizaré acá mismo cuando encuentre solucionar este pequeño desperfecto.Lo solucioné colocando un ANDI con 0x07, para colocar a cero los otros pines que están flotantes:
toggle:
rcall delay20m ;retardo antirrebote
in r16,pind ;leer puertoD
andi r16,$07 ;AND con 7 que son los pines habilitados como entradas cpi r16,0 ;comparar con cero, para asegurar que se solto el pulsador
brne toggle ;si no se solto seguimos con el retardo
eor r20,r19 ;xor
out portb,r20 ;salida al puertob
ret ;retorno de subrutina
Corregido el error ahora funciona todo ok!
Ya se viene el 4to ejemplo.