Click here to Skip to main content
15,888,325 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hi guys, i'm working with an ATMEL microcontroller and looking into some codes example. I learned about micro in a class a while ago and can't recall what this 1<<PORTD1 means in this example

C#
int main() {
    DDRD |= (1<<DDD1);          // set LED pin PD1 to output
    while (1) {
        PORTD |= (1<<PORTD1);   // drive PD1 high
        _delay_ms(100);         // delay 100 ms
        PORTD &= ~(1<<PORTD1);  // drive PD1 low
        _delay_ms(900);         // delay 900 ms
    }
}



also that 1<<DDD1 too.
Doesn't look like a shift, I think.
Could you guys enlighten me ?
#######################
I know |= and shift. Just not sure why the PORTD1 would equal to 1 or whatever bit we are trying to set (i.e., if PORTD3 is used here instead,then it means we'd like to set the 3rd bit from right. How would we know that PORTD3 equals to 3? ) . Maybe this question is too AVR specific.
Posted
Updated 19-Nov-12 8:20am
v4
Comments
Mehdi Gholam 19-Nov-12 12:36pm    
Try asking your classmates your teacher about it.
Ed Nutting 19-Nov-12 12:48pm    
"PORTD OrEquals 1 left shifted the number of times of the value of PORTD1" i.e. PORTD = PORTD | (1<<PORTD1);
X << Y left shifts X, Y times e.g. 1 << 5 lefts shifts 1 5 times giving 10000b i.e. 32. Put some examples into Wolfram Alpha and you'll get the idea.

Hope this helps,
Ed
Chuck O'Toole 19-Nov-12 13:05pm    
you should put the in as a solution as it precisely answers his question
Ed Nutting 19-Nov-12 13:20pm    
Thanks :) I will post it as a solution then - I wasn't sure how good an explanation it really was.

Ed

Hi there,

Same as my comment but as suggested, now posted as a solution (so that this stops showing as an "Unanswered question":

"PORTD OrEquals 1 left shifted the number of times of the value of PORTD1" i.e. PORTD = PORTD | (1<<PORTD1);
X << Y left shifts X, Y times e.g. 1 << 5 lefts shifts 1, 5 times giving 00010000b i.e. 32. Put some examples into Wolfram Alpha and you'll get the idea.

Hope this helps,
Ed

Edit: To clear up the confusion of how this is related to "// drive PD1 high":

Regardless of what micro-controller hardware you are using, the terminology is the same. If you have an output pin e.g. PORTD1, making the output voltage on that pin +ve is called "driving it high" i.e. if you drew a graph of the voltage of that pin, the line would go high. In code, to drive the output voltage high means setting the pin's output to 1. Driving a pin low means making it go to 0 voltage i.e. setting the output to 0. We use the word "drive" because the micro-controller actually forces the pin voltage to that level rather than just allowing the pin to reach that level of it's own accord (not the best explanation but hopefully simple enough).

So the statement:

PORTD |= (1<<PORTD1);

(As pointed out in a comment on my answer) uses a bit mask to turn on the bit which is PORTD1 positions from the left. Since PORTD1 actually refers to the second bit in the PORTD register, it will either be 0 or 1. Thus the statement really equates to either of the following:

PORTD = PORTD | (1<<0); which will always result in: PORTD = PORTD | 1 (Noteably: PORTD refers to all the bits in PORTD where as PORTD1 refers to just the first bit. Thus the value of PORTD is: 00000000b if all bits are set to 0 and there are 8 bits in PORTD).

or it results in:
PORTD = PORTD | (1<<1);. However, since it was the second bit that we tested for in the first place, it will have no effect on the PORTD output. (Since the code basically means: if PORTD1 is 1, set PORTD1 to 1 thus no change.)

It seems like a pretty odd piece of code to be using therefore. So I would suggest the OP replaces it with something a little simpler (unless I have missed something???):

C
if(PORTD1 == 0)
{
    PORTD |= 1;
}


Hope this clears up some of the confusion (or creates some new, interesting questions),
Ed

Improved version of code (now that I have seen the original article):

C
int main() {
    DDRD |= (1<<DDD1);          // set LED pin PD1 to output
    PORTD = 0b00000000;         //Clear PORTD. 
    while (1) {
        //Bit mask on bit 2 of PORTD i.e. PD1 
        //    - sets PD1 to 1 and leaves other bits the same.
        PORTD |= 0b00000010;   // drive PD1 high
        
        _delay_ms(500);        // delay 500 ms
        
        //Bit mask on bit 2 of PORTD i.e. PD1 
        //    - sets PD1 to 0 and leaves other bits the same.
        PORTD &= 0b11111101;   // drive PD1 low
        
        _delay_ms(500);        // delay 500 ms

        //500ms delays should create a flash with:
        //Up time 0.5 seconds and down time 0.5s
    }
}


This could probably be made more compact using "~" operator (the name has slipped my mind) but for simplicity sake I have simply used to bit masks to toggle the second bit of PORTD.

The original code, I think, was trying to be too clever with toggling based on whether PORTD1 was already on or not. It significantly overcomplicated the code...especially for a beginners' tutorial. Or even for practical application really...
 
Share this answer
 
v3
Comments
CPallini 19-Nov-12 14:21pm    
Yes, but how is this related with "drive PD1 high"? Still I cannot figure out the connection.
SandiegoSSD 19-Nov-12 14:26pm    
"|=" is a set bit mask. PORTD1 |= 1<<1, or just PORTD1 |= 0x01 (00000001b), simply set the first bit high
Ed Nutting 19-Nov-12 14:55pm    
If I'm right, it actually starts at PORTD0 so PORTD1 is the second bit. In which case, this code makes not a great deal of sense... I would sort of expect it to be:

PORTD |= 1;

Your final simplification does not quite work as that would clear all the other bits in the PORTD register thus losing the other outputs - you still need the "|=".

It looks likely that PORTD1 is an input switch and so driving PORTD0 high depends on PORTD1 being high, however, it is not 100% clear, especally given the fact that PORTD1 is not set as an input...

Perhaps not a very good example for the OP to learn from after all...
Ed
CPallini 19-Nov-12 15:30pm    
My five for your analysis. I wonder how that could be a 'code sample' (are we missing something?).
Ed Nutting 19-Nov-12 16:11pm    
Thank you :) Mmmm...I was wondering that too...However, looking at the original page that the OP linked to, it appears that the original code was simply poor code...When I look at it, I get the distinct feeling that there is significant redundancy in the first line of the loop (the one the OP queried in the first place). I think the OP ought to find a better set of tutorials - especially given the total lack of decent explanation of the code given in that tutorial.

Ed
OK, that makes sense provided PORTD1 = 1;
You should be able to find #define PORTD1 1 in one of the included header files (I suppose in avr/pinports.h).
This way (as Ed already showed)
C
PORTD |= (1 << PORTD1);

turns ON bit 1 of port <code>D, because 1 << 1 = 00000010B

While
C
PORTD &= ~ (1 << PORTD1); 

clears (turns OFF) bit 1, because ~(1 << 1) = 11111101B.
 
Share this answer
 
Comments
SandiegoSSD 19-Nov-12 17:04pm    
yes....it turns out
#define PORTD _SFR_IO8(0x0B)
#define PORTD7 7
#define PORTD6 6
#define PORTD5 5
#define PORTD4 4
#define PORTD3 3
#define PORTD2 2
#define PORTD1 1
#define PORTD0 0

this is in iom324p.h , since I'm using ATmega324p
Ed Nutting 19-Nov-12 17:08pm    
What the??? O.o PORTD1 = 1??? Weird... That really is an AVR quirk... in PIC C PORTD1 would refer to the first bit of PORTD i.e. if you read the value of PORTD1 it would tell you the input/output value for the pin PD1...odd that it is set to a constant... Oh well, explains a lot :)

Ed
SandiegoSSD 19-Nov-12 17:12pm    
yes..I learned PIC in school and that's the impression i have for PORTD1, an individual field of the register you can r/w
SandiegoSSD 19-Nov-12 17:13pm    
well,what a learning curve..
CPallini 19-Nov-12 17:11pm    
OK, now it is clear. Like Ed, I was confused by my 'familiarity' with PIC microcontrollers (to us such a define, at first glance, looks a bit weird).

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900