First 'C' program - Question

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

Ok, I wrote one. My first c program. I did it first in programmers notepad, compiled with winAVR, then played a little in Studio REgardless, it does what I expected, and I have a few questions.

First the code:

//Tiny2313 i/o...my first c program

#include 



main(void)
{//set port b as outputs port d as inputs
	DDRB= 0xff;
	DDRD = 0x00;
	
		while(1) {
		PORTB = PIND;
		}
}

No biggie, portb reflects portd. It works.

My first question is the compiler in WinAVR kicked up a fuss and said something about ddrb, ddrd, portb, portd, pind as undefined. I made everything capitals as you see above and that went away.
Why can't you use lower case?

Second thing I saw in the WinAVR compiler was a warning that "return type defaults to 'int'"
I noticed that if I put 'int' before main that warning goes away.
Since this was not a numerical function I assumed that int was not needed...Am I wrong?

When I created a gcc project in studio I pointed to a new folder that had my .c and makefile in it, and there was everything I did in programmers notepad. OK, I went and hit COMPILE in Studio and got this back in the BUILD window:

Quote:
mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT 2313_first.o -MF dep/2313_first.o.d -c ../2313_first.c
/usr/bin/sh: -Wall: command not found
make: [2313_first.o] Error 127 (ignored)
Build succeeded with 0 Warnings...

The program loaded into the Tiny and runs fine. What is that error 127(ignored) about?

also, in assembler there is usually a command at the end of the code that says jump back to the beginning...something like RJMP BEGIN to tell the AVR to start over, or in the case of branches etc, to jump back to the beginning. Where is that in C? To me this program looks like it runs off the end of the flas then starts over which kind of is silly.
Am I missing something?

Enlighten me away!! :)

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:
Why can't you use lower case?
The C language is case sensitive.
Quote:
Since this was not a numerical function I assumed that int was not needed...Am I wrong?
The return value is intended for a program running in a hosted system (which C was intended for). It is not necessary in an embedded system.
Quote:
When I created a gcc project in studio I pointed to a new folder that had my .c and makefile in it, and there was everything I did in programmers notepad.
But did you tell Studio to use the makefile.
Quote:
...something like RJMP BEGIN to tell the AVR to start over, or in the case of branches etc, to jump back to the beginning. Where is that in C?
That is what the "while(1)" is for. It is an endless loop (it will continue as long as 1 is not equal to 0).

Regards,
Steve A.

The Board helps those that help themselves.

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

jgmdesign wrote:
First the code:
Enlighten me away!! :)

Did you steal my code Jim? :wink:

There is an .lss file generated that you can look at that will have what I think you may find very handy, given your asm background.

Congratulations and welcome to the club. 8)

"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

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

jgmdesign wrote:
Second thing I saw in the WinAVR compiler was a warning that "return type defaults to 'int'"
I noticed that if I put 'int' before main that warning goes away.
Since this was not a numerical function I assumed that int was not needed...Am I wrong?

All functions have a return type. If your function doesn't return anything, declare it void.
void f()
{
}

main() is a special case. It is expected to return an int - so declare it as int.

(Some platforms allow declaring main() as void, but that is a non-standard extension.)

It is good practice to specify the return type of all functions.

It is also good practice to always explicitly return something from a function that is not declared void.

Sid

Life... is a state of mind

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

jgmdesign wrote:

My first question is the compiler in WinAVR kicked up a fuss and said something about ddrb, ddrd, portb, portd, pind as undefined. I made everything capitals as you see above and that went away.
Why can't you use lower case?

Atmel defines ports and bits in uppercase in datasheets, assembly language headers, and it is also logical to define them similarly in C headers.

If you want to use lower case, then define them yourself. I have never questioned this or wanted to use lower case, so I just happily use the uppercase definitions, just like in other micros.

jgmdesign wrote:

also, in assembler there is usually a command at the end of the code that says jump back to the beginning...something like RJMP BEGIN to tell the AVR to start over, or in the case of branches etc, to jump back to the beginning. Where is that in C? To me this program looks like it runs off the end of the flas then starts over which kind of is silly.
Am I missing something?

Yes, this is compiler specific. Many years ago AVR-GCC did continue running the code after returning from main. Nowadays when it returns from main, it has a "loop: rjmp loop" thing to jam execution. Other compilers, I don't know.

So if you want to do that yourself, then make an infinite loop in C code as suggested.

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

Quote:

mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT 2313_first.o -MF dep/2313_first.o.d -c ../2313_first.c
/usr/bin/sh: -Wall: command not found
make: [2313_first.o] Error 127 (ignored)
Build succeeded with 0 Warnings...

Ah ha! A man trying to use WinAVr and 4.19 eh? Sadly foryou Atmel have tried to make this difficult in 4.19 (everything up to 4.18 SP3 was OK). Head on over to the AS4 forum and read my sticky at the top about fixing 4.19

As such you simply never built the code inside AS4. The thing that will have confused you is that if you have:

\project\main.c
         makefile

and build inside PN then you get:

\project\main.c
         makefile
         main.elf
         main.hex
         etc.

If you now start an AS4 project and tell it to build using \project\main.c what it *should* create is:

\project\main.c
         makefile
         main.elf
         main.hex
         etc.
         default\proj.elf
         default\proj.hex
         default\etc.

But because the build failed those files under "default\" were not created. However you did not notice as you still had the old main.hex in \project from when you were playing with PN.

So apply the 4.19 fix and then look for the files that are built under .\default\

Quote:

To me this program looks like it runs off the end of the flas then starts over which kind of is silly.

