attiny2313 problem

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

Hi,

Ok so I'm an AVR newb. I have this bit of ASM code that drives a LCD display on a AVR-MT development terminal.

I tried making my own C code to do the same. And while it seems to me that the two pieces of code are equivalent-- apparently they are not. Can anyone take a look? ESPECIALLY the lcd_init function.

Is this a configuration issue?

Thanks!
Vindication

Attachment(s): 

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

It's a bad idea to use a macro to pretend you are using a function call by appending parentheses, so they should be dropped.
Then too, you should enforce evaluation order with parentheses, and finally it is usual practice to enclose macros in parentheses to minimise side-effects when used in code.
Therefore, I suggest trying -

#define rs_high  (PORTD |= (1 << PD4))
#define rs_low   (PORTD &= ~(1 << PD4))

Removing the parentheses from the code where you use the macros, and let us know how that goes.

I have coded for about 2 dozen architectures, and they all have their place.
Don't get too religious about them (but AVR is excellent!)

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

I am not sure if binary constants have been added to the latest avr-gcc -
http://gcc.gnu.org/ml/gcc-patche...
In the past I have had to resort to my own include file.
Example line-

#define B10011111 (0x9f)

If you turn on the listing output, you can always look at the .lst mixed C and Assembly file for clues to your problems.

I have coded for about 2 dozen architectures, and they all have their place.
Don't get too religious about them (but AVR is excellent!)

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

It wasn't the #defines... Also I have used the binary constants on some other code. So no dice.

I'm looking at the .lst file now... Assembly is hard to read in the first place- machine generated assembly- even worse hehe.

Any other ideas? I really wonder if it's a configuration issue...

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

Do a Google search for "My_LCD Serial Backpack".

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define F_CPU 10000UL

Is your AVR really running at 10kHz? I suspect that it is 1MHz. Since _delay_us and _delay_ms rely on this value, you really need to get it correct.

_delay_ms(1000);

Please read the comments in delay.h about the maximum value that you can pass to this function.

void toggle_e()
{
	PORTD |= 1 << PD6;
	_delay_us(100);
	PORTD &= ~(1 << PD6);
	_delay_us(100);
}

The first _delay_us is unnecessary. The delay only needs to be 500ns. At 1MHz each clock cycle is 1us.

asm("cli"::);

Just use:

cli();
ACSR = 0b01000000;

Not sure why you are doing this. I presume that you will use it latter.

int main(void)
{
        ...
	return 0;
}

Where do you expect main to return to and how do you expect the AVR to behave when it does?

Regards,
Steve A.

The Board helps those that help themselves.

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

Hehehe,

Good points all. The MCU is actually running at 10MHz. I dunno why I set it wrong. I now realize that _delay_ms is kind of a strange function... at 10 MHz the maximum value is 25 ms. Not as useful in my opinion...

The long delays were just because I wasn't sure where i was going wrong. The cli and ACSR thing were just for trying to mess w/ configuration- disabling interrupts and turning off the analog comparator-- these things are evidence of my newbness.

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

Ok so I've found a smaller problem-

The delay functions. They don't seem to be working right for me. Where am I going wrong? For example I have attached another simple file. All it does is set output pin PD3 high (an LED) and then goes into a loop. The program works if I comment out the _delay_ms call but doesn't work if I have it there... this seems bizzare to me.

BTW I took out the F_CPU define and set the clock speed to 10MHz in the avr studio project properties.

Thanks guys

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
PORTD ^= 1 << PD3;

Actually this does not set the bit high, it toggles the value of the bit. Since the default value of the bit after reset is 0, it should work in this case, but you shouldn't rely on it.

Quote:
The MCU is actually running at 10MHz.

Are you sure it is running at 10MHz? Just adding a crystal is not sufficient. You must also set the fuses properly.

Regards,
Steve A.

The Board helps those that help themselves.

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

Steves' last point is critical, Main should be coded to run forever, when it 'exits' you may find it just loops anyway.
What actually happens is usually compiler dependant.
I tried the binary constants and sure enough they work now, so I can drop my 'binclude.h' file from projects with a little editing.
I hope you have had some success, whilst there are times when assembler is the only way to go, C code is easier to work on and often largely portable between different chip families.
I have used bits of code largely unchanged on 8051, AVR, PIC and PC at one time or another saving time and effort, so I do hope you don't give up on C.

I have coded for about 2 dozen architectures, and they all have their place.
Don't get too religious about them (but AVR is excellent!)

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

Thanks guys.

So about the fuses- I cooked a couple of 2313 messing with the fuses and setting them to external clocks. Heheh I have an external crystal.. not clock. Well I threw them out- I don't want to bother with hooking up a 555 or anything else. hehe

Ok so what should my fuses be? I have a 10 MHz crystal so I think my CKSEL3..0 should be either 1111 or 1110 meaning I have a crystal above 8 MHz. Well neither one seems to work on mess_around.c above.

Now I'm doubting that the fuses are the issue as some stuff works and some stuff doesn't....

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

Holy Crap!

