Some simple questions from a beginner

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

Hi eveyone.

I'm at a beginner at this AVR stuff, and I have some questions on really basic stuff. I would really appreciate your help. Anyway, here are some of my questions:

1) In some of the gcctest c files, I have noticed that there is SIGNAL(SIG_OVERFLOW0) function. I have no idea where this is called in the main function. I suspect sei() calls it. If this is so, what exactly does sei() do, and if not, where is SIGNAL(SIG_OVERFLOW0) called?

2) What is the difference between outb(), outp()? What function(s) do I need to use to get input through the switches (PIND)?

Thanks for you help! :)
Anita

admin's test signature
 

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

Hi

I'm a beginner too but

For your second question : outp is out port
and outb is out bit
(I think)

yann

admin's test signature
 

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

Hi Anita,

SIGNAL() is not really a function (a meta function?) but sets up an interrupt handler for the interrupt source in its argument in this case SIG_OVERFLOW0 which is Timer 0 overflow. An entry is made in the interrupt vector table for this interrupt pointing to this handler in your code. Also, the SIGNAL thingy sets up the code to save and restore the machine state by pushing a bunch of registers on the stack and restoring them at the end.

So this will never actually be "called" by your main program. There are some tricky issues about using C variables in SIGNAL code areas and such that you should research.

For the second question I won't answer it directly but point you to the AVR specific include files where you can read what these and lots of other functions do. Specifically look in

(gcc root directory)/avr/include/iomacros.h and for your specific processor you can see the register and port defines in (gcc root)/avr/include/io8515.h or whatever

Good Luck,

Chris Baron

admin's test signature
 

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

Hi Anita,

to get input from the switches I use

" inp(PIND); " or for specific bits " bit_is_clear(PIND, bit);" and " bit_is_set(PIND, bit); "

"sei(); ", is a function to set the interrupt enable bit. When this bit is set all the interrupts which have their specific enable bits set are carried out when that interrupt appears to happen.

Possible interrupts are timer overflows or external pins.