avr-gcc, like most C compilers, adds a small amount of "hidden code" that you cannot see called the "C Run Time" (CRT). That involves a JMP at 0 to skip over the interrupt vector table that is also provided for you, then some code that runs before main() that does stuff like setting the stack pointer (yes, even on the chips where the stack defaults to RAMEND anyway) and making sure that R1 always contains 0 (which saves the compiler having to specifically load a register with 0 when it's (so often) later required. It can always rely on R1=0.

After that setup stuff has been done there may be up to two loops. One that copies initial values for some variables out of LPM and puts it in a known location in RAM (known as .data) and possibly another loop if there are any global variables that default to 0 that clears an area of SRAM where they are located (known as .bss - block started by symbol).

Finally and at last the CRT is ready to enter main() and the code you wrote. Now if it did a "JMP main" to get there then your concerns about "falling out the bottom" of main() would be justified. However (in GCC at least) this is not what happens. It does "CALL main" instead. and the very next instruction is a "JMP exit". exit: is also part of the CRT and consists of:

_exit:
  cli
__stop_program:
  rjmp __stop_program

so if execution is ever given a chance to return from main() it will stop right there. Notice the CLI - that can rain on your parade. Some people knowing they are only going to work inside interrupts write code like:

int main(void) {
  start_interrupts();
  sei();
}

ISR(SOME_vect) {
  do_all_the_work_here();
}

Sadly that program design will not work as after the sei() in main() it falls out and hits the CLI at _exit: so the AVR does nothing more (apart from the endless RJMPs). The design needs to be:

int main(void) {
  start_interrupts();
  sei();
  while(1) {
    // nothing going on here - all happens in ISR()
  }
}

or simply:

int main(void) {
  start_interrupts();
  sei();
  while(1);
}

While you can just end the while(1) with a semi-colon and that will generate the code:

here: rjmp here

it is good programming practice to follow all while(), if(), else(), do and son on with { } even if they are (initially - and that's the point) empty.

To illustrate what I've said I built your code and then looked at the (very useful!) .lss file that was generated:

Disassembly of section .text:

00000000 <__vectors>:
   0:	12 c0       	rjmp	.+36     	; 0x26 <__ctors_end> //CJL: this is the RJMP at 0x0000 to skip ints
   2:	2a c0       	rjmp	.+84     	; 0x58 <__bad_interrupt>
   4:	29 c0       	rjmp	.+82     	; 0x58 <__bad_interrupt>
[several more vectors snipped]

//CJL: so this is where the reset RJMP comes to
00000026 <__ctors_end>:
  26:	11 24       	eor	r1, r1          // CJL: make sure R1 always holds 0
  28:	1f be       	out	0x3f, r1	; 63 //CJL: then store at SREG which includes clearing I
  2a:	cf ed       	ldi	r28, 0xDF	; 223 //CJL: load RAMEND
  2c:	cd bf       	out	0x3d, r28	; 61 //CJL: store at SPL

// CJL: now set up a loop to copy variables from flash to RAM
// but your program doesn't have any so the CPI at 0x3E is taken
// immediately and the loop is pointless (other versions of
// GCC don't even include this loop when not required).
0000002e <__do_copy_data>:
  2e:	10 e0       	ldi	r17, 0x00	; 0
  30:	a0 e6       	ldi	r26, 0x60	; 96
  32:	b0 e0       	ldi	r27, 0x00	; 0
  34:	ec e6       	ldi	r30, 0x6C	; 108
  36:	f0 e0       	ldi	r31, 0x00	; 0
  38:	02 c0       	rjmp	.+4      	; 0x3e <__SP_H__>
  3a:	05 90       	lpm	r0, Z+
  3c:	0d 92       	st	X+, r0
  3e:	a0 36       	cpi	r26, 0x60	; 96
  40:	b1 07       	cpc	r27, r17
  42:	d9 f7       	brne	.-10     	; 0x3a <__CCP__+0x6>

// CJL: next is a loop to clear any variables in RAM that default
// to 0 (.bss) but again there are none so this does nothing in
// fact (again other GCCs don't include this when not needed).
00000044 <__do_clear_bss>:
  44:	10 e0       	ldi	r17, 0x00	; 0
  46:	a0 e6       	ldi	r26, 0x60	; 96
  48:	b0 e0       	ldi	r27, 0x00	; 0
  4a:	01 c0       	rjmp	.+2      	; 0x4e <.do_clear_bss_start>

0000004c <.do_clear_bss_loop>:
  4c:	1d 92       	st	X+, r1

0000004e <.do_clear_bss_start>:
  4e:	a0 36       	cpi	r26, 0x60	; 96
  50:	b1 07       	cpc	r27, r17
  52:	e1 f7       	brne	.-8      	; 0x4c <.do_clear_bss_loop>

//CJL: This is where the BSS loop ends - now ready to enter main()
  54:	03 d0       	rcall	.+6      	; 0x5c 
//CJL: and this is where it gets back to if main() should ever return 56: 08 c0 rjmp .+16 ; 0x68 <_exit> //CJL: just in passing note that all the interrupt vectors // are initially loaded with an RJMP to here and see what this // does - this is why if you enable an interrupt but don't provide // an ISR() then the AVR "resets" because it does this jump to 0 00000058 <__bad_interrupt>: 58: d3 cf rjmp .-90 ; 0x0 <__vectors> // CJL: finally your code... 0000005c
: #include int main(void) {//set port b as outputs port d as inputs DDRB= 0xff; 5c: 8f ef ldi r24, 0xFF ; 255 5e: 87 bb out 0x17, r24 ; 23 DDRD = 0x00; 60: 11 ba out 0x11, r1 ; 17 while(1) { PORTB = PIND; 62: 80 b3 in r24, 0x10 ; 16 64: 88 bb out 0x18, r24 ; 24 66: fd cf rjmp .-6 ; 0x62 // CJL: and this is where it comes to after a return from main() 00000068 <_exit>: 68: f8 94 cli 0000006a <__stop_program>: 6a: ff cf rjmp .-2 ; 0x6a <__stop_program>

(my comments added with "// CJL:")

==================================================================================

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

Larryvc:
Was not aware that you had the corner on that. :)

Japael:

Quote:
Atmel defines ports and bits in uppercase in datasheets, assembly language headers

I just looked at some assembler code and when I configured a port all of my code is in lowercase. But that is for another thread.

Cliff:
I will have to sit and digest your post. Good info. I did just take a peek and correct the code did not build or compile as I did not go into project options and let studio know where to look for the makefile. Once I did that, the code compiled, and a build created the hex. Oh well live and learn. :?

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

OK, I added to the program where I want an interrupt to cause portb to do the cylon eyes from smileymicros book, but I am getting an error when I go to compile
Code first:

//Tiny2313 i/o...my first c program

#include 
#include 

//declarations
	


main(void)
{//set port b as outputs port d as inputs
	DDRB= 0xff;
	DDRD = 0x00;
	
		while(1) {
		PORTB = PIND;
		}

}

ISR(INT0_vect) 
while(PORTD.2 = 0) {
		for(int i = 1; i <128;i = i*2)
		{
			PORTB = ~i;
			_delay_loop_2(7500);
			}
			
			for(int i = 128; i >1; i -= i/2)
			{
				PORTB = ~i;
				_delay_loop_2(7500);
				}
		}
		

The error(s):

Quote:
2313_first.c:11: warning: return type defaults to 'int'
2313_first.c: In function '__vector_1':
2313_first.c:22: error: expected declaration specifiers before 'while'
2313_first.c:34: error: expected '{' at end of input
make: *** [2313_first.o] Error 1
Build failed with 2 errors and 1 warnings...

I know I blew it, just asking where I went wrong

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

You're missing the outermost pair of brackets in the ISR function (like you have in main).

And you're spending way, way too much time in the ISR (unless you're the 0.1% that really intended that)

