Author Options:

How do you read a digital input on an avr in c? Answered

The type of input I am talking is one 0 to 255.



Best Answer 9 years ago

Simple overview of reading a pin

AVR ports are labeled port A though port D on most DIP packages (look at the datasheet for your AVR to find the right port.) For instance, for port B:

You write to port B with the PORTB register
You read (input) port B with the PINB register

The input or output status of each bit in the port can be controlled with the DDR (Data Direction Register), so that each pins in a single port can serve different purposes.

Set port B, pin 2 for input (this clears bit DDB2 in the DDR):

DDRB &= ~_BV(DDB2);

To get the value on port B, pin2:

val = PINB & _BV(PB2);

This ANDs the PINB register with the bit value of pin 2 (PB2)--masking out the other unwanted bits.

Here's the best tutorial on bit operators and manipulation. Read it. Then read it again.

No such thing as a single-pin, 0-255 digital input. Digital is 0 or 1. It's probably a serial interface. One byte of data is transmitted via a serial protocol encompassing several bits of data, which is then assembled.

If it's a "one input digital thermometer," then it could be the 1-wire protocol. That link has some nice firmware and explanation. It is specifically tailored to digital thermometers (the DS18B20, in this case.)

There are other serial protocols that are built-in to many AVRs, such as SPI, I2C, etc.

It would be very helpful if you listed the AVR chip you're using...

You can read 8 digital lines just like any other digital input. It helps to put them all on the same port, with the least significant input on pin 0. Then you can just go myvar = PORTB. It's as easy as that.

I do this on the Arduino, but there are no open ports like this. Instead, I have a list of pins that I digitalRead, then shift the result left by 1. Do this 8 times and you've read a single byte from 8 lines.

I'm sure lots has changed with the Arduino IDE since UziMonkey replied. So this is meant as a sanity check for the state of things 5 years later... Thankfully things have changed for the better.

I just checked and as of the Arduino IDE version 1.0.5 the following code compiles for me. It uses nothing but the raw AVR ports. It executed fine on an Arduino Nano v3.0 knockoff I have. I used Linux.

#include "avr/delay.h" // I'm an odd duck. I prefer the look of the delay function names provided by the avr/delay.h header file. They should function the same.

void setup() {

DDRB &= ~_BV(DDB5); // set DDB5 to output. (Onboard LED/Digital Pin 13 on ATMEGA based Arduino's)


void loop() {

PORTB |= _BV(DDB5); // turn the LED ON


PORTB &= ~_BV(DDB5); // turn the LED OFF



How does the basic stamp do this with only one pin.

Is there any way to do this with only one pin. Like a one input digital thermometer.

You can do it with 2 or 3 pins using a parallel in, serial out shift register. That way, you can just shift in the bits instead of using 8 pins. There are also IO extenders from companies like Microchip that work on i2c, and give bi-directional IO ports. Alternatively, you can make a resistor ladder and use a single analog pin. This is good if the number doesn't have to be exact.