Paso 5: Temporizador/contador 0
Echa un vistazo a la imagen de arriba. Se trata de la decisión en el proceso de elaboración de la "PC" cuando algunos fuera de influencia "interrumpe" el flujo de nuestro programa. Lo primero hace cuando recibe una señal de fuera que se ha producido una interrupción comprueba si hemos puesto "habilitar la interrupción" es poco para ese tipo de interrupción. Si no tenemos, entonces sólo sigue a ejecutar la siguiente línea de código. Si hemos fijado ese poco de habilitar interrupción particular (de modo que hay un 1 en ese lugar de bits en lugar de 0) entonces comprobará o no hemos habilitado "interrupciones globales", si no nuevamente ir a la siguiente línea de código y continuar. Si hemos activado las interrupciones globales así, luego se vaya a la ubicación de memoria de programa de ese tipo de interrupción (como se muestra en la tabla 12-6) y ejecutar cualquier comando que hemos colocado allí. Así que veamos cómo hemos implementado todo esto en nuestro código.
El Reset con la etiqueta sección de nuestro código comienza con las dos líneas siguientes:
Reset: ldi temp, 0b00000101 out TCCR0B, temp
Como ya sabemos, esto carga en la temperatura (es decir, R16) el número inmediatamente después, que es 0b00000101. A continuación, escribe este número en el registro llamado TCCR0B con el comando "out". ¿Qué es este registro? Bien, vamos a ir a la hoja de datos en la página 614. Esto está en medio de una tabla que resume todos los registros. En la dirección 0x25 se encuentra TCCR0B. (Ya sabes la línea "hacia fuera 0x25, r16" de donde vino en mi versión no comentada del código). Vemos por el segmento de código que hemos establecido el bit 0 y el bit 2 y despejó todos los del resto. Observando la tabla vemos que esto significa que hemos creado CS00 y CS02. Ahora vamos a la cabeza sobre el capítulo en la hoja de datos llamado "8-bit Timer/Counter0 con PWM". En particular, ir a la página 107 de dicho capítulo. Verá la misma descripción del registro "Timer/Counter Control Register B" (TCCR0B) que acabamos de ver en el resumen del registro de la tabla (por lo que nos podríamos haber venido directamente aquí, pero quería ver cómo utilizar las tablas resumen para futura referencia). La hoja de datos sigue una descripción de cada uno de los bits de dicho registro y lo que hacen. Vamos a omitir todo lo que por ahora y dar vuelta la página a la tabla 15-9. Esta tabla muestra el "reloj seleccione Bit Descripción". Ahora mira hacia abajo de la mesa hasta encontrar la línea que corresponde a los bits que sólo en ese registro. La línea dice "clk/1024 de prescaler)". Lo que esto significa es que queremos Timer/Counter0 (TCNT0) a marcar a lo largo a una velocidad que es la frecuencia de la CPU dividido por 1024. Ya que tenemos nuestro microcontrolador alimentado por un oscilador de cristal de 16MHz, significa que la velocidad que la CPU ejecuta instrucciones es 16million instrucciones por segundo. Por lo que la velocidad que nuestro contador TCNT0 se marque es entonces 16million/1024 = 15625 veces por segundo (prueba con seleccionar bits de reloj diferentes y ver qué pasa - recordar nuestra filosofía?). Vamos a mantener el número 15625 en nuestra mente para más adelante y pasar a las siguientes dos líneas de código:
ldi temp, 0b00000001 sts TIMSK0, temp
Esto establece el bit 0 del registro llamado TIMSK0 y borra todo el resto. Si usted echa un vistazo a la página 109 en la hoja de datos, verá que el TIMSK0 está parado para "interrumpir el temporizador/contador de registro de máscara 0" y nuestro código ha establecido el bit 0 que lleva el nombre de TOIE0 que significa "Timer/Counter0 desbordamiento interrupción habilitar"... Allí! Ahora puedes ver lo que esto es todo sobre. Ahora tenemos el "enable bit establecido interrumpir" como queríamos en nuestro cuadro en la parte superior de la primera decisión. Así que ahora todos tenemos que hacer es activar "interrupciones globales" y nuestro programa serán capaces de responder a este tipo de interrupciones. Se permiten interrupciones globales poco, pero antes de hacer usted puede han sido confundido por algo... ¿por qué diablos utilizar el comando "sts" para copiar en el registro de TIMSK0 en lugar de la habitual "out"?
Cada vez que me ves utilice una instrucción que no has visto antes lo primero que debes hacer es girar la página 616 en la hoja de datos. Este es el Resumen de"Set de instrucciones". Ahora encontrar la instrucción "STS", que es la que utiliza. Dice que tiene un número de un registro de R (hemos utilizado R16) y "Tienda directa a SRAM" Ubicación k (en nuestro caso de TIMSK0). Así que ¿por qué tenemos que usar "sts" que lleva 2 ciclos de reloj (ver última columna en la tabla) para almacenar en TIMSK0 y sólo necesita "out", que toma el ciclo solamente un reloj, para almacenar en TCCR0B antes? Para responder esta pregunta tenemos que volver a nuestra tabla de Resumen de registro en la página 614. ¿Ve que el registro de TCCR0B en dirección 0x25, sino también a la derecha (0x45)? Esto significa que es un registro en la SRAM, pero también es un tipo de registro llamado "puerto" (o registro de entrada-salida). Si miramos la tabla resumen de instrucciones al lado del comando "out", verá que toma valores de los registros de"trabajo" como R16 y envía a un puerto. Así que podemos usar "out" al escribir en TCCR0B y salvarnos a nosotros mismos un ciclo de reloj. Pero ahora ver TIMSK0 en la tabla de registro. Verás que tiene dirección 0x6e. Esto está fuera del rango de puertos (que son sólo el primer 0x3F ubicaciones de SRAM) y lo tienes que bajar de nuevo el comando sts y tomando dos ciclos de reloj de CPU para hacerlo. Ahora Lea Nota 4 al final de la tabla de Resumen de instrucciones en la página 615. También aviso que todos nuestros puertos de entrada y salidas, como PORTD están situados en la parte inferior de la tabla. Por ejemplo, PD4 es de tipo bit 4 en dirección 0x0b (ahora puedes ver todas las cosas 0x0b proceden en mi código no comentada)!... ¿bueno, pregunta rápida: cambió el "sts" para "out" y ver qué pasa? Recuerde nuestra filosofía! ¡ lo rompen! simplemente no tome mi palabra para cosas.
Bueno, antes de continuar, gire a la página 19 de la hoja de datos durante un minuto. Verá un cuadro de la memoria de datos (SRAM). Los primeros 32 registros en SRAM (desde 0 x 0000 a 0x001F) son los "registros de trabajo de propósito general" R0 a R31 que utilizamos todo el tiempo como variables en nuestro código. Los registros a continuación 64 son puertos de la entrada-salida hasta 0x005f (es decir, los que estábamos hablando de que esos corchetes direcciones al lado de ellos en el registro de tabla que podemos usar el comando "out" en lugar de "sts") finalmente la siguiente sección de SRAM contiene todos los registros en la tabla de Resumen hasta dirección 0x00FF, y por último el resto interno SRAM. Ahora, volvamos a página 12 durante un segundo. Allí verá una tabla de los "registros de trabajo de propósito general" que siempre usamos como nuestras variables. ¿Ver la línea gruesa entre números R0 a R15 y R16 a R31? Eso es por qué siempre utilizamos R16 como el más pequeño y voy a tener en él un poco más en el siguiente tutorial donde también necesitamos los tres registros de 16 bits de dirección indirecta, X, Y y Z. No tengo en todavía aunque ya no lo necesitamos ahora y nosotros estamos obteniendo empantanados bastante aquí.
Flip de nuevo una página a página 11 de la hoja de datos. ¿Ver un diagrama del registro SREG arriba a la derecha? Ves que bit 7 del registro que se llama "I". Ahora ve abajo en la página y leer la descripción de los bits 7... ¡ Yay! Es el bit de interrupción Global permiten. Es lo que necesitamos para pasar a través de la segunda decisión en el diagrama anterior y permitir interrupciones de desbordamiento del temporizador/contador en nuestro programa. Por lo que debe leer la siguiente línea de nuestro programa:
sbi SREG, I
que establece el bit llamado "I" en el registro SREG. Sin embargo, en lugar de esto hemos utilizado la instrucción
sei
en su lugar. Este bit se encuentra tan a menudo en programas que sólo hicieron una manera más simple de hacerlo.
Muy bien! Ahora tenemos las interrupciones de rebosadero listo para que nuestros "jmp overflow_handler" se ejecutará cada vez que uno ocurre.
Antes de continuar, tome un vistazo al registro SREG (Status Register) porque es muy importante. Leer lo que cada uno de las banderas representa. En particular, muchas de las instrucciones que vamos a utilizar serán conjunto y compruebe estos parámetros todo el tiempo. Por ejemplo, más adelante vamos a estar usando el comando "IPC" que significa "comparar inmediata". Echa un vistazo a la tabla resumen de instrucciones de esta instrucción y observe Cuántas banderas establece en la columna de "banderas". Estas son todas las banderas en SREG y nuestro código se les ajuste y comprobación de constantemente. Usted verá ejemplos poco. Finalmente la última parte de esta sección de código es:
clr temp out TCNT0, temp sbi DDRD,4
La última línea aquí es bastante obvia. Sólo establece el bit 4 del registro de dirección de datos de PortD causando PD4 ser salida.
El primero de ellos establece a la variable temp a cero y luego copia hacia fuera el registro TCNT0. TCNT0 es nuestro Timer/Counter0. Esto establece a cero. Tan pronto como la PC ejecuta esta línea el timer0 Inicio en cero y contar a un ritmo de 15625 veces cada segundo. ¿El problema es el siguiente: TCNT0 es un registro de "8 bits" correcto? ¿Cuál es el número más grande que puede contener un registro de 8 bits? 0b11111111 bien es él. Este es el número 0xFF. Que es de 255. ¿Así ves lo que pasa? El temporizador es comprimir por aumento de 15625 veces por segundo y cada vez que llegue a 255 "desborda" y vuelve a 0 otra vez. Al mismo tiempo que vuelve a cero envía una señal de desbordamiento interrumpir el temporizador. ¿El PC obtiene esto y sabes lo que hace por la derecha ahora? YEP. Se va a la ubicación de memoria de programa 0x0020 y ejecuta la instrucción que se encuentra.
¡ Excelente! Si usted está todavía conmigo eres un superheroe incansable! Vamos a seguir adelante...