I'm trying to get a Timer0 overflow with an overflow every 500us, but can't find a solution to get it so low.
I'm running the Attiny85 on its internal 1 MHz clock, so I know it is not gonna be the most precise thing. Right now the lowest overflow I can achieve is 2 ms.
In my setup, the Timer0 starts counting when a pin change happens on PCINT0 and stops after 4 counts. Timer0 is setup up to CTC and with the prescaler to 1024.
I set the value of OCR0A with SERIAL_BIT_TIME
The code I'm trying is here
#define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define SERIAL_SEND PB1
#define SERIAL_RECEIVE PB0
#define SERIAL_RATE 9600
#define SERIAL_BIT_TIME 0x01
int main() {
DDRB |= 1 << PB1;
DDRB &= ~(1 << PB0);
//PORTB |= 1 << PB1;
TCCR0A |= 1 << WGM01; // clear on compare
TCCR0B |= (1 << CS02) | (1 << CS00); // ( F_CPU/1024 = 976 Hz )
GIMSK = 1 << PCIE; // general intertupt mask enable pin change int
PCMSK |= 1 << PCINT0; // Pin change mask
sei(); // set interrupt enabled
while(1); // Do a heap of useful calculations
}
uint8_t position = 0;
ISR(TIM0_COMPA_vect) { // Timer interrupt
PORTB ^= (1 << PB1);
if (++position == 4) { // If at end of byte
TIMSK &= ~(1 << OCIE0A); // Disable interrupt for compare register A (this interrupt)
PCMSK |= 1 << SERIAL_RECEIVE; // Enable pin change interrupt to start next byte
} else {
OCR0A = SERIAL_BIT_TIME; // Set delay time equal to the length of a single bit
}
}
ISR(PCINT0_vect) {
TCNT0 = 0; // Set counter to 0
OCR0A = SERIAL_BIT_TIME; // Call timer interrupt in middle of first bit
position = 0; // Reset position and data
TIMSK |= 1 << OCIE0A; // Enable interrupt for compare register A (timer interrupt)
TIFR |= 1 << OCF0A; // Clear timer interrupt flag to prevent it jumping directly there
PCMSK &= ~(1 << SERIAL_RECEIVE); // Disable pin change interrupt
}
And the result measured with my Analog Discovery 2:
The yellow line is the pin that toggles in the overflow and the blue line is the output of a signal generator, used to change state of the input pin.
Any help or explanation would be lovely
New image with no prescaler
As per request from @G36 here is the result when the prescaler is set to 8 and OCR0A to 61.
result with 8 prescaler and OCR0A = 61
With the suggestions, I got what I want. Thanks a lot guys.
-
\$\begingroup\$ If you want 500uS? So why did you decide to use 1024 as a prescaler? \$\endgroup\$G36– G362021年11月20日 13:42:20 +00:00Commented Nov 20, 2021 at 13:42
-
\$\begingroup\$ I think maybe I misunderstood the prescaler and thought "the higher the prescaler, the faster the delay" \$\endgroup\$jonas– jonas2021年11月20日 13:44:21 +00:00Commented Nov 20, 2021 at 13:44
-
1\$\begingroup\$ No, wrong, set the Prescaler to 2 So that Timer0 clock is 1MHz/2 = 500kHz = 2us and you want 500us thus, set OCR0a to--->(500 us/2 us -1) = 249 because counter will count from 0. \$\endgroup\$G36– G362021年11月20日 13:49:18 +00:00Commented Nov 20, 2021 at 13:49
-
1\$\begingroup\$ I haven't looked into the datasheet but now I see that is a 8-bit timer. So to get 500us we need to use a Prescaler (clock divider). So if we set the Prescaler value to 8 the counter clock frequency is 1MHz/8 = 125kHz and we want to get 1/500us = 2kHz. So we need to divide by 125KHz/2kHz = 62. So the OCR0A value is 62 - 1 = 61 because as I said we start the counting cycle from 0. \$\endgroup\$G36– G362021年11月20日 15:11:04 +00:00Commented Nov 20, 2021 at 15:11
-
1\$\begingroup\$ Can you show us the resulting timing when OCR0A is set to 61 and prescaler is 8? \$\endgroup\$G36– G362021年11月20日 16:52:37 +00:00Commented Nov 20, 2021 at 16:52
1 Answer 1
An interrupt every 500us is a rate of 2 kHz. As you have only a limites set of prescalers available and the resolution of the timer is only 8 bits, you can't use it without prescaler, and the next prescaler is 8.
As the MCU works at 1 MHz, the timer will run at 125 kHz. Divide by 62 and it is approximately 2 kHz.
Explore related questions
See similar questions with these tags.