// Define some macros for convenience #define TCCR1A \_SFR\_IO8(0x80) // Timer/Counter1 Control Register A #define TCCR1B \_SFR\_IO8(0x81) // Timer/Counter1 Control Register B #define OCR1A \_SFR\_IO16(0x88) // Output Compare Register 1 A #define CS10 0 // Clock Select bit 0 #define CS11 1 // Clock Select bit 1 #define CS12 2 // Clock Select bit 2 #define WGM12 3 // Waveform Generation Mode bit 2 #define COM1A0 6 // Compare Output Mode bit 0 for Channel A #define COM1A1 7 // Compare Output Mode bit 1 for Channel A
void setup() { pinMode(9, OUTPUT); // Set pin 9 as output TCCR1A = 0; // Clear Timer1 Control Register A TCCR1B = 0; // Clear Timer1 Control Register B OCR1A = 249; // Set compare value to 249 TCCR1A |= (1 << COM1A0); // Set output mode to toggle on compare match TCCR1B |= (1 << WGM12); // Set waveform generation mode to CTC (Clear Timer on Compare match) TCCR1B |= (1 << CS10) | (1 << CS11); // Set clock source to prescale by 64 }
void loop() { // Nothing to do here, the timer will generate the signal automatically }
// Define some macros for convenience #define TCCR2 \_SFR\_IO8(0x45) // Timer/Counter2 Control Register #define TCNT2 \_SFR\_IO8(0x44) // Timer/Counter2 Register #define OCR2 \_SFR\_IO8(0x43) // Output Compare Register 2 #define ICR2 \_SFR\_IO16(0x46) // Input Capture Register 2 #define TIMSK \_SFR\_IO8(0x59) // Timer/Counter Interrupt Mask Register #define TIFR \_SFR\_IO8(0x58) // Timer/Counter Interrupt Flag Register #define CS20 0 // Clock Select bit 0 for Timer2 #define CS21 1 // Clock Select bit 1 for Timer2 #define CS22 2 // Clock Select bit 2 for Timer2 #define WGM21 3 // Waveform Generation Mode bit 1 for Timer2 #define WGM20 6 // Waveform Generation Mode bit 0 for Timer2 #define FOC2 7 // Force Output Compare for Timer2 #define ICES2 WGM20 // Input Capture Edge Select for Timer2 #define ICIE2 FOC2 // Input Capture Interrupt Enable for Timer2
volatile unsigned int lastCapture = 0; // Variable to store the last captured value volatile unsigned int timeDiff = 0; // Variable to store the time difference between two captures volatile unsigned long frequency = 0; // Variable to store the calculated frequency
void setup() { Serial.begin(9600); // Initialize serial communication at baud rate of 9600 bps TCCR2 = 0; // Clear Timer2 Control Register TCNT2 = 0; // Clear Timer2 Counter Register OCR2 = 255; // Set Output Compare value to maximum (not used) TCCR2 |= (1 << ICES2); // Set input capture edge to rising TCCR2 |= (1 << CS21); // Set clock source to prescale by TIMSK |= (1 << ICIE2); // Enable input capture interrupt
}
void loop() { // Nothing to do here, the timer will measure the frequency and print it in the ISR. }
// Define the ISR for input capture interrupt ISR(TIMER2_CAPT_vect) { unsigned int currentCapture = ICR2; // Read the current captured value from the input capture register timeDiff = currentCapture - lastCapture; // Calculate the time difference between two captures lastCapture = currentCapture; // Update the last captured value frequency = 1000000UL / timeDiff; // Calculate the frequency by dividing one second by the time difference (in microseconds) Serial.print("Frequency: "); // Print a label on the serial monitor Serial.print(frequency); // Print the frequency on the serial monitor Serial.println(" Hz"); // Print a unit on the serial monitor }
2.3 示例 3:创建自定义延迟函数
在此示例中,我们将在正常模式下使用 Timer0 创建自定义延迟函数,该函数可以将草图的执行暂停指定的毫秒数。 我们将使用此函数使 Arduino Uno 引脚 13 上的 LED 闪烁。 步骤如下:
// Define some macros for convenience #define TCCR0 \_SFR\_IO8(0x33) // Timer/Counter0 Control Register #define TCNT0 \_SFR\_IO8(0x32) // Timer/Counter0 Register #define OCR0 \_SFR\_IO8(0x3C) // Output Compare Register 0 #define TIMSK \_SFR\_IO8(0x59) // Timer/Counter Interrupt Mask Register #define TIFR \_SFR\_IO8(0x58) // Timer/Counter Interrupt Flag Register #define CS00 0 // Clock Select bit 0 for Timer0 #define CS01 1 // Clock Select bit 1 for Timer0 #define CS02 2 // Clock Select bit 2 for Timer0 #define WGM01 3 // Waveform Generation Mode bit 1 for Timer0 #define WGM00 6 // Waveform Generation Mode bit 0 for Timer0 #define FOC0 7 // Force Output Compare for Timer0 #define TOIE0 FOC0 // Timer/Counter0 Overflow Interrupt Enable
volatile unsigned long millisCount = 0; // Variable to store the number of milliseconds elapsed since the sketch started
void setup() { pinMode(13, OUTPUT); // Set pin 13 as output TCCR0 = 0; // Clear Timer0 Control Register TCNT0 = 0; // Clear Timer0 Counter Register OCR0 = 249; // Set overflow value to TCCR0 |= (1 << CS00) | (1 << CS01); // Set clock source to prescale by TIMSK |= (1 << TOIE0); // Enable overflow interrupt
}
void loop() { // Blink an LED on pin 13 using the custom delay function digitalWrite(13, HIGH); // Turn on the LED customDelay(500); // Wait for half a second digitalWrite(13, LOW); // Turn off the LED customDelay(500); // Wait for half a second }
// Define the ISR for overflow interrupt ISR(TIMER0_OVF_vect) { millisCount++; // Increment the milliseconds count by one }
// Define the custom delay function void customDelay(unsigned long ms) { unsigned long start = millisCount; // Store the current value of milliseconds count in a local variable while (millisCount - start < ms) { // Wait until the difference between the current and previous values is equal to or greater than the parameter // Do nothing, just wait } }