Won me over to the dark side

Go To Last Post
64 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey Freaks,

For almost a year, I have been learning about AVRs. Because I already use Visual Basic, I chose to program in the simple BASCOM-AVR language. It has all the features you could want.

But EVERYONE has been hassling he to learn C or ASM, and I want to control an old Nokia screen with an AVR. It seems all the really advanced projects are C based. So i've now installed WinAVR.

I'm going to need a lot of help from you guys to get started and get my first project underway. First off, how do I define the use of an 90S8535, set the stack correctly and make a LED on PD3 flash? I think it's best to start simple.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Well if you have the right hardware, www.avrbeginners.net has some C examples.

I'd suggest that google i syour best friend, dump in "AVR example gcc code" or something similar.

Also before you have a C related problem search these forums, lots of ppl previously hae usually had the same problem.

I intend to post a few really really basic examples on my website soon.

Oh and finally, it is totally different to Bascom - at first don't expect to just find a command to help you out with a problem like you can in Bascom - the solution may involve getting someone else's code hacking a bit, changing a few #defines at least and then dealing with all the compiler errors. Sometimes it mught just be easy as and you just link to someone elses code.

Don't forget to search the academy section too.

The biggest thing to remember is that at first you most probably will not be able to do the really simple stuff without lots of effort. Don't set your expectations too high at first. Once you know what your doing it will all "happen" a lot faster.

Don't forget to download the Procyon AVRLib aswell - it is gold!

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

Hmmmm, i've bit the bullet, but now it's gone off in my mouth.

I just read the free version of SmileyMicro's doco, and tried to follow his instructions to the letter (a first for me, I like to learn by myself). I copied his "blinky" example:

// blinky.c

#include 
#include 

int main(void)
{
	ddrd = 0xFF

	while(1){
		for(int i=1;i<=128;i=i*2) {
			PORTD=i;
			_delay_loop_2(30000)
		}

		for(int i=128;i>1;i=i*2) {
			PORTD=i;
			_delay_loop_2(30000)
		}

	}
	
	return 1;
}

And, stragely, I understand everything. In many ways, all languages are similar. But I digress...

The part I have difficulty with is the "makefile". I just downloaded the latest version, against the doco's reccomendations, and there seems to be a difference in this file. The doco reffers to \WinAVR\Samples\MakeFile, but there is only the folder "\WinAVR\Examples". No biggie, but the makefile isn't there. I found a makefile in on of the Examples\ subdirectories, as follows:

PRG            = blinky.c
MCU_TARGET     = at90s8535
OPTIMIZE       = -O2

DEFS           =
LIBS           =

# You should not have to change anything below here.

CC             = avr-gcc

# Override is only needed by avr-lib build system.

override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS)
override LDFLAGS       = -Wl,-Map,$(PRG).map

OBJCOPY        = avr-objcopy
OBJDUMP        = avr-objdump

all: $(PRG).elf lst text eeprom

$(PRG).elf: $(OBJ)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)

clean:
	rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak 
	rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)

lst:  $(PRG).lst

%.lst: %.elf
	$(OBJDUMP) -h -S $< > $@

# Rules for building the .text rom images

text: hex bin srec

hex:  $(PRG).hex
bin:  $(PRG).bin
srec: $(PRG).srec

%.hex: %.elf
	$(OBJCOPY) -j .text -j .data -O ihex $< $@

%.srec: %.elf
	$(OBJCOPY) -j .text -j .data -O srec $< $@

%.bin: %.elf
	$(OBJCOPY) -j .text -j .data -O binary $< $@

# Rules for building the .eeprom rom images

eeprom: ehex ebin esrec

ehex:  $(PRG)_eeprom.hex
ebin:  $(PRG)_eeprom.bin
esrec: $(PRG)_eeprom.srec

%_eeprom.hex: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@

%_eeprom.srec: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@

%_eeprom.bin: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@

# Every thing below here is used by avr-libc's build system and can be ignored
# by the casual user.

FIG2DEV                 = fig2dev
EXTRA_CLEAN_FILES       = *.hex *.bin *.srec

dox: eps png pdf

eps: $(PRG).eps
png: $(PRG).png
pdf: $(PRG).pdf

%.eps: %.fig
	$(FIG2DEV) -L eps $< $@

%.pdf: %.fig
	$(FIG2DEV) -L pdf $< $@

%.png: %.fig
	$(FIG2DEV) -L png $< $@

-- Note that i've changed the target to an 8535, and told it to use blinky.c (in the same directory). I pressed "Make All", and the following appears:

> "make.exe" all
avr-gcc -g -Wall -O2 -mmcu=at90s8535  -Wl,-Map,blinky.c.map -o blinky.c.elf  
C:/PROGRA~1/WINAVR/BIN/../lib/gcc/avr/3.4.1/../../../../avr/lib/crts8535.o(.init9+0x0): undefined reference to `main'
make.exe: *** [blinky.c.elf] Error 1

> Process Exit Code: 2
> "make.exe" extcoff
make.exe: *** No rule to make target `extcoff'.  Stop.

> Process Exit Code: 2

Any ideas? Also, sorry for the misuse of the "code" function...

- Dean :twisted: (15 year old Auzzie with a deflated ego)

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

1. To get over the Makefile hurdle, use the MFile utility that comes with WinAVR. I would suggest not re-using Makefiles found in the \examples directory. Also read up a little in the Make User Manual, in general I recommend the first 5 chapters. Everything after that is pretty advanced and IMO not as necessary for a Makefile for an AVR project.

2. Don't forget to read the WinAVR README file. There's some good info in there.

3. I'll be dead honest: Learning to program in C is definitely harder to do on an embedded system, than learning the language on a PC. You'll definitely want to get a good C book/reference/tutorial, one that can explain well some of the finer points of the language, such as pointers. Subscribe to the comp.lang.c newsgroup, read the posts, and ask general language questions there. I would recommend to practice writing C on PCs first.

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

AVRbeginners.net I think just recently started at least 1 C code example (great site for learning basic AVR architecture and assembly language) I'd recommend learning at least a little assembly before diving into C, it will help you understand what you're doing in C much better even if you have no intention of writeing assembly code. Even in C most of the low end I/O handling routines are pretty much based on the assembly code.

-Curiosity may have killed the cat
-But that's why they have nine lives

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

I had to go offline for a few hours, which forced me to resolve the issue on my own. It all works now! (inset warm fuzzy feeling here).

Now, after only an hour or so since installing it i'm off writing my own code. The syntax is very similar to BASIC - at least, I can adapt my knowlege to it - and it offers more flexibility.

Heres what I just wrote:

#include 	// Include I/O and Register adresses
#include  // Include delay routines

#include "tlcd.c" // Include the Display Routines (Downloaded off the internet)

