Attiny85 to use complementary pwm output using timer 1

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi I am new to Attiny85. I want to get two complementary outputs which are at high frequency (at least 100 KHz). I already use timer 0 and ctc mode and got the result. But My timer 0 is used for other application now and want to use timer1. Can anybody help me with the code to get two complementary PWM outputs at PB0 and PB1 or PB3 and PB4. I saw there are complementary output compare register. I tried to use it but cant find the solution. i tried with this code and got output only on PB1 with 252 KHz

Thanks

#define F_CPU 8000000
#include <avr/io.h>

int main() {
	// Enable PLL and async PCK for high-speed PWM
	PLLCSR |= (1 << PLLE) | (1 << PCKE);
	TCCR0A |=(1<<WGM00)|(1<<WGM01);
	// Set prescaler to PCK/2048
	TCCR1 |=(1 << CS10) | (0 << CS11) | (0 << CS12) | (0 << CS13);

	// Set OCR1B compare value and OCR1C TOP value
	OCR1A = 128;
	OCR1B =128;
	

	// Enable OCRB output on PB4, configure compare mode and enable PWM B
	DDRB |= (1 << PB1);
	TCCR1|=(0<<COM1A1)|(1<<COM1A0);
	//GTCCR |= (1 << COM1B0) | (1 << COM1B1);
	TCCR1 |=(1<<PWM1A);
	GTCCR |= (1 << PWM1B);

	
	while (1) 
	{
		
	}

	return 0;
}

 

george

Last Edited: Thu. Sep 5, 2019 - 09:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Haven't looked at this in any detail (like digging out a datasheet) but I can't help noticing that in:

	TCCR1|=(0<<COM1A1)|(1<<COM1A0);

it only appears to be setting functionality for 1A but not 1B. If you want 1B to be the inverse then presumably you want to set its bits the "other way up" too?

 

PS forgot to say that spaces in C cost nothing - spaces around operators make code much easier to read. Also don't go over-board with the use of |= and &=~ , only use those when you want to change some bits in a register you already wrote to. If you are setting the bits in a register for the first time use plain assignment (just '=').

Last Edited: Thu. Sep 5, 2019 - 02:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson i used the term outputs on PB0 and PB1 OR PB3 and PB4. Because i only want 2 outputs that are complementary to each other. The above code is for  trying to get complementary outputs on PB0 and PB1 using timer1 

george

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you everyone. I solved the problem. To those who look for the same problem

#define F_CPU 8000000
#include <avr/io.h>

int main()
 {
	 DDRB |=(1<<PB0)|(1<<PB1);
	// Enable PLL and async PCK for high-speed PWM
	PLLCSR |= (1 << PLLE) | (1 << PCKE);
	TCCR1 = 1<<PWM1A | 0<<COM1A1 | 1<<COM1A0 | 0<<CS13 | 0<<CS12 | 1<<CS11 | 1<<CS10;
	GTCCR = 0<<PWM1B | 0<<COM1B1 | 0<<COM1B0;
	OCR1C = 159;
	OCR1A = 80;  // (103+1)/(205+1) = 0.50 = 50% duty cycle
	//DTPS1 = 1<<DTPS11 | 1<<DTPS10;
	//DT1A = 1<<DT1AH3 | 1<<DT1AH2 | 1<<DT1AH1 | 1<<DT1AH0 | 1<<DT1AL3 | 1<<DT1AL2 | 1<<DT1AL1 | 1<<DT1AL0;


	while (1) 
	{
		
	}

	return 0;
}

The commented out is for introducing dead time for safer opertion of MOSFET

george

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Oh I see:

 

 

So what you are trying to get is OC1A and _OC1A on pins 6 and 5? So OC1B and _OC1B on pins 3 and 2 is not relevant to this. In which case why are you bothering to write to OCR1B at all?



As this shows:

the one combination where you should get OC1A and _OC1A is the 01 bit combination. So your:

TCCR1|=(0<<COM1A1)|(1<<COM1A0);

should be achieving this. Oh but wait a minute, both the pins need to be outputs. You currently have:

	DDRB |= (1 << PB1);

that only sets PB1 as output. Surely this needs to be:

	DDRB = (1 << PB1) | (1 << PB0);

?