EDIT - and you're overwriting your ISR PORTB values in your main while() loop.

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

Quote:

ISR(INT0_vect)

Think of the ISR as a function with a fancy macro "title line".

Pull out your C book, and a function definition requires a "compound statement". That is stuff between { and }.

The text will read something like

(
)
{
your stuff here
}

You skipped some squigglies.

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

kk6gm wrote:
You're missing the outermost pair of brackets in the ISR function (like you have in main).

And you're spending way, way too much time in the ISR (unless you're the 0.1% that really intended that)

EDIT - and you're overwriting your ISR PORTB values in your main while() loop.


Yes I am aware I am overwriting the port b values. THat is the intent.

I want to remain in the ISR as long as the INT0 is pressed. When released, go back to MAIN

Lee,
Not sure what you are driving at and my 'c' fom k/r is not near me...care to give me an idea?

EDIT: You mean this:

//Tiny2313 i/o...my first c program 

#include  
#include  

//declarations 
    


main(void) 
{//set port b as outputs port d as inputs 
   DDRB= 0xff; 
   DDRD = 0x00; 
    
      while(1) { 
      PORTB = PIND; 
      } 

} 

void ISR(INT0_vect) 
{while(PORTD.2 = 0) { 
      for(int i = 1; i <128;i = i*2) 
      { 
         PORTB = ~i; 
         _delay_loop_2(7500); 
         } 
          
         for(int i = 128; i >1; i -= i/2) 
         { 
            PORTB = ~i; 
            _delay_loop_2(7500); 
            } 
      } 
  }     


I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
Yes I am aware I am overwriting the port b values. THat is the intent.

I want to remain in the ISR as long as the INT0 is pressed. When released, go back to MAIN


OK, fair enough.

You want

ISR(vect_name)
{ <-- note
  ..ISR code..
} <-- note

BTW, I just noticed this infamous error (everybody does it)

while(PORTD.2 = 0)

You want == to compare. One = is assignment.

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

It'll be an interesting day when GCC accepts PORTD.2 syntax!

And isn't it supposed to be PIND ?

I would explain more but I'm being tortured by an iPad keyboard!

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

Change

main(void)

to

int main(void)

The explanation for why was given above in a previous post.

"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

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

kk6gm wrote:

while(PORTD.2 = 0)

Also, PORTD.2 is not a valid notation in GCC. Besides inputs are read from PIND register, not PORTD.

  while ( PIND & (1<<2) == 0 )

1<<2 or 0x04, it does not matter how you define the bit mask for bit 2 as long as you like it.

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

Oh and get out of the habit of using "int" before it becomes ingrained, use unit8_t or int8_t.

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

Quote:

Lee,
Not sure what you are driving at and my 'c' fom k/r is not near me...care to give me an idea?

As was mentioned:
Quote:

You're missing the outermost pair of brackets in the ISR function (like you have in main).


Now, I've always called the square-thingies "brackets" and the squigglie-thingies "braces". I think there is a specific word for the squigglies.

Anyway, here is one of my functions:

// **************************************************************************
// *
// *		S H O W _ M E N U
// *
// **************************************************************************
void						show_menu			(char flash *mptr, unsigned char line)
{                  <== opening brace/"curly bracket"
		// Show the correct menu
	lcd_gotoxy (0, line);
	lcd_putsf (mptr);
}                  <== closing brace/"curly bracket"

So there is a return value, the function name, the parameter list, and the compound statement that comprises the body of the function.

You had no opening or closing braces for your ISR. Modified:

ISR(INT0_vect)
{
	while(PORTD.2 = 0) 
		{
		for(int i = 1; i <128;i = i*2)
			{
			PORTB = ~i;
			_delay_loop_2(7500);
			}
         
		for(int i = 128; i >1; i -= i/2)
			{
			PORTB = ~i;
			_delay_loop_2(7500);
			}
		}
}      

Let's look at another bit:

Quote:

while(PORTD.2 = 0)

The short answer is that = is assignment operator, and == is the equality operator. You want ==

The rest of the story is that the while() will never be carried out. ;)

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

theusch wrote:
Quote:

You're missing the outermost pair of brackets in the ISR function (like you have in main).


Now, I've always called the square-thingies "brackets" and the squigglie-thingies "braces". I think there is a specific word for the squigglies.

Yes, I think "braces" is right. My fingers have a life of their own.

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

Quote:

Yes, I think "braces" is right. My fingers have a life of their own.

Or "curly brackets", apparently. There are also votes for "squiggles".
http://english.stackexchange.com... and others

In my search I didn't find a "dictionary style" word for them like entotiplety or such.

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

Wow, your first C program did what you expect?

Not sure my 21st C program does anything near what I expect!

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

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

Quote:

Or "curly brackets", apparently.

One Swedish name for them becomes gull-wings translated literally..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

If you look at my EDIT I added the braces.

I knew the code did not work and I even said it in my post. I also see I did not enable the interrupt either.

I am attempting to do something in c that I know what the result is in ASM as I have already tried it. And I also hijacked some of Smileys code from his book that I know works.

@Johan,
I like the 'gull wings' idea.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Ok, I am stumped some more.
I want to watch portd pin0. If it is logic 1 send a led scan accross port b. Keep doing this as long as portd pin0 is at logic 1.

I know the code is wrong, but how do I watch one pin in 'C'? :?

//Tiny2313 i/o...my first c program

#include 
#include 
#include 

//declarations

#define TRUE 1;	
#define FALSE 0;
unsigned int getval = 0;
//set port b as outputs port d as inputs
	DDRB= 0xff;
	DDRD = 0x00;
	PORTD = 0xff;
	getval = PIND;

void main(void)
{
	
	if(getval == 1) for(int i = 1; i <= 128; i = i*2)
		{
			PORTB = i;
			_delay_loop_2(30000);
			}
		

}

Tips greatly appreciated

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
getval = PIND & (1<<0);

or

getval = PIND & 0x01;

and for the test, don't compare to 1, just compare to 0 or non-zero

if (getval != 0)

or (implicit test for non-zero)

if (getval)

You've got other problems
1) You have code outside a function (the setup before main())

2) You don't have an infinite loop in main - typically a while(1) loop

3) You don't read PIND each time through your (non-existent) main loop

Last Edited: Fri. Sep 21, 2012 - 08:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you haven't already, go through the Tutorials forum article with "Bit Manipulation" in the title.

Short answer for a single particular pin: replace (getval == 1) with (PIND & (1<<0))

In the real world, buttons/signals/keys bounce. So you sample the appropriate inputs every few milliseconds and enter that sample into your debouncing routine. Then you use that confirmed debounced value.

