uso timerone tiempo temporizadores temporizador rele rbd programable libreria interrupciones contador con timer arduino

tiempo - timerone arduino



Timer1 Arduino hace que Serial no funcione (5)

Ejecutando el código de abajo, cuando envío cualquier caracter en el arduino serial no imprimo "a". Creo que es algo malo con el código timer1, pero debería funcionar porque este código fue dado por mi profesor en la clase C.

void setup() { Serial.begin(115200); //http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS noInterrupts(); TCCR1A = 0;// set entire TCCR1A register to 0 TCCR1B = 0;// same for TCCR1B TCNT1 = 0;//initialize counter value to 0 // set compare match register for 1000000hz increments with 8 bits prescaler OCR1A = 1;// = (16*10^6) / (1000000*8) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS11 bit for 8 prescaler. Each timer has a different bit code to each prescaler TCCR1B |= (1 << CS11); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); interrupts(); } void loop() { if (Serial.available()) { Serial.println("a"); } }


usted escribió 2 veces este registro

TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS11);

mientras que creo que probablemente podría ser:

TCCR1A |= (1 << WGM12); TCCR1B |= (1 << CS11);

Probablemente, el único error está ahí, porque olvidó configurar TCCR1A y ​​estableció 2 veces el otro.


La forma de configurar TCCR1A y ​​B es correcta.

Consulte la hoja de datos de ATmega328 de 660 pg. 132 ~ 135 para obtener más ayuda e información si desea saber dónde buscar a partir de ahora para obtener ayuda de bajo nivel.

Sin embargo, tienes 2 problemas principales, 1 problema menor y 1 recomendación.

Aquí están los 2 problemas principales que rompen completamente su código:

  1. Dado que está habilitando la interrupción Timer Compare Match 1A ("TIMSK1 | = (1 << OCIE1A);"), DEBE también definir la Rutina de Servicio de Interrupción (ISR) que se llamará cuando esto suceda, de lo contrario se habrá ejecutado tiempo (pero no en tiempo de compilación). Es decir, si no define el ISR para la comparación de salida de la coincidencia A, una vez que se produce la interrupción de la comparación de salida de salida, el procesador quedará atascado en un ISR vacío infinito, vacío, creado por el compilador y su bucle principal no avanzará (Vea el código a continuación como prueba de esto).

Agregue esto al final de su código:

ISR(TIMER1_COMPA_vect) { //insert your code here that you want to run every time the counter reaches OCR1A }

  1. Se necesita un par de microsegundos para ingresar a un ISR, y un par de microsegundos para salir de un ISR, más el tiempo que sea necesario para ejecutar el código EN el ISR, necesita usar un valor de OCR1A que sea lo suficientemente grande como para que el ISR tiene tiempo para ejecutarse, en lugar de ser llamado continuamente tan rápido que nunca sale del ISR (esto bloquearía su código esencialmente en un ciclo infinito ... lo cual también está sucediendo en su caso).
    Te recomiendo que llames a un ISR no más de cada 10us. Como está utilizando el modo CTC (Clear Timer on Compare match), con un preescalador de 8, le recomiendo que configure OCR1A a nada menos que 20 o más. OCR1A = 20 llamaría al ISR cada 10us. (Un preescaler de 8 significa que cada tic-tac 1 toma 0.5us, por lo que OCR1A = 20 llamaría al ISR cada 20 * 0.5 = 10us).

Si configura OCR1A = 20 y agrega el código ISR como se describió anteriormente, su código se ejecutará correctamente.

1 problema menor:

Es una buena práctica configurar OCR1A después de configurar el resto del temporizador o, en algunas situaciones, el temporizador puede no comenzar a contar (consulte el comentario de "Thorsten" aquí: http://www.righto.com/2009/07/secrets). -of-arduino-pwm.html )

Entonces, mueva OCR1A = 20; a después de su última línea TCCR1B y antes de su línea TIMSK1.

1 recomendación:

Deshágase de "no Interrumpidos" e "interrupciones". No son necesarios aquí.

Ahora, aquí hay un código que escribí que demostrará mejor lo que estás tratando de hacer, y de lo que estoy hablando:

/* timer1-arduino-makes-serial-not-work.ino -a demo to help out this person here: http://.com/questions/28880226/timer1-arduino-makes-serial-not-work By Gabriel Staples http://electricrcaircraftguy.blogspot.com/ 5 March 2015 -using Arduino 1.6.0 */ //Note: ISR stands for Interrupt Service Routine //Global variables volatile unsigned long numISRcalls = 0; //number of times the ISR is called void setup() { Serial.begin(115200); //http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS // noInterrupts(); //Not necessary TCCR1A = 0;// set entire TCCR1A register to 0 TCCR1B = 0;// same for TCCR1B TCNT1 = 0;//initialize counter value to 0 // set compare match register for 1000000hz increments with 8 bits prescaler OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536) //better to put this line AFTER configuring TCCR1A and B, but in Arduino 1.6.0 it appears to be ok here (may crash code in older versions, see comment by "Thorsten" here: http://www.righto.com/2009/07/secrets-of-arduino-pwm.html // turn on CTC mode [Clear Timer on Compare match---to make timer restart at OCR1A; see datasheet pg. 133] TCCR1B |= (1 << WGM12); // Set CS11 bit for 8 prescaler [0.5us ticks, datasheet pg. 135]. Each timer has a different bit code to each prescaler TCCR1B |= (1 << CS11); // enable timer compare match 1A interrupt; NOW YOU *MUST* SET UP THE CORRESPONDING ISR OR THIS LINE BREAKS THE CODE TIMSK1 |= (1 << OCIE1A); // OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536) //SETTING OCR1A TO 1 OR 2 FOR SURE BREAKS THE CODE, as it calls the interrupt too often // interrupts(); Serial.println("setup done, input a character"); } void loop() { if (Serial.available()) { Serial.read(); //read and throw away the first byte in the incoming serial buffer (or else the next line will get called every loop once you send the Arduino a char) Serial.println("a"); //also print out how many times OCR1A has been reached by Timer 1''s counter noInterrupts(); //turn off interrupts while reading non-atomic (>1 byte) volatile variables that could be modified by an ISR at any time--incl while reading the variable itself. unsigned long numISRcalls_copy = numISRcalls; interrupts(); Serial.print("numISRcalls = "); Serial.println(numISRcalls_copy); } // Serial.println("test"); // delay(1000); } //SINCE YOU ARE ENABLING THE COMPARE MATCH 1A INTERRUPT ABOVE, YOU *MUST* INCLUDE THE CORRESPONDING INTERRUPT SERVICE ROUTINE CODE ISR(TIMER1_COMPA_vect) { //insert your code here that you want to run every time the counter reaches OCR1A numISRcalls++; }

Ejecútalo y mira lo que piensas.

Prueba de que el "Problema principal 1" anterior es real (al menos hasta donde yo lo entiendo, y se basa en pruebas en un Arduino Nano, usando IDE 1.6.0):
Este código a continuación compila, pero no continuará imprimiendo la "a" (sin embargo, puede imprimirlo una vez). Tenga en cuenta que, por simplicidad-sake, comenté la porción que esperaba datos en serie, y simplemente le dije que imprimiera una "a" cada medio segundo:

void setup() { Serial.begin(115200); //http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS TCCR1A = 0;// set entire TCCR1A register to 0 TCCR1B = 0;// same for TCCR1B TCNT1 = 0;//initialize counter value to 0 // set compare match register for 1000000hz increments with 8 bits prescaler OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS11 bit for 8 prescaler. Each timer has a different bit code to each prescaler TCCR1B |= (1 << CS11); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); } void loop() { //if (Serial.available()) { // Serial.println("a"); //} Serial.println("a"); delay(500); } //ISR(TIMER1_COMPA_vect) //{ // //insert your code here that you want to run every time the counter reaches OCR1A //}

Por otro lado, este código funciona y la "a" continuará imprimiéndose. La única diferencia entre este y el anterior es que este tiene la declaración ISR sin comentar en la parte inferior:

void setup() { Serial.begin(115200); //http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS TCCR1A = 0;// set entire TCCR1A register to 0 TCCR1B = 0;// same for TCCR1B TCNT1 = 0;//initialize counter value to 0 // set compare match register for 1000000hz increments with 8 bits prescaler OCR1A = 20;// = (16*10^6) / (1000000*8) - 1 (must be <65536) // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS11 bit for 8 prescaler. Each timer has a different bit code to each prescaler TCCR1B |= (1 << CS11); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); } void loop() { //if (Serial.available()) { // Serial.println("a"); //} Serial.println("a"); delay(500); } ISR(TIMER1_COMPA_vect) { //insert your code here that you want to run every time the counter reaches OCR1A }

Recursos adicionales:

  1. Mantengo una lista actualizada de los recursos de Arduino más útiles que encuentro en la parte inferior de un artículo que escribí aquí: http://electricrcaircraftguy.blogspot.com/2014/01/the-power-of-arduino.html . Échales un vistazo.

  2. Especialmente mira los primeros enlaces, en la sección "Avanzado", por Ken Shirriff y Nick Gammon. Ellos son excelentes!

Por favor, vote esta respuesta si resuelve su problema, y ​​acéptelo como la respuesta correcta; ¡Gracias!

Sinceramente,
Gabriel Staples
http://www.ElectricRCAircraftGuy.com/


Gabriel Staples tiene toda la razón, la razón por la que no está viendo la "a" es porque no ha proporcionado un controlador ISR para la interrupción. Por lo tanto, el código generado por el compilador salta a la dirección 0x0000 y su boceto se reinicia.

Una alternativa para proporcionar el controlador ISR "vacío" es esto:

EMPTY_INTERRUPT (TIMER1_COMPA_vect);

Con el controlador EMPTY_INTERRUPT allí obtuve una respuesta (la "a") con OCR1A tan bajo como 1:

OCR1A = 1;

Aunque uno tiene que preguntarse por qué habilita las interrupciones si no planea hacer nada con ellas.

Más información sobre interrupciones en Arduino.


Dependiendo de lo que el programa necesite hacer con una interrupción tan rápida, por ejemplo generando un reloj de alta velocidad en un pin de salida, uno puede configurarlo en hardware usando los bits COM en TCCR1A (fuera de mi memoria los 4 bits más significativos) para alternar el salida en un pin asociado con el temporizador sin necesidad de escribir la devolución de llamada ISR () maneja la interrupción del temporizador en el software.


TCCR1A | = (1 << WGM12); es una operación bit a bit (OR bit a bit). En este caso particular, se establece solo un bit de TCCR1A, el que está en la posición WGM12. TCCR1B | = (1 << CS11); está configurando un bit diferente en la posición CS11