1276Views17Replies

Author Options:

AVRDUDE C programming and random - help Answered

I've tryed a few code samples but none are working. I use AVR dude and i've been doing #include but i cant get rand() with RAND_MAX to work, cuz i just get a expression error. code sample please!

Discussions

Hey um, I know you can do rand() to get a random 0 - max, but isnt there a easy way? like for my calc / lua its random(1,4); to get a random digit 1-4. Each time i've tryed rand() with RAND_MAX i never had it working :l gmoon? xD

Killa--get a good book on C. Even if it's not AVR specific....

RAND_MAX is a constant; it's there if you want to know the maximum possible result from rand(). Use the modulo operator (%), which is essentially the remainder from a division:
// variable defined at the start of the functionunsigned char randnum;randnum = rand() % 4;
...which will give you a random number in the 0-3 range. To get 1-4, just add one:
randnum = (rand() % 4) + 1;
If you want 4 unique random numbers, you'll have to keep track of the previous randoms....

I just bought the C language on amazon for like 20 dollars. Hope to read it soon

Thanks for all the help gmoon, But heres a little challange that will get me a step closer. I was told it's possible to have 2 pins on portB, run at different speeds, without effecting the other. But when you want PB1 to blink at the rate of 1/sec, and PB2 to blink at the rate of 5/sec.... it wont. instead they blink the same rate at like 6 blinks/sec. I was told theres something called "Mask" which allows ports to run at their own rate. How?

Sure, I don't mind, when I have the time ;).

I see what you're saying. For one thing, these blink functions are "blocking"--for the duration of the delay, they are "lost" inside the functions.

RE: masks--first of all, the blink() functions so far have been bit operations--individual bit operations do an "end run" around a the concept of a mask. If we had written:
PORTB = _BV(bit); 
instead of
PORTB &= ~_BV(bit); 
..then we'd have overwritten all the other bits in PORTB--we didn't do that, so we've been "self-masking," so to speak. Masks are usually applied either to eliminate certain bits or to include certain bits. Bit-wise logic doesn't need masks, but if you were converting computational results to bit fields, you would use a mask. You really should study this tutorial on bit-wise operations...

To get back to it, there's more than one way to do it--the more complex way is to use IRQs (interrupts.) But better to start simply.... Remove the delay from the functions, and implement blinkon() and blinkoff() functions, placing the delay outside of the function:
void blinkon(unsigned char bit){	PORTB &= ~_BV(bit);}void blinkoff(unsigned char bit){	PORTB |= _BV(bit);}// blink a single bit on PORTBvoid blink(unsigned char bit, unsigned int rate){	PORTB &= ~_BV(bit);  // turn on bit	delay_ms(rate);      // wait	PORTB |= _BV(bit);   // turn it off	delay_ms(rate);}
Now to blink PB4 long and PB2 short:
blinkon(PB4);  //turn on PB4blink(PB2);     // blink PB2 three timesblink(PB2);blink(PB2);blinkoff(PB4);  // turn off PB4blink(PB2);     // blink PB2 three timesblink(PB2);blink(PB2);
This is just one simple way of doing it. You can remove the internal function delays completely--do other processing and then a short delay between each blink, if you need other processing during the interim, also.