For (up to) 8 or 16 input bits in parallel, an example below starting with the 10ms work:

// ***********
// Switches -- every 10 ms.
// ***********
		// Fetch switch state every 10ms.
		input_prev = input_current;	// for calculating edges

		scratch = key_fetch();		// strobe and process switch inputs
		input_current = signal_debounce(scratch, inputs);		//  and create edge triggers & current state

// Rising & falling edges
//
// Note:  no edges.  If needed:
//	Rising & falling edges = composite_io ^ previous_io;
//	Rising edges = (composite_io ^ previous_io) & composite_io;
//	Falling edges = (composite_io ^ previous_io) & previous_io;
//
		input_rising = (input_current ^ input_prev) & input_current;
		input_falling = (input_current ^ input_prev) & input_prev;

For "_fetch()" I write a different routine for each app. Sometimes the bits are lined up nicely; sometimes they are scattered across ports:

//
// **************************************************************************
// *
// *		K E Y _ F E T C H
// *
// **************************************************************************
//
//	Eight push-button switches are connected, active low.
//
//	Gather the values from PINA & PINB & make active high
//
unsigned char				key_fetch			(void)
{
	return ~((PINA & 0xfc) | (PINB & 0x03));
}

I typically make mask #defines:

//	Masks into input_*
//	=========================
//
//	Expected 8-kepad layout:  Two rows of 4
//	Top row lines up with short "prompts" on the bottom line of LCD
//		20 characters; 4x4 character prompts and a space between  (e.g. YEAR MON  HRS  MINS)
//	Bottom row has generally fixed functions:  MENU/BACK, ENTER, DOWN, UP
//
//	TOP:	K1		K2		K3		K4		(schematic nomenclature)
//	Mask:	0x01	0x10	0x04	0x40
//
//	BOT:	K5		K6		K7		K8
//	Mask:	0x80	0x08	0x20	0x02
//
							//	Top row -- "function" keys
#define	SW0			0x01	// BCD 0 -- left button
#define	SW1			0x10	// BCD 4 -- 2nd left
#define	SW2			0x04	// BCD 2 -- 2nd right
#define	SW3			0x40	// BCD 6 -- right button

							//	Bottom row -- "menu" keys
#define	SW4			0x80	// BCD 7 -- left button
#define	SW5			0x08	// BCD 3 -- 2nd left
#define	SW6			0x20	// BCD 5 -- 2nd right
#define	SW7			0x02	// BCD 1 -- right button



// Preliminary assignments
//	=========================
#define	SW_F1		(SW0) 	// left button
#define	SW_F2		(SW1)	// 2nd left
#define	SW_F3		(SW2)	// 2nd right
#define	SW_F4		(SW3)	// right button

#define	SW_MENU		(SW4) 	// left button
#define	SW_ENTER	(SW5)	// 2nd left
#define	SW_DOWN		(SW6)	// 2nd right
#define	SW_UP		(SW7)	// right button

and then a couple uses:

			if (input_rising & (SW_F1 | SW_F2 | SW_F3 | SW_F4))
				{
				// Function key pressed
...
				}

			if (input_rising & SW_ENTER)
				{
				// Show the CIP summary
				state = STATE_RUN;
				subitem = 0;
				// Restart the timer
				sec_idle_seqs = 0;
				do_refresh = 1;
				}

// ***********
// Application Soft Timers
// ***********
		if (input_current & SW_MENU)
			{
			if (ticks_menu_held < 250)
				{
				ticks_menu_held++;	// about 2.5 seconds max
				}
			}
		else
			{
			ticks_menu_held = 0;
			}


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

Will make the changes
Lee:
I have not looked at the tutorial but I will this evening.

Right now I am not concerned about the switchbounce but later on yes, I will be.
Thanks all

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

My suggestion is to write a dozen small programs, where each one adds a new routine. Start with led output, next add switch input, then add serial output, then add serial input. Now you can have a menu to call the next routines. A/D read and display on the serial. Maybe a text lcd out next. Then a timer interrupt to keep track of 100ms tics. Etc.

Imagecraft compiler user

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

Good idea!

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Well ok, I have that working. Time to add an interrupt.
Taking some of Bobs advice.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

How about trying the imagecraft compiler and see if its gets you going faster? I still have a hard time dealing with gcc progmem. But I'm an obstinate old coot.

Imagecraft compiler user

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

I was thinking about downloading the demo versions of ICC and CV but I don't want to get too hooked on either one of them yet because I don't have the extra funds to BUY the real deal at this time. For now FREE is my second favorite four letter 'F' word ;)

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:

I still have a hard time dealing with gcc progmem.

Then get 4.7 which now has __flash.

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

Interupts aer working now(gotta be careful where you put the gull wings), and I am playing with the USART. Working with Smileys book but a little confused, so off to the tutorials forum to see what I can find there.

Just looking to send out a string(Hello World) to the PC when I press a button...nothing fancy

EDIT#1:
THis is confusing. PRINTF, SPRINTF...I dunno, In ASM I keep my message 'Hello World' in program memory and load the message via the Z register and LPM

Doing this in 'C' is not so simple or am I missing something as usual? I read Deans TUT and it was not much help(Nuthin personal Dean)

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

I'd recommend staying away from any compiler other than the infinite value compiler, especially as it used by the Arduino, until you get facile with the C syntax. Learning the idiosyncrasies of the other compilers will just slow you down in learning the basics.

I think the best way by far to learn C is just to read other folks programs. Start with the simplest and make minor modifications on it. If a program blinks an LED on and off once per second, change it to be on for two seconds and off for 1/2 second. Things like that. Next in order of 'best way' that when you run into an issue with one of these simple mods, just post the code here and ask why it didn't work or how to make it work.

printf and sprintf can be a bit tedious to get set up properly, but once set up then printf is easy to use. I'm not sure sprintf ever gets easy to use. I've written a library that helps transition from the Arduino serial that I can link you to later I'd recommend sticking with the Arduino way of doing things using Serial.print and Serial.println until you get good and familiar with overall syntax.

Once you get where you want to do something with regular C that isn't easily done with Arduino, then you'll need to make a transition from the Arduino way to the C way. I've written some stuff on that process that I'll link you to when you get to that point.

Smiley

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

Smiley,
I am actually doing two things at once. This thread is for some stuff I have been working on a Tiny2313 on my own with your book and some stuff I have been writing myself. I am looking to create functions of things I use quite often in ASM so I have a better understanding of how the 'c' way works. For example I am now trying to send 'Hello World' to the PC when a button is pushed. I know how to do this in ASM and is a piece of cake. In 'c' not so much for me. So once I figure out how to do this, and relate it to the ASM I know better for me.

