martes, 11 de agosto de 2015

Manejo de teclados matriciales(barrido clásico)

En ocasiones debemos manejar teclados conectados de forma matricial por lo que debemos manipular las filas y columnas de este teclado para saber que tecla ha sido presionada. En la figura 1 podemos observar un teclado 4x4 de membrana con su forma de conexión.

Fig. 1. Teclado de membrana

Para poder realizar el barrido en esta ocasion debemos configurar como entradas las columnas y como salidas las filas, después debemos ir prendiendo fila por fila para observar si se tiene un cambio de estado en alguna columna y de esta manera saber que tecla ha sido presionada.


 Fig. 2. Circuito que se va a utilizar

En la figura 2 podemos observar como está distribuida las conexiones en el teclado y las salidas que vamos a tener. Como se puede ver hay una descripción de como van a ser las teclas, que valor tomarán al presionarlas, en los 4 leds verdes se mostrara este valor de la tecla en binario y en el led rojo nos mostrara si no hemos aun presionado ninguna tecla. Cabe recalcar que los leds se pueden reemplazar por displays de 7 segmentos y otros indicadores, pero por ser una aplicación lo dejaremos solo con leds. Recordar que si se quiere llevar a la vida real el circuito se deben poner resistencias en serie con los leds para limitar la corriente.


Programa:

/*
 * barrido_clasico_de_teclado.asm
 *
 *  Created: 11/08/2015 14:49:55
 *   Author: cdtoap
 */

 .include "m164pdef.inc"

 .def tempo=r16
 .def tecla=r17
 .def ante=r18

 .cseg
 .org 0x00
 ;configuracion de puertos

 ldi tempo,$0F; defino filas como salidas y columnas como entradas
 out ddra,tempo
 ldi tempo,$1F; defino las salidas de los leds
 out ddrb,tempo
 ldi tempo,$00; configuro lo que no voy a usar como entradas para el pull-up
 out ddrc,tempo
 out ddrd,tempo

 ldi tempo,$FF; configuro pull-up y mantengo apagada la lectura
 out porta,tempo
 out portc,tempo
 out portd,tempo
 ldi tempo,$F0; apago los leds de las teclas y dejo encendido el led rojo
 out portb,tempo

 ;configurar pull-up
 in   tempo,mcucr
 andi tempo,$EF
 out  mcucr,tempo
 ;fin de configuracion de puertos

 ldi ante,16; cargamos para que antes tenga el valor de no presionado

 salto0:
 ldi tecla,16
 ldi tempo,$FE; pongo un 0 en la primera fila para ver si se ha presionado algo
 out porta,tempo

 sbis pina,7;salta una instruccion si no ha habido cambio en ese bit
 ldi  tecla,3; carga el valor correspondiente si no salta
 sbis pina,6
 ldi  tecla,2
 sbis pina,5
 ldi  tecla,1
 sbis pina,4
 ldi  tecla,0
 ;el proceso se repite en cada fila

 ldi tempo,$FD; pongo 0 en la segunda fila
 out porta,tempo

 sbis pina,7
 ldi  tecla,7
 sbis pina,6
 ldi  tecla,6
 sbis pina,5
 ldi  tecla,5
 sbis pina,4
 ldi  tecla,4

 ldi tempo,$FB; pongo 0 en la tercera fila
 out porta,tempo

 sbis pina,7
 ldi  tecla,11
 sbis pina,6
 ldi  tecla,10
 sbis pina,5
 ldi  tecla,9
 sbis pina,4
 ldi  tecla,8

 ldi tempo,$F7; pongo 0 en la cuarta fila
 out porta,tempo

 sbis pina,7
 ldi  tecla,15
 sbis pina,6
 ldi  tecla,14
 sbis pina,5
 ldi  tecla,13
 sbis pina,4
 ldi  tecla,12

 cp   ante,tecla; comparo si ha habido un cambio en la tecla ya ingresada antes
 breq salto0; si es igual vaya a revisar hasta que haya un cambio
 mov  ante,tecla; se pone la tecla actual ahora como la anterior
 cpi   tecla,16; si es igual a 16 es porque se ha soltado la tecla pero no hay un cambio
 breq salto0

 ori tecla,0xE0; se asegura pull-up
 out portb,tecla; se prende los leds correspondiente al numero binario
 rjmp salto0

Circuito al presionar la tecla D




lunes, 10 de agosto de 2015

Circuito de aplicación del conversor análogo digital 1

En esta ocasión se presenta un circuito que realiza la operación de 4 diferentes conversores análogos-digitales y muestra el resultado de la suma de los 4. Para realizar esto es obligatorio trabajar solo con un conversor a la vez ya que no nos permite otra opción el microcontrolador Atmega164P, por lo tanto se prende cada conversor, se realiza la lectura, se apaga ese conversor y se prende el siguiente y asi lo realizamos hasta que acabe las 4 conversiones y despues realizamos la suma. Como el conversor es de 10 bits, debemos realizar una suma de 16 bits para poder mostrar el resultado en leds. El resultado se va a mostrar en 12 leds porque con 12 bits es el número mayor que se puede obtener con la suma de 4 números de 10 bits.

