# Generating 40 kHz square wave using ATtiny13

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?

• Hello Alex , EE is not working like that. Firstly show what you have tried so far , what problems you faced. Put some works of you so that we try to find a solution. – emre iris Feb 18 '20 at 17:55
• Read ATTiny13 manual. There you can find the whole list of registers and how to achieve what you want – John Am Feb 18 '20 at 18:23
• Are you wanting to use PWM or are you simply toggling pin states? – JYelton Feb 18 '20 at 18:58
• So take a look at the timer/counter section of the datasheet for the microcontroller. That holds the answer to your question. – Jaywalk Feb 18 '20 at 19:16
• @JYelton Pulse width does not need to change so I assume toggling the pin state at the desired frequency would be the simplest and best solution. – alex Feb 18 '20 at 19:21

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.

Most microcontrollers have a dizzying array of counter-timer features, and it can certainly be tricky to set them up how you want them.

The critical information is in chapter 11. 8-bit Timer/Counter0 with PWM of the ATTiny13 datasheet.

The place to start is with table 11.8 where you want a mode which goes from BOTTOM (0) to a number you choose OCRA (modes 2, 5 or 7 of that table). "Counter-Timer Match" mode 2 is probably the simplest, but you can probably do what you want with the 5 and 7.

All the code will look pretty much like the example at the top of page 52.

I didn't try it, but this is what you'll have to do.

• No interrupts (TIMSK0)
• Pins A and B to be outputs (DDR etc in 10.2.1, note text about pullups)
• a counting mode which counts from 0 to N and then resets to 0 ("Clear Timer on Compare Match", mode 2 of table 11.8)
• N is OCR0A, needs to be 1.2e6 / 40e3 = 30
• Ouptput on pin A, invert every time the counter gets to P (COM0A1:0, mode b01 of Table 11-2.)
• P is defined to be the same as N (it's OCR0A)
• Output on another pin B, inverts B every time the counter gets to Q (COM0B1:0 mode b01 of table 11-5)
• Q is OCR0B, also 30
• No prescaler (CS02:0) and counter values (30) to get your desired frequency
• Make it start (GTCC0)
• Force B to invert once (FOC0B Force Output Compare B)