The Arduino stuff I have not shared here and really have no intention to at this moment as I am approaching the arduino in a different light where I am not asking any questions here, but writing them down and exploring the answers on my own through trial and error in the arduino way of thinking using their adaptation of 'C'. While arduino is 'c' it is done differently and I am approaching it as such. FWIW I am in the serial section of the arduino as well, but thats another story.

Ahh, well Off to get the little one in his bath and then bed, then back to this.

Thanks all,

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Back to the USART issue.
Here is what I use in ASM to output a message to the usart:

;send via uart
messsend:;rcall	delay45
uout:
		lpm		r22,Z+	;load the register with charachter 
		tst		r22		;and check if it is the end 
		brne	output	
;		rcall	delay45
	
		ret				;if done return
;output*********************************************************************
output:	 
ulpb:	lds		temp,ucsr0a
		sbrs	temp,5
		rjmp	ulpb
		sts		udr0,r22
		rcall	delay45
		rjmp	uout	;go get the next charachter

;Messages:
esn:		.db  "Enter unique 10 digit serial number press ",0x0d,0,0

The message "esn" is loaded into the z register and then the subroutine Messsend is called.

THis works, but I am stumped on how to set this up in 'c'.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

char esn[]={"Enter unique 10 digit serial number press \n"};


to print the message:
 uout(esn); //I would probably call uout, pstring or putstr

void uout(char *msg)
{
    while (*msg)    //while what Z points to is non-zero do..
      {
      output(*msg++); //grab the char, z+
      }
}

void output (char ch)
{
    while ((UCSR0A & (1<<5) == 0)
        {
        UDR0 = a;
        }
    delay45();
}

Some things to remember:
A pointer is like the X,Y,Z registers , &Z is the address, *Z is what Z is pointing to
*Z++ is what Z is pointer to, then increment Z by the size of the variable. If the size is a char, then +1, is it is a long int, +4.
++*Z increments first then loads/stores what Z is pointing to

== is 'equal to'. you'll normally find this in a conditional - while(), if() etc
= is assignment
!= is 'not equal to'

I haven't done any progmem stuff - so read up on the tutorial. You'll need to put progmem and pgm_read_byte() in strategic places. progmem basically tells the compiler to to the stuff in the flash, pgm_read_byte() basically does the lpm.

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

Thanks! I think I get it but a Couple of questions:

void output (char ch) 

I kind of understand the 'char' for charachter, but what does the 'ch' represent?

UDR0 = a; 

Where did the 'a' come from?

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:

void output (char ch) 

I kind of understand the 'char' for charachter, but what does the 'ch' represent?


char is the type of the parameter. ch is the name of the parameter.

jgmdesign wrote:

UDR0 = a;

Where did the 'a' come from?

Looks like a mistake to me. There is also a parenthesis missing in the while statement.

Sid

Life... is a state of mind

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

Quote:

I read Deans TUT and it was not much help(Nuthin personal Dean)

Can we explore that a bit? What about Dean's tutorials did you not understand. One of his skills is explaining potentially complex stuff in clear and concise ways that most people can understand so I'm a bit surprised you had a problem.

Of course it could be that you are making a mistake here. You are not only learning how to use C on an AVR to drive peripherals like IO and USART but you are actually trying to learn C at the same time.

You'd be far better off learning C first then worry about how to use it on an AVR later. As you've seen just doing something as simple as printing "Hello world" can be fraugth in an embedded enviornment. Yet if you use a PC you can do:

clawson@ws-czc1138h0b:~$ cat test.c
#include 

int main(void) {
  printf("Hello world\n");
}

clawson@ws-czc1138h0b:~$ gcc test.c -o test
clawson@ws-czc1138h0b:~$ ./test
Hello world

I just wrote, compiled and ran that program in less than a minute. That's how quick you can get results on a PC.

Better yet do it inside an IDE like Microsoft Visual Studio Express or Pelles C (possibly a better choice as it's quicker/easier to just write something like that Hello World program there). If you use an IDE then when you add some other stuff to make the program more complex you benefit from advanced debugging that outshines anything you are going to find for AVRs.

Use the PC to learn why a print string function looks like:

void print_string(char * str) {
   while (*str) {
     print_char(*str++);
   }
}

But, to be honest, you shouldn't even be considering a function like this at the very start of learning C. That's using some pretty advanced concepts in just a few lines which will just blow your brains. Far better yet is to get a good book on C that has been written to build slowly through the simple stuff up to the complex stuff - not to dump you into real complex stuff on day one.

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

Quote:
Quote:

I read Deans TUT and it was not much help(Nuthin personal Dean)

Can we explore that a bit? What about Dean's tutorials did you not understand. One of his skills is explaining potentially complex stuff in clear and concise ways that most people can understand so I'm a bit surprised you had a problem.

I realised that my choice of words could be misleading even though they are true. I did predicate the comment about Deans TUT with :

Quote:
Doing this in 'C' is not so simple or am I missing something as usual?

What I should have elaborated on was that Deans Tutorial simple echo's what comes in back to the PC. In that respect then his TUT is spot on, but I have already hit that part. I am looking to send out text strings like Hello World as I descrived how I do it in ASM with a few lines of assembler. Kartman came back with an answer that I understood and had two questions on which in turn were answered. so off to the races I go with this.

If I get this part to work, then I can elaborate more on this area and if it does not work, I can revert back to a known working spot and debug accordingly. Slow? YES, but trial and error is a good teacher as well.

Quote:
Of course it could be that you are making a mistake here. You are not only learning how to use C on an AVR to drive peripherals like IO and USART but you are actually trying to learn C at the same time.

Yes, Yes, and sort of. :shock:

YES the ASM'er in me says this is a mistake as I have done well in ASM over the last 25 years, but I am losing jobs because the customer wants the job done in the evil letter, and if Jim no program in C and George does, who gets the job? Maybe some of you are wealthy enough to be able to stand your ground, but not me.

YES I am trying to learn C for the AVR as it is the only processor I use. I am being forced to use a competitors(NOT THE EVIL EMPIRES, THis one's named after a tree), but that project may fall flat for other reasons. Am I to be faulted for wanting to learn the AVR's version of the evil letter?

Sort of learning the true C language at the same time as both AVR c and K&R C intertwine as K&R intertwines with the Tree processor et. al. I bought the K&R book and refer to it while I go through Smileys book, and the tutorials, and the stuff I find on the web. I have been playing with Pelle's which Smiley recommendd in another thread a while back but AS4/6 is my preferred learning enviroment of choice.

All I am looking to do is put together my own library of code chunks that I wrote with a little freakin' guidance that I understand and can build on as I noted earlier. Once I have that then I shall look at Peter Fleury's stuff and other goodies I have come across. I myself don't think it's a bad idea to write the same thing your way if it gives you a better understanding of what the end result is supposed to be. If it works ship it.

In some respects C is certainly easier to use than ASM, but for things like printing messages at the moment C-SUCKS.

Bob Gardner:
Taking your idea has worked better than mine about working on one thing at a time. I am going to stay in the atmel GCC/WinAVR for now, and move into something roomier(compiler) when knowledge and money both come together....which will be a long time :)

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

To C or not to C, that's the question. :-)

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

Yes, and at the moment I want to C the usart doing stuff! ;)

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:

In some respects C is certainly easier to use than ASM, but for things like printing messages at the moment C-SUCKS.

Quote:
Just looking to send out a string(Hello World) to the PC when I press a button...nothing fancy

EDIT#1:
THis is confusing. PRINTF, SPRINTF...I dunno, In ASM I keep my message 'Hello World' in program memory and load the message via the Z register and LPM

Doing this in 'C' is not so simple or am I missing something as usual?


Quote:

I do it in ASM with a few lines of assembler.

Quote:

All I am looking to do is put together my own library of code chunks

1) First, describe what "few" means to you.
2) Next, consider that there is some magic in the few lines that you posted. Upon entry to the ASM you posted, Z is pointing to the string.
3) The "library of code chunks" has been done for many common operations in C. It is called the "standard library".
4) (or maybe 3a) ) What can trip one up, or cause confusion, is that there needs to be separate treatment for the different storage spaces in an AVR. Your Hello, world! could be in SRAM, EEPROM, or flash. Note that your "few lines of ASM" also needs to take that into account.
5) There are some assumptions in your ASM "output" routine--that you are using USART0 on some AVR model, in polled mode. Again, on an AVR there may be multiple USARTs, you might be operating interrupt-driven, there might be flow control involved, and etc.
5a) You have integrated two pieces--the string output and the character output. They will be separate below...
5b) You really put delays in there?!? :twisted:

6) Generic/standard C has two routines already defined: putchar() and puts() for the string. Now, these go to the "standard output stream". Depending on your toolchain, there are different ways to tell the compiler to use USART0 of your AVR. Let's assume there is some magic as in CodeVision that assumes USART0 in polled mode. The entire thing then becomes "puts("Hello world!");". Or maybe

unsigned char my_string[] = "Hello world!";\
...
    puts(my_string);

7) And/or, the toolchain allows you to do your own putchar(). The straight-forward polled version looks just like your code--"blocking".

void putchar (char c)
{
  while ((UCSR0A & (1<<UDRE0)) == 0) ; // ,== empty statement
  UDR0 = c;
}

All told, just "few" lines. There will be toolchain options to adjust for e.g. USART1. The point is that one size won't fit all--just as with your ASM fragment.

8) puts() then becomes what Kartman posted

void puts(char *msg)
{
    while (*msg)    //while what Z points to is non-zero do..
      {
      putchar(*msg++); //grab the char, z+
      }
}

8a) But you want a flash string. OK, then you do what CodeVision does...

Quote:
void putsf(char flash *str)

outputs, using putchar, the null terminated character string str, located in FLASH, followed by a new line character.

You may or may not want the newline insertion. So you create your own primitives. You see that it is fewerlines than your ASM example.

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

bobgardner wrote:
How about trying the imagecraft compiler and see if its gets you going faster? I still have a hard time dealing with gcc progmem. But I'm an obstinate old coot.
Why don't you use __flash then?

avrfreaks does not support Opera. Profile inactive.

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

So I could just add one of my programs to a project in as6 and edit the includes and the interrupt handlers and I'm golden? I'll have to try it.

Imagecraft compiler user

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

Lee,
Thank you for that explanation. I will sit tonight and work that out and see how I do.

I am aware of teh Standard Library and have been looking at it. My Z register is pointing at the string in Flash as my code tells Z where it is located. In comparisons to some of the code I have looked at for the usart what I posted to send out a message string is a few lines.

Quote:
5b) You really put delays in there?!?

:lol: That code is not communicating to a PC but to another system that needs a 45us delay to do it's thing before the next charachter comes in.

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:

I am aware of teh Standard Library and have been looking at it.

Just to note that in some C compilers an assumption is made that your puts()/putchar/printf() wil want to use UART(0) by default so they are already wired up that way and to use them all you need to do is iniitialise the UART to the right baud rate and framing and then you can just use puts()/printf() to your heart's content.

GCC makes no such default assumption. The output of puts()/printf() is sent to a "file stream" called stdout but there's nothing then connecting that stream to a physical device such as a UART or an LCD. That's your job.

An example in the user manual shows how this is done:

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

but that maybe complicates things a bit by using both an LCD and a UART at the same time. The simplest program that allows you to just use printf() and have it output to the UART would be:

#include 
#include 

int	uart_putchar(char c, FILE *stream);
void	uart_init(void);

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

int main(void) {
  // configure UART for 2400 on 1MHz
  uart_init();
  // connect uart_putchar to the stdout stream
  stdout = &uart_str;

  printf("Oh my God it works\n");

  puts("this works to\n");

  putchar('a'); putchar('n'); putchar('d');
  putchar(' ');
  putchar('t'); putchar('h'); putchar('i'); putchar('s');

  // printf can then do fancy stuff like
  printf("pi = %f, char = %c, int = %d", 3.1415926, 'A', -12345);

  while(1);
}

void uart_init(void) {
  // simplest UARt setup possible just enables transmit
  UCSRB = (1 << TXEN);
  // and sets some baud rate value
  UBRR = 25; // 2400 baud on 1MHz
}

int uart_putchar(char c, FILE *stream) {
  // wait to send
  while(!(UCSRA & (1 << UDRE)));
  // then do it
  UDR = c;

  // 0 says the character transmission worked
  return 0;
}

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

Was perusing some old PC stuff and ran across this advertisement from Microsoft in a Dec 1990 issue of PC Magazine.

Jim, this ad seems like it was tailor-made for you. ;) :)

Attachment(s): 

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

Is that the Source Safe?

Imagecraft compiler user

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

bobgardner wrote:
Is that the Source Safe?
This is Microsoft we're talking about here, so their idea of "safe source" would look a lot more like this: :lol:

Attachment(s): 

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

Meteor: When the hell do you have time to search old magazines to find that! I love it. Going to print an 8 x 10 and put it over my primary pc as an inspiration piece. :)
Well I have Assembler under control, so now it's a matter of the A,B,......errr

@ Cliff

Quote:
int uart_putchar(char c, FILE *stream);
Going to have to do my homework and figure out the FILE *stream thingie
Quote:
FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
Another homework assignment
Quote:
stdout = &uart_str;
I think this will be answered when I figure out quote 2.

Yes, this works and I understand it as well to some degree, I also stumbled upon the article you posted as well earlier so I will add that to my evenings read.

Thanks! Some progress

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

jgmdesign wrote:
I love it. Going to print an 8 x 10 and put it over my primary pc as an inspiration piece. :)
Glad to be a source of inspiration, however minor and/or frivolous. :)
jgmdesign wrote:
When the hell do you have time to search old magazines to find that!
I was (finally!) cleaning up some very old (back to 1986 :shock:) articles I'd saved on PC video (CGA, EGA, VGA, etc) and ran across that ad on the backside of one. I immediately thought of you. Be either flattered or offended -- your choice. ;) :)

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

Quote:

Going to have to do my homework and figure out the FILE *stream thingie

Well here's the thing. Once again, like that UART_putstring() implementation with all it's *str++ nonsense this file stream stuff is a real black art - pretty advanced stuff for a beginner so for the time being do NOT try to understand how it works. Just take the code as a template then feel free to use printf() and friends inside you main() function and don't concern yourself (for the time being) with how it's actually working as you'll get bogged down in that and not learn the simple bits of C which having printf() working should make a lot easier.

If you have it working I guess you already spotted that the UBRR= value needed adapting to whatever F_CPU and desired baud you use.

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

I am confused.

Surely everyone has a requirement to "print a character" to some device. Whether you use ASM, C, Basic, ... you still have the same need.

So you look up the documentation for CALL, putchar(), PRINT, ... and see both the syntax and examples.

You don't debate the traffic rules every time you drive your car. You just drive on the left side of the road. (or whichever is customary in your country)

I can fully understand people having problems with the semantics of a computer language. However if you understand ASM you should understand variables, parameters, addresses etc.

Many C or Basic programs can be written with the simplest construction. You progress from Blinky to Hello World to Flight Simulator.

Oh, at some stage you may want to look under the hood. Or perhaps you don't. You can still drive the car or write a working program.

David.

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

Well, suppose OP is very good at atmel's assembly (and AVR) -I noticed it-. He is entitled to find C/ Basic very strange (even if things work, and an optimiser can make things often smaller/faster than what an ordinary man could do with assembly : having things already working is not very stimulating).

There is a thing which is often forgotten with C : as it is highly portable, parts of an AVR program (say, dealing with date arithmetics/ conversions/ general purpose algorithms) can be easily tested ... on a PC (most of the people have such things, to try to program their AVRs, say).

And, if one wants to change, pieces of code can be ported to ARMs , and one "just" has to concentrate on ones new hardware specificities.

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

It can be simpler. C has been around since the 70s and its workings are well known and standardized. On a computer with a file system, printf generates calls to putchar which output to a file, usually stdout, usually the console. On a micro with no file system, it sort of makes sense to have printf call putchar, which has a default to write to uart0, but it could also write to an lcd etc. Imagecraft provides a default putchar, but once you have a putchar that writes a char to where you want it to go, you just call printf and everything is cool. I have a 'fancy' putchar that writes to one of the four uarts on a mega1280 based on a global variable that I put a 0,1,2 or 3 in. Just call printf, and it calls putchar. Too simple.

Imagecraft compiler user

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

Yes. And an ASM programmer is used to the concept of passing parameters to a subroutine. And that subroutine passing other parameters to an output subroutine.

I just accept that my PC will be eventually writing bits to my LCD screen. No doubt I could disassemble the BIOS or write my own operating system, but I might be dead before I ever get there.

Of course an AVR application is a lot simpler. Not only can you read the complete ASM code, you may even understand the individual gates inside the Silicon.

I find it easier to read library documentation and follow instructions. I might have a specific interest in one tiny component, and drill down to a 'lower level'.

Think about it. Common tasks like 'output character' have been perfected since the beginning of time. Just use the prior knowledge. Gain experience and confidence with the new language first. Broaden your knowledge at a later stage.

David.

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

Quote:

Yes. And an ASM programmer is used to the concept of passing parameters to a subroutine. And that subroutine passing other parameters to an output subroutine.

In my experience (mainly from posts here) the C concepts Asm programmers do have a problem with when trying to migrate are variable types and stack frames. I know the Asm programmer already had a "foo: .dw 12345" and might have treated it as either 0..65535 or -32768..+32767 but they didn't call this "unsigned int "or "signed int" but just knew what range the held value would represent without a type. As for stack frames and automatics - that simply doesn't have an equivalent in the Asm world. A called function either used some number of the 32 registers for its "locals" or they farmed them out to named locations in SRAM. The idea of dropping the stack and pointing an index register at its base and indexing off that for variables is an "odd" concept. (it's also, on the whole, what mainly makes it tricky to disassemble C code).

Oh and type promotion. If an Asm programmer wants a 24bit value passed to a function he picks 3 registers to hold it. The idea of the value first being padded out to 4 registers (especially if "signed") and then passed is an anathema.

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

I am trying to post a new reply to this and when I include code and quotes I get PAGE NOT FOUND??

Edit:
I had to look up "ANATHEMA". Cliff I assume the dictionary term of LOATHING/DESPISE is what you were driving at and not the English band from Liverpool bearing the same name? :)

AS my header states I can not post code or quotes else I get the HTTP ERROR:400 Page not found

I got Cliffs usart code running. When I inserted it into my code the compile was successful, but the build notes that the code takes up 2300+ bytes of space with CODE+DATA+BOOTLOADER. I never asked for a bootloader.

Now if I comment out the part where pi, and a few other tidbits are printed I get CODE+DATA+BOOTLOADER equals 746 bytes which is still high, but not unreasonable. Whats with the BOOTLOADER?

Can anyone explain this while I go over the assembler code?

Thanks

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Quote:

CODE+DATA+BOOTLOADER. I never asked for a bootloader.

No, it's saying that if you had put something into .bootloader it would be added into that figure (but usually it's 0).

If FP is causing that much bloat make sure you link with libm.a (I'm about to eat my kebab so I'll leave others to explain more if necessary).

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

Looked at my makefile and see this:

MATH_LIB = -lm

From this post:
https://www.avrfreaks.net/index.p...

references to it.

So does this mean that I am in fact looking at libm.a?

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

OK as long as it is being used. Obviously there is a cost for using float but if you stick to just +-*/ then (with libm.a) it generally only "costs" about 700 bytes. If you start using library functions like sin()/cos()/tan() then the cost goes up and could be several K.

Unless you are generating sound waves or something I'm guessing an embedded engineer probably doesn't need to use much more than +-*/ in floats and as an interesting thread the other day showed you can usually replace that with integer ratios anyway.

Of course if you have a "big micro" the few K that things like float or printf/scanf support cost probably don't matter in the great scheme of things. 1-2K here or there matters little in 64K or 128K but perhaps is a little more important in 2K-4K micros!

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

The compiler organizes code and data in segments. For historical reasons (from Unix) the "ordinary" code segment is called "text". The data, global variables', is in the segments "bss" (for variables that are not explicitly initialized by you in the code, and thus initialized to zero by the compiler) and "data" (for global variables that are explicitly initialized by you in the code).

The contents of the latter has to be kept somewhere so that it can be loaded into RAM when execution starts, and for AVRs this somewhere is in flash. Thus the initialization values will have a flash cost also.

To report the total flash consumption the tool chain thus has to sum the code segment ("text"), the "data" segment, and also any code segment for bootloader code. The text "CODE + DATA + BOOTLOADER" is used at all times, even if there is no bootloader.

For more on data segments see the Wikipedia article on "Data_segment".

HTH!

I have stopped referring to other threads here at AVRfreaks, or to any external web pages, by actually giving the URL. I refuse to fill in a stupidly dysfunctional CAPTCHA when referring to threads here at AVRfreaks, or to absolutely legitimate sites such as Wikipedia, Savannah etc. It should not take someone at Atmel long to fix this, but the writing on the wall is that their web department is also dysfunctional.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

"I have stopped referring to other threads here at AVRfreaks, or to any external web pages, by actually giving the URL. I refuse to fill in a stupidly dysfunctional CAPTCHA when referring to threads here at AVRfreaks, or to absolutely legitimate sites such as Wikipedia, Savannah etc. It should not take someone at Atmel long to fix this, but the writing on the wall is that their web department is also dysfunctional. "

It is one of the least stupidly dysfunctional CAPTCHAs I could see (try posting here http://rroms.blogspot.fr/ without getting crazy : on AVRfreaks, there remains a little tiny hope) ... Things might be WORSE....
(do they detect locked caps?)

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

Unfortunately I have been banned from putting quotes, and code into replies, bothe NEW REPLY and quick reply so I cannot post what is confusing me as to why the printf statement that has pi, a charachter, and a negative number takes up so much space in CODE that the Tiny is over its limit, but if I take the line out then I only use 700bytes

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

The % (percent sign) is known to cause problems here.

The easiest workaround is to add a space after each percent sign. The usual suspects will understand why your format strings look like that (e.g. "% d").

If your pi is a float and that is the only float you use, that could account for the code size increase as libraries to handle floats will be included.

Sid

Life... is a state of mind

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

Post an attached image with a screenshot showing the line in question.

Note:

1) that floating point math has two potential "costs". One is about 700 bytes to get +-*/ and another is >1K to also get trig and other floating point functions.

2) printf actually has three costs. There is a "min" version that can only print simple formats including integers but not floats. It only costs a few hundred bytes. There is a "normal" version that costs about 1K or more that can do pretty much every format EXCEPT %f for float. Then there is a "float" version that costs the most and can do pretty much everything including floats.

I imagine your code is trying to use libprintf_flt.a and a minmum of +-*/ from the fp lib for a total cost of a bit over 2K?

As I said previously this "heavy stuff" (printf and also float) don't matter one jot in a 16/32/64/128K micro but you'll really feel the squeeze in a 1/2/4K micro. Only use them when appropriate (the right chip and the right requirement that really needs them). Often in a 1/2/4K micro you can give the appearance of float support (say a 0..1023 ADC reading shown on an LCD as 0.00V..5.00V) using scaled integer at the cost of only a few hundred bytes.

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

This built for mega16:

#include 
#include 
#include 

char buff[20];

int main(void) {
	sprintf(buff, "2pi = %f", 2 * M_PI);
}
	Program Memory Usage 	:	2096 bytes   1.5 % Full

But it just prints ?" in place of %f

Using libprintf_min.a:

	Program Memory Usage 	:	1744 bytes   1.3 % Full

this too just prints ?.

Finally with libprintf_flt.a:

	Program Memory Usage 	:	3646 bytes   2.6 % Full

and the output is:

2pi = 6.283185

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

Cliff,
The code snippet is what you posted in the third page of this thread.
https://www.avrfreaks.net/index.p...

About half way down. THe PRINTF statement with the pi, the charachter and the negative number.

I'll try to post a screenshot in the morning if you don't see it

Thanks

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

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

Ah you mean:

  printf("pi = %f, char = %c, int = %d", 3.1415926, 'A', -12345); 

Well that's almost identical to the examples I quoted above (where I realised afterwards that the build target was set to xmega128a1 so the sizes are a bit bloated because of the huge interrupt table)

If you want %f support it requires the big printf library (libprintf_flt.a) and that is going to cost about 3K.

As I keep saying - this doesn't matter in a >=16K chip but does in a <=4K chip. So just accept the fact that you aren't going be able to use floats and print them in small AVRs. Either use a big chip in which case you don't care or come up with a solution that does not involve using and printing floats.

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

Quote:

So just accept the fact that you aren't going be able to use floats and print them in small AVRs. Either use a big chip in which case you don't care or come up with a solution that does not involve using and printing floats.

Well, there are more options. We found recently that integer and FP "scaling" have about the same cost:
https://www.avrfreaks.net/index.p...
This is in line with what I've found in the past: If you need to e.g. convert A/D counts to arbitrary [pressure or whatever] units, a single FP multiply has about the same cost as an elaborate integer scaling.

Now, on to the output: No-one says that (s)printf is the only way to convert this FP value to a displayable string. ftoa() comes to mind as a straightforward approach. (Remember that we've been through this exhaustively with integers and long integers and printf family and itoa/ltoa and homegrown solutions.) With my toochain, ftoa() costs 878 bytes and big (s)printf() costs 2183 bytes.

In my past work I referred to, the destination was 7-seg displays. So I indeed wanted BCD and an implied decimal point. I found a posted project here on 'Freaks that broke up a FP number into the pieces useful for such a display. I don't remember the cost but it was less than printf or ftoa. If I had to guess, perhaps half?

I guess I'm just telling my experience. I use very little FP in my apps. "Normal" work starts with small integer numbers such as A/D counts or timer counts. Given 8/10/16 bit inputs there is no need to calculate e.g PID values to 5 decimal places.

Thus, it is very ironic that where I >>have<< used FP is on Mega48 apps, resource constrained, where I found that it was efficient and straightforward. But remember, that was >>a single FP multiply<<, and perhaps the to/from FP routines. Throw in + and - and / and a different ballgame.

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

meteor wrote:
bobgardner wrote:
Is that the Source Safe?
This is Microsoft we're talking about here, so their idea of "safe source" would look a lot more like this: :lol:
'Tain't orange, but I have one of those safes.

Moderation in all things. -- ancient proverb