1

I'm interested in writing a C program without the Arduino IDE and related libraries and am trying to figure out how I can access the GPIO pins for read and write.

My assumption is that the GPIO pins are - at the hardware layer - just memory addresses, and so if I know what their address is I can send/receive data to and from them.

  • For writing to the digital pins, do I just send an int with a value of 0 or 1 to the pin's address? If so, what might that code look like? Can I then assume I could poll that address for a value, which would be either 0 or 1?
  • Can I assume the same for analog pins, but instead of binary values, I'd get an integral value between 0 and 1023?

And if I'm way off here, and pins are not accessed via memory addresses, then how?

Again, the solution I'm looking for wouldn't involve Arduino software, just the Arduino hardware (an AVR or ARM MCU). Bonus points for C pseudo-code examples! Thanks in advance!

6
  • 1
    I know the AVR stuff is easy, but I couldn't tell you how the ARM stuff works; I have an ARM board but I haven't had a chance to look at it. Commented May 12, 2015 at 17:02
  • Thanks @IgnacioVazquez-Abrams (+1) - I only mentioned ARM because that is what the Arduino Due is using, and I am interested in the Due for its beefier computing power. In any event, am I on track or way off in dodo bird land? Any chance I could see a few lines of C code for reading/writing pins (digital or analog)? Thanks again!
    – smeeb
    Commented May 12, 2015 at 17:05
  • 1
    For the AVR-based Arduinos, a good reading: Port Registers. Commented May 12, 2015 at 17:25
  • Thanks @EdgarBonet (+1) - good find! Any ideas what the Arduino Due (ARM) might be using? Thanks again!
    – smeeb
    Commented May 12, 2015 at 18:15
  • 1
    No, DDRD does not come from the Arduino "language", it's defined by avr-libc. Just #include <avr/io.h> and you get all the I/O registers you see in the MCU datasheet. Commented May 12, 2015 at 19:01

1 Answer 1

3

In theses cases you are right, using register address is the way to read/write data from/to digital pins. In the case you use analog input, the process is similar but you have to follow some procedures before getting the value of the data.

GPIO REGISTERS

For AVR micro-controllers these registers are: DDRn – Data Direction Register PORTn – Port Output data Register PINn – Port Input Register n- Indicates the port name i.e. A, B, C & D If you have arduino board and want to use these pins, look for mapping pictures about arduino and avr pins.

The following is an example from the Arduino website.

DDRD is the direction register for Port D (Arduino digital pins 0-7). The bits in this register control whether the pins in PORTD are configured as inputs or outputs so, for example:

DDRD = B11111110; // sets Arduino pins 1 to 7 as outputs, pin 0 as input
DDRD = DDRD | B11111100; // this is safer as it sets pins 2 to 7 as outputs
                         // without changing the value of pins 0 & 1, which are RX & TX 

See the bitwise operators reference pages and The Bitmath Tutorial in the Playground

PORTD is the register for the state of the outputs. For example;

PORTD = B10101000; // sets digital pins 7,5,3 HIGH

You will only see 5 volts on these pins however if the pins have been set as outputs either by using the DDRD register directly or by using the pinMode() function.

For analog read

You just need to include the headers and start using the registers. They hold the equivalent hexadecimal values for your microcontroller. And the procedure is described in the datasheet. All you have to do is to translate it to code.

// this code scans ADC1 for an analog signal upon request, using 8Mhz processor clock

#include <avr/io.h>
#include <stdint.h>       // needed for uint8_t

int ADCsingleREAD(uint8_t adctouse)
{
    int ADCval;

    ADMUX = adctouse;        // use #1 ADC
    ADMUX |= (1 << REFS0);   // use AVcc as the reference
    ADMUX &= ~(1 << ADLAR);  // clear for 10 bit resolution

    // 128 prescale for 8Mhz
    ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);

    ADCSRA |= (1 << ADEN);    // Enable the ADC
    ADCSRA |= (1 << ADSC);    // Start the ADC conversion

    while(ADCSRA & (1 << ADSC)); // waits for the ADC to finish

    ADCval = ADCL;
    ADCval = (ADCH << 8) + ADCval; // ADCH is read so ADC can be updated again

    return ADCval;
}
   

int main(void)
{
    int ADCvalue;

    while (1)
    {
        ADCvalue = ADCsingleREAD(1);
        // ADCvalue now contains an 10bit ADC read
    }
}

For more information about analog read, see this.  

6
  • Thank you so much @bpinhosilva (+1) - however, I'm not 100% sure you understand my exact question. Take DDRD for instance. In your code example above you have: DDRD = B11111110. You state that this sets Arduino pins 1 - 7 as OUTPUT. But DDRD is a variable... but what library is it define inside of? In other words, what #include statement do I need to add to my source code to gain access to DDRD? If the answer is one of the Arduino libraries, then this doesn't help me! I need non-Arduino access to the AVR/ARM pins! Thanks again!
    – smeeb
    Commented May 12, 2015 at 19:27
  • I just noticed your 2nd code sample above includes avr/io.h - if you can confirm that DDRD (and other similar port/register vars) are defined in this file, I think I'm all set!
    – smeeb
    Commented May 12, 2015 at 19:29
  • 1
    You use #include <avr/io.h>. This is a standard library for avr units. Inside that you find definitions for these registers. Other point is that I am assuming you use Arduino but want to develop with a different IDE. So you need to find the equivalent avr pin to your board's labels. That's why the code says Arduino pinx and so on. Commented May 12, 2015 at 19:30
  • 1
    These names are not variables, they are mnemonics for addresses so you can easily remember them. You are welcome! Commented May 12, 2015 at 19:32
  • Thanks again @bpinhosilva (+1 again) - last followup question: I am wondering what the equivalent is for ARM registers. I found this EE.SE question but no one has answered it. Any idea what I would use for an ARM MCU? Thanks again!
    – smeeb
    Commented May 12, 2015 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.