Fast Port writing problem on ATTiny45

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

Programming an ATTiny45 via Arduino and USBasp.   Key part of the code is this unrolled loop where I'm writing to the port B as fast as possible :

 

            PORTB = 0b00000001 | out;  // digitalWrite(PWM, HIGH);
            PORTB = 0b00000000 | out;  // digitalWrite(PWM, LOW);

            PORTB = 0b00000001 | out;  // digitalWrite(PWM, HIGH);
            PORTB = 0b00000000 | out;  // digitalWrite(PWM, LOW);

... (50 repeats in total)

            PORTB = 0b00000001 | out;  // digitalWrite(PWM, HIGH);
            PORTB = 0b00000000 | out;  // digitalWrite(PWM, LOW);

 

Where out is a byte containing the data for the other pins set as outputs which don't change often.

 

I would expect this to be a 50% squarewave on the PB0 pin but instead I get a high 3 microseconds wide but the low is 4 microseconds wide !

 

I've tried it with internal clock of 1MHz and 8 MHz and nothing changes which also seems odd to me.

 

Any suggestions what I'm doing wrong ?

 

Thanks in advance

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

MikeDB1 wrote:

      PORTB = 0b00000001 | out;  // digitalWrite(PWM, HIGH);

      PORTB = 0b00000000 | out;  // digitalWrite(PWM, LOW);

 

If you really want full speed, then these need to be precomputed:

 

    uint8_t output_hi = 0b00000001 | out;
    uint8_t output_lo = 0b00000000 | out;

    PORTB = output_hi;
    PORTB = output_lo;
    PORTB = output_hi;
    PORTB = output_lo;
    // repeated

 

In your code, the optimizer recognized that OR'ing with zero is

unnecessary so it's faster to switch from HIGH to LOW.

 

--Mike

 

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

But the optimizer would surely have precalculated and cached the OR 1 too? (IOW it will have effectively done what you just wrote anyway).

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

You may be right about that.  Unless out is volatile....

 

--Mike

 

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

Thanks very much both of you - it's obvious now :-)    I'll pre-calculate the numbers into two variables as suggested and see what happens

 

Thanks again.

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

Show the .lss

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

where I'm writing to the port B as fast as possible

I feel the need, the need for speed!

 

Anyway, if the Mega is meeting your needs that's great.

If, however, you find yourself needing a little bit more speed then know that the XMega chips run at 32 MHz, significantly faster than the 16 ot 20 MHz of the Mega chips.

 

Likewise the XMegas have a DMA controller, which might, (untested by me), provide an alternative method for fast I/O.

And finally the Xmegas have "Virtual Ports", (untested by me), which again might play a role in speeding up your I/O operations.

 

JC   

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

Yes the ATTiny45 is more than fast enough.  When I want real speed I use ARM devices (usually from STM) but whilst there used to be an 8 pin ARM device, the LPC810, it seems to have been discontinued so I needed another device to mop up simple analogue functions.