Electronic – arduino – Generating 40 kHz square wave using ATtiny13

arduinoattinymicrocontrollerregistersquare

I'm using an ATtiny13 running at 1.2 MHz and would like to generate a 40 kHz square wave on PB3 and PB4. The signal on PB4 should be 180 degrees offset (inverted) from PB3.

I know that I need to set certain registers to achieve this, but I do not know which registers or which values they need to be set at.

Any help with the code would be appreciated.


Update:

Thank you for the help so far. This is what I have got:

void setup() {

// Disable all interrupts
TIMSK0 |= (0<< OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);

// Define outputs
DDRB = (1<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);

// Enable CTC
TCCR0A |= (1<<WGM01) | (0<<WGM00); 
TCCR0B |= (0<<WGM02);

// 1.2MHz / 40kHz 
OCR0A = 30;
OCR0B = 30;

// Toggle on Compare Match
TCCR0A |= (0<<COM0A1) | (1<<COM0A0) | (0<<COM0B1) | (1<<COM0B0);

// No prescaler
TCCR0B |= (0<<CS02) | (0<<CS02) | (1<<CS00);

// Make it start
GTCCR |= (1<<PSR10);

// Force one invert
TCCR0B |= (1<<FOC0B);
}

void loop() {
}

With this code, I am getting an 18.5 kHz signal on PB2 and PB1, with a 180 degree phase shift between them.

Does the code look correct or have I missed something? If I play around with the OCR0A and OCR0B values, I might be able to get the desired 40 kHz. However I should not have to do that, since 30 should be the correct value if the microcontroller is running at 1.2 MHz.

Any ideas?

Best Answer

I often use the ATtiny13 for little one-off projects that blink LEDs or control timing of external switches (theatrical props). Sometimes I just need them to change an IO pin at a given frequency and literally nothing else. The following is a quick and dirty way to toggle a GPIO using a delay.

Note: this is not a timing-accurate nor recommended way to accomplish this in an efficient manner. Using a timer and PWM allows you to continue executing other code while the signal is generated.

#define F_CPU 1200000

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    // Set PB3 and PB4 as output
    DDRB |= (1 << DDB3) | (1 << DDB4);
    // Start PB4 high
    PORTB |= (1 << PORTB4);

    while (1) 
    {
        // Toggle PB3 and PB4
        PORTB ^= (1 << PORTB3) | (1 << PORTB4);
        // 40kHz period is 25µs
        _delay_us(25);
    }
}

Toggling pins isn't a single clock-cycle, and the util/delay function is not accurate, so delaying for 25 microseconds is a naive approach, but if your requirements are not strict, it may suit your purpose. Adjust the delay value if needed.

Related Topic