Programming AVR in C (Help me!)

Hi! I've been trying to figure this out, and I can't seem to find the answer. I've seen it done in Assembler, so it is possible. I'm using ATiny2313's, if it makes a difference. I want to know how I can output a negative voltage through a pin. I'm trying to do some multiplexing. Thanks. I just started with AVR microcontrollers.

sort by: active | newest | oldest
1-10 of 15Next »
westfw10 years ago
In general, to have a pin output 5+, you put a "1" in the appropriate io port bit, and to output GND, you put a "0" in the appropriate bit. Exactly how you do this will depend some on the compiler and your environment. For example, Arduino wraps a function digitalWrite around it:
 digitalWrite(ledPin, HIGH);   // sets the LED on  delay(1000);                  // waits for a second  digitalWrite(ledPin, LOW);    // sets the LED off  delay(1000);                  // waits for a second
Internally, though, these resolve to sbi() and cbi() pseudo-functions that mimic the assembly language instructions of the same names. The other common method I've seen (in a PIC compiler; I don't know about AVRs) is to map the IO port into memory space, so you would do something like:
          porta.bit1 = 1;          portb.bit2 = 2;
Usually the arguments you use are going to be pre-defined in a .h file specific to the processor you are using.

Perhaps you are confused by comments like those in the arduino code I quoted, where it says that it's turning the LED off when it sets the bit to zero. That's only true because the other side of the LED is connected to GND as well, and having both sides at GND means off. To ACTUALLY turn off a pin so that it is outputting neither +5 or GND, you could set it to be an input.
westfw westfw10 years ago
(note that gmoon's advice is good even though it doesn't look like mine. He's setting the whole port register at once with an appropriate read/modify/write instruction and computer value, while the arduino sbi/cbi code is using the single bit set/clear instructions of the avr.)
gmoon westfw10 years ago
The sbi() and cbi() macros are still present in avrgcc (or avr-libc, actually), but they are depreciated. I'm not sure why, but probably has something to do with macro expansion (and problems that result.) They now recommend the more explicit logic. But you can still use the older macros, if you like. Just include "compat/deprected.h"
westfw gmoon10 years ago
In somewhat recent gcc, someone rewrote the pre-processor in a way that changed quite a lot about how macro expansion works (especially in conjunction with string catenation and other "fringe" macro featues.) This caused us all sorts of problems at work; I believe we patched in some of the old behavior. It's sorta amazing how much of a popularly used language can be left "undefined"...
gmoon westfw10 years ago
I suspect C macros are something the designers wish would be eliminated altogether (but they are useful), and existing ones replaced with functions.

RE: undefined--yeah, I was always taught that variables are in an 'undefined' state unless initialized. But avrgcc variables are always initially 0. Probably just a case of the initial RAM state always being zero. So right off, that's not ANSI (and not portable.)

But in a wider sense, that's different in every target, so it's a way of keeping C thinner (no automatic init code included.)
gmoon10 years ago
OK, I see you just want to set the pin state. So for example, PB0 (port B, bit 0), starting with setting the pin for output:

You first need to set the DDR (data direction register) to output:

DDRB |= _BV(DDB0); // set DDR bit 0, output

Now change the state
PORTB |= _BV(PB0); // set bit (hi)

(cannot show the clear bit instruction, instructables refuses to show an apersand...and I'm too lazy to look up the html value.)

PORTB (ampersand)= ~_BV(PB0); // clear bit (lo)

These examples use the avrgcc defines for PORTB, PB0, etc., and the Bit Value macro, _BV(). Also, read the data sheet section on "I/O Ports", it has a table with DDR and port combinations.

This is output only, you'll need to change the DDR for input, and read PINB (PORTB is output for portb, PINB is input...) I cannot guarantee this works, as it's from memory--but the data sheet has all the info you need...

And obviously, your Makefile needs to load the correct defines for the chip you are using, or nothing will work right....
zachninme (author)  gmoon10 years ago
I know. I understand all that stuff. The problem I was having was I didn't think low would work as a GND on an LED. I guess it does, thanks.
gmoon gmoon10 years ago
I should mention this drives the pin, i.e., provides current when HI. If you want an open-collector type output, the simplest, quickest way is not to enable pullups, but switch between input tri-state and output LO with the DDR. Using internal pullups requires an additional step/code.
gmoon10 years ago
Maybe share in more detail what you're trying to achieve. I've used ATtiny2313 ICs (not sure about 2321), among others. Just about anything that can be done using assembly lang is also possible w/ C (exceptions might involve speed/efficiency/size, though avrgcc produces decently optimized code.)
zachninme (author)  gmoon10 years ago
I'm sorry, its 2313
1-10 of 15Next »