I just found the problem. Man what a dumb issue.

It was this:
Any of the C code I was compiling automatically took up too much room to actually fit on the PIC. So of course I was only programming on the first n bytes which never really ran correctly.

This was happening because I had all the avrgcc optimizations turned off[-O0]. When I told it to use -O1 in avrstudio-- EVERYTHING WORKED!

What is a good optimization flag to use? [1-3,s]

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

Vindication wrote:
Holy Crap! ... took up too much room to actually fit on the PIC...

Holy Crap ... indeed!

Ross McKenzie ValuSoft Melbourne Australia

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

Quote:
What is a good optimization flag to use? [1-3,s]

This can depend on what you need optimized and how your code, but for general purposes Os will do.

Quote:
Any of the C code I was compiling automatically took up too much room

The functions is delay.h are specifically designed to be use with optimization turned on. When it is not, it uses floating point which takes up a considerable amount of room. This can also happen when you pass _delay_ms a value that is not a constant.

Didn't you at least get a warning that the code size was too big?

Regards,
Steve A.

The Board helps those that help themselves.

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

No I didn't get a warning. Weird huh?

Sorry guys I meant AVR not PIC above.

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

Quote:

It's a bad idea to use a macro to pretend you are using a function call by appending parentheses, so they should be dropped.

Hmmmm--beauty may be in the eye of the beholder on this one.

I've got RS485 drivers that need to set TE (Transmit Enable) and /RE (Receive Enable) when appropriate. Usually, the two signals are tied together on the RS485 driver chip, but not always.

So in practice I have

...   RS485_TE0();	// ensure that the MAX485 is transmit-enabled
...
...	RS485_RE0();	// switch the MAX485 to receive mode

In the board-dependent part of the .h file (CodeVision syntax) I can have

#define	TE0_PIN		PORTD.1
#define	RS485_TE0()	PORTD.1 = 1
#define	RS485_RE0()	PORTD.1 = 0

or

void RS485_TE0 (void);
void RS485_RE0 (void);

and have actual functions that carry out the needed operations. I think macros-that-look-like-functions are fairly common, with or without parameters. I don't see where it is not a 'good thing'.

Lee

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

Hi Lee,
Well, I am glad to see that you upper-cased the macro name, that at least gives the reader a strong clue that they will be looking in vain for the 'function'.
I DO use macros that look like functions when I have parameters to pass (as one does), like this bit of my flags library -

//###########################################
//##  PUBLIC MODULE FUNCTION DECLARATIONS  ##
//###########################################
extern void FlagsInit(void);
extern void ClearFlag(uint8_t ui8Flag);
extern void SetFlag(uint8_t ui8Flag);
extern void ToggleFlag(uint8_t ui8Flag);
extern uint8_t TestFlag(uint8_t ui8Flag);

#ifdef  FLAGBITS

#define INITFLAGS       FlagsInit()
// USE THESE MACROS FOR THE BIT FUNCTIONS
#define CLEARFLAG(x)    ClearFlag((x))
#define SETFLAG(x)      SetFlag((x))
#define TOGGLEFLAG(x)   ToggleFlag((x))
#define TESTFLAG(x)     TestFlag((x))

// USE THESE MACROS FOR THE BIT INLINE CODE
//#define CLEARFLAG(x)    ucaFlags[(x)>>3] &= ~(1<<((x)&7))
//#define SETFLAG(x)      ucaFlags[(x)>>3] |=  (1<<((x)&7))
//#define TOGGLEFLAG(x)   ucaFlags[(x)>>3] ^=  (1<<((x)&7))
//#define TESTFLAG(x)   ((ucaFlags[(x)>>3] &   (1<<((x)&7))) != 0)

#else

// USE THESE MACROS FOR THE BYTE INLINE CODE
#define INITFLAGS       FlagsInit()
#define CLEARFLAG(x)    ucaFlags[(x)]=false
#define SETFLAG(x)      ucaFlags[(x)]=true
#define TOGGLEFLAG(x)   ucaFlags[(x)]=!ucaFlags[(x)]
#define TESTFLAG(x)     (ucaFlags[(x)]==true)

#endif

As you can see, INITFLAGS has no parentheses.
I just thought it a likely cause of confusion down the track for a C beginner and best avoided.
I probably shouldn't have phrased that like it was a rule or something though.

I have coded for about 2 dozen architectures, and they all have their place.
Don't get too religious about them (but AVR is excellent!)

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

Either way doesn't matter to me much. I don't use macros often. The macros from the code I posted were something I cut and pasted so not even originally mine. :)

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

Quote:
Well, I am glad to see that you upper-cased the macro name, that at least gives the reader a strong clue that they will be looking in vain for the 'function'.

but if the reader is doing any kind of worthwhile search, they'll find it regardless. it's a beginner's mistake to assume that anything that looks like a function is a function, or that anything in all-caps is a macro. conventions are nice, but i find that they're as likely to mislead as to lead. (oh -- i'm speaking of reading "foreign" code. when it's your own code, then conventions are the One True Way, of course. ;-)

paul