ATTiny85 assembly - timing a event at 1ms.

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

Using a 16 bit counter.
PB0 goes low via a push button and the 16 bit counter starts counting up from 00 00 at 1ms intervals. (I don't know how to do the 16 bit count up but have the 1ms software timer coded).
The button is pressed again and the 16 bit value accumulated is stored in SRAM (I know how to store values in SRAM). If the two values reach FFh FFh then a red error LED comes on (PB1 low), indicating it took to long before the button was pressed a second time.
The two values saved are now loaded back into a counter and this 16 bit value is now counted down (don't know how to do this) at 1ms intervals until it reaches zero. When it reaches zero (time out) PB2 sends out a brief 1ms. pulse (I know how to make the 1ms. pulse).
How do I code a 16 bit counter that counts up and down at 1ms. intervals?

BADBAUD

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

Setup one of the timers to fire it's interrupt every 1ms. In your code declare a timer variable that will hold your count. When the interrupt fires, increment the counter variable until the button is pressed. Use a similar process for counting down.

Last Edited: Mon. Nov 14, 2011 - 03:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You want a state machine that acts every 1ms (either in the timer tick ISR or activated by a flag set in the ISR). You will have states such as

WAITING_FOR_START
GOT_START
WAITING_FOR_STOP
GOT_STOP
SENT_PULSE
and perhaps others. Note that GOT_START and WAITING_FOR_STOP may be the same state in your case.

When the 1ms code runs, depending on the current state it might count a software variable up or count it down. It might also change the state depending on the activity on PB0 & PB1, and on whether the count has reached 0xFFFF. And at some combination of state and software variable value, it will send the output pulse.

To count a 16-bit value up or down by 1 in asm, use the ADIW or SBIW instruction with an argument of 1.

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

The register pair for the 16 bit count is defined as R24, R26, R28, R30 in the instruction set summary when using ADIW and SBIW. How do I predefine the (selected) register pair in assembly?

BADBAUD

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

You don't need to predefine it, you could just use
ADIW r25:r24,1

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

Thanks, I'm thinking a 65 second timeout is a long wait for this application but if I do use 0Xffff as my high value is there a over flow flag set when the counter rolls over to 0x0000 or do I have to do a compare on each register? Is there an easy way to do a 16 bit compare if I decide on a smaller value?

BADBAUD

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

In a possibly syntax-challenged pseudocode:

   cpi rlo, #LO_CONST
   bne no_match
   cpi rhi, #HI_CONST
   bne no_match
have_a_match:
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW, it's often useful to use a compiler to generate idiomatic asm code for a simple operation. Write the operation in the HLL, like

if (var == CONSTANT)
{
..do something..
}

Compile that in a minimal program and look at the generated assembly language to get at least one guaranteed correct way to perform the operation.

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

Thanks, good suggestion.

BADBAUD

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

Quote:
Compile that in a minimal program and look at the generated assembly language to get at least one guaranteed correct way to perform the operation.

We used to do that to get Z80 maths routines. Some times you have to strip some compiler gumf (this was before optimizing was common or even available at all) but the technique works well.

______
Rob

Scattered showers my arse -- Noah, 2348BC.
Rob Gray, old fart, nature photographer, embedded hardware/software designer, and serial motorhome builder, www.robgray.com

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

badbaud wrote:
Thanks, I'm thinking a 65 second timeout is a long wait for this application but if I do use 0Xffff as my high value is there a over flow flag set when the counter rolls over to 0x0000 or do I have to do a compare on each register? Is there an easy way to do a 16 bit compare if I decide on a smaller value?

This is where the AVR instruction set document if useful. Simply lookup the ADIW instruction and see how if affects the various flags. If you don't have this document, hopefully you can still case it down on the Atmel site. You definitely need it for ASM coding. Here's the section on the status bits changed with the ADIW instruction. AS you can see the carry flag will set on an overflow.

Attachment(s): 

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

Got it. Set it for a 5 second timeout and it worked.

BADBAUD