¿Es posible implementar RC-5 sin usar interrupciones?

1

El problema con mi atmega8 es que no tengo las interrupciones externas INT0 o INT1 disponibles. Hay algunas bibliotecas agradables, por ej. éste , que se basa en las interrupciones, sin embargo, me gustaría lograrlo al no usarlas.

¿Es un plan factible?

    
pregunta sitilge

4 respuestas

2

Sí, es bastante factible. Una palabra clave RC-5 toma ~ 25ms para transmitir y se repite cada 114ms. Así que puede sondear la entrada hasta que se reciba una palabra de código completa, luego tiene 89 ms para hacer otras cosas antes de volver a sondear. Si pierde una o dos palabras, no importará porque el mismo comando se retransmite todo el tiempo que se presiona el botón en el control remoto.

El código de ejemplo en la biblioteca a la que enlazaste en realidad sondeos. Todo lo que tiene que hacer es cambiar el controlador de interrupciones a una función normal y esperar a que el pin cambie de estado antes de llamarlo. Si incluye un tiempo de espera en espera, puede ser sin bloqueo.

    
respondido por el Bruce Abbott
2

Claro, puedes sondear uno de los pines del ADC, pero tu chip tiene otras interrupciones que podrías poner en uso. La tabla de vectores de interrupción de Atmega8 interrumpir vector incluye ADC_vect , ANA_COMP_vect , EE_RDY_vect , INT0_vect , INT1_vect , SPI_STC_vect , SPM_RDY_vect , TIMER0_OVF_vect , TIMER1_CAPT_vect , TIMER1_COMPA_vect , TIMER1_COMPB_vect , TIMER1_OVF_vect , TIMER2_COMP_vect , TIMER2_OVF_vect , TWI_vect , USART_RXC_vect , USART_TXC_vect y USART_UDRE_vect . Usted mencionó que los pines de interrupción externos se han propuesto para otra cosa, y la biblioteca vinculada utiliza el temporizador 1.

Podría usar la interrupción del comparador analógico a digital:

  

Usando mega8515 como ejemplo:

     

ACSR = 0x0B; // Configured the Analog Comparator sei(); // Enable ACIE and set interrupt to // trigger whenever AC0 go high. That // is both ACIS1 and ACIS0 are set to 1.

     

Úsalo así:

     

while(!(PINA & 0x10)) { // Turn/keep everything off // Can make this non-blocking by calling it from another timer ISR } // Do your thing

por Atmel (función de interrupción del comparador analógico AVR)

  

Usando mega16 como ejemplo:

     

Configuración, inicio, etc:

     

DDRA&=~(1<<AINpin); //as input PORTA&=~(1<<AINpin); //no Pull-up ACSR|= (0<<ACD)| //Comparator ON (1<<ACBG)| //Connect 1.23V reference to AIN0 (1<<ACIE)| //Comparator Interrupt enable (0<<ACIC)| //input capture disabled (0<<ACIS1)| //set interrupt on output toggle (0<<ACIS0); sei(); //enable global interrupts

     

controlador ISR:

     

ISR(ANA_COMP_vect) { if bit_is_clear(ACSR, ACO) // Do your thing }

de Ejemplo de programación AVR Comparator C

Puede configurar un temporizador como una interrupción externa configurándolo para que se ejecute fuera de un reloj externo y para que se desborde después de un solo reloj, y use la señal que está buscando como reloj externo. No tengo una referencia, pero aquí hay un resumen rápido:

  1. Configure Timer 2 para usar un reloj externo. Este pin será su [disculpa excusa para un] pin de interrupción externo.
  2. Configúrelo en uno de los dos modos Clear Timer on Compare (CTC) con el valor de comparación establecido en 1. (¿Quizás 2? ¿Se inicia en 1 o 0? De todos modos, lo resolverá.)
  3. Escribe ISR (TIMER2_COMPA_vect) ( ...COMPB... ) para hacer lo tuyo.

La alternativa al modo CTC es usar TIMER2_CAPT_vect , que se dispara en cada pulso. (En realidad, eso suena mejor que la opción CTC).

Un ejemplo de temporizador decente está aquí: QEEWiki - Mis libros & gt ; GUÍA AVR > Temporizadores en el ATmega8

Es posible que pueda reutilizar una de las interrupciones de comunicación de hardware para que actúe como una interrupción externa. Por ejemplo, haga que su señal parezca válida a la transmisión USART de 115200 bps colocando un circuito que arrastre el pin LOW durante al menos 1/115200 segundos (8.7us) (por ejemplo, RC y transistor) entre la salida RC-5 y RXD ( PD0 ), que disparará un USART_RXC_vect después de unos 9/115200 segundos (78us).

Si se aleja del antiguo Atmega8, podría usar interrupciones de cambio de pin:

  

Usando un mega48 / 88/168 como ejemplo:

     

Establezca los bits de PCMSKx register high para habilitar el pin   cambio de detección en ese pin. Para PD2 ( PCINT18 ) sería:

     

PCMSK2 |= (1<<PCINT18);

     

Entonces habilita la interrupción para el correspondiente   Vector y por supuesto la bandera de interrupción global:

     

PCICR |= (1<<PCIE2); sei();

     

Luego, proporcione el ISR para ese vector que hace lo que necesita.   Para avr-gcc esto se vería así:

     

ISR(PCINT2_vect) { // Your code here }

     

Para un pin (o más generalmente, un pin por PCINT vector), eso es todo lo que realmente necesitas. Si tienes más de uno   pin por vector habilitado, entonces tienes que tener código   en el ISR que determina cuál de los pines causó el cambio. Esta   se puede hacer manteniendo una variable que almacena el valor de la   registrar la última vez que se ejecutó el ISR y compararlo con el actual   valor. Sin embargo, puede haber problemas con los problemas de tiempo, ya que por   Cuando llega al ISR, es posible que otro pin haya cambiado (o incluso peor,   el que cambió cambió de nuevo). Estos pueden ser difíciles de tratar   con, pero la gravedad de un problema depende de las características   de su aplicación.

de Koichi en AVRFreaks

    
respondido por el tyblu
2

Bueno, puedes hacerlo encuestando la entrada regularmente en tu programa, sin embargo, esto sería muy ineficiente en comparación con el uso de interrupciones. El Atmega8 tiene interrupciones externas disponibles.

    
respondido por el John
-4

Tienes pcint, muchos de ellos.

Las entradas del temporizador también se pueden reconfigurar como interruots externos.

    
respondido por el dannyf

Lea otras preguntas en las etiquetas