int main(void) {
	tlcd_init(); // Initialise the display
	tlcd_cls(); // Clear the display
	
	tlcd_write_string("Hello World!"); // Write "Hello World" to the display
	
	int z; // Used in the FOR loop - I assume define here to prevent the variable from
	// being reset to 0 everytime, although not nessesary in this situation
	
	for(int i=1;i<=128;i=i*2) { // Shift through PORTB, illuminating LEDs
		z = 255-i;
		PORTB = (i && z); // AND the variables together and whack them into the PORTB register
		
		_delay_loop_2(30000); // Wait a bit
	}
	
	return 1;
}

It uses a LCD library I just downloded from the Academy section. I have absolutly no idea as to whether it will actually work - but at least it compiles OK!

I wanted PORTB's LEDs to flash on in sequence, starting from outer 2 LEDs, then the inner LEDs, etc. Would the code I wrote achieve that? I must say, my greatest pet hate at the moment is HEX. I cand stand it - I prefer binary and decimal. I know you can use binary in C, but can you use:

    Assembler Commands
    Arrays
    Matrixes

I REALLY want matrixes as BASIC does not offer this functionality, and it's crucial to what I want to do (non-linear regression). Seems like the world of C will be interesting; there's no going back to BASIC fo me....

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I've just started a collection of really really simple examples of C with AVR. Hopefully giving newbies the basic building blocks.

I also have an explaination of the simplest way to use makefiles just to get them to work for you.

It is all here
http://www.users.on.net/~symes/C...

Not a lot yet but it will grow steadily

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

Few remarks about the C style only:

Declarations of variables not immediately after an opening brace (your
`i' and `z') variables are a C99 feature not yet very commonly used.
Just keep that in mind, it'll make your code less portable as many
other compilers probably don't support C99 by now. (Strictly spoken,
// comments are a C99 feature as well, also adopted from C++, but
there are certainly much more compilers implementing it. Plain C
comments look /* like this */.)

Also, declaring the loop control variable of a for loop inside the for
statement itself offers yet another pitfall: the scope of the variable
declared that way has been changed in the C++ standard over years, so
it's always hard to remember what it is actually right now. I believe
it once used to extend to the end of the current block (i. e. to the
next closing brace even beyond the for loop), while the current
standard restricts the scope to the statement controlled by the for
loop itself (which is usually a curly-braced block by itself). As it
is often needed to access the loop control variable even after the
loop has ended (e.g. to verify whether the for loop had been
terminated prematurely), declaring the variable inside the for
statement would make this impossible. (I believe the C99 standard
adopted the current C++ scope, but I would have to verify that
assumption in the standard.)

Just keep in mind that

i = i * 2

can be expressed as well like

i = i << 1

Actually, the compiler's optimization is supposed to detect the
constant multiplication, and reduce it to the (much cheaper) bit shift
operation. Note that most C programmers probably write the above in
its short form

i *= 2

or

i <<= 1

which is exactly the same. Just get used to the notion, as it is
something you could not write that way in BASIC.