You can re-write blinkon() and blinkoff() to accept bit fields (masks) instead of individual bits.
void blinkon(unsigned char mask){	PORTB &= ~mask;	 // turn on multi bits}
...and send blinkon() a bit field instead:
blinkon(_BV(PB4) | _BV(PB2));
...which uses the OR operator to combine the two bits into a bit field, which is kinda like a mask.... You'd write a complementary blinkoff() function to also accept bit fields (the _BV() macro is one bit only.)

These functions aren't perfect--if you blink() a bit that was "turned on" by blinkon() previously, it will be be "turned off" inside blink().... To do that, you'd need a "state" variable for the port.

It should be mentioned, as it was in the previous thread, that these functions and bit operators are using negative logic--ON is low, and OFF is high.
Sorry, left the rate variable off of blink() in the example:

Now to blink PB4 long and PB2 short:
blinkon(PB4);  //turn on PB4blink(PB2, 200);     // blink PB2 three timesblink(PB2, 200);blink(PB2, 200);blinkoff(PB4);  // turn off PB4blink(PB2, 200);     // blink PB2 three timesblink(PB2, 200);blink(PB2, 200);

function blink(port,rate)
{
PORTB = port;
delay_ms(rate);
PORTB = 0x0;
delay_ms(rate)
}
int main(void)
{
blink(0x2,10);
}

What about doing stuff like that? that's one BIIIIIG thing i need for my microcontroller, else im stuck with 9 IF's statements D:

What about the info in this previous thread? If you have any specific questions about converting that code into the above example, please ask. Everything you're trying to achieve was already covered there....

Commenting on the snippet above:

--there is no "function" keyword in C
--you need to specify the type for each argument in a function (and a return value), like this function definition:

void blink(unsigned char port, unsigned int rate)
{
//do something here
}

port is an unsigned char (a byte), and rate is an unsigned integer. The function returns nothing (void type.)

You can also use the more modern syntax of uint8_t (unsigned 8bit integer) or uint16_t (unsigned 16bit) or int8_t (signed 8bit), etc. :

void blink(uint8_t port, uint16_t rate)
{
//do something here
}

As well as float, double, etc., and all the other standard C variable types--although don't use floating point math unless you absolutely must, it consumes too much memory.

To get you started, here are two blink functions (and the delay function). You must include at least:

#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h>

...or it won't work; you need the I/O constants for your AVR chip (which you set externally), to get the root delay function, and to set the clock constant for the delay function....

You have to initialize the ports, too--like the other thread.

void delay_ms(unsigned int ms)/* delay for a minimum of <ms> */{	// calibrated delay.	while(ms){		_delay_ms(0.96);		ms--;	}}// blink a single bit on PORTBvoid blink(unsigned char bit, unsigned int rate){	PORTB &= ~_BV(bit);  // turn on bit	delay_ms(rate);      // wait	PORTB |= _BV(bit);   // turn it off	delay_ms(rate);}// blink multiple bits on PORTBvoid blinkmulti(unsigned char val, unsigned int rate){	PORTB &= ~val;	 // turn on multi bits	delay_ms(rate);	 // wait	PORTB |= val;	 // turn it off	delay_ms(rate);}

The blink() function uses the bit number (seen the _BV() explanation below), so to blink the 4 bit, you input:

blink(PB4, 100);
or
blink(4, 100);

The last function lets you input a raw #, so more than one bit is changed....

Two points:


1) The macro _BV() is very important in avrgcc. All bit definitions in the .h files are in this format:

/* General Interrupt MaSK register */#define    INT1    7#define    INT0    6

These are NOT bit values but bit numbers. We know bits are numbered from 7 to 0.

So INT1 == the 7th bit. INT1 therefore equals %10000000, or 128, or 0x80 (depending you your base, binary, decimal or hex.)

_BV() converts those constants into the actual number, with a simple shift operation. When avrgcc compiles, it will optimize the shift away and substitute the correct bit value.

Unless you're doing something computationally with the bits you should use the predefined constants (like PB2, PB5, etc.) They've been provided to make it easy to move the code from one AVR to another...



2) Why write a ms_delay() function, when there's already a avrlibc function _ms_delay() (with an underscore to start)????

Well, you don't have to....But... To quote from the delay.h file:

The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.

In other words, if you use the library function the delay might suddenly be different, depending how high a value you plug in, and what the CPU speed is...If you only need small millisecond delays (in the mid-to-low hundreds), you can eliminate the wrapper and just use _delay_ms()...

It was originally "calibrated" to compensate for the inaccuracy of the internal clock, but I reuse it and don't bother to recalibrate--a crystal is better if you need precise timing.
0
None
gmoon

10 years ago

Not that it's a big deal....but AVRDUDE is the programmer software only (transfers the code to the AVR) and not the C compiler.

The compiler is avrgcc (technically it's a cross-compiler, since it's running on a different platform--i.e., not the AVR itself.) While "gcc" is the standard GNU c complier, it's GPL and part of every Linux system; in fact linux itself is compiled with gcc. The standard set of C libraries and functions for the AVR is avr libc, which is called "libc" in *nux (anyone see a pattern here?)

That's it for today's trivia lecture... ;P

One aspect of this is that you COULD be including the wrong "stdlib.h"; if your paths and such aren't set right, you could have gotten the unix/windows/cygwin version of instead of the avr version. (RAND_MAX on my linux system is 32bits instead of the 16bit value in the AVR version.)

Could be. Maybe Killa-X will tell us if your code snippet worked on his setup.

The error msgs in (avr)gcc are also hard to decipher if you're new to C--especially if there's more than one syntax error...


It could be as simple as:

#include <stdlib.h>
vs
#include stdlib.h

It's one of one of many "gotchas" for C beginners. The first example looks for the include file in the standard "include" path, while the second looks in the current path....

Oops. Should be: #include vs #include "stdlib.h" But you get the idea...

I don't know if this applies or not, but here's a batchfile I made to make avrdude easier (it's my first ever batch file that I made by myself so don't critisise... well, maybe constructive critisim, and don't make fun of my spelling!)

here's a link, if nobody downloads it within 10 days then it gets deleated. the link is near the bottom where the tiny red arrow is pointing

http://www.sendspace.com/file/ra9d8v

To use it:
First right click and hit edit (opn it up with notepad)
find and replace stk200 to your programmer (mines stk200, that's why it's like that)
put the bat file in the same directory as your C file.
go to the directoy using CMD
Type in upload programname
it's upload because that's the name of the batchfile
program name is the name of the C file (don't type in .hex afterwards)

example:
upload blink

oh, and I forgot, it's meant to make it so you don't have to type that long thing in everytime with the code for the avr press ctrl+C to exit the program, it's meant for a robot to program a bunch of avrs with the press of a button oever and over and over again (automatic programming)

oh, and last thing, when a long thing comes up with a bunch of different uController names, just type in the uController you are using, for example, attiny13

0
None
westfw

10 years ago

#include <stdlib.h>main(){    int i;    i = rand();}
This compiled fine with: /Applications/arduino-0010/hardware/tools/avr/bin/avr-gcc -I /Applications/arduino-0010/hardware/tools/avr/avr/include rand-example.c

rand() doesn't take an argument; RAND_MAX is just the max value that the function will return...