NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » Digital Write Question
June 21, 2009 by Ethanal |
I noticed in the Nerdkits guide you guys use a different method of writing to digital pins than what I am accustomed to. For example, if i wanted to turn on an led a PB1, I would use this code: DDRB = 0x2; PORTB = 0x2; It appears you would use this code: DDRB |= (1<<PB1); PORTB |= (1<<PB1); What is the difference? Any help is appreciated. |
---|---|
June 21, 2009 by mcai8sh4 |
Aha, I had some confusion with this initially, there's a post in here (maybe by wayward) explaining this very nicely. But for a quick answer.... 0x2 (hex) = 00000010 (binary) = 2 (decimal) We can use any method really, but it depends on what we are trying to achieve. Your latter example says set the the register to 1, but bit shift it by PB1 (1). If you used PB3 it would move the bit across (left) three places, ie. 00001000 The '|=' is an OR A nice thing about this method, is that it leaves all the other bits as they where. So if your register is set to : 001010 You can set just the third bit by using PORTB |= (1<<PB2) to give you 001110 - you can see that all the other bits are left as they where. Check out THIS it explains it very well. If you're still confused, shout out, I'll try to explain better (when sober) |
July 01, 2009 by Ethanal |
O.K.-- I understand how to set a pin to high now, but how do I turn it off without affecting the other bits? |
July 01, 2009 by Ethanal |
Never mind the last question. I figured that out, but I have a new question. How do you turn more than one pin to high or low at the same time? |
July 01, 2009 by jbremnant |
to turn on multiple without affecting the currently "on" pins: PORTB |= (1<<PB1) | (1<<PB2) | (1<<PB3) ... you get the idea. to turn off multiple without affecting the other pins: PORTB &= ~((1<<PB1) | (1<<PB2) | (1<<PB3)) Additionally, I have some nifty macros you can use in C code: #define pinOn(X,Y) PORT ## X |= (1<<P ## X ## Y) #define pinOff(X,Y) PORT ## X &= ~(1<<P ## X ## Y) Put those lines on the top of your .c file and then use it like: pinOn(B,1); pinOff(C,0); The first argument corresponds to port, and the second arg is the number of the pin |
July 01, 2009 by jbremnant |
Sorry, I botched up the format of the previous post... here you go. to turn on multiple without affecting the currently "on" pins:
to turn off multiple without affecting the other pins:
Additionally, I have some nifty macros you can use in C code:
Put those lines on the top of your .c file and then use it like:
The first argument corresponds to port, and the second arg is the number of the pin |
July 01, 2009 by mcai8sh4 |
I like the macro idea. Could you explain the '##' bits. I don't really get how it works. Thanks |
July 01, 2009 by jbremnant |
The "##" syntax is C macro concatenation operator. Basically, when you feed in two variables, it just joins them together. So, doing
would get preprocessed and become
in your C code before it gets compiled. For more info, try: |
July 01, 2009 by mcai8sh4 |
Ah, got you. All makes sense, quite nifty that - I'll give it a go. Stuff like that could really obfuscate things if you wanted to - I like it. |
July 01, 2009 by Ethanal |
Thanks guys: that helped a lot. I found my mistake. I was "NOT"ing each one then "OR"ing them instead of "OR"ing them then "NOT"ing that (if that makes sense). I love how helpful the Nerdkits Community is. P.S. Cool macro |
July 05, 2009 by BobaMosfet |
I think it is important to understand what this really is. This is called MASKING. You clear and set bits and use "masks" to achieve this. C and C++ have many ways you can do this, including left and right shifting in order to create the 'mask'. When you say "1 Left Shift PBn", what you're really saying is: create a temporary variable on the stack to hold a byte value. Put a 1 there and then left shift it by PBn bits. Whatever that value ends up being is your 'mask' during the operation. PBn is a defined constant that represents a 1, 2, 3....n value (number of bits to shift). PORTB is a register (another byte-length variable location at a hardwired location in the process (MCU)). When you '|=' it you are adding or combining the masked value to whatever already exists in that register. And then the 'mask' variable that was kept on the stack will be discarded.
Using the above, here are the bytes in binary:
Hope this helps. Get real familiar with working between hex, decimal, and binary. If you learn to think in terms of nybbles (4 bits, 0000 through 1111 or 0x0 through 0xF) using hex, it makes the binary work much easier to think about. |
July 05, 2009 by mcai8sh4 |
BobaMosfet - great explaination, I must admit I struggled with this concept at the beginning and you're right - getting a good understanding of what you're doing (in 1's and 0's) really helps. |
July 05, 2009 by jbremnant |
Great explanation on bit operations. To add to it, the statement for turning off 3 pins while retaining the state of others:
And btw, I think the define statements above in BobaMosfet's post should be:
|
July 07, 2009 by Ethanal |
Thanks to everyone. You guys are a real help. Wonderful explanations. I think I understand it now. jbremnant: I think BobaMosfet is correct. Remember PB0 is bit 1, PB1 is bit 2, etc. |
Please log in to post a reply.
Did you know that NerdKits also has extra parts available for its customers? Learn more...
|