Is there a command that can execute a loop until a certain bit is set ???

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

Hello everybody. I'm just a newbie to AVR and I'm very interested in AVR. So I'm doing a simple circuit with ATMEGA 8 that blinks from LED 1 to 8 and then goes back to LED 1

I wrote a simple code like this and it works just fine

 while(1){
            for (int i=0;i<7;i++){
			PORTB=val;
            _delay_loop_2(65000);
			
            val*=2;
			
			}
			
            for (int i=0;i<7;i++)
			 {
			
			PORTB=val;
            _delay_loop_2(65000);
			val=val/2;
			
			}
		        
      }

but I was wondering if there is anyway to make this shorter, like is there some sort of command that loops only until a certain bit connecting to a certain LED is set ??

In my situation, said bits are PB0 and PB7. I attached a screenshot of my project in Proteus.

Please help me, I will be much appreciated

And forgive me for my English

Attachment(s): 

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

but I was wondering if there is anyway to make this shorter, like is there some sort of command that loops only until a certain bit connecting to a certain LED is set ??

Think about what you are asking, does it make sense?

 

You are setting the bits that control the LEDs in the loops.  You are not reading those bits, and even if you were what purpose would it have?

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Thu. Mar 5, 2015 - 08:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why do you want it shorter? And shorter in what sense? I would first try to make it more readable with proper indentation, then be happy with that (well I'd probably replace _delay_loop_2 with _delay_ms).

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

You mean like a while statement?

The largest known prime number: 282589933-1

Without adult supervision.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>

int main(void)
{

    DDRB = 0xFF;
 
    while(1)
    {
        for (uint8_t i = 0; i < 7; i++)
        {
            PORTB = (1 << i);
            _delay_ms(500);
        }

        for (uint8_t i = 7; i > 0; i--)
        {
            PORTB = (1 << i);
            _delay_ms(500);
        }
    }
}

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Mar 6, 2015 - 12:08 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

(well I'd probably replace _delay_loop_2 with _delay_ms)

If OP indeed wants to get down to the cycle, isn't the underlying "delay cycles" upon which the modern GCC _delay_XX() are built?

http://www.nongnu.org/avr-libc/u...

__builtin_avr_delay_cycles(unsigned long)

https://gcc.gnu.org/onlinedocs/g...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Larry, the first for() loop should be less than 8 instead of 7. 2nd for(), <= 0.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

theusch wrote:

(well I'd probably replace _delay_loop_2 with _delay_ms)

If OP indeed wants to get down to the cycle, isn't the underlying "delay cycles" upon which the modern GCC _delay_XX() are built?

http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html

__builtin_avr_delay_cycles(unsigned long)

https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/AVR-Built_002din-Functions.html 

Well yes, if someone really wants an exact number of cycles as delay, and maybe that's the case here, I don't know.

 

Actually I was going to suggest in another thread, where someone wanted an exact delay in C without util/delay.h

#define delay_ms(x) __builtin_avr_delay_cycles(F_CPU * (x) / 1000)

(untested) but I didn't.

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

indianajones11 wrote:

Larry, the first for() loop should be less than 8 instead of 7. 2nd for(), <= 0.

No, the first loop hits bits 0 through 6, the second loop hits bit 7 through 1, no overlap on bits 0 and 7.

 

Besides, I like it the way I wrote it.smiley

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Mar 6, 2015 - 08:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I'm not going to make many change in your code(because I'm not sure what you have asked us) but I think you want a code like this:

 

while(1){
            for ( int i=0 ; i<16 ; i++ ){
				PORTB = val;
				_delay_loop_2(65000);
				if( i<8 ){
					val *= 2;
				} else{
					val = val/2;
				}
				
			
			}
		        
		}

 

is it right?

"One's value is inherent; money is not inherent"

 

Chuck, you are in my heart!

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

I offer an alternative

 

#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
	
enum { false = 0, true };
typedef unsigned char bool;

int main(void)
{
	DDRB = 0xFF;
	
	volatile uint8_t mask = 1;
	volatile bool dirUp = true;
	while(1)
	{
		for (uint8_t i = 0; i < 7; i++)
		{
			PORTB = mask;;
			_delay_ms(500);
			
			if (dirUp)
				mask <<= 1;
			else
				mask >>= 1;
		}
		
		dirUp = !dirUp;
	}
}

 

Happy Trails,

Mike

JaxCoder.com

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

mike32217 wrote:

I offer an alternative

Mine's less elegant. cheeky 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Mar 6, 2015 - 07:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

larryvc wrote:

mike32217 wrote:

I offer an alternative

Mine's shorter. cheeky

 

Hmmm, How bout now?  devil

 

#define F_CPU 8000000UL
#include <util/delay.h>
#include <avr/io.h>
	
enum { false = 0, true };
typedef unsigned char bool;

int main(void)
{
	DDRB = 0xFF;
	
	volatile uint8_t mask = 1;
	volatile bool dirUp = true;
	while(1)
	{
		for (uint8_t i = 0; i < 7; i++, PORTB = mask)
		{
			_delay_ms(500);
			
			(dirUp) ? (mask <<= 1) : (mask >>= 1);
		}
		
		dirUp = !dirUp;
	}
}

 

 

 

Happy Trails,

Mike

JaxCoder.com

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

mike32217 wrote:
Hmmm, How bout now?  devil
  I was lying before.wink

 

But don't use the bool, the enum, or the volatiles.  It is more efficient and shorter without them.

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

#define DDR DDRB
#define PORT PORTB

#define delay 500

int main(void)
{
 DDR = 0xFF;
 
 uint8_t mask = 1, dirUp = 1;
 
 while(1)
 {
  for (uint8_t i = 0; i < 7; i++, PORT = mask)
  {
   _delay_ms(delay);
   
   (dirUp) ? (mask <<= 1) : (mask >>= 1);
  }
  
  dirUp = !dirUp;
 }
}

Weighs in at 300 bytes with -Os optimization.

 

I think the OP should be quite happy with all of these examples.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Mar 6, 2015 - 08:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks everybody for replying. And I apologized for my English since I could not make my question more understandable for you guys.

I did some research yesterday and found out the macro bit_is_clear

#include <avr/io.h>
#include <util/delay.h>
unsigned char val=1;
int main(void){
      DDRB=0xFF; //set PORTB as output lines
      while(1){
            while(bit_is_clear(PINB,7)){
			PORTB=val;
            _delay_loop_2(65000);
			
            val*=2;
			
			}
			
            while(bit_is_clear(PINB,0))
			 {
			
			PORTB=val;
            _delay_loop_2(65000);
			val=val/2;
			
			}
		        
      }
      return 0;
}

can I use the macro like this for the code ?

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

Here's one I wrote a couple of years ago:

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

int main(void)
{
    uint8_t d = 0, i = 0;

    DDRB = 0xFF;
    while (1) {
	if (!(i = d ? i>>1 : i<<1))
	    i = (d = !d) ? 0x40 : 2;
	PORTB = i;
	_delay_ms(100);
    }
    return 0;
}

devil

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

Quote:
can I use the macro like this for the code ?

 

Why don't you try it? You have to test the bits in PORTB or val, not PINB.

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

larryvc wrote:

 

mike32217 wrote:

Hmmm, How bout now?  devil

  I was lying before.wink

 

 

But don't use the bool, the enum, or the volatiles.  It is more efficient and shorter without them.

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

#define DDR DDRB
#define PORT PORTB

#define delay 500

int main(void)
{
 DDR = 0xFF;
 
 uint8_t mask = 1, dirUp = 1;
 
 while(1)
 {
  for (uint8_t i = 0; i < 7; i++, PORT = mask)
  {
   _delay_ms(delay);
   
   (dirUp) ? (mask <<= 1) : (mask >>= 1);
  }
  
  dirUp = !dirUp;
 }
}

Weighs in at 300 bytes with -Os optimization.

 

I think the OP should be quite happy with all of these examples.

 

Larryvc,

 

Yours was a very elegant and simple solution I was just trying to show the OP that there is more than one way to do things when programming.

 

The voices in my head made me do it. wink

Happy Trails,

Mike

JaxCoder.com

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

mike32217 wrote:
The voices in my head made me do it. wink

Probably the same voices I hear.

snigelen wrote:
Here's one I wrote a couple of years ago:devil

Show off!wink

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Fri. Mar 6, 2015 - 06:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

pokemon.master wrote:

thanks everybody for replying. And I apologized for my English since I could not make my question more understandable for you guys.

I did some research yesterday and found out the macro bit_is_clear

 

can I use the macro like this for the code ?

Yes, but it really is not a very good way to control the for loops.  Please take the time to look at the other examples that were given.  You can learn a lot from studying code written by others.

 

Here is a working version modeled on what I see as your vision for the program.  You need to define val as an integer and there are some changes that need to be made to the code.  Also note that the LEDs on PORTB pins 0 and 7 will be on for 1000ms after the first time through the first loop whereas the other LEDs will only be on for 500ms.

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

#define delay 500

int main(void)
{
    DDRB = 0xFF; //set PORT pins to outputs

    while(1)
    {

        int val = 1;
        while(bit_is_clear(PINB,7))
        {
            PORTB = val;
            _delay_ms(delay);
            val *= 2;
        }

        // val is now = 256 so divide first
        while(bit_is_clear(PINB,0))
        {
            val /= 2;
            PORTB = val;
            _delay_ms(delay);
        }
    }
}

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Sat. Mar 7, 2015 - 05:21 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thank you mr.Larry for replying. I really appreciate your help

I have one more problem. I just read a code which is used to print the number 4 on a dot matrix 7x5

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

void led(uint8_t chr){
	uint8_t line=1;
	uint16_t temp=chr;
	for (int i=0;i<=4;i++)
	{
	PORTC=line;
	PORTD=~pgm_read_byte(&font7x5[(temp-32)*5+i]);
	line<<=1;
	_delay_loop_2(1000);
	}
}
int main(void){
	DDRD=0xFF;
	DDRC=0xFF;
	while(1)
	{
	
	led('4');
	
	}
	return 0;
}

I decided to try making it display the number from 0 to 9 so I changed the code a bit

while(1)
	{
	for (int j=0;i<=9;j++){
	led('j');
	_delay_ms(100);
	}
	}

but it just shows the letter j on the matrix. Can you please tell me how to fix this ?

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

Try

	for (char j='0';i<='9';j++){
	  led(j);
	  _delay_ms(100);
	}

EDIT: to change int to char. 

Last Edited: Sat. Mar 7, 2015 - 04:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
led('j');

Isn't

led(j);

And also j is integer you should convert it to char.

dude, I think you should review a C book.

"One's value is inherent; money is not inherent"

 

Chuck, you are in my heart!

Last Edited: Sat. Mar 7, 2015 - 04:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Pokemon.master,

 

I highly recommend you reading the classic K&R C to get a better grasp of the language.

Also learning some good debugging techniques would be useful.

 

If you keep asking basic question and just looking for answers people will get tired of it and will quit responding.

 

 

 

Happy Trails,

Mike

JaxCoder.com

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

thanks everybody. And I really apologize for my lack of knowledge.

thanks Mr.Mike, I'll try to read your book

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

Another example for pokemon.master to study:

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

#define DDR DDRB
#define PIN PINB
#define PORT PORTB

#define delay 500

int main(void)
{
    DDR = 0xFF;

    while(1)
    {
        uint8_t led;
        for (uint8_t i = 0; i < 14; i++)
        {
            if (i & 8)
                (led = (14 - i));
            else
                (led = i);
            PORT = (1 << led);
            _delay_ms(delay);
        }
    }
}

 

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

Last Edited: Sun. Mar 8, 2015 - 09:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think tha OP was originally asking for something like this:

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

int main(void)
{
    while(1) {
        for(uint8_t mask=1; mask; mask<<=1} {
            PORTB=mask;
            _delay_ms(1000);
        } // mask

        for(uint8_t mask=0x40; !(mask & 1); mask>>=1) {
            PORTB=mask;
            _delay_ms(1000);
        } // mask
    } // forever
}

If one really wants cute:

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

int main(void)
{
    for(uint8_t mask=1, up=0;  ; mask=mask<<up>>!up) {
        PORB=mask;
        _delay_ms(1000);
        up^=!!(mask & 0x81);
    } // mask, up
} // main

 

Iluvatar is the better part of Valar.