Also note that the `z' variable will be optimized away, so don't ever
expect it to be displayed correctly within a debugger (unless you turn
off optimization, which I would not recommend).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

This won't do what you want:

     PORTB = (i && z); // AND the variables together and whack them into the PORTB

The result of '&&' is either 0 or 1 (in this case always 1). From your
description, I suspect you want:

     PORTB = ~i; // Turn on one LED according to mask i
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mckenney wrote:
This won't do what you want:

     PORTB = (i && z); // AND the variables together and whack them into the PORTB

The result of '&&' is either 0 or 1 (in this case always 1). From your
description, I suspect you want:

     PORTB = ~i; // Turn on one LED according to mask i

Oh, ick.

Dean, be sure to read this thread:
https://www.avrfreaks.net/phpBB2/viewtopic.php?t=8764&highlight=programming+101
Go to the with the post that starts with "Programming 101" (highlighted). It will show how to manipulate bits in C.

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

In the example I used:

for(int i = 1; i <= 128; i = i*2)

I didn’t use either i *= 2 or i <<= 1 because I believe that neither of these constructs would make sense to a novice programmer. I explain both in detail later in the C book. I’ve already had a bit of a go round with someone over the teaching style I use in the book. Some folks want to introduce everything all at once, which in addition to being impossible, is confusing. I try to make things as simple as possible early on and get to the details gradually. The statement ‘i = i * 2’ looks like ordinary grammar school algebra, the ‘i *=2’ looks weird, and the ‘i <<= 1’ looks Martian. Neither the Quick Start Guide nor the C book are for people who know C programming. Though the Guide might help a C programmer get up to speed on using WinAVR with the Butterfly.

Also, Dean got the Blinky program wrong, in the second loop, its actually:

#include 

int main (void)
{	
   // set PORTD for output
   DDRD = 0xFF;

   while(1) {

      for(int i = 1; i <= 128; i = i*2)
      {
          PORTD = i;
          _delay_loop_2(30000);
      }	
			
      for(int i = 128; i > 1; i -= i/2)
      {
          PORTD = i;
         _delay_loop_2(30000);
      }	
   }	
   return 1;
}

And you might notice that I didn’t follow my own ideas about simplicity in the second for loop where I have ‘i -= i/2’ which is bad and I will change it. Having a division that can be done by a binary shift in a for loop is dumb, but won’t hurt in a beginning example.

And all feedback is appreciated since the Quick Start Guide is likely to be used by a lot of novices the more feedback I get the fewer questions we’ll have to answer on the forum.

Thanks,

Joe

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

smileymicros wrote:
I try to make things as simple as possible early on and get to the details gradually. The statement ‘i = i * 2’ looks like ordinary grammar school algebra, the ‘i *=2’ looks weird, and the ‘i <<= 1’ looks Martian.

There are two almost vastly different concepts here: learning the C language, and how to use the C language on embedded systems.

When one learns the C language, one should learn all parts of it including the meaning of all of these statements:

i = i * 2;
i *= 2;
i <<= 1;

I don't care how "weird" they look, they are all part of the language, and are valid statements to achieve the same thing. Yes, it is getting into the advanced parts of the language as to the subtle differences between each of those statements, and why one would want to use one statement over the others.

The big problem is what type of audience are you writing for? If you are teaching C language, then you should do it outside of the embedded area; The embedded world is not necessarily a nice place for C language beginners because there are usually so many "advanced" topics that are used daily. If you are teaching how to get started in microcontrollers (using C), then a certain basic understanding of C language would almost have to be a prerequisite. Otherwise you're tutoring your audience in C and you're going to lose the audience that already knows C and just wants to learn microcontroller stuff. Like all engineering, it's a tradeoff.

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

(Insert jaw dropping/confuzed expression here). Whoa? C99? I just want it to compile and work!

If not straight after the brace, where and how do I declare a variable? I understand all the i *= 2, etc. commands - these will DEFINETLY make life easier - but you've stumped me with the i << 1. What does this do, and how does it do it? I assume the << is a incremental binary shift (thus multiplying the number by 2 via binary), but I could be wrong.

Also, what's the purpose of the ~? As in "PORTB = ~i;"? The irritating part of C is all the *&*&^ semicolons. I see how and where they are used, but they are a pain nonetheless. Still, that's just the joys of C, i guess.

Smileymicros, sorry for getting your code wrong! Just goes to show how tired one can get after minimal sleep. Still, your free manual rocks!

Finally, what is _delay_loop_2? I know it's part of the Library, but why is it called #2? And is it ms delay? If it is, it would logically suggest that _delay_loop_1 would be seconds wait, and _delay_loop_3 is us wait.

EDIT: How do you use lookup tables and binary in C? And also:

Outp(0xFF, DDRB);

Wouldn't DDRB = 0xFF; make more sense?

EDIT2: By the way, smileymicros, I think your blinky example has an extra "}" at the end of the code on your free doco, but I may be wrong.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

abcminiuser wrote:
(Insert jaw dropping/confuzed expression here). Whoa? C99? I just want it to compile and work!

It refers to the C standard. First, there was K&R C, then C89 which was the C standard that was set in 1989. C99 is the latest version of the standard that was set in 1999. The lastest standard added a few new things. I'm sure you can search Google to find out more info as this is beyond the scope of this forum. If I've gotten anything wrong above, I'm sure somebody (probably, Joerg) will correct me.

abcminiuser wrote:

If not straight after the brace, where and how do I declare a variable?

After the brace is what the C89 standard says. With C99, you can declare a variable anywhere, but it only has scope within the block (pair of braces) that it was declared in. This can make things easier to do. GCC will allow this.

abcminiuser wrote:

I understand all the i *= 2, etc. commands - these will DEFINETLY make life easier - but you've stumped me with the i << 1. What does this do, and how does it do it? I assume the << is a incremental binary shift (thus multiplying the number by 2 via binary), but I could be wrong.

Also, what's the purpose of the ~? As in "PORTB = ~i;"? The irritating part of C is all the *&*&^ semicolons. I see how and where they are used, but they are a pain nonetheless. Still, that's just the joys of C, i guess.

Dean, go read my post above, about going to another thread that has "Programming 101".

abcminiuser wrote:

Finally, what is _delay_loop_2? I know it's part of the Library, but why is it called #2? And is it ms delay? If it is, it would logically suggest that _delay_loop_1 would be seconds wait, and _delay_loop_3 is us wait.

1. Go read the avr-libc user manual.
2. Remember that everything in C language is case-sensitive. So it is not , it is . The .h in there is important.

abcminiuser wrote:

EDIT: How do you use lookup tables and binary in C? And also:

1. Binary or bit fiddling is covered in the thread I gave you in my earlier post.
2. Lookup tables are done via arrays and pointers. Again, this is beyond the scope of this forum. Go visit a good C book, or comp.lang.c newsgroup.

abcminiuser wrote:

Outp(0xFF, DDRB);

Wouldn't DDRB = 0xFF; make more sense?

Absoultely! The outp() macro is deprecate and should not be used. The direct access method (such as DDRB = 0xFF) is preferred.

And again, C language is case-sensitive, so it is not Outp(), it is outp().

Eric

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

Ok, Ok, I surrender. I'll read the thread and go play with GCC for a while. I'm trying to write a keypad scan routine, and almost finished. I don't really care about the standards (at this stage) as I just want the thing to compile and work, not look pretty.

Small stepts first, I suppose.

- Dean :evil:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

abcminiuser wrote:
Ok, Ok, I surrender. I'll read the thread and go play with GCC for a while. I'm trying to write a keypad scan routine, and almost finished. I don't really care about the standards (at this stage) as I just want the thing to compile and work, not look pretty.

*sigh* :roll:

The stuff with the standard has nothing to do with "looking pretty", it has to do with what you are allowed to do with the language.

The thread I gave you answers your questions about working with bits in a byte.

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

EW: I really appreciate the comments; this is helping me get some insight into how good programmers think about learning C. But, I disagree with a couple of points.

EW wrote:
The big problem is what type of audience are you writing for? If you are teaching C language, then you should do it outside of the embedded area;

First, is the embedded world the right place to learn C, or should it be learned elsewhere? Of course C was written by Dennis Ritchie using a Teletype machine on a PDP-8 (or 11?). It provided a very practical solution to some problems concerning getting data into and out of computers efficiently. C continued to be useful in the DOS world and even into Windows where it bogged down. The Windows API was written in C became a bloated beast and nobody knows how to use it correctly anymore. It is a monster. So along comes C++ and Microsoft’s cockamamie MFC and that programming style. So that helped a little but didn’t fix the growing problem so out with it and now they are pushing C# and Visual Basic and recommending that you don’t look at the man behind the curtain. C is dead in windows (that would get me flamed on some forums) and there is no reason to learn it except as a base for C++ or C# and confusion reigns. So where is C actually used today? Microcontrollers. IMHO, the embedded arena IS the appropriate place to learn C. (I don’t know diddly about Linux so forgive me if C is still useful there).

EW wrote:
The embedded world is not necessarily a nice place for C language beginners because there are usually so many "advanced" topics that are used daily.

I think the embedded world is exactly the right place for a C Language beginner because they can have fun with it. Light up some LEDs, spin a disk, measure its speed, play a crappy tune on an annoying piezo speaker… I love this kind of stuff and I assume that most beginners will still have their ‘sense of wonder’ intact and not destroyed yet by sitting through too many engineering meetings.

Maybe I should rethink the title. This book is not for people who already know C. It is intended to progressively introduce the topics, have a little fun, and learn enough to go on to the advance topics on your own. I really don’t think anyone who is dealing with “advanced’ topics on a daily basis would give this book a second look. Why would they?

EW wrote:
If you were teaching how to get started in microcontrollers (using C), then a certain basic understanding of C language would almost have to be a prerequisite. Otherwise you're tutoring your audience in C and you're going to lose the audience that already knows C and just wants to learn microcontroller stuff. Like all engineering, it's a tradeoff.

My intent is exactly that: ‘tutoring your audience in C’, I never really expected to get an audience that already knows C. If you already know C, then get the data books and have at it. I’ve even recommended against the book in one thread for someone who knows C. Your comments are very similar to some others that I have gotten from experienced C programmers, so I’m going to have to give this some serious thought.

Dean: Yes there is an extra brace in there. Good catch. I’ve read this thing a bunch of times and am still finding defects. It’s a little embarrassing, but I’ve read a load of technical books and find defects in them all (except K&R). I could spend another couple of months editing or just do like Microsoft does and sell it while its still really a beta and let my customers yell at me, revealing the defects that I can then fix and release again charging them again. Hey, sounds like a plan!

Thanks for all feedback good and bad,
Joe

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

dl8dtl wrote:

Also, declaring the loop control variable of a for loop inside the for
statement itself offers yet another pitfall: the scope of the variable
declared that way has been changed in the C++ standard over years, so
it's always hard to remember what it is actually right now. I believe
it once used to extend to the end of the current block (i. e. to the
next closing brace even beyond the for loop), while the current
standard restricts the scope to the statement controlled by the for
loop itself (which is usually a curly-braced block by itself). As it
is often needed to access the loop control variable even after the
loop has ended (e.g. to verify whether the for loop had been
terminated prematurely), declaring the variable inside the for
statement would make this impossible. (I believe the C99 standard
adopted the current C++ scope, but I would have to verify that
assumption in the standard.)

That is not really correct!

In standard ISO/ANSI C++ the scope has always been limited to the loop itself!
Only in "pre ISO/ANSI" version of the C++ language it may have been different.

The big problem is that many compilers used to have *very* broken implementations of C++, like for example MSVC 6.0 did. Partly because the compiler implementation dates back to per ISO/ANSI days, partly because some companies simply choos to ignore existing international standards and continued to sell broken products.

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

I get your point(s). I'm trying to adhere to the new coding standards. At the moment, i'm trying to replicate my PLD2 project from BASIC into the new (for me) C language. I've started to write the main functions, and wrote my own keypad scanning routine. In case anyone's interested, i've posted what i've done below.

Don't expect me to post the completed code later though - my employer won't like it!

By the way, how do I set up a lookup table or text array for my menu function names? And also, can the C language use matrixes?

I simply LOVE the power of C!! I can't believe I didn't like it! The flexibility is amazing, and it seems to make much smaller programs the the BASIC equivelents.

Once again, thanks to all. And if anyone spots the millions of bugs in my code, please say so.

- Dean :twisted:

Attachment(s): 

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

... And i'm aware that _delay_loop_2 is NOT milliseconds, and _delay_loop_1 is NOT seconds, I just have to work out how to do this.

I'm not going to ask, as I just read a thread of you guys toasting a newbe asking the same question :o .

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Quote:
Don't expect me to post the completed code later though - my employer won't like it!

You should maybe explain to your employer that the kind people at AVRFreaks have given you almost endless assiistance and guidance in your endeavours.

Four legs good, two legs bad, three legs stable.

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

Well, i'm sure they wont know - and it wont matter anyway. Any code I write is protected by international copyright law - except, it seems, in china - so I can post with assurance that no-one will steal the code and make a rival product.

C is fun!

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

smileymicros wrote:
Of course C was written by Dennis Ritchie using a Teletype machine on a PDP-8 (or 11?). It provided a very practical solution to some problems concerning getting data into and out of computers efficiently....

Kernighan and Ritchie in "The C programming language", first edition, page ix wrote:
C was originally designed for and implemented on the UNIX operating system on the DEC PDP-11, by Dennis Ritchie.

C was first developed as a systems programming language to rewrite UNIX.

(The comma is there in the 16th printing - would that count as an error in K&R?)

- John

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

Joe, I much appreciate your effort with the book (and it really looks
good from what I've read so far!), but I also agree with Eric that if
possible at all, learning C on a microcontroller is taking it the hard
way. It's about as hard as it used to be on MS-DOS years before, with
no memory protection, no seat belts, and on the microcontroller, with
much poorer debugging support than on a larger host processor.

This is completely irrespective of the fact that the MS-Win world
might have moved away from plain C. The issue wasn't about learning C
*for* the host operating system, but learning it *on* a host running
an operating system (with memory protection!), as it makes your life
quite a bit easier. (Btw. there's a world outside Microsoft-land,
where C is still used a lot.)

Sure, there are differences between C on a typical host OS, and C on a
microcontroller -- as can easily be seen when looking at all the
questions about what these << >> & ~ | ^ operators might do: you're
rarely using bit manipulation for programs under an operating system
(only for the OS'es device drivers, but they are about as hard to
maintain and debug as C on a microcontroller.

This doesn't mean it's impossible to learn C directly on the micro.
It's only quite a bit harder.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

smileymicros wrote:

First, is the embedded world the right place to learn C, or should it be learned elsewhere? Of course C was written by Dennis Ritchie using a Teletype machine on a PDP-8 (or 11?). It provided a very practical solution to some problems concerning getting data into and out of computers efficiently. C continued to be useful in the DOS world and even into Windows where it bogged down. The Windows API was written in C became a bloated beast and nobody knows how to use it correctly anymore. It is a monster. So along comes C++ and Microsoft’s cockamamie MFC and that programming style. So that helped a little but didn’t fix the growing problem so out with it and now they are pushing C# and Visual Basic and recommending that you don’t look at the man behind the curtain. C is dead in windows (that would get me flamed on some forums) and there is no reason to learn it except as a base for C++ or C# and confusion reigns. So where is C actually used today? Microcontrollers. IMHO, the embedded arena IS the appropriate place to learn C. (I don’t know diddly about Linux so forgive me if C is still useful there).

As was said earlier C was created to help write the Unix OS which has been around for a lot longer than Micro$oft's crud. C is still extensively used in Unix-like OSes, which includes but not limited to: FreeBSD, OpenBSD, NetBSD, Linux, QNX, Mac OS X, etc. (I'm sure others can add to this list....)

smileymicros wrote:

Maybe I should rethink the title. This book is not for people who already know C. It is intended to progressively introduce the topics, have a little fun, and learn enough to go on to the advance topics on your own. I really don’t think anyone who is dealing with “advanced’ topics on a daily basis would give this book a second look. Why would they?

My intent is exactly that: ‘tutoring your audience in C’, I never really expected to get an audience that already knows C. If you already know C, then get the data books and have at it. I’ve even recommended against the book in one thread for someone who knows C. Your comments are very similar to some others that I have gotten from experienced C programmers, so I’m going to have to give this some serious thought.

And that's perfectly fine if the book is not for people who already know C. :) As long as it's clear who the target audience is for the book.

And as long as you're aware that sometimes it's easier to teach the basics of the language on a full-blown PC with OS, just so other aspects of the hardware don't get in the way of learning the language. For example, it's much easier learning how pointers work when you can quickly build and run your software on a PC to get immediate feedback. The whole subject of pointers seems to be tricky to new students.

Eric

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

jfiresto wrote:
(The comma is there in the 16th printing - would that count as an error in K&R?)

K&R is the perfect word of C handed down to us mere mortals. Any apparent errors are just our poor inability to understand the ineffable mystery of C almighty. Have care lest yea fall into sin by questioning this infallible Book.

dl8dtl wrote:
Joe, I much appreciate your effort with the book (and it really looks
good from what I've read so far!), but I also agree with Eric that if
possible at all, learning C on a microcontroller is taking it the hard
way. It's about as hard as it used to be on MS-DOS years before, with
no memory protection, no seat belts, and on the microcontroller, with
much poorer debugging support than on a larger host processor.

I certainly appreciate the kind remark about the book looking good so far.

Like I said in my response to Eric, I’ve got some serious thinking to do. But I’m tending to disagree with both of you. I hate to age myself, but I learned C on a DOS machine and I could fill a novel with my coding war stories, but the overall theme would be that I had a blast torturing that poor machine and making it do surprising things.

What would be a better way for people to learn C? Especially considering that the Butterfly is $19 and the C compiler is free (thanks to the labor of many generous folks like you and Eric).

dl8dtl wrote:
(Btw. there's a world outside Microsoft-land,
where C is still used a lot.)

Linux? Someday…

dl8dtl wrote:

This doesn't mean it's impossible to learn C directly on the micro.
It's only quite a bit harder.

EW wrote:
And as long as you're aware that sometimes it's easier to teach the basics of the language on a full-blown PC with OS, just so other aspects of the hardware don't get in the way of learning the language. For example, it's much easier learning how pointers work when you can quickly build and run your software on a PC to get immediate feedback. The whole subject of pointers seems to be tricky to new students.

Maybe I’m a dreamer. I see someone using muscle wire, balsa wood, and tissue paper to make a Butterfly fly. Some people get excited about microcontrollers. When I mentioned a ‘sense of wonder’ earlier, I was talking about the childlike awe that we feel when we actually get a LED to blink for the first time. Did you see the enthusiasm in Dean’s comments? Maybe he would be better off following a formal curriculum that begins as one thread suggested with an exposition on the AVR architecture followed by a treatise on assembly language and then a catechism on the formal aspects of using C with microcontrollers. But I suspect that by the time he did get an LED to blink that he would have a glazed look in his eyes and instead of experiencing the joy of learning he’d just be thankful that the darn thing lit up so the Procter wouldn’t smack him with a righteous rod.

I do get carried away don’t I? But, like I said, I am seriously rethinking some things. There has got to be compromise in this somewhere.

Can you guys suggest an appropriate platform for learning C that is cheap and doesn’t have a mind numbing learning curve just to get to one’s first ‘Hello, World!” program?

Thanks all,

Joe

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

I think Joe has a good point (some way back in this thread). I can see the value of starting out with
i = i+ 1;
and later graduating onto
i += 1;
after all, any halfway decent compiler is going to generate the same code. Same with multiplication by powers of two and left shifts, as far as I know.
My code abounds with redundant brackets because I'm too stupid to remember all the operator precedences (is that the right word?), but I assume they only serve to make my source code bloatier, and have no effect on the binary. Wasn't there a discussion some time ago about the merits of the[/b]? operator? Surely readabilty counts for something.
Anyway, Dean, wait till you start using pointers, and pointers to pointers, and pointers to functions returning pointers.... That's when the fun starts.

Four legs good, two legs bad, three legs stable.

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

John_A_Brown wrote:

My code abounds with redundant brackets because I'm too stupid to remember all the operator precedences (is that the right word?), but I assume they only serve to make my source code bloatier, and have no effect on the binary.

You are not stupid. It is stupid to remember the operator precedence. We have better things to do with our brain cells. I my book I say:

In my book I wrote:

Precedence, Order of Evaluation, and Associativity
When a statement has a sequence of operators such as:

x = 50 + 10 / 2 - 20 * 4;

The compiler follows an order of calculation based on operator precedence (Table 7). But what the compiler does, may not be what you intended. Calculate the value of x. Did you get 40? If you performed the calculations sequentially as listed you get:

x = 50 + 10 / 2 - 20 * 4
x = 60 / 2 - 20 * 4
x = 30 - 20 * 4
x = 10 * 4
x = 40

So the answer is 40, right? Wrong, according to C it is -25. The compiler does the division and multiplication first, then the addition and subtraction:

x = 50 + 10 / 2 - 20 * 4
x = 50 + 10 / 2 - 80
x = 50 + 5 - 80
x = 55 - 80
x = -25

Some C gurus will memorize the precedence and associatively table and actually write statements like x = 50 + 10 / 2 - 20 * 4. Such clever programmers are dangerous and should be killed immediately. The Germans have a word for clever: kluge, and in programming kluge’ is a well-deserved insult. Don’t be clever be clear. Clever programming is difficult to read and understand. If the clever programmer gets run over by a truck (hopefully) his code will be inherited by some poor guy who will have to figure things out. DO NOT memorize the Table of Operator Precedence and Associatively in C. DO use ’( and )’ to make your program clear!

Which is clearer:

x = 50 + 10 / 2 - 20 * 4;
	or
x = 50 + (10 / 2) - (20 * 4);?

The second adds nothing for the compiler, but tells the reader what was intended. But what if you really meant to have the operations performed in the order listed? Then you would write:

x = ((((50 + 10) / 2) - 20) * 4);

Which would make x = 40. The parentheses can get mighty confusing, but not nearly as confusing as their absence.

I would like to emphasize the rant paragraph especially the kludge’ and kill immediately’ parts.

John_A_Brown wrote:

Anyway, Dean, wait till you start using pointers, and pointers to pointers, and pointers to functions returning pointers.... That's when the fun starts.

I was fortunate (?) to learn programming in assembly, so pointers weren’t that hard for me. Pointers are a pain for the novice to learn, but once you get the swing of them they seem perfectly reasonable. I too get confused when I see things like array pointers to arrays of pointers to pointers to structures to ad nauseum. There are many reasons for such things: they can be stylistic peculiarities of a given programmer, attempts to assure job security, mean spirited gurus showing off, or because it is the most efficient way to do something. Often it is hard to tell. Usually when I finish wading through one of these chains I think either Damn that guy is smart’ or If I ever meet this guy I will kill him.’

Good Luck,
Joe

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

Well, operator precedence has been made `logical' to a certain degree.
Sorry, I really cannot follow your rant here: it's not an invention of
C to get multiplication/division a higher precedence than addition/
subtraction, but it's a basic rule of mathematics to work that way
(which I cannot even remember when we've been taught it in school, it
must have been around age of 10 or so). So any programming language,
and even all the better pocket calculators implement it that way.

There are other operators which have a not so logical precedence rule,
and in that case, if you cannot remember, just add a pair of paren's.
C does many things a bit more logical than e. g. Pascal did, for
example you can safely do multiple logical comparisions without
paren's:

if (a < b && a >= c) { ... }

As soon as going into bit-wise operators (ya'know, all that hairy <<
>> ~ & | ^ stuff), do always parenthesize. Their order of precedence
is hard to remember. Also, when nesting && and || in logical
operations, set paren's. Virtually nobody can remember which of both
gets a higher precedence anyway. ;-)

As for pointers to complicated functions, well, it's a nice feature
once you got used to them. There's an opensource tool called `cdecl'
for those who do not fear to type a few words on a command-line:

$ cdecl
declare bar as pointer to function ( c as pointer to int ) returning pointer to char
char *(*bar)(int *c)
declare mumble as array of pointer to function ( cp as const pointer to char ) returning int
int (*mumble[])(char * const cp)
explain void *(*bar)(int, void *(*)(void *))
declare bar as pointer to function (int, pointer to function (pointer to void) returning pointer to void) returning pointer to void

(There's always one line of what I typed, followed by one line of
program's output.)

Isn't it nice? :-)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

Quote:
Isn't it nice? :-)

Yes, it is nice. IIRC one of the example programs in the original K&R did something similar, didn't it?

Four legs good, two legs bad, three legs stable.

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

One thing that Dean keeps asking that hasn't been answered yet is about matrices. The only way I've heard a matrix as it relates to programming is a dual indexed array.

Dean, you can do an array such as the following:

uint8_t my_matrix[10][20]

This would give you an array with basically 10 columns and 20 rows. You can also expand on that to do my_matrix[x][y][z].......

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

smileymicros, about the operator precedence

I agree using () is really a good thing, but being shot or run over is really rude.

If you know how things work, thats good! Use those brainy bits :)
Killing somebody for knowing how the precedence of the operators work is insane.

Just use () even if you know the right order of those operators.

Also a nice comment I once read was:

Quote:
If a program was really hard to write, then...
it should be really hard to read.

That will ofcourse cause some problems if you work in a team :)

MY MICROCONTROLLER CAN BEAT THE HELL OUT OF YOUR MICROCONTROLLER /ATMEL

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

That cdecl program is great!

I also wanted to point out the sticky at the Top of the AVRForum, which is all about C Programming books.

IMHO if you really want to learn C there is no way to do it without at least one book. I'm sure you can make a program compile without a book, but a general C book is required to really learn it.

In addition to that I would recommend the ANSI C standard for when you run across stuff not in your C book, and also the 'Code Complete' book. The 'Code Complete' is a general programming book - but it you do not have a formal introduction to programming (or maybe if you do, I don't know because I didn't) it is worth its weight in gold.

The Code Complete book contains is all about program readibility. Commenting, using obscure parts of the language, etc. Very handy, I found it made my C code a lot easier to understand!

Regards,

-Colin

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

dl8dtl wrote:

Isn't it nice? :-)

Oh, I wasn't aware of this program. That is nice!

Luckily I'm one of those people who can do that stuff off the top of my head, so I haven't ever needed such a thing.... But's it is good to know that it is out there.

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

dl8dtl wrote:
Well, operator precedence has been made `logical' to a certain degree.
Sorry, I really cannot follow your rant here: it's not an invention of
C to get multiplication/division a higher precedence than addition/
subtraction, but it's a basic rule of mathematics to work that way
(which I cannot even remember when we've been taught it in school, it
must have been around age of 10 or so).

Probably a result of my primary school education in a third world country (Tennessee).

dl8dtl wrote:

As soon as going into bit-wise operators (ya'know, all that hairy <<
>> ~ & | ^ stuff), do always parenthesize. Their order of precedence
is hard to remember. Also, when nesting && and || in logical
operations, set paren's. Virtually nobody can remember which of both
gets a higher precedence anyway. ;-)

I agree and extend it to say use the parens for ALL precedence, you never know when someone as dumb as me will have to maintain your code.

dl8dtl wrote:

As for pointers to complicated functions, well, it's a nice feature
once you got used to them. There's an opensource tool called `cdecl'

Isn't it nice? :-)

Now that is cool. I may have to move on over to Linux just to get cdecl. Well there goes another year or two.

MaxK wrote:

Killing somebody for knowing how the precedence of the operators work is insane.

And your point is…?

MaxK wrote:

Also a nice comment I once read was:
Quote:
If a program was really hard to write, then...
it should be really hard to read.


I’d make a comment here but it might risk a flame war, so I’ll just admit to being insane and as such I am probably having more fun than some folks.

Oh, well, I’ll make one comment:
Smiley Rule #1: No program properly written should be hard to read.
And a corollary:
Smiley Rule #1 Corollary #1: Be very suspicious of programs that are hard to read. Either somebody doesn’t know how to clearly express themselves in code, or they are trying to put something over on you.

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

OK, I am a hardware design engineer and I have many years experinece writing code for PCs and microcontrollers. I have followed after many other programmers both good and bad, and downloaded many bits of sample code. I have mainly focused on Micorchips PIC series microcontrollers for embedded applications, but have heard so much good stuff about the Atmel AVR chips, that I thught it time to give them a try. So I went to a free Atmel semenar and got a free JTAGICE for my trouble (sweet deal). They convinced me that the GCC AVR compiler was really nice and the it integrated nicely with their IDE. So after a series of downloads I have all of the goodies at hand. AVR Studio is nice and so is WinAVR. In trying to work out the integration of WinAVR into AVR Studio, I found myself here on this forum. Now, I usually avoid forums because I invariably get sucked into some discussion where I have a strong opinion. It has happened again. Several of Joe's posts sparked my fuel, but the rant below and the subsequent post by dl8dtl that finally drew a flame.

Quote:
Some C gurus will memorize the precedence and associatively table and actually write statements like x = 50 + 10 / 2 - 20 * 4. Such clever programmers are dangerous and should be killed immediately. The Germans have a word for clever: kluge, and in programming kluge’ is a well-deserved insult. Don’t be clever be clear. Clever programming is difficult to read and understand. If the clever programmer gets run over by a truck (hopefully) his code will be inherited by some poor guy who will have to figure things out. DO NOT memorize the Table of Operator Precedence and Associatively in C. DO use ’( and )’ to make your program clear!

[ soap box]
[ flame]
I could not agree more strongly with Joe. Computers, whether it a full blown system with OS, bios, APIs and memory protection or a simple microcontroller, execute instructions (opcodes) that are encoded as a series of ones and zeros that represent various instructions or "opcodes". The processor core is nothing more than a FANCY state machine. People, however, do not follow ones and zeros well. We can do it but it's hard and time consuming. So at the lowest level we give the various opcodes text names that people can understand. We use an assembler to convert that text to the 1-0 code understood by the CPU. Still, we have decided that speaking the native language of the CPU, even in a more people friendly form, is hard and different for each CPU so we have created "high level languages" with many advantages such as machine independance, loops, conditionals, structures, etc. A few examples are various flavors of C, Pasacl, Basic, ... the list goes on.

Finally to the meat of my rant: High level languages are designed to make it easier for PEOPLE to communicate their intent to the processor and to OTHER PEOPLE. Those who choose to be clever are wasting everyone's time and energy. All clever programmers should be killed immediately.

Quote:
Don’t be clever be clear.

AMEN to that brother! That's the whole point of source code in any form other than ones and zeros. Use a few extra () and a few extra {} and a little white space. It all results in the same binary image. Unless you are writing a book or magazine article where white space costs money, spread it out a little. Don't try to cram it all on one line, make it readable, the compiler does not care.

While it is absolutely correct that order of operations is defined by the general rules of mathematics and is completely unrelated to whether or not some programming language decides to implement it, it is none the less much more clear to just put the () in and to make your intent BLATANTLY obvious. It just costs a few keystrokes and has no bearing on the final image, just the clarity of the source code.

[ /flame]
[ /soap box]

--Steve

Life is sweet in Sugar Land.

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

sbates wrote:

I could not agree more strongly with Joe.

Hey, thanks!

sbates wrote:

All clever programmers should be killed immediately.

I notice that you also are from the southern part of the United States. I wonder if has something to do with the climate here?

Smiley Rule #2: Don’t be clever be clear.

I'm starting to like this rule thing.

sbates wrote:

AMEN to that brother!

Careful, we Americans are already scaring the world too much.

Thanks,
Joe

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

(point (is? (the (if (too (many (parens)))) you (end up) with
(something (like (lisp))))))

Doesn't make reading really easier, does it? ;-)

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

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

dl8dtl wrote:
(point (is? (the (if (too (many (parens)))) you (end up) with
(something (like (lisp))))))

Aaaahhhh the horror!

Great, just when I though t I didn't need therapy anymore after studying lisp in school. You just HAD to remind me didn't you? ;)

Though I have to admit, your statement makes no sense after placing order of precedence on it:

"lisp like something end up parens many too if the you with is? point"

:P

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

I think differences can be made in source code.

1 bad written program which is hard to read.
2 good written program, which is hard to read.
3 good written program which is really easy to read, but requires uneseary extra instructions or code steps.

type 1, everybody hates,, drag that type of code into the bin!

The 2nd type often requires a few scratches and then finaly a:
"DUH I knew that! "

The 3rd type often comes from not knowing sure if the operations are being performed like you think they will, so adding a extra temp variable just to make sure it will work.
Thats ok in my opion. Just time critical parts might suffer.

MY MICROCONTROLLER CAN BEAT THE HELL OUT OF YOUR MICROCONTROLLER /ATMEL

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

Hmmm, seems i'm sparking off an internal religious war. Still, adds to the exitement. C is very good, but VERY frustrating. Cool about the dual arrays, though.

Ok, I've followed SmileyMicro's suggestion of using an array of pointers to my menu function names.

//MAIN.H

// Main Include Section
#include 
#include 

// Module Include Section
#include 
#include 

// Variables
int MenuLoc;
int TempInt;

// Arrays & Constants
const char MenuFunc1[] = "Dispense";
const char MenuFunc2[] = "Manual Control";
const char MenuFunc3[] = "Add Liquid";

const char *MenuFuncNames[] = {MenuFunc1, MenuFunc2, MenuFunc3};

// Function Declare
void MainMenu (void);
void ManualControl (void);
//MAIN.C

/*
============================================
===============TECHNICHEM PLD2==============
  Programmable Volumetric Liquid Dispenser
    (Hardware Version 2, Code Version 2)
============================================
 (C) Dean Camera, 2004. All rights reserved.

 No part of this code may be used, modified
 or copied without prior permission from the
 copyright holder, unless indicated.
============================================
  Designed to be executed on an AT90S8535.
============================================

Uses LCD routines written by Knut Baardsen. 
 
*/

#include  // Main header file

int main(void) {
  InitDisplay(); // Initialise the display and clear it
  tlcd_goto(1,4); // Set LCD location to (1,1)
  tlcd_write_string("Technichem"); // Write intro screen
  tlcd_goto(2,7); // Set LCD location to (2,7)
  tlcd_write_string("PLD2"); // Write bottom half of intro screen
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  _delay_loop_2(30000); // Wait for ~1/8 of a second
  
  MenuLoc++; // Set the MenuLoc variable to 1 (increment it)
  
  MainMenu(); // Run the Main Menu routine
}

void MainMenu(void) {
	tlcd_cls(); // Clear the LCD screen
	tlcd_goto(1,1); // Set the LCD location to (1,1)
	tlcd_write_string("Select  Function"); // Write top half of screen
	tlcd_goto(2,15); // Set LCD location to (2,15)
	tlcd_write_string("<>"); // Write the <> indicators to the far right
	tlcd_goto(2,1);	// Set the LCD location to (2,1)

	tlcd_write_string(MenuFuncNames[MenuLoc]); // Write the seperated string to the LCD

	while(1) { // Eternal loop
		_delay_loop_2(30000); // Wait for 60000 cycles
		TempInt = GetKPD(); // Run keypad scanning routine
		
		if (TempInt==15) { // Key 15 = "<" key
			MenuLoc--; // Decrease MenuLoc variable
			if (MenuLoc==0) {MenuLoc=4;} // Wrap MenuLoc variable
		}

		if (TempInt==16) { // Key 16 = ">" key
			MenuLoc++; // Increment MenuLoc variable
			if (MenuLoc==5) {MenuLoc=1;} // Wrap MenuLoc variable
		}		
	}
}

void ManualControl(void) {
	tlcd_cls(); // Clear the LCD
	tlcd_goto(1,1); // Set the LCD location to (1,1)
	tlcd_write_string(" Manual Control"); // Write the top half of the LCD
	tlcd_goto(2,2); // Set the LCD location to (2,2)
	tlcd_write_string("A B C D E F"); // Write pump channel letters to the LCD

	WriteLCD:

	TempInt = 0; // Reset TempInt variable
	for(int i=2;i<=9;i=i+2) { // Loop to write the pump on/off indicators to the LCD
		tlcd_goto(2,i); // Set the LCD location to the i variable (set by loop)
		if ((PORTC & (1 << TempInt)) != 0) {tlcd_write_byte(DATA,0xFF);} else {tlcd_write_byte(DATA,0xF4);}
		TempInt++; // Increment the TempInt variable      ^- Write on or off indicator, depending on corresponding
	} 			   //                                         Port C bit (pump channel A = Port C bit 0)
	
	while(1) { // Eternal loop
		_delay_loop_2(30000); // Wait for 60000 cycles
		TempInt = GetKPD(); // Run the keypad scanning routine
		
		if (TempInt==5) {MainMenu();} // Key 5 = Stop/Cancel - return to Main Menu function

		if ((TempInt<=7) && (TempInt!=0)) { // Key 1-6 pressed (1 = Channel A, etc.)
			PORTB = PORTB | ~(PORTB << TempInt); // Invert Port C bit
			goto WriteLCD; // Skip back to the start of the function to refresh the LCD
		}		
	}
}

When I compile, I get the message "main.c:50: warning: passing arg 1 of `tlcd_write_string' discards qualifiers from pointer target type". What does this mean? I should be passing a pointer to a string the the LCD routine, which is what the pointer array does, right?

Also, how the *&%*( hell do I invert a single port bit, but ignore the rest? I've been mucking with my code for over an hour, but so far can only invert a single bit if I set all other bits to 0 at the same time.

A little help? I'm hoping my mistakes arn't TOO bad...

- Dean

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

sbates wrote:

Several of Joe's posts sparked my fuel, but the rant below and the subsequent post by dl8dtl that finally drew a flame.

[ soap box]
[ flame]
I could not agree more strongly with Joe. Computers, whether it a full blown system with OS, bios, APIs and memory protection or a simple microcontroller, execute instructions (opcodes) that are encoded as a series of ones and zeros that represent various instructions or "opcodes". The processor core is nothing more than a FANCY state machine. People, however, do not follow ones and zeros well. We can do it but it's hard and time consuming. So at the lowest level we give the various opcodes text names that people can understand. We use an assembler to convert that text to the 1-0 code understood by the CPU. Still, we have decided that speaking the native language of the CPU, even in a more people friendly form, is hard and different for each CPU so we have created "high level languages" with many advantages such as machine independance, loops, conditionals, structures, etc. A few examples are various flavors of C, Pasacl, Basic, ... the list goes on.

Thanks. This is first year CompSci... :roll:

sbates wrote:

Use a few extra () and a few extra {} and a little white space. It all results in the same binary image.

While it is absolutely correct that order of operations is defined by the general rules of mathematics and is completely unrelated to whether or not some programming language decides to implement it, it is none the less much more clear to just put the () in and to make your intent BLATANTLY obvious.

I don't understand why you got so upset. We are all saying the same thing here.

Joerg mentioned that, yes, the C language standard follows the mathematical convention when it comes to the math operators (mul, div, add, minus). He also said in the 2nd paragraph of that post that a person should feel free to add parens where it is ambiguous (to be defined by the author).

There's no need for a soapbox, rant, or flame. We all want to Keep It Simple, Stupid.

Now, on to more interesting things:

sbates wrote:

So I went to a free Atmel semenar and got a free JTAGICE for my trouble (sweet deal). They convinced me that the GCC AVR compiler was really nice and the it integrated nicely with their IDE. So after a series of downloads I have all of the goodies at hand. AVR Studio is nice and so is WinAVR. In trying to work out the integration of WinAVR into AVR Studio, I found myself here on this forum.

Oh, really? Which seminar did you go to? (Which town?) Who told you that AVR GCC / WinAVR would integrate nicely with their IDE? I'm assuming they meant AVR Studio.

Currently, AVR Studio 4, does not integrate with other 3rd party compilers (including WinAVR). Notice the bolded text.

I'm interetested in what you found out.....

Oh, and btw, Welcome to AVRs! :D

Eric

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

abcminiuser wrote:

Also, how the *&%*( hell do I invert a single port bit, but ignore the rest?

Good God! How many times do I have to tell you to go read this thread!:

https://www.avrfreaks.net/phpBB2/viewtopic.php?t=8764&highlight=programming+101

That thread tells you how to do all your bit-wise operations.

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

abcminiuser wrote:
Hmmm, seems i'm sparking off an internal religious war.

"It seems they were having a bit of a squabble."

"They're all dead!"

"Well, perhaps it was more of a tiff..."

- Yellowbeard (movie).

:)

abcminiuser wrote:

[code]
//MAIN.H

// Main Include Section
#include
#include

// Module Include Section
#include
#include

It's generally not a good idea to include .c files. #include is mainly used for .h files.

You'll want to compile your .c files seperately and then link them.

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

"Welcome to AVRs my foot." Over 1000 posts?! I've been here a year and only racked up a few hundred.

You all sound like my parents; "we must ensure he gets a proper education..." etc. Don't worry, my sense of wonder is still intact. I'm as stubborn as a mule, once I start I don't give up. Rest assured that getting a blinky LED will make me feel as fuzzy as when I did the same in BASCOM.

The bad thing about C is that it's really difficult to debug. AFAIK, you cant view the values of the different variables like BASCOM, nor can you see what's on the LCD. Before anyone comments, I know AVR Studio 4 + LCD plugin will allow you to do this, but on a 56k modem, a ~25meg download isn't exactly quick. I'll stick with AVRStudio 3 for now unless there's a compelling reason to leave my laptop downloading all month.

For the debate at hand: ()'s are good! I program on VB and my TI-83 Graphics Calculator, and I find it makes everything much easier to read when each "idea" is encompassed in ()'s. While having too many may be detrimental, a few more than nessesary won't hurt. It's not like they'll take up all your HD space!

BTW, I fully understand all the operators such as ++, --, =+, etc. as well as having a rudementary grasp of pointers. It's just a few things i'm having trouble with (like my problem above - any help?).

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I'm reading, I'm reading! I'm going to use the BitFlip macro:

bit_flip(foo, BIT(0));

Which works, and it makes everything a lot simpler. Anywho, how do I link the C files? Including 'em works fine, so why reinvent the wheel? DON'T go on about coding standards, I can't STAND these - if it works, then don't complain about it!

I still need help on the Array of Pointers question, though.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Oh, and I might as well ask - it's the best way to learn - how to define my own LCD characters in C. I've done this is BASIC, but my LCD library dosn't have this function, a forum search was fruitless and the datasheet that came with my LCD was useless.

Please; no abuse, and no shouting!

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

abcminiuser wrote:

Ok, I've followed SmileyMicro's suggestion of using an array of pointers to my menu function names.

I beg to differ; I would never suggest such a thing. The very idea!

abcminiuser wrote:

The bad thing about C is that it's really difficult to debug. AFAIK, you cant view the values of the different variables like BASCOM, nor can you see what's on the LCD. Before anyone comments, I know AVR Studio 4 + LCD plugin will allow you to do this, but on a 56k modem, a ~25meg download isn't exactly quick. I'll stick with AVRStudio 3 for now unless there's a compelling reason to leave my laptop downloading all month.

Dean, at the risk of mentioning THE BOOK that you have (and no I didn’t sell it to him), I’d suggest that you note that down in there somewhere you will find out how to communicate with the PC. This useful feature allows you to quickly compile test code, download it with AVR Studio 4, and then see the results on your PC in HyperTerminal. I do this all the time. By using known good code that will respond in a predictable way, I can add a little snippet of something and see what happens. I find this a very quick and cheap way to debug. If you don’t want to follow the book working the examples sequentially, the at least try out the ‘Is anybody out there? Communicating with a PC’ project and then further along in the book, the ‘messenger’ project.

Good Luck,
Joe

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

abcminiuser wrote:
Oh, and I might as well ask - it's the best way to learn - how to define my own LCD characters in C. I've done this is BASIC, but my LCD library dosn't have this function, a forum search was fruitless and the datasheet that came with my LCD was useless.

Okay, I'm seeing something now. You don't have a Butterfly and my advice is somewhat off target.

Sorry,
Joe

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

abcminiuser wrote:

// Arrays & Constants
const char MenuFunc1[] = "Dispense";
const char MenuFunc2[] = "Manual Control";
const char MenuFunc3[] = "Add Liquid";

const char *MenuFuncNames[] = {MenuFunc1, MenuFunc2, MenuFunc3};

While what you wrote is perfectly legal C. It is not likely going to do what you think it is.

By defining a const(ant), I'm assuming you're expecting it to exist in Flash. This will not be the case with the above code. The strings will still reside in RAM, but the compiler will complain if you write any code that tries to modify their value.

Note: The C standard does not lend it self well to different address spaces. Several workarounds are often implemented by the compielr designer when this functionality is required. MAkaing an allowance for the difference between Flash, and RAM on the AVR is one of these occasions.

Though I could be wrong, perhaps Eric can clarify a bit more. I believe you will want to use the FLASH modifier here, if you want the strings to be stored in the Flash. Though this will add other cmplexities to the rest of your code. (one of the many reasons that it's better to learn C on a conventional PC with an OS)

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Last Edited: Wed. Dec 8, 2004 - 02:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:

When I compile, I get the message "main.c:50: warning: passing arg 1 of `tlcd_write_string' discards qualifiers from pointer target type". What does this mean? I should be passing a pointer to a string the the LCD routine, which is what the pointer array does, right?

you defined your menu strings as 'const char' while the tlcd routine probably expects a 'char' hence the warning (see my previous post)

As for strings, they are jsut arrays of char in C. when you pass an array, you ARE passing a pointer to that array.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Pages

Topic locked