delay problem attiny 2313

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

hello,

i have a problem with my C code :

#include 
#include 
#include 
#include 


void init()
{
  
  DDRD = (1<<PD5); // PORTB PB0-PB6 als uitgang
  
  DDRB |= (1<<PB2)|(1<<PB3)|(1<<PB4); // PB0 en 1 als ingang, PB2 tot 4 als uitgang
  DDRB |= (PB0<<1)|(PB1<<1);

}

int main()
{
	switch( PCINT0)
  	 {
		case (1):
			switch (PCINT1)
			{
				case (1):
				PB4 == 1;
  				PB3 == 0;
  				PB2 == 0;
  				PD5 == 0;
				_delay_ms(1);
				break;

				case (0):
				PB4 == 1;
  				PB3 == 0;
  				PB2 == 1;
  				PD5 == 0;
				_delay_ms(1);
				break;

				default:
				break;
			}
		break;
		
		case (0):
			switch (PCINT1)
			{
				case (1):
				PB4 == 0;
  				PB3 == 1;
  				PB2 == 1;
  				PD5 == 0;
				_delay_ms(1);
				break;

				case (0):
				PB4 == 1;
  				PB3 == 0;
  				PB2 == 0;
  				PD5 == 1;
				_delay_ms(1);
				break;

				default:
				break;
			}
			break;

		default:
		break;
	}	
	
}

It is for a controlling a robot.

PB2 - 4 and PD5 are outputs

But there seems to be a problem wit the _delay_ms(1);
When I try to place the program in my attiny 2313 then i get a message : The contents of the hex file doesn't fit in de device.

When i leave thouse delays out of my program than it goes perfect.

Mathias Deneire
newby

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

Did this require the use of compiler optimizations -Os or the like? I bet your current setup understands the 1 as floating point number which it has to convert to integer, so it includes floating point libraries.

Basically I just use _delay_loop1 and _delay_loop2 macros instead of delay_ms because of its oddities and I am no longer familiar what it really does, as the new avr-libc versions have more wrappers to how delay_ms really uses _delay_loops to get over the limitations.

- Jani

Edit: And besides, all those lines with == are wrong, I think you want just one =

Edit2: And if you really use avr-gcc, I think even PB5=0; does not do what you want. You can't control single bits like this, just use |= and &=~ in some macros.

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

Jepael wrote:
Did this require the use of compiler optimizations -Os or the like? I bet your current setup understands the 1 as floating point number which it has to convert to integer, so it includes floating point libraries.

Basically I just use _delay_loop1 and _delay_loop2 macros instead of delay_ms because of its oddities and I am no longer familiar what it really does, as the new avr-libc versions have more wrappers to how delay_ms really uses _delay_loops to get over the limitations.

- Jani

Edit: And besides, all those lines with == are wrong, I think you want just one =

Edit2: And if you really use avr-gcc, I think even PB5=0; does not do what you want. You can't control single bits like this, just use |= and &=~ in some macros.

its already updated :

#include 
#include 
#define F_CPU 1000000UL
#include 



void init()
{
  
  DDRD = (1<<PD5); // PORTB PB0-PB6 als uitgang
  
  DDRB |= (1<<PB2)|(1<<PB3)|(1<<PB4); // PB0 en 1 als ingang, PB2 tot 4 als uitgang
  //DDRB |= ~(1<<PB0)|~(1<<PB1);

}

int main()
{
	switch( PB0)
  	 {
		case (1):
			switch (PB1)
			{
				case (1):
				PORTB |= (1 << PB4);
  				PORTB |= ~(1 << PB3);
				PORTB |= ~(1 << PB2);
  				PORTD |= ~(1 << PD5);
				_delay_ms(500);
				break;

				case (0):
				PORTB |= (1 << PB4);
  				PORTB |= ~(1 << PB3);
				PORTB |= (1 << PB2);
  				PORTD |= ~(1 << PD5);
				_delay_ms(500);
				break;

				default:
				break;
			}
		break;
		
		case (0):
			switch (PB1)
			{
				case (1):
				PORTB |= (1 << PB4);
  				PORTB |= ~(1 << PB3);
				PORTB |= ~(1 << PB2);
  				PORTD |= (1 << PD5);
				_delay_ms(500);
				break;

				case (0):
				PORTB |= (1 << PB4);
  				PORTB |= ~(1 << PB3);
				PORTB |= ~(1 << PB2);
  				PORTD |= (1 << PD5);
				_delay_ms(500);
				break;

				default:
				break;
			}
			break;

		default:
		break;
	}	
	
}

but still i have the same mistake

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

Some remarks,

The routine void init() is not called in your main loop.

as far as I can see your program crashes after its first switch statement. goes back to reset and starts all over.

If I remember correctly the delay_ms routen only can go to 255. Check the compiler library to see what the max allowed value is for delay_ms.

regards

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

Quote:
goes back to reset and starts all over

Well that actually depends on your WinAVR version. Most have a catch all while(1) beyond main() but there was a version where this was not present and a return from main() did indeed lead off into rogue code and an eventual reset. FAQ#2 below.

BTW the very latest _delay_ms() breaks the former limitation on parameter usage - though the granularity suffers beyond a certain point.

Cliff

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

mathias.deneire wrote:

its already updated :

	PORTB |= ~(1 << PB3);

but still i have the same mistake

Yes you do - it still does not do what you want.

You set bits with or operator |=, you clear bits by anding the inverted mask &=~ .

Therefore, the quoted line would leave PB3 as it were, and would set all other bits in port B.

- Jani

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   switch( PCINT0)
      {
      case (1):
         switch (PCINT1)
   switch( PB0)
      {
      case (1):
         switch (PB1)

PCINT0 and PCINT0 are constants. Switching on them will accomplish nothing. The same goes for PB0 and PB1. The only code that is being run at all is case 0 in the outer switch, and case 1 in the inner switch.

Aside from that, your code would only run through once anyways and then exit main (something that you should never do). And you have a nice init function that you never call.

Regards,
Steve A.

The Board helps those that help themselves.

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

#include 
#include 
#include 
unsigned char pin;

void init()
{
 
    
  DDRB |= (1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5); // PB0 en 1 als ingang, PB2 tot 4 als uitgang
  DDRB |= ~(1<<PB0)|~(1<<PB1);

}


int main()
{
  
  

  init();
  pin = PINB;

  if (pin &((1<<PB0)&&(1<<PB1)))
    {		
	  PORTB |= (1 << PB4);
  	  PORTB &= ~(1 << PB3);
	  PORTB &= ~(1 << PB2);
  	  PORTB &= ~(1 << PB5);
	 
	  _delay_ms(1000);
	 } 
			

   if (pin &(1<<PB0))
  	{
	  PORTB |= (1 << PB4);
  	  PORTB &= ~(1 << PB3);
	  PORTB |= (1 << PB2);
  	  PORTB &= ~(1 << PB5);  

	  _delay_ms(1000);
	}			
	

   if (pin &(1<<PB1))
	{
	  PORTB |= (1 << PB4);
  	  PORTB &= ~(1 << PB3);
	  PORTB &= ~(1 << PB2);
  	  PORTB |= (1 << PB5);

	  _delay_ms(1000);
	}

  if (pin &(~(1<<PB0)&&~(1<<PB1)))
 	{
	  PORTB &= ~(1 << PB4);
  	  PORTB |= (1 << PB3);
	  PORTB |= (1 << PB2);
  	  PORTB &= ~(1 << PB5);

	  _delay_ms(1000);
	
	}		
}

i've changed the program, but i can't read notting in,

hope some of you guys know a sollution :D :D

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

I'm not that super in C code, but

if (pin &((1<<PB0)&&(1<<PB1))) 

I have a suspicious feeling that it should be :
pin &&((1<<PB0)&(1<<PB1))

as far as i'm correct this means that both PB0 AND PB1 have to be set in pin (that is pinB )
I might be mistaking though as I'm not very experienced in C code.

Another thing is that you still don't have an infinite loop in your main routine. Wich can cause unexpected behaviour.

also the init can be the following line if your comments hold. (for the english readers the comments state that PB0 & PB1 should be input, all other pins in portB are output)

DDRB = ~((1<<PB1)|(1<<PB0))
this first sets pb1&0 high (wich normally is output) to then invert it and thus making every pin output except pb0&1

In addition I would like to know if your code now fitting in the device.

regards

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
if (pin &((1<<PB0)&&(1<<PB1))) 

i've i were you, usually i use this macro to detect logic on PB0 and PB1 :

if ((bit_is_set(pin,PB0))&&(bit_is_set(pin,PB1)))

to gain a readable code...
but for C compatibility issue, I use this:

if(pin&((1<<PB0)|(1<<PB1))==((1<<PB0)|(1<<PB1)))

& = AND operation
| = OR operation
&& = logical AND test
|| = logical OR test
use brackets to determine priorities.
please read delay.h
your _delay_ms(1000); won't work well. It will work in good way only under 262ms per MHz.

KISS - Keep It Simple Stupid!

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

Quote:
your _delay_ms(1000); won't work well. It will work in good way only under 262ms per MHz.

That old limit no longer exists in the most recent avr-libc, see:

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

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

Ooops. I've should read that.
There is statement

Quote:
"When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality."

I don't understand the meaning of decreased resolution. What is the effect of decreased resolution?

KISS - Keep It Simple Stupid!

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

This is how it has changed. Previous version:

void
_delay_ms(double __ms)
{
	uint16_t __ticks;
	double __tmp = ((F_CPU) / 4e3) * __ms;
	if (__tmp < 1.0)
		__ticks = 1;
	else if (__tmp > 65535)
		__ticks = 0;	/* i.e. 65536 */
	else
		__ticks = (uint16_t)__tmp;
	_delay_loop_2(__ticks);
}

New version - notice how large values are in 0.1ms increments:

void
_delay_ms(double __ms)
{
	uint16_t __ticks;
	double __tmp = ((F_CPU) / 4e3) * __ms;
	if (__tmp < 1.0)
		__ticks = 1;
	else if (__tmp > 65535)
	{
		//	__ticks = requested delay in 1/10 ms
		__ticks = (uint16_t) (__ms * 10.0);
		while(__ticks)
		{
			// wait 1/10 ms
			_delay_loop_2(((F_CPU) / 4e3) / 10);
			__ticks --;
		}
		return;
	}
	else
		__ticks = (uint16_t)__tmp;
	_delay_loop_2(__ticks);
}

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

I'm still not sure of the point of this program is. It will read PINB once, do one of the 4 if's (that is, if you correct your conditions to do what you really want it to do), then exit.

Regards,
Steve A.

The Board helps those that help themselves.

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

euhm, yes, your right

#include 
#include 
#include 



void init()
{
 
    
  DDRB |= (1<<PB2)|(1<<PB3)|(1<<PB4)|(1<<PB5); 
  

}


int main()
{
  
 init();
  
  while(1)
  {


  
  		PORTB &= ~(1 << PB5);
  		PORTB |= (1 << PB4);
  		PORTB &= ~(1 << PB3);
  		PORTB &= ~(1 << PB2);

		

   if ((bit_is_set(PINB, PINB1)) && (bit_is_clear(PINB, PINB0)))
 	{
		PORTB |= (1 << PB5);
	  	PORTB &= ~(1 << PB4);
  	  	PORTB &= ~(1 << PB3);
	  	PORTB |= (1 << PB2);
  	  
	  	_delay_ms(1000);
	  
	
	}			
	

   if ((bit_is_set(PINB, PINB0)) && (bit_is_clear(PINB, PINB1)))
	{
	  	PORTB |= (1 << PB5);
	  	PORTB &= ~(1 << PB4);
  	  	PORTB |= (1 << PB3);
	  	PORTB &= ~(1 << PB2);
  	  

	  	_delay_ms(1000);
	  
	}

  if ((bit_is_clear(PINB, PINB0)) && (bit_is_clear(PINB, PINB1)))
 	{
	  PORTB |= (1 << PB5);
	  PORTB &= ~(1 << PB4);
  	  PORTB &= ~(1 << PB3);
	  PORTB |= (1 << PB2);
  	  

	  _delay_ms(1000);
	  
	}
			
  }
}

It works fine for leds :p but not with a motor, i'll need to find an other way