loading

AVRDUDE C programming and random - help

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!

sort by: active | newest | oldest
1-10 of 17Next »
Killa-X (author) 9 years ago
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
gmoon Killa-X9 years ago
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
Killa-X (author) 9 years ago
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?
gmoon Killa-X9 years ago
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.
gmoon gmoon9 years ago
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);
Killa-X (author) 9 years ago
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:
gmoon Killa-X9 years ago
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.
gmoon gmoon9 years ago
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.
gmoon9 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
1-10 of 17Next »