Paso 9: ¿Cómo funciona la interrupción TWI?
Primero deben ir al siguiente paso y descargar el código final y armar para que usted pueda utilizar en este paso (como para mantener el código final y el video en el ultimo paso para aquellos que quieren simplemente omitir mis balbuceos y ejecuta el código).
El TWI es confuso al principio porque trabaja diferentemente que otras interrupciones. Generalmente cuando ocurre una interrupción y el correspondiente manejador de interrupción se ejecuta, la I bandera en SREG automáticamente se establece en 0 para que las interrupciones globales están deshabilitadas, entonces cuando el "RETI" se ejecuta para volver desde la interrupción, la I bandera en SREG se establece automáticamente en 1 otra vez para volver a habilitar las interrupciones globales y también la bandera de interrupción individual correspondiente a la interrupción (es decir, el bit en el registro de control para esa interrupción) está despejado para que el sistema nuevo responderá a ese tipo de interrupción (ver el estado de registro de descripción en la página 11). Si permitimos mantenerse dentro de una interrupción de las interrupciones tenemos "interrupciones anidadas". Usted podría hacer esto por realmente volver a lo que les permite dentro de su rutina de interrupción, pero normalmente no desea hacer esto, desde luego, otra llamada a la interrupción de la misma sería expulsar de la interrupción sólo para volver a entrar en la parte superior.
Ejercicio 3: ¡ Pruébalo! Activar interrupciones globales al comienzo de su rutina de TWI, entonces en algún lugar dentro del conjunto la TWIE bit en el registro TWCR y ver qué pasa la próxima vez que se establece el TWINT.
Sin embargo, esto es no como la interrupción de TWI funciona! TWINT es la bandera de interrupción. En el TWI no permanece durante el manejador de interrupción, cambia todo el tiempo. Eso es porque el TWI debe usar la bandera de interrupción para comunicarse. Por lo que no podemos dejarlo en. En su lugar nos desactivar interrupciones utilizando TWIE = 0 de modo que la CPU no sale expulsado nos hacia el vector de interrupción cuando TWINT cambia a 1. De todos modos, esto puede todavía parecer confuso así que vamos a discutir en el contexto de nuestro código. ¿Es exactamente cuando TWINT = 1 y cuando es TWINT = 0 en nuestra rutina de TWI?
Vamos a descubrirlo.
En lugar de saltar hacia adelante y hacia atrás en la hoja de datos para averiguar lo que está sucediendo. Vamos a utilizar nuestro rodillo de dados y mostrar. Entonces seremos absolutamente claros de qué pedacitos se fijan y cuando.
Comience agregando la siguiente definición para la parte superior de tu código de rodillo de dados:
prueba Def = r23
Ahora bajar a la rutina de tw_transmit y en la parte superior de la misma, cuando el PC entra primero en la subrutina, coloque la línea siguiente
prueba de LDS, SREG
por último, ir a los dos lugares en el código donde transmiten los datos a la pantalla. Una segunda donde transmite el byte bajo, reemplazar el dicetotal con la prueba. Ahora cuando pulse el botón, el contenido del registro SREG, cuando entramos primero en la subrutina, se enviará a la pantalla.
Ahora, cuando montamos esta y ejecutarlo, nos encontramos con que un 0000 demuestra para arriba en la pantalla. Esto significa que la I bandera de SREG es discapacitada como debe ser ya que no permitimos interrupciones globales en nuestro rodillo de dados.
Ahora cambie el código para que eso prueba de cargas TWCR en vez de SREG y ver el contenido de TWCR.
Encontramos y que el TWEN bandera es la única en TWCR. Lo que significa el TWI está habilitado como también debe ser puesto que estamos utilizando el TWI.
Ahora permite pasar nuestra línea de prueba a una ubicación diferente. Mover hacia abajo a sólo después de que el TWCR por primera vez. Esto es cuando enviamos la condición start. El resultado es una 36 en nuestra pantalla. Esto significa que TWCR es 0b00100100.
TWCR = (TWINT TWEA, TWSTA, TWSTO, TWWC, TWEN, -, TWIE) = (0,0,1,0,0,1,0,0)
Tan TWSTA es en como debe ser ya hemos cargado la condición de start, y el TWEN es en como también debe ser. ¡ Pero mira! En la línea anterior hemos cargado TWINT = 1 en el registro TWCR y cuando inmediatamente copia del registro y visto encontramos que TWINT es 0! ¿Por qué es? Ves que "ajuste TWINT = 1" hace algo diferente a solo poner ese pedacito en TWCR igual a uno. Si te fijas en la parte inferior de la página 17 donde describe que transmite una condición de inicio, verá que dicen, "TWINT debe escribirse 1 para borrar la bandera TWINT"... Así que lo que está ocurriendo aquí es cuando se escribe un 1 a TWINT establece el valor de TWINT igual a cero! Eso es porque ambos TWINT * controles * el TWINT bandera y * es * la bandera TWINT. Luego dice que el TWI se prueba el autobús serial de 2 hilos y generan una condición de inicio tan pronto como el bus se convierte en libre. Entonces, después de una condición de inicio se ha transmitido, se fija la bandera TWINT por hardware. Esto significa que TWINT será 1 cuando este ha terminado. Ya sabemos que esto es así porque nuestra línea siguiente es una subrutina de tw_wait que sólo mantiene probando TWINT hasta que se convierte en 1 y luego lee el registro del estado. El hecho de que el envío de un 1 a TWINT sólo que se establece en 0 es la fuente de mucha confusión para las personas tratando de entender cómo funciona el protocolo I2C. La clave está en darse cuenta de que el TWCR es un "control activo" registrar así como un montón de interruptores. Envío de un 1 a TWINT borra la bandera de interrupción y este indicador pasa a ser el TWINT mismo bit en el registro TWCR así que el resultado es TWINT = 0.
Ahora permite cambia nuestra variable de prueba de modo que copie el registro del estado TWSR en su lugar. No mover la ubicación todavía. Sólo ejecútelo y averiguar lo que está en el registro del estado inmediatamente cuando le decimos a la TWCR para transmitir una condición de inicio pero antes de que la condición se ha transmitido.
Tengo 251. En binario es 0b11111011. Dice que la hoja de datos, en sección 22.5.5 en la página 213, que el TWSR registro sólo contiene información de estado actual cuando se establece el TWINT (recordar cuando estamos hablando de "banderas" entonces los medios de "la bandera se encuentra" palabras TWINT = 1, cuando estamos hablando de "control de interrupciones" a continuación, las palabras "establecer el indicador" significaría escribir un 0 en TWINT, dando por resultado TWINT = 1... extraño pero que es la forma de sus trabajos). Ya que estamos leyendo TWSR cuando TWINT = 0, es decir, la interrupción está apagado y TWI está ocupado, significa que no debe contener información relevante, en cambio, la sección llega a decir que debe contener "un estatuto especial código que indica que no hay información relevante está disponible". Pues bien, entonces. Supongo que ahora sabemos lo que es el "código de estado especial". Es 248. En otras palabras todos los bits se establecen salvo el 3 que nosotros generalmente la máscara. Ahora una pregunta que podría hacerse es "¿Qué pasa con el prescaler bits en TWSR, ¿afectan este código de estatus especial? recuerda que enmascararlos cuando queremos leer los códigos de estado, así que si el TWI es simplemente leer el TWSR hacia arriba no que muestran los bits del divisor? Bueno, subir a la cima y establezca los bits divisor en un valor diferente. Usted encontrará que si partimos de los bits del divisor (para que el valor de divisor es ahora 1 y SCL funcionando a una frecuencia más alta) y ejecutarlo obtenemos 248, que es 0b11111000, si nosotros sólo TWPS0 a 1 y ejecutarlo otra vez (este precaler tiempo sería 4) encontrarás que ahora lee 249. Si se establece TWPS1 a 1 (así que el prescaler está ahora 16) obtendrá 250 y con tanto juego como normalmente lo tenemos hemos visto llegar 251. Así vemos que el verdadero "código de estado especial" 248, decir todos los bits de la parte de "status" de TWSR se establece en 1 y los otros 3 bits quedarse como estaban.
Ahora "prueba de lds, TWSR" comando para después esperar a que la interrupción (es decir, después de TWINT = 1).
Cuando pulse el botón vemos 0011 Mostrar hacia arriba en la pantalla, es decir, el número decimal 11. ¿Qué significa el código de estado 11? Bien, recordemos que los últimos dos bits del registro TWSR son nuestro divisor bits que, en nuestro caso, son ambos 1. Tenemos que deshacernos de los (¿recuerdan cómo nos las máscara cuando queremos comprobar el estado?) que permite resta 3 de nuestro resultado (3 es lo que dan esos dos pedacitos cuando convierte a decimal). Por lo que el estado es en realidad 8, o 0x08 en hexadecimal. Que es exactamente lo que esperamos.
Ahora bajar la línea del test por debajo del punto donde entramos la dirección del esclavo en el registro TWDR. Usted encontrará que todavía Lee 11. Por lo que mantiene 11 hasta que realmente hacer algo más con el TWI. Dicking alrededor con los otros registros como TWDR no afecta el registro del estado. Sólo cambia cuando el TWI está activo.
Ahora mover abajo la próxima vez que se carga el registro de control y usted encontrará que se convierte en el "estatus especial" otra vez... tienes la imagen.
Como una prueba final, vaya a la sección donde enviar el dicetotal a la pantalla y agregar las siguientes 3 líneas al comienzo de esa sección:
LDI temp, 0b00000100
STS TWCR, temp
prueba de LDS, TWCR
Ves lo que hace esto. Mantiene el TWEN en lo que queda habilitado el TWI, pero ahora escribimos TWINT = 0 en el registro de control. Luego leemos el valor del registro de control. ¿Qué conseguimos? ¡ Tenemos 132 aparece en la pantalla! En binario es 0b10000100. En otras palabras, el bit TWEN es en como hemos establecido, pero ahora el TWINT bit está encendido. Enviamos TWINT = 0 para el control de registro y el resultado es TWINT = 1. ¿Ahora ves por qué derecho? Envío TWINT = 0 para el control de registro establece realmente la bandera de interrupción. Por lo que el resultado es la interrupción es bandera, es un 1.
Está bien. Ahora sabemos lo que está sucediendo en el rodillo de dados con la broca TWINT del registro TWCR. La parte sólo potencialmente confusa fue cuando TWINT = 1 y luego leer sólo para encontrar su valor es 0 y cuando establecemos TWINT = 0 encontramos que su valor era de 1. Creo que ver ahora por qué es y cómo funciona. Establecer valores en la TWCR es igual a enviar comandos al TWI. El TWINT = 1 comando significa "ejecuta el comando en el TWCR", pero el valor que obtenga en el TWINT bits cuando se ejecuta ese comando es el "claro la bandera de interrupción" que significa "poner en marcha el TWI y enviar algunos datos". Preocupado por lo que es la bandera de interrupción (el valor real de la broca), TWINT = 0 significa bandera de interrupción está apagado, el TWI está ocupado haciendo algo. Cuando TWINT vuelve a 1 significa que se fija la bandera de interrupción y ahora puede modificar las cosas otra vez. Por otro lado, en cuanto la * comandos * enviar a TWCR, escribiendo TWINT = 0 * conjuntos * la bandera de interrupción y resultados en TWINT = 1, y el TWI se apaga lo que le permite modificar el registro de datos. ¿He vencer al caballo muerto lo suficiente? Sólo hago esto porque es tan confuso como f... bien. usted consigue la idea. Si usted es todavía confuso solo juega con ella un rato.
Ahora examine la figura 22-10, que muestra las cosas que suceden durante una transmisión típica. Ahora que entendemos cómo TWINT trabaja es clara cuál es el valor realmente de ese bit en cualquier momento durante la transmisión. En blanco las secciones TWINT = 0 y en el negro secciones TWINT = 1. Siempre que la descripción dice "Asegúrese de TWINT está escrita para una" ahora sabes que el resultado TWINT = 0, es decir, la interrupción bandera está apagado, o "". La declaración citada anterior asegurar TWINT está escrita a uno debe ser la fuente de nada más que confusión a las personas cuando están tratando de averiguar cómo funciona el TWI. Es molesto que los escritores de la hoja de datos no toman el tiempo de explicar realmente lo que está sucediendo. Otras banderas de interrupción en AVR funcionan del mismo modo, por ejemplo la bandera de desbordamiento temporizador/contador que hemos tratados en anteriores tutoriales. Escribir un 1 en el bit TOV0 del TIFR0 Timer/Counter0 interrumpir bandera registro también * claros * la bandera y lo traduce en una lógica 0 en este bit. Sin embargo en el caso de otras banderas de interrupción que generalmente no necesitamos y claro con el software, el hardware se encarga de eso. Es sólo porque en el caso de la TWI necesitamos y claro la bandera dentro de la rutina de interrupción real que debe preocuparse de él y existe el potencial para la confusión.
Vamos a ahora restaurar nuestro código del rodillo de dados a como estaba y pasar a la pantalla de 4 dígitos.
En el código de 4 dígitos, agregar un nuevo registro de propósito general llamado "prueba" como hicimos con el rodillo de los dados. Entonces en nuestro manejador de interrupción tw_int, agregue las dos líneas siguientes al principio de nuestra etiqueta de tw_return, es decir al final justo antes de volver a la principal:
LDI playercashH, 0
MOV playercashL, prueba
para que la pantalla mostrará lo que está en el registro de prueba. Ahora vamos a probar algunas cosas.
Primero vamos a probar SREG en varios lugares en el controlador de interrupción. Poner a "prueba de lds, SREG" en derecho en la parte superior cuando primero se llama a la interrupción. Usted encontrará que lee 0. Esto significa que el "yo" bandera se desactivarán automáticamente cuando entramos en el manejador de interrupción. Usted también encontrará que permanece apagado durante la interrupción toda. Esto es lo normal que se comporta el SREG.
Ahora vamos a probar TWSR. Aquí es donde podemos encontrar algo que puede parecer extraño. Si tenemos la prueba justo después de la interrupción se llama obtenemos muestra 96. ¿Por qué es esto? Bueno, recordarán que los códigos de estado TWSR son en hexadecimal. Si convierte 96 hexadecimal usted encontrará que es 60. Cual es el valor que deberíamos obtener cuando primero se llama a la interrupción.
Ejercicio 4: ¿Qué es el "código de estado especiales" utilizado en el receptor esclavo?
Ahora mira el registro TWDR cuando usted primero entra en la interrupción. Usted encontrará que es igual a la dirección que hemos puesto en marcha para el esclavo, como debe ser desde la dirección de la TWI en el registro de datos es cómo sabíamos que estábamos llamados lectura.
Por último, echemos un vistazo a TWCR y el TWINT poco. Si pones "prueba de lds, TWCR" desde el principio, cuando primero se introduce el controlador tienes 197 que es 0b11000101. Esto significa que TWINT = 1, TWEA = 1, TWEN = 1 y TWIE = 1. Esto es exactamente cómo fijamos cosas en nuestra sección de reinicio del programa (ir a buscar, ver?) excepto que ahora la bandera de interrupción TWINT está encendido. Que también es normal ya que apenas hemos entrado en la interrupción, no estaría aquí si algo no puso esa bandera.
Vaya ahora a la parte superior de su programa a la sección de reinicio y agregue las dos líneas siguientes:
LDI temp, 0
STS TWDR, temp
como si nos íbamos a iniciar nuestros registro de datos TWDR a cero. ¿Qué sucede ahora cuando se compruebe el registro TWCR al principio de la interrupción? Llegar a 205.
Ejercicio 5: ¿Por qué obtengo 205?
Ahora que te gustaría probar los valores de registros en otros lugares en el código. Creo que usted encontrará que son como usted espera.