Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C Microcontroller
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
 
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 19-Nov-12 6:34am
Edited 19-Nov-12 8:20am
v4
Comments
Mehdi Gholam at 19-Nov-12 12:36pm
   
Try asking your classmates your teacher about it.
Ed Nutting at 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 at 19-Nov-12 13:05pm
   
you should put the in as a solution as it precisely answers his question
Ed Nutting at 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
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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???):
 
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):
 
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...
  Permalink  
v3
Comments
CPallini at 19-Nov-12 14:21pm
   
Yes, but how is this related with "drive PD1 high"? Still I cannot figure out the connection.
SandiegoSSD at 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 at 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 at 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 at 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
Ed Nutting at 19-Nov-12 16:25pm
   
Please see my last update - looked at the original article and created a new improved version that is simpler and hopefully more understandable - for a beginners tutorial, it really wasn't a very good article!
 
Ed
CPallini at 19-Nov-12 16:57pm
   
The problem (at least for me) is that PORTD1 is (probably ) 'simply' a define for 1.
That is PORTD1 is somewhat a misleading name.
Ed Nutting at 19-Nov-12 17:10pm
   
+5 your solution - that makes sense of the original code but I agree entirely, PORTD1 is an insanely confusing name (goes against everything I have seen with other micro-controllers such as PICs).
 
Ed
CPallini at 19-Nov-12 17:15pm
   
Thank you. Yes #define PORTD1 1 looks a bit weird to an old PIC dog like me.
CPallini at 19-Nov-12 15:32pm
   
It doesn't make sense, written that way. If you want to turn ON bit 0 then you use PORTD |= 1;
BTW could you post the original code?
SandiegoSSD at 19-Nov-12 16:02pm
   
http://www.pololu.com/docs/0J36/3.b
 
that's the page I was looking at to get started with the avr studio
Ed Nutting at 19-Nov-12 16:14pm
   
Odd...that article seems to suggest that PD1 will flash on and off...but the first bit of PORTD relates to PD0 not PD1 doesn't it? Thus I am confused as to how it is supposed to work. It also looks like there is a lot of redundancy in the code too since the first line of the loop wouldn't change anything if PORTD1 does relate to PD1 & the first bit of PORTD. The code is more complex than it needs to be. Looking at it again, it is trying to be too clever. Please see my updated solution for what I think is the best version.
 
I would recommend finding a better or at least better explained set of tutorials.
 
Ed
Sergey Alexandrovich Kryukov at 19-Nov-12 15:51pm
   
Explained. A 5.
--SA
Ed Nutting at 19-Nov-12 16:07pm
   
Thank you :)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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)
PORTD |= (1 << PORTD1);
turns ON bit 1 of port D, because 1 << 1 = 00000010B
 
While
PORTD &= ~ (1 << PORTD1); 
clears (turns OFF) bit 1, because ~(1 << 1) = 11111101B.
  Permalink  
Comments
SandiegoSSD at 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 at 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 at 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 at 19-Nov-12 17:13pm
   
well,what a learning curve..
CPallini at 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).
Chuck O'Toole at 19-Nov-12 18:28pm
   
Programmers define bits in registers as "masks", e.g., 0x00000002, 0x00000004. In my experience with hardware guys who write code define bits as "bit numbers", 0, 1, 2, 3, etc. It is a characteristic of code written by hardware guys is that they like to do lots of "shift" operators. It's "artistic" versus "sledgehammer" style of coding.
CPallini at 19-Nov-12 18:43pm
   
:-)
Interesting.

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

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 746
1 OriginalGriff 345
2 Magic Wonder 131
3 Kishore Pogaru 130
4 Fredrik Bornander 130
0 OriginalGriff 5,705
1 Sergey Alexandrovich Kryukov 4,763
2 CPallini 4,570
3 George Jonsson 3,142
4 Gihan Liyanage 2,450


Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 19 Nov 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100