This works great if you want your main program to run and do things, without continuously checking specific external pins or timers. ( Because it's handled by the interrupts...)

Great help on this issue can be found in the docs on avrgcc on this site..

Regards,
Chris

Question to Chris Baron:
Do you mean variables have to be volatile? That's the only thing I can think of.?

admin's test signature
 

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

Thanks for all the help everyone!

Anita

admin's test signature
 

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

Uh-oh...sorry...I have yet another question.

I'm looking at the interrupt programming section of one of the online manuals. I've come across some code and need some help understanding it. Here it is.....

/*
Turn on leds with switch on PD3 (Int1)
Turn off leds with switch on PD2 (Int0)
10/00 Leitner Harald
*/
#include
#include
#include
SIGNAL (SIG_INTERRUPT0) /* PD2 */
{
outp(0xFF, PORTB); /* turn off leds */
}
SIGNAL (SIG_INTERRUPT1) /* PD3 */
{
outp(0x00, PORTB); /* turn on leds */
}
int main( void )
{
/* define PortB as Output (Leds) and PortD as Input (Switches) */
outp(0xFF, DDRB);
outp(0x00, DDRD);
/* enable interrupt Int0 and Int1 */
outp((1<<INT0)|(1<<INT1), GIMSK);
/* falling edge on Int0 or Int1 generates an interrupt */
outp((1<<ISC01)|(1<<ISC11), MCUCR);
sei();
for (;;){}
}

My question is......

Is there any way of choosing other switches other than PD2 for off and PD3 for on? I've tried changing some numbers in the code but, I still couldn't get it. I know it has something to do with the bit shifiting. Maybe I just know exactly what's going on with these two lines:

outp((1<<INT0)|(1<<INT1), GIMSK);

outp((1<<ISC01)|(1<<ISC11), MCUCR);

Could someone briefly explain what these two lines are doing? I've read the the code explanation in the manual, but I don't entirely understand it. Your help is greatly appreciated.

admin's test signature
 

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

I mean, I don't know what's going on with the two lines, in the last message. Forgot to put the "don't" in.............

admin's test signature
 

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

In the following Interrupt 0 uses Port D pin 2 (PD2)
SIGNAL (SIG_INTERRUPT0) /* PD2 */
{
outp(0xFF, PORTB); /* turn off leds */
}

In the following Interrupt 1 uses Port D pin 3 (PD3)
SIGNAL (SIG_INTERRUPT1) /* PD3 */
{
outp(0x00, PORTB); /* turn on leds */
}

So that is what we are stuck with.

Mike

admin's test signature
 

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

In answer to your quiery on the 2 code lines, they are in fact very similar so I will describe only one

outp((1<<INT0)|(1<<INT1), GIMSK);

This line is in fact composed of 4 individual instructions
I will deal with two together
1 << INT0
1<< INT1

In each case the 1 is a simple value (a binary 1) INT0 and INT1 also represent individual values and somewhere in a *.h file you will find
#define INT0 6 Note the numeric value here is an example
#define INT1 7 Also an example value
The above are generally known as macros.

The << is a standard way of saying shift left in C. So 1<<INT0 translates to 1<<6 i.e. shift 1, 6 places left = 0x40 and 1<<INT1 translates to shift 1, 7 places left = 0x80 or 128 decimal.
The inner part of the command now looks like this (0x40) | (0x80) the vertical bar between the two parts is the C convention for an inclusive OR. Thus the value becomes (0xC0).

Your command line now looks like this
outp(0x18, GIMSK) which as you may recognise is a standard output macro

You can probably guess that GIMSK also a #define (or more correctly macro) is a value which you will find in a *.h file. In this case It is the General Interrupt Mask register and by setting the two bits INT0 and INT1 you enable those interrupts.

I suggest you look in the io*.h file for your processor. For instance if you are using the 8535 look in io8535.h

Hope this helps

DaveB

PS If you haven't already got it. The bible for C programming is "The C Programming Language" By Brian W. Kernighan and Dennis M. Ritchie This is an extremely terse book but contains all you need to know about C.

admin's test signature
 

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

Hi DaveB.

I understand the code a bit more now, especially the bit shifting stuff. Thanks for the help! :) I still have another stupid question though. Is it possible to change the switches that are used to turn on and off the LEDs? I've looked at another similar program, and it uses the same 2 switches (ie, switches 2 and 3).

Sorry for all the stupid questions. My school hasn't taught me interrupt programming yet.

Anita

admin's test signature
 

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

INT0 and INT1 are tied in hardware to PD2 and PD3 - you can't change them and use the interrupt mechanism. You could set up a timer interrupt and poll other bits on a periodic basis. You could simply check those bits periodically in your main program.

You need to research the AVR data book and read about the internal architecture of the chips. Then many of your questions will be answered. There are specific I/O locations that do specific things. Many I/O pins have alternative functions (e.g. INT0 and INT1) that can be enabled or disabled. In order to enable interrupts, for example, there are specific bits in other I/O register that have to be set. Timers, USARTs, I/O direction, input capture functions, etc. all depend upon setting the correct magic bits in the correct I/IO register before they will work. Without understanding how this stuff is connected and knowing where to look when trying to set something up (e.g. knowing the manual) you will be lost.

To understand things like SIGNAL() and INTERRUPT(), inp(), outp() and sei(), etc. you need to search the various header files for their definitions and read them. This is the pain with GCC: the true documentation is the source!

I know what I am saying is a pain, but really, the AVR is very sweet architecture. Focus on getting one thing working, then add something. Very shortly you will be answering the questions instead of asking them!

admin's test signature
 

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

Anita,

I would suggest learning assembly first. It is much easier than C. There are only a few instructions, they all have the same general logical idea behind them, (there is no high level and low level and in between level, and weird things to know aobut etc) and when you write something, it typically works a lot sooner than the equivalent would in C. (debugging time.)

admin's test signature