Circuito con el que se va a trabajar

Código:

*  Created: 09/07/2015 17:39:41
 *   Author: cdtoap
 */

 ;variables que vamos a usar en el programa
 .def unol=r15
 .def unoh=r16
 .def dosl=r17
 .def dosh=r18
 .def tresl=r19
 .def tresh=r20
 .def cuatrol=r21
 .def cuatroh=r22
 .def auxl=r23
 .def auxh=r24
 .def tempo=r25
 ;----------------------------------------------

 .cseg
 .org 0x00
 /*configurar puertos*/
 ldi  tempo,$00
 out  ddra,tempo
 out  ddrc,tempo
 ldi  tempo,$FF
 out  ddrb,tempo
 ldi  tempo,0b00001111
 out ddrd,tempo

 ldi tempo,$FF
 out portc,tempo
 ldi tempo,0
 out portb,tempo
 ldi tempo,0b11110000
 out portd,tempo
 ldi tempo,0b11110000; apagamos los pull-up de los conversores
 out porta,tempo
 ldi tempo,0b00001111;convertimos en entrada análoga
 sts didr0,tempo

 in   tempo,mcucr
 andi tempo,$EF
 out  mcucr,tempo

 ;Encendemos el stack pointer
 ldi  tempo,high(ramend)
 out  sph,tempo
 ldi  tempo,low(ramend)
 out  spl,tempo
 /*Fin configurar puertos*/
 inicio:
 ldi  tempo,0b01000000; configuramos el admux para referencia el AVCC, ajuste a la derecha, y escogemos el ADC0
 sts  admux,tempo

 ldi  tempo,0b11000110; prendemos la conversion y activamos para que empiece a convertir
 sts  adcsra,tempo; preescalador 1:64

 call lazo; llamamos a la subrutina que comprueba si la conversion ha terminado
 lds  tempo,adcl; cargamos lo del valor bajo del adc
 mov  unol,tempo; guardamos ese valor en un registro
 lds  tempo,adch; cargamos lo del valor alto del adc
 andi tempo,0b00000011; hacemos una and para asegurar que solo trabajemos con 10 bits
 mov  unoh,tempo; guardamos en el registro del primer conversor

 ldi  tempo,0b00000110; apagamos el conversor
 sts  adcsra,tempo

 conver2:
 ldi  tempo,0b01000001; encendemos el segundo conversor
 sts  admux,tempo

 ldi  tempo,0b11000110; empieza a convertir
 sts  adcsra,tempo

 call lazo; comprueba si acabo de convertir
 lds  tempo,adcl
 mov  dosl,tempo; guardamos en registros
 lds  tempo,adch
 andi tempo,0b00000011
 mov  dosh,tempo; guardamos en registro del segundo conversor

 ldi  tempo,0b00000110; apgamos el conversor
 sts  adcsra,tempo

 conver3:
 ldi  tempo,0b01000010; obtenemos datos del tercer conversor
 sts  admux,tempo

 ldi  tempo,0b11000110
 sts  adcsra,tempo

 call lazo
 lds  tempo,adcl
 mov  tresl,tempo
 lds  tempo,adch
 andi tempo,0b00000011
 mov  tresh,tempo

 ldi  tempo,0b00000110
 sts  adcsra,tempo

 conver4:
 ldi  tempo,0b01000011; obtenemos datos del conversor 4
 sts  admux,tempo

 ldi  tempo,0b11000110
 sts  adcsra,tempo

 call lazo
 lds  tempo,adcl
 mov  cuatrol,tempo
 lds  tempo,adch
 andi tempo,0b00000011
 mov  cuatroh,tempo

 ldi  tempo,0b00000110; apagamos las conversiones
 sts  adcsra,tempo

 call operacion; llamamos a la subrutina que realiza la operacion de sumar
 rjmp inicio; realizamos el programa infinitamente

 lazo:
 lds  tempo,adcsra; carga el valor del adcsra en tempo
 sbrc tempo,6; comprueba el pin que dice si se acabo de convertir
 rjmp lazo; si es que no acaba quedese repitiendo
 ret; si acabo de convertir continue el programa

 operacion:
 clr tempo; borramos el tempo
 mov auxl,unol; guardamos en auxiliar lo del primer conversor
 mov auxh,unoh
 add auxl,dosl; sumamos 1 y 2 y guardamos en el auxiliar el resultado
 adc auxh,dosh
 add auxl,tresl; la suma de 1 y 2 sumamos con 3
 adc auxh,tresh
 add auxl,cuatrol; la suma de 1,2 y 3 sumamos con 4
 adc auxh,cuatroh

 out portb,auxl; sacamos por el puerto b los 8 bits menos significativos
 ori auxh,0b11110000; para asegurar pull-up hacemos una or
 out portd,auxh; sacamos por el puerto d los 4 bits mas significativos
 ret; regresamos al programa



Circuito Funcionando: