Tabla de contenido:

Tutorial de ensamblador AVR 7:12 pasos
Tutorial de ensamblador AVR 7:12 pasos

Video: Tutorial de ensamblador AVR 7:12 pasos

Video: Tutorial de ensamblador AVR 7:12 pasos
Video: Lecture 8/12: Data Alignment 2024, Noviembre
Anonim
Tutorial de ensamblador AVR 7
Tutorial de ensamblador AVR 7

¡Bienvenido al Tutorial 7!

Hoy vamos a mostrar primero cómo buscar un teclado, y luego mostraremos cómo usar los puertos de entrada analógica para comunicarse con el teclado. Haremos esto usando interrupciones y un solo cable como entrada. Cablearemos el teclado para que cada pulsación de tecla envíe un voltaje único a la entrada analógica que nos permitirá distinguir por el voltaje qué tecla se presionó. Luego, enviaremos el número presionado a nuestro analizador de registros para mostrar que todo está sucediendo como debería. Hay una serie de trampas que puede encontrar al usar el convertidor analógico a digital (ADC) en el ATmega328p y así lo haremos tome las cosas en algunas etapas en el camino para tratar de descubrir cómo evitarlas. También veremos por qué usar el convertidor de analógico a digital no es la mejor manera de controlar un teclado a pesar de que usa menos puertos en su microcontrolador. En este tutorial necesitará:

  1. un teclado. Puedes comprar uno o puedes hacer lo que yo hice y buscar uno.
  2. 2 encabezados femeninos para el teclado (si está buscando uno)
  3. cables de conexión
  4. una placa de pruebas
  5. 4 resistencias de 1 Kohm
  6. 1 resistencia de 15 Kohm
  7. 1 resistencia de 3.3 Kohmios
  8. 1 resistencia de 180 ohmios
  9. 1 resistencia de 680 ohmios
  10. un multímetro digital
  11. su analizador del Tutorial 5

Es posible que desee omitir los primeros pasos si ya tiene un teclado y no necesita buscar uno.

Aquí hay un enlace a la colección completa de mis tutoriales de ensamblador AVR:

Paso 1: Buscar un teclado 1

Buscar un teclado 1
Buscar un teclado 1
Buscar un teclado 1
Buscar un teclado 1
Buscar un teclado 1
Buscar un teclado 1
Buscar un teclado 1
Buscar un teclado 1

Hace mucho tiempo, cuando incluso tus abuelos eran simples niños, la gente solía usar estos dispositivos de aspecto extraño, que tenían cables largos enchufados a la pared, para comunicarse entre sí. Se llamaban "teléfonos" y por lo general eran cosas de plástico baratas que hacían un sonido molesto cuando alguien te llamaba (no es que los tonos de llamada de "Justin Bieber" de hoy no sean igualmente molestos). En cualquier caso, estos dispositivos tenían teclados que estaban conectados de manera muy simple y, por lo tanto, son fáciles de buscar y tienen 2 teclas adicionales ("volver a marcar" y "flash") de los teclados que puede comprar y que tal vez desee reutilizar. como "teclas de flecha", "teclas de menú", o algo más. Así que vamos a empezar a buscar un teclado de un teléfono antiguo. Primero toma el teléfono (yo uso uno GE como se muestra en las imágenes) y haz palanca para revelar el cableado, luego toma un cincel y rompe las pequeñas perillas de plástico que sujetan el teclado y retíralo.

Paso 2: Buscar un teclado 2

Buscar un teclado 2
Buscar un teclado 2
Buscar un teclado 2
Buscar un teclado 2
Buscar un teclado 2
Buscar un teclado 2

Ahora tome una sierra de PVC y corte el plástico alrededor de los orificios de la cerradura y luego corte alrededor del borde para obtener la profundidad correcta dejando un teclado delgado.

Luego, vuelva a colocar el teclado usando las pequeñas clavijas que quedan después de que recortó la parte superior de ellas en el último paso y use un soldador para simplemente empujar el hierro caliente en cada orificio de clavija que derretirá el plástico y lo extenderá sobre el parte inferior del teclado formando nuevas "perillas" que mantendrán el teclado en su lugar como antes.

Me gusta hurgar en los tres altavoces y tal vez las otras cosas como interruptores y todo lo que hay en el tablero. Sin embargo, esta vez no voy a hurgar en los interruptores y esas cosas porque tenemos otros objetivos en este momento. Además, hay un IC lineal TA31002 en el que hay un timbre de teléfono. La hoja de datos se encuentra y descarga fácilmente en línea con el pinout y las características. Así que voy a dejarlo soldado a la placa por ahora y luego jugar con él más tarde. Me gustaría conectarlo a un osciloscopio y ver qué señales interesantes puedo obtener de él. Tal vez incluso hacer un timbre con eso. Quién sabe.

De todos modos, una vez que hayas terminado de destruir el teléfono y de limpiar las partes, terminaremos de hacer nuestro teclado.

Paso 3: Buscar un teclado 3

Buscar un teclado 3
Buscar un teclado 3
Buscar un teclado 3
Buscar un teclado 3
Buscar un teclado 3
Buscar un teclado 3

Use una mecha desoldadora y retire los cables planos de la parte inferior del teclado asegurándose de que los orificios en la placa de circuito estén despejados y luego coloque dos cabezales hembra en la placa donde están los orificios. Probablemente tendrá que recortar sus encabezados para que sean encabezados de 4 pines.

Ahora que los encabezados están conectados, puede conectarlos a una placa de pruebas, tomar un multímetro y probar las teclas colocando el multímetro en pines aleatorios y midiendo la resistencia. Esto le permitirá mapear las claves. Es difícil ver cómo las teclas están conectadas a las salidas mirando el circuito, pero si usa un multímetro, puede conectarlo a dos pines y luego presionar los botones hasta que vea un número en la pantalla en lugar de un circuito abierto.. Este será el pinout para esa clave.

Asigne todas las claves a los pines de salida de esta manera.

Paso 4: Cablee el teclado

Cablee el teclado
Cablee el teclado
Cablee el teclado
Cablee el teclado

Ahora siga el diagrama de cableado y conecte el teclado a su tablero.

Cómo va a funcionar esto es que colocaremos 5V en el lado izquierdo y el lado derecho va a GND. El primer pin a la derecha en el diagrama va al primero de nuestros pines analógicos en el microcontrolador Atmega328p. Cuando no hay botones presionados, la señal será 0V, y cuando se presionan cada uno de los diferentes botones, la entrada al puerto analógico variará entre 0V y 5V con una cantidad diferente dependiendo de la tecla que se presionó. Elegimos los valores de la resistencia para que cada ruta contuviera una resistencia diferente al resto. El puerto analógico del microcontrolador toma una señal analógica y la divide en 1024 canales diferentes entre 0 V y 5 V. Esto significa que cada canal tiene un ancho de 5 V / 1024 = 0,005 V / canal = 5 mV / canal. Por lo tanto, el puerto analógico puede distinguir los voltajes de entrada siempre que difieran en más de 5 mV. En nuestro caso, hemos elegido valores de resistencia de modo que dos pulsaciones de tecla cualesquiera envíen una señal de voltaje que difiera en más de esto, por lo que el microcontrolador debería poder decidir fácilmente qué tecla se presionó. El gran problema es que todo el sistema es muy ruidoso, por lo que tendremos que elegir un rango de voltajes para asignar a cada pulsación de botón, pero llegaremos a eso un poco más tarde.

Observe que podemos controlar un teclado de 14 botones usando solo una línea de entrada al controlador. Ese es uno de los aspectos útiles de las entradas analógicas.

Ahora nuestro primer intento de controlar el teclado será hacer que una pulsación de tecla cause una interrupción, la subrutina de interrupción leerá el puerto de entrada analógica y decidirá qué tecla se pulsó, y luego enviará ese número a nuestra subrutina analizadora de registros que mostrará la valor clave en binario en nuestros 8 LED que configuramos en el Tutorial 5.

Paso 5: Conecte el teclado a su analizador

Conecte el teclado a su analizador
Conecte el teclado a su analizador
Conecte el teclado a su analizador
Conecte el teclado a su analizador

Las imágenes muestran cómo queremos conectar el teclado al microcontrolador para que podamos ver la salida en la pantalla de nuestro analizador. Básicamente, simplemente conectamos la salida del teclado al pin 0 de PortC, que también se llama ADC0 en el ATmega328P.

Sin embargo, hay un par de cosas adicionales. También vamos a conectar un botón a PD2. Es decir. tome un cable de su riel de 5V a un botón y del otro lado del botón a PD2, y por último, queremos desconectar el pin AREF de nuestro riel de 5V y en su lugar dejarlo desconectado. Podríamos insertar un condensador de desacoplamiento de 0,1 microfaradios si quisiéramos. Este es un capacitor cerámico con un 104 escrito en él. Los dos primeros dígitos son el número y el último dígito es la potencia de 10, lo multiplicamos por para obtener una respuesta en picofaradios (pico significa 10 ^ -12), entonces 104 significa 10 x 10 ^ 4 picofaradios, que es lo mismo que 100 nanofaradios (nano significa 10 ^ -9), que es lo mismo que 0,1 microfaradios (micro significa 10 ^ -6). De todos modos, todo lo que esto hace es estabilizar el pin AREF cuando podemos usarlo como nuestro pin de referencia.

También queremos una resistencia de 1 Mohm entre PD2 y tierra. Vamos a configurar PD2 como un pin de salida a 0V y dispararemos en un flanco positivo en ese pin. Queremos que el borde desaparezca inmediatamente cuando sueltemos el botón, por lo que insertaremos esta resistencia "pull down".

La razón por la que queremos el botón es porque queremos activar nuestro convertidor analógico a digital fuera del pin INT0 en el chip, que también es PD2. Eventualmente, nos gustaría que la pulsación de la tecla active el ADC y también proporcione la entrada para convertir sin tener un botón separado, pero debido a la forma en que funciona el tiempo, comenzaremos por tener un botón separado para activar el ADC y una vez que planchemos todo. los errores y estamos seguros de que todo está funcionando correctamente, entonces abordaremos los problemas de ruido y sincronización que vienen con la activación desde el mismo botón que queremos leer.

Entonces, por ahora, la forma en que funciona es que mantendremos presionada una tecla, luego presionaremos el botón para activar el ADC, y luego lo soltaremos y, con suerte, el valor binario del botón que presionamos aparecerá en el analizador.

Entonces, escribamos un código que logre eso.

Paso 6: ¿Qué interruptores de palanca deberíamos configurar?

¿Qué interruptores de palanca deberíamos configurar?
¿Qué interruptores de palanca deberíamos configurar?

Primero pensemos en cómo vamos a codificar esto para que el controlador pueda leer la entrada del teclado y convertirla en un valor numérico correspondiente al botón que se presionó. Vamos a utilizar el Convertidor Analógico a Digital (ADC). que está integrado en el Atmega328p. Usaremos AREF como nuestro voltaje de referencia y la salida de nuestro teclado se conectará a PortC0 o PC0. Tenga en cuenta que este pin también se llama ADC0 para el convertidor analógico a digital 0. Podría ser una buena idea que lea la Sección 12.4 sobre interrupciones para el ATmega328P y también el capítulo 24 sobre el convertidor analógico a digital antes de obtener Para configurar el microcontrolador para que sepa qué hacer con una señal de entrada analógica y cómo interactuar con nuestro programa, primero tenemos que configurar algunos de los distintos ADC bits de registro relacionados. Estos son esencialmente equivalentes a los viejos interruptores de palanca de las primeras computadoras. O enciende o apaga un interruptor, o incluso más atrás, enchufa los cables entre una toma de corriente y otra para que los electrones que lleguen a esa bifurcación en la carretera encuentren una puerta cerrada y otra abierta, lo que la obligará a seguir un camino diferente en el laberinto de circuitería y, por lo tanto, realizar una tarea lógica diferente. Al codificar en lenguaje ensamblador, tenemos acceso cercano a estas funciones del microcontrolador, lo cual es una de las cosas atractivas de hacerlo en primer lugar. Es más "práctico" y mucho menos "detrás de escena" por así decirlo. Así que no piense en configurar estos registros como una tarea tediosa. ¡Esto es lo que hace que el lenguaje ensamblador sea interesante! Estamos ganando una relación muy personal con el funcionamiento interno y la lógica del chip y haciendo que haga exactamente lo que queremos que haga, ni más ni menos. Sin ciclos de reloj desperdiciados, así que aquí hay una lista de los interruptores que debemos configurar:

  1. Desactive el bit ADC de reducción de potencia, PRADC, que es el bit 0 del registro PRR, ya que si este bit está activado, apagará el ADC. El registro de reducción de energía es esencialmente una forma de apagar varias cosas que usan energía cuando no las necesita. Dado que estamos usando el ADC, queremos asegurarnos de que no esté desactivado de esta manera. (Consulte PRADC en la página 46)
  2. Seleccione el canal de entrada analógica para ser ADC0 apagando MUX3… 0 en el registro ADC Multiplexer Selection (ADMUX) (Ver tabla 24-4 página 249). Estos ya están desactivados por defecto, por lo que realmente no necesitamos hacer esto. Sin embargo, lo incluyo ya que si alguna vez usa un puerto que no sea ADC0, deberá alternar estos interruptores en consecuencia. Varias combinaciones de MUX3, MUX2, MUX1, MUX0 le permiten usar cualquiera de los puertos analógicos como su entrada y también puede cambiarlos sobre la marcha si desea ver un montón de señales analógicas diferentes a la vez.
  3. Desactive los bits REFS0 y REFS1 en el registro ADMUX para que usemos AREF como nuestro voltaje de referencia en lugar de una referencia interna (consulte la página 248).
  4. Active el bit ADLAR en ADMUX para que el resultado se "ajuste a la izquierda", discutiremos esta opción en el siguiente paso.
  5. Configure el bit ADC0D en el registro de desactivación de entrada digital (DIDR0) para desactivar la entrada digital a PC0. Estamos usando ese puerto para entrada analógica, por lo que también podríamos deshabilitar la entrada digital.
  6. Configure ISC0 e ISC1 en el Registro de control de interrupciones externas A (EICRA) para indicar que queremos disparar en el flanco ascendente de una señal de voltaje al pin INT0 (PD2), consulte la página 71.
  7. Borre los bits INT0 e INT1 en el registro de máscara de interrupción externa (EIMSK) para indicar que no estamos usando interrupciones en este pin. Si tuviéramos que habilitar interrupciones en este pin, necesitaríamos un controlador de interrupciones en la dirección 0x0002, pero en su lugar lo estamos configurando para que una señal en este pin active la conversión ADC, cuya finalización es manejada por la interrupción completa de conversión ADC en dirección 0x002A. Consulte la página 72.
  8. Establezca el bit de habilitación de ADC (ADEN) (bit 7) en el control de ADC y el registro de estado A (ADCSRA) para habilitar el ADC. Consulte la página 249.
  9. Podríamos comenzar una conversión única configurando el bit de conversión de inicio de ADC (ADSC) cada vez que queramos leer la señal analógica, sin embargo, por ahora preferimos que se lea automáticamente cada vez que alguien presione el botón, por lo que habilitaremos el ADC Bit de habilitación de disparo automático (ADATE) en el registro ADCSRA para que el disparo se realice automáticamente.
  10. También establecemos los bits ADPS2..0 (los bits AD Prescalar) en 111 para que el reloj ADC sea el reloj de la CPU dividido por un factor de 128.
  11. Seleccionaremos la fuente de activación del ADC para que sea PD2, que también se llama INT0 (Solicitud de interrupción externa 0). Hacemos esto alternando los distintos bits en el registro ADCSRB (consulte la Tabla 24-6 en la página 251). Vemos en la tabla que queremos ADTS0 desactivado, ADTS1 activado y ADTS2 desactivado para que el ADC se active con ese pin. Tenga en cuenta que si quisiéramos muestrear continuamente el puerto analógico como si estuviéramos leyendo alguna señal analógica continua (como muestreo de sonido o algo así), lo configuraríamos en Modo de ejecución libre. El método que estamos usando para configurar el disparo en PD2 dispara una lectura ADC del puerto analógico PC0 sin causar una interrupción. La interrupción vendrá cuando se complete la conversión.
  12. Habilite el bit ADC Interrupt Enable (ADIE) en el registro ADCSRA para que cuando se complete la conversión de analógico a digital, genere una interrupción para la cual podamos escribir un controlador de interrupciones y poner en.org 0x002A.
  13. Establezca el bit I en SREG para habilitar interrupciones.

Ejercicio 1: asegúrese de leer las secciones relevantes en la hoja de datos para cada una de las configuraciones anteriores para que comprenda lo que está sucediendo y lo que sucedería si las cambiamos a configuraciones alternativas.

Paso 7: escriba el controlador de interrupciones

En el último paso, vimos que lo hemos configurado para que un flanco ascendente detectado en PD2 active una conversión de analógico a digital en PC0 y cuando esta conversión se complete, lanzará una interrupción de conversión completa de ADC. Ahora queremos hacer algo con esta interrupción. Si examina la Tabla 12-6 en la página 65, verá una lista de las posibles interrupciones. Ya hemos visto la interrupción de RESET en la dirección 0x0000 y la interrupción de Desbordamiento del Temporizador / Contador0 en la dirección 0x0020 en Tutoriales anteriores. Ahora queremos ver la interrupción de ADC que vemos en la tabla está en la dirección 0x002A. Entonces, al comienzo de nuestro código en lenguaje ensamblador, necesitaremos una línea que diga:

.org 0x002Arjmp ADC_int

que saltará a nuestro controlador de interrupciones etiquetado ADC_int siempre que el ADC haya completado una conversión. Entonces, ¿cómo deberíamos escribir nuestro controlador de interrupciones? La forma en que funciona el ADC es realizando el siguiente cálculo:

ADC = Vin x 1024 / Vref

Así que veamos qué sucede si presiono el botón "volver a marcar" en el teclado. En ese caso, el voltaje en PC0 cambiará a algún valor, digamos 1.52V, y dado que Vref está en 5V tendremos:

ADC = (1.52V) x 1024 / 5V = 311.296

y entonces se mostraría como 311. Si quisiéramos convertir esto de nuevo a voltaje, simplemente revertiríamos el cálculo. Sin embargo, no necesitaremos hacer esto ya que no estamos interesados en los voltajes reales solo en distinguirlos. Cuando finaliza la conversión, el resultado se almacena en un número de 10 bits colocado en los registros ADCH y ADCL y hemos hecho que se "ajuste a la izquierda", lo que significa que los 10 bits comienzan en el bit 7 de ADCH y bajan a bit 6 de ADCL (hay 16 bits en total en estos dos registros y solo usamos 10 de ellos, es decir 1024 canales). Podríamos tener el resultado "ajustado a la derecha" si quisiéramos borrando el bit ADLAR en el registro ADMUX. La razón por la que elegimos el ajuste a la izquierda es porque nuestras señales están lo suficientemente separadas como para que los dos últimos dígitos del número de canal no sean relevantes y son probablemente solo ruido, por lo que distinguiremos las pulsaciones de teclas usando solo los 8 dígitos superiores, en otras palabras, solo necesitaremos mirar ADCH para averiguar qué botón se presionó. registrar, convertir ese número en un valor del teclado, y luego enviar ese valor a nuestro analizador de registros LED para que podamos verificar que presionando un "9" digamos, hará que los LED correspondientes a "00001001" se enciendan. Sin embargo, necesitamos ver primero lo que aparece en ADCH cuando presionamos los distintos botones. Así que escribamos un manejador de interrupciones simple que simplemente envíe el contenido de ADCH a la pantalla del analizador. Así que esto es lo que necesitamos:

ADC_int: analizador de lds, ADCH; carga el valor de ADCH en nuestros analizadoresbi EIFR, 0; borre el indicador de interrupción externa para que esté listo para funcionar de nuevo

A estas alturas, debería poder copiar el código de nuestro analizador en el tutorial 5 y agregar esta interrupción y la configuración de alternancia y ejecutarlo. Ejercicio 2: Escriba el código y ejecútelo. Verifique que aparezca ADCH en la pantalla de su analizador. Intente presionar la misma tecla varias veces. ¿Obtiene siempre el mismo valor en ADCH?

Paso 8: mapear los valores de pulsación de teclas

Asignar los valores de pulsación de teclas
Asignar los valores de pulsación de teclas

Lo que tenemos que hacer ahora es convertir los valores en ADCH en números correspondientes a la tecla que se presionó. Hacemos esto escribiendo el contenido de ADCH para cada pulsación de tecla y luego convirtiéndolo en un número decimal como hice en la imagen. En nuestra rutina de manejo de interrupciones, consideraremos un rango completo de valores como correspondientes a cada pulsación de tecla, de modo que el ADC mapeará cualquier cosa en ese rango a una pulsación de tecla determinada.

Ejercicio 3: haga este ma-p.webp

Esto es lo que obtuve para el mío (es muy probable que el tuyo sea diferente). Observe que lo configuré con un rango de valores para cada pulsación de tecla.

ADC_int:; Analizador de manejo de interrupciones externo; prepárese para el nuevo botón numérico H, ADCH; ADC se actualiza cuando se lee ADCH clccpi buttonH, 240brlo PC + 3; si ADCH es más grande, entonces es un analizador 1ldi, 1; así que cargue el analizador con un retorno de 1rjmp; y vuelva clccpi buttonH, 230; si ADCH es más grande que un analizador 2brlo PC + 3ldi, 2rjmp return clccpi buttonH, 217brlo PC + 3ldi analyzer, 3rjmp return clccpi buttonH, 203brlo PC + 3ldi analyzer, 4rjmp return clccpi buttonH, 187brlo PC + 3ldi analyzer, 5rjmp return clccpi buttonH, 155brlo PC + analizador 3ldi, 6rjmp return clccpi buttonH, 127brlo PC + analizador 3ldi, 255; configuraremos flash como todos los botones de retorno clccpi de onrjmp H, 115brlo PC + analizador 3ldi, 7rjmp botón de retorno clccpiH, 94brlo PC + analizador 3ldi, 8rjmp retorno botón clccpiH, 62brlo PC + analizador 3ldi, 9rjmp retorno botón clccpiH, 37brlo PC + analizador 3ldi, 0b11110000; el asterisco es la mitad superior onrjmp return clccpi buttonH, 28brlo PC + 3ldi analyzer, 0rjmp return clccpi buttonH, 17brlo PC + 3ldi analyzer, 0b00001111; el signo de almohadilla es la mitad inferior onrjmp return clccpi buttonH, 5brlo PC + 3ldi analyzer, 0b11000011; volver a marcar es el analizador ldi de retorno 2rjmp superior 2 inferior, 0b11011011; de lo contrario se produjo un error volver: reti

Paso 9: código y video para la versión 1

He adjuntado mi código para esta primera versión del controlador del teclado. En este, debe presionar la tecla y luego presionar el botón para que el ADC lea la entrada del teclado. Lo que preferiríamos no es ningún botón, sino que la señal para hacer la conversión proviene de la propia pulsación de tecla. Ejercicio 3: Reúna y cargue este código y pruébelo. Puede que tenga que cambiar los distintos umbrales de conversión para que se correspondan con los voltajes de pulsación de tecla, ya que probablemente difieran de los míos. ¿Qué sucede si intentas usar una entrada desde el teclado tanto para el ADC0 como para el pin de interrupción externo en lugar de a través de un botón? También adjuntaré un video del funcionamiento de esta primera versión de nuestro controlador de pulsación de teclas. en mi código hay una sección que inicializa el Stack Pointer. Hay varios registros que es posible que queramos empujar y extraer de la pila cuando estamos manipulando variables y otras cosas, y también hay registros que es posible que queramos guardar y restaurar más tarde. Por ejemplo, SREG es un registro que no se conserva a través de las interrupciones, por lo que las diversas banderas que se establecen y borran como resultado de las operaciones pueden cambiarse si ocurre una interrupción en medio de algo. Por lo tanto, es mejor si empuja SREG a la pila al comienzo de un manejador de interrupciones y luego lo saca de nuevo al final del manejador de interrupciones. Lo he colocado en el código para mostrar cómo se inicializa y para anticipar cómo lo necesitaremos más adelante, pero como no nos importa lo que suceda con SREG durante las interrupciones en nuestro código, no usé la pila para esto. que he usado la operación de cambio para establecer varios bits en los registros al inicializar. Por ejemplo en la línea:

temperatura de ldi, (1 <> pts EICRA, temp

El comando "<<" en la primera línea de código anterior es una operación de cambio. Básicamente, toma el número binario 1, que es 0b00000001, y lo desplaza a la izquierda por la cantidad del número ISC01. Ésta es la posición del bit denominado ISC01 en el registro EICRA. Dado que ISC01 es el bit 1, el número 1 se desplaza a la posición 1 de la izquierda para convertirse en 0b00000010. De manera similar, el segundo, ISC00, es el bit 0 de EICRA y, por lo tanto, el desplazamiento del número 1 es la posición cero a la izquierda. Si mira, eche otro vistazo al archivo m328Pdef.inc que descargó en el primer tutorial y ha estado usando evrr desde entonces, verá que es solo una larga lista de declaraciones ".equ". Encontrará que ISC01 es igual a 1. El ensamblador reemplaza cada instancia con 1 antes incluso de comenzar a ensamblar nada. Son solo nombres para bits de registro que nos ayudan a los humanos a leer y escribir código. Ahora, la línea vertical entre las dos operaciones de cambio anteriores es una operación lógica "o". Aquí está la ecuación:

0b00000010 | 0b00000001 = 0b00000011

y esto es lo que estamos cargando (usando "ldi") en temp. La razón por la que la gente usa este método para cargar valores en un registro es que permite usar el nombre del bit en lugar de solo un número y esto hace que el código sea mucho más fácil de leer. También hay otras dos técnicas que hemos usado. Usamos las instrucciones "ori" y "andi". Estos nos permiten FIJAR y BORRAR bits respectivamente sin cambiar ninguno de los otros bits en un registro. Por ejemplo, cuando usé

temperatura ori, (1

esta "or" s temp con 0b00000001 que pone un 1 en el bit cero y deja el resto sin cambios. También cuando escribimos

andi temp, 0b11111110

esto cambia el bit cero de la temperatura a 0 y deja el resto sin cambios.

Ejercicio 4: debe revisar el código y asegurarse de comprender cada línea. Puede resultarle interesante encontrar mejores métodos para hacer las cosas y escribir un programa mejor. Hay cientos de formas de codificar cosas y estoy bastante seguro de que puedes encontrar una forma mucho mejor que la mía. También puede encontrar (¡Dios no lo quiera!) Errores y omisiones. En ese caso, me gustaría saber sobre ellos para que puedan solucionarse.

Bien, ahora veamos si podemos deshacernos de ese botón superfluo …

Paso 10: Código para la versión 2

La forma más sencilla de deshacerse del botón es simplemente eliminarlo por completo, olvidar la entrada a PB2 y simplemente cambiar el ADC al "Modo de ejecución libre".

En otras palabras, simplemente cambie el registro ADCSRB para que ADTS2, ADTS1 y ADTS0 sean todos ceros.

Luego, establezca el bit ADSC en ADCSRA en 1, lo que iniciará la primera conversión.

Ahora cárguelo en su microcontrolador y verá que el número correcto aparece en la pantalla mientras presiona el botón y solo mientras presiona el botón. Esto se debe a que el ADC muestrea continuamente el puerto ADC0 y muestra el valor. Cuando quita el dedo del botón, el "rebote del botón" hará que se produzcan algunos valores aleatorios muy rápidamente y luego volverá a establecerse en la entrada de 0V. En nuestro código, tenemos este 0V que aparece como 0b11011011 (porque al presionar la tecla `0 'ya se usa el valor de visualización 0b00000000)

Sin embargo, esta no es la solución que queremos por dos razones. Primero, no queremos tener que mantener presionado el botón. Queremos presionarlo una vez y que se muestre el número (o se use en algún código nuevo en un tutorial posterior). En segundo lugar, no queremos probar continuamente el ADC0. Queremos que tome una sola lectura, la convierta y luego se suspenda hasta que una nueva pulsación de tecla active una nueva conversión. El modo de ejecución libre es mejor si lo único que desea que haga el microcontrolador es leer continuamente alguna entrada analógica, como si quisiera mostrar temperaturas en tiempo real o algo así.

Así que busquemos otra solución …

Paso 11: ¿Cómo nos deshacemos del botón? Versión 3

¿Cómo nos deshacemos del botón? Versión 3
¿Cómo nos deshacemos del botón? Versión 3

Hay muchas formas de proceder. Primero podríamos agregar hardware para deshacernos del botón. Por ejemplo, podemos intentar poner un transistor en el circuito en la línea de salida de la pulsación de tecla para que tome un pequeño goteo de la corriente de la salida y envíe un pulso de 5 V al pin de interrupción PD2.

Sin embargo, eso probablemente sería demasiado ruidoso al menos y, en el peor de los casos, no permitiría suficiente tiempo para una lectura precisa de pulsación de tecla, ya que la salida de voltaje del teclado no tendría tiempo de estabilizarse antes de que se capture la lectura del ADC.

Por eso, preferimos encontrar una solución de software. Lo que nos gustaría hacer es agregar una interrupción en el pin PD2 y escribir un manejador de interrupciones para él que llame a una sola lectura del pin del teclado. En otras palabras, nos deshacemos de la interrupción del disparador automático del ADC y agregamos una interrupción externa que llama al ADC dentro de él. De esa manera, la señal para leer el ADC llega después de que la señal PD2 ya se haya producido y esto podría dar a las cosas el tiempo suficiente para estabilizarse a un voltaje preciso antes de que se lea y convierta el pin PC0. Todavía tendríamos una interrupción de finalización de ADC que envía el resultado a la pantalla del analizador al final.

¿Tener sentido? Bueno, hagámoslo …

Eche un vistazo al nuevo código adjunto.

Verá los siguientes cambios:

  1. Agregamos un rjmp en la dirección.org 0x0002 para manejar la interrupción externa INT0
  2. Cambiamos el registro EIMSK para indicar que queremos interrumpir en el pin INT0
  3. Cambiamos el pin ADATE en el registro ADCSRA para deshabilitar el disparo automático
  4. Nos deshicimos de la configuración de ADCSRB ya que son irrelevantes cuando ADATE está apagado
  5. Ya no tenemos que restablecer el indicador de disparo externo ya que la rutina de interrupción INT0 lo hace automáticamente cuando se completa; anteriormente no teníamos una rutina de interrupción, solo activamos el ADC de una señal en ese pin, por lo que tuvimos que limpia esa bandera a mano.

Ahora, en el controlador de interrupciones, simplemente llamamos a una sola conversión desde el ADC.

Ejercicio 5: Ejecute esta versión y vea qué sucede.

Paso 12: Código y video para la versión de trabajo

Como vimos en la última versión, la interrupción del botón no funciona muy bien porque la interrupción se activa en un flanco ascendente al pin PD2 y luego el controlador de interrupciones llama a la conversión ADC. Sin embargo, el ADC obtiene la lectura de voltaje antes de que se haya estabilizado y, por lo tanto, lee tonterías.

Lo que necesitamos es introducir un retraso entre la interrupción en PD2 y la lectura de ADC en PC0. Haremos esto agregando un temporizador / contador, una interrupción de desbordamiento del contador y una rutina de retardo. ¡Afortunadamente ya sabemos cómo hacer esto con el Tutorial 3! Así que copiaremos y pegaremos el código relevante desde allí.

Le he dado el código resultante y un video que lo muestra en funcionamiento.

Notará que las lecturas no son tan precisas como cabría esperar. Es probable que esto se deba a varias fuentes:

  1. estamos tocando desde la salida de voltaje del teclado para disparar en PD2, lo que afecta la lectura en PC0.
  2. Realmente no sabemos cuánto demorar después del disparo para obtener la mejor lectura.
  3. Se necesitan algunos ciclos para que se complete la conversión de ADC, lo que significa que no podemos disparar rápidamente en el teclado.
  4. Probablemente haya ruido en el propio teclado.
  5. etc …

Entonces, aunque logramos que el teclado funcionara, y ahora podríamos usarlo en aplicaciones usando los valores de pulsación de teclas de alguna otra manera en lugar de simplemente enviarlos a la pantalla del analizador, no es muy preciso y es muy molesto. Es por eso que creo que la mejor manera de conectar los teclados es simplemente pegar cada salida del teclado en un puerto diferente y decidir qué tecla se presiona y qué puertos ven un voltaje. Eso es fácil, muy rápido y muy preciso.

De hecho, solo hay dos razones por las que uno querría manejar un teclado de la forma en que lo hemos hecho aquí:

  1. Solo usa 2 de los pines de nuestro microcontrolador en lugar de 8.
  2. Es un gran proyecto para mostrar diferentes aspectos del ADC en el microcontrolador, que es diferente de las cosas estándar que puede encontrar allí, como lecturas de temperatura, potenciómetros giratorios, etc. Quería un ejemplo de lecturas individuales activadas y activación automática de pines externos. en lugar de simplemente ejecutar el modo de absorción de CPU de ejecución libre.

De todos modos, aquí hay un par de ejercicios finales para ti:

Ejercicio 6: Vuelva a escribir el manejador de interrupción completa de conversión de ADC para usar una tabla de búsqueda. Es decir. De modo que prueba el valor analógico con el primer elemento de la tabla y, si es más grande, regresa de la interrupción, si no lo es, aumenta Z al siguiente elemento de la tabla y vuelve a la prueba. Esto acortará el código y limpiará la rutina de interrupción y hará que se vea mejor. (Daré una posible solución como paso siguiente) Ejercicio 7: Conecte su teclado a 8 pines en el microcontrolador y escriba el controlador simple para él y experimente cuánto mejor es. ¿Puedes pensar en algunas formas de hacer que nuestro método funcione mejor?

Eso es todo por este tutorial. Adjunto la versión final con punteros. A medida que nos acerquemos a nuestro objetivo final, usaremos el teclado una vez más en el Tutorial 9 para mostrar cómo controlar pantallas de siete segmentos con él (y construir algo interesante que use las teclas adicionales en el teclado del teléfono) y luego En su lugar, cambie a controlar las cosas presionando botones (ya que ese método se adapta mejor al producto final que estamos construyendo con estos tutoriales) y simplemente dejaremos de lado el teclado.

¡Hasta la próxima!

Recomendado: