Monday, May 13, 2013

Arduino: Port Manipulation on Mega 2560

I am writing a library to output PAL/NTSC signals to a TV terminal, and I think it would be better to manipulate the port directly to gain faster access. 

From http://www.arduino.cc/en/Reference/PortManipulation it was said PORTD can be used to control pin 0-7. However, sadly it does not work for me. digitalWrite and pinMode works well. But DDRD and PORTD has no response at all.

I start suspecting the document and trying other ports, and happily find PORTE works for pin 2-3. But not for the others. I think now it is time to test other ports and make a new mapping.

By testing, here's the ports corresponding to pin of Mega2560. It seems a little weird and I don't know why. If you have the same problem, I would suggest you to also try different PORT names on your board.

Hope this would help others that encounter the same problem.


PIN numberPORT
2PORTE (0x10)
3PORTE (0x20)
4PORTG (0x20)
5PORTE (0x08)
6PORTH (0x08)
7PORTH (0x10)
8PORTH (0x20)
9PORTH (0x40)
10PORTB (0x10)
11PORTB (0x20)
12PORTB (0x40)
13PORTB (0x80)
22-29PORTA (0x01-0x80)
30-37PORTC (0x80-0x01)
38-45PORTD (0x80-0x01)
46-53<NOT_FOUND>

5 comments:

  1. Hi,
    this post helped me a lot!!! I searched in the internet a whole day, but this is the only post which helped me out. I think that, this should be included on the arduino reference page.

    Btw, Regarding to the missing Pins 46-53M:
    Maybe the table at the bottom is a help http://arduino.cc/en/Hacking/PinMapping2560
    Regarding to the table and if i checked the coherence right,
    PIN 50-53 should be in PORTB,
    PIN 42-49 should be in PORTL, and so on
    but i hadnt the time right now to check it.

    Thanks a lot!

    ReplyDelete
  2. BTW PORTF is used for pins A0 to A7

    ReplyDelete
  3. OH Yes its very helpful to know about the PORT register of ATMEGA2560
    by using these port i will write a code to print minute counts on seven segment display
    i have used TWO SEVENSEGMENTS prints 0-59,after that reset,compatible with TIMER1 on ARDUINO board

    CODE IS HERE
    // Arduino timer CTC interrupt example
    //With seven segment display

    // avr-libc library includes
    #include
    #include
    #define LEDPIN 13

    //variable for switch state2
    int y=11;
    //variable for switch state1
    int x=2;

    void setup()
    {

    //PORT A FOR SEGMENT 1
    DDRA = B11111111; //initialize port pins as output 22-29

    //PORT C FOR SEGMENT 2
    DDRC = B11111111; //initialize port pins as output 37-30

    //sets both segment as zero
    PORTA = B0111111;
    PORTC = B0111111;

    pinMode(LEDPIN, OUTPUT);

    // initialize Timer1
    //for timer configuration visit "https://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/"


    cli(); // disable global interrupts
    TCCR1A = 0; // set entire TCCR1A register to 0
    TCCR1B = 0; // same for TCCR1B

    // set compare match register to desired timer count:
    OCR1A = 15624;

    // turn on CTC mode:
    TCCR1B |= (1 << WGM12);

    // Set CS10 and CS12 bits for 1024 prescaler:
    TCCR1B |= (1 << CS10);
    TCCR1B |= (1 << CS12);

    // enable timer compare interrupt:
    TIMSK1 |= (1 << OCIE1A);

    // enable global interrupts:
    sei();
    }

    void loop()
    {
    // main program
    }

    //create a function for counts 0-59,after that reset
    void counts(int chk)
    {
    if(chk<=10)
    {
    switch (chk) //Ist switch state is to print 1-9 on segment2
    {
    case 2:
    {
    //print seg2=1
    PORTC = B0000110;
    x++;
    }break;
    case 3:
    {
    //print seg2=2
    PORTC = B1011011;
    x++;
    }break;

    case 4:
    {
    //print seg2=3
    PORTC = B1001111;
    x++;
    }break;

    case 5:
    {
    //print seg2=4
    PORTC = B1100110;
    x++;
    }break;

    case 6:
    {
    //print seg2=5
    PORTC = B1101101;
    x++;
    }break;

    case 7:
    {
    //print seg2=6
    PORTC = B1111101;
    x++;
    }break;

    case 8:
    {
    //print seg2=7
    PORTC = B0000111;
    x++;
    }break;

    case 9:
    {
    //print seg2=8
    PORTC = B1111111;
    x++;
    }break;

    case 10:
    {
    //print seg2=9
    PORTC = B1101111;
    x++;
    //y=11;
    }break;
    }
    }

    else
    {
    switch(y) //second state is to print1-5 on segment1
    {
    case 11:
    {
    //seg1=1,seg2=0
    PORTA = B0000110;
    PORTC = B0111111;
    x=2;
    y++;
    }break;

    case 12:
    {
    //seg1=2,seg2=0
    PORTA = B1011011;
    PORTC = B0111111;
    x=2;
    y++;
    }break;

    case 13:
    {
    //seg1=3,seg2=0
    PORTA = B1001111;
    PORTC = B0111111;
    x=2;
    y++;
    }break;

    case 14:
    {
    //seg1=4,seg2=0
    PORTA = B1100110;
    PORTC = B0111111;
    x=2;
    y++;
    }break;

    case 15:
    {
    //seg1=5,seg2=0
    PORTA = B1101101;
    PORTC = B0111111;
    x=2;
    y++;
    }break;

    case 16:
    {
    //seg1=0,seg2=0
    PORTA = B0111111;
    PORTC = B0111111;
    x=2;
    y=11;
    }break;


    }
    }

    }





    ISR(TIMER1_COMPA_vect)
    {
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    counts(x);//call counts function
    }

    ReplyDelete
  4. So I tried implementing Port Manipulation like this for a Mega 2560 but get this error with this code
    void setup(){
    PORTA = B0000000;
    PORTC = B0000000;
    }

    void loop(){
    PORTA = B1000110;
    PortC = B0111000;
    delay(1000);
    PortA = B0100000;
    delay(500);
    PORTA = B1110000;
    PortC = B0001110;
    delay(1000);
    PortA = B0001000;
    delay(500);
    PORTA = B0011100;
    PortC = B1100010;
    delay(1000);
    PortA = B0000100;
    delay(500);
    PORTA = B000111;
    PortC = B111000;
    delay(1000);
    PortA = B1000000;
    delay(500);
    }



    error exit status 1
    'PortC' was not declared in this scope

    ReplyDelete
    Replies
    1. Hi. try 'PORTC' instead of 'PortC' the compiler is case sensitive...

      Delete