Hello, I've been having trouble getting this little timer routine to work correctly. I started out with a little program that switches the output of a pin every 240µs which turned out to work as expected:
Then I started on the manchester encoding program building on the first program.
The output was really unexpected, I put in mid-bit time(T) of 200µs so it would be easy to see if it was working right with the oscilloscope grid at 200µs per div (I zoomed out to 400µs/div when I saw it), it ended up looking like this:
Realizing something was wrong with the timing, I took the new delay function and put it in its own program to try to figure out where I messed up. I noticed that it seems to take a long time to access certain registers, when I change TCCR0B to turn the timer on and off from inside the delay function, it adds a lot of extra delay in the function.
The call to the function calls it with the value 200, so I would have liked to see 200µs between toggles on the scope. But it's actually toggling it at around 235µs. I know it's a software issue because the first basic timer program worked just fine. I'm just not seeing where I messed up in making the software. Also if I made some mistakes in the manchester encoding part please let me know, I haven't really gotten that far yet. I used this guide by atmel to put together the manchester encoding part.
C:
// This program switches the output of PB3 every 240µs.
#include <avr/interrupt.h>
#include <avr/io.h>
ISR(TIMER0_COMPA_vect)
{
PORTB ^= _BV(PB3);
}
int main()
{
DDRB |= _BV(PB3);
TCCR0A = _BV(WGM01);
TCCR0B = _BV(CS00);
TIMSK = _BV(OCIE0A);
OCR0A = 240;
sei();
while(1);
}

Then I started on the manchester encoding program building on the first program.
C:
// This program shifts out one byte on PB3 manchester encoded.
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdbool.h>
#include <stdint.h>
#define set(X) PORTB |= _BV(X)
#define clr(X) PORTB &= ~_BV(X)
#define tgl(X) PORTB ^= _BV(X)
volatile bool waiting;
ISR(TIMER0_COMPA_vect)
{
waiting = 0;
}
void delay(uint8_t t)
{
waiting = 1;
TCCR0A = _BV(WGM01);
TCCR0B = _BV(CS00);
TIMSK = _BV(OCIE0A);
OCR0A = t;
sei();
while(waiting);
cli();
TCCR0B = 0; // stop timer
TCNT0 = 0; // reset timer counter
return;
}
int main()
{
DDRB |= _BV(PB3);
set(PB3); // 1. Begin with the output signal high.
uint8_t byte = 0X55;
int i;
for(i = 0; i < 8; i++) // 2. check if all bits have been sent
{ // 3. 4. 5.
if(byte & 1)
{ // ManchesterOne
clr(PB3);
delay(200);
set(PB3);
delay(200);
}
else
{ // ManchesterZero
set(PB3);
delay(200);
clr(PB3);
delay(200);
}
byte >>= 1;
} // 6. Return to step 2.
set(PB3); // 7. Set output signal high and return.
while(1);
}

Realizing something was wrong with the timing, I took the new delay function and put it in its own program to try to figure out where I messed up. I noticed that it seems to take a long time to access certain registers, when I change TCCR0B to turn the timer on and off from inside the delay function, it adds a lot of extra delay in the function.
C:
// This program is a simple delay routine from 1 to 255 µs.
#include <avr/interrupt.h>
#include <avr/io.h>
#include <stdbool.h>
#include <stdint.h>
#define set(X) PORTB |= _BV(X)
#define clr(X) PORTB &= ~_BV(X)
#define tgl(X) PORTB ^= _BV(X)
volatile bool waiting;
ISR(TIMER0_COMPA_vect)
{
waiting = 0;
}
void delay(uint8_t t)
{
waiting = 1;
TCNT0 = 0;
OCR0A = t;
sei();
while(waiting);
cli();
return;
}
int main()
{
DDRB |= _BV(PB3);
TCCR0A = _BV(WGM01);
TCCR0B = _BV(CS00);
TIMSK = _BV(OCIE0A);
set(PB3); // 1. Begin with the output signal high.
while(1)
{
delay(200);
tgl(PB3);
}
}

The call to the function calls it with the value 200, so I would have liked to see 200µs between toggles on the scope. But it's actually toggling it at around 235µs. I know it's a software issue because the first basic timer program worked just fine. I'm just not seeing where I messed up in making the software. Also if I made some mistakes in the manchester encoding part please let me know, I haven't really gotten that far yet. I used this guide by atmel to put together the manchester encoding part.
Last edited: