Posted by JohanEkdahl: Sun. Jul 4, 2010 - 12:15 AM
1
2
3
4
5
Total votes: 0
Have you tried it out? (For this kind of stuff the simulator in AVR Studio is excellent.)
But yes, that looks reasonable.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
typefef struct
{
unsigned int data :8;
unsigned int control :2;
unsigned int address :2;
} whateverYouWantToCallIt;
or:
typefef struct
{
unsigned int :4; //4 bits of fiiler
unsigned int control :2;
unsigned int address :2;
unsigned int data :8;
} whateverYouWantToCallIt;
Posted by JohanEkdahl: Wed. Jul 21, 2010 - 08:16 AM
1
2
3
4
5
Total votes: 0
[Removed as I totally mis-understood the post above. Snigelen nailed the correct interpretation and answer below.]
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Posted by abcminiuser: Wed. Mar 2, 2011 - 01:32 PM
1
2
3
4
5
Total votes: 0
Quote:
how should i access the registers R0-R32? using c programming.
Just give me an example..
You don't - the point of C is that you don't need to directly access the CPU temporary registers. They are handled by the compiler in order to implement your code.
The I/O and peripheral registers (like the timer control registers) are manipulated by you, but not the CPU scratch registers.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
In this code the compiler initially uses R24 to output 0xFF to DDRB. It then reuses R24 as 'mask' and initialises it to be 0x55. It reads PORTB into R25 then exclusive-or's this with 'mask' (R24). It then checks bit 0 of PIND and if that is set it complements the contents of 'mask' (so 0x55 switches to 0xAA).
You, the programmer, need never be aware which registers the compiler has chosen to put values or variables into.
//***********************************************************
// Project: Analog Comparator example
// Author: winavr.scienceprog.com
// Module description: Analog comparator example with positive comparator
// input connected to Vref 1.23V. When compared voltage exceed 1.23V LED lighst on.
// When voltage drops bellow - LED turns OFF. Comparator inputis connected to ADC3 pin.
// ***********************************************************
#include
#include
#define AINpin PA3
#define LED PD0
void Init(){
DDRA&=~(1<<AINpin);//as input
PORTA&=~(1<<AINpin);//no Pull-up
DDRD|=(1<<LED); //Led pin as output
PORTD|=(1<<LED);//Initally LED is OFF
SFIOR|=(1<<ACME);//enable multiplexer
ADCSRA&=~(1<<ADEN);//make sure ADC is OFF
ADMUX|=(0<<MUX2)|(1<<MUX1)|(1<<MUX0); //select ADC3 as negative AIN
ACSR|=
(0<<ACD)| //Comparator ON
(1<<ACBG)| //Connect 1.23V reference to AIN0
(1<<ACIE)| //Comparator Interrupt enable
(0<<ACIC)| //input capture disabled
(0<<ACIS1)| //set interrupt on output toggle
(0<<ACIS0);
sei();//enable global interrupts
}
// Interrupt handler for ANA_COMP_vect
//
ISR(ANA_COMP_vect) {
if bit_is_clear(ACSR, ACO)
PORTD&=~(1<<LED);//LED is ON
else PORTD|=(1<<LED);//LED is OFF
}
// ***********************************************************
// Main program
//
int main(void) {
Init();
while(1) { // Infinite loop; interrupts do the rest
}
}
Posted by JohanEkdahl: Wed. Mar 30, 2011 - 08:10 PM
1
2
3
4
5
Total votes: 0
Cliff!
When those post totally unrelated to the thread occur I think we should tossin an explanation of the difference between the "new topic" and the "new reply" buttons. I have a feeling that the distinction is not clear for many newcomers, or thet they even do not see the buttons and think that the only way to post on the forum is the "Quick Reply" area.
ghost800!
If you want to start a discussion on a new topic, use the "new topic" button at the top or bottom thread pages and forum listings here at AVRfreaks. Each discussion should commence in a separate "thread" (topic) or things become very confused and out of order. When creating a new thread please take the time to think out a really smart title (subject) so that it reflects the content of your post (extremely bad subjects are things like "Help!", "Why does my code not work" etc).
Hope this helps!
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Yes and my question is why obfuscate code with layers of macros when the plain C to achieve the same would actually be simpler. There seems to be a recent trend to try and wrap code in N levels of macro at the drop of a hat. As someone who has to read/maintain other programmers code I find that it very rarely aids the mainatainability/readability of the code but instead just makes it more difficult to follow. Perhaps you can explain what how your bit_get() macro makes the code easier to follow. ALL programmers know what an AND operation is!
thanks, and well as u said it will be simpler to use plain c but the reason is that, i am working on a project and the panel where i have to present it to has a few members who have well little or no knowledge of programming so i am hoping the macros will help in making them understand more easily.
so i am hoping the macros will help in making them understand more easily.
Eh? You have the option of teaching them your very specific macro or the generic C & operator. With the latter they can write 1000's of programs, with the former they are tied to some very specific code for a single situation. Why not teach them how AND works?
well cos i am a student myself. and i am showing a presentation to justify the funding of my project, and the people on the panel will be staff of various departments, some of who may not know programming .that's why am using the macros to give a generalized presentation. I have even broken down my whole code into functions with general names for hopeful easier understanding.
i do have some idea on the working of macros now,thanks to the tutorial. And i do know basic programming so i know what happens when u use a particular macro. I am already done with my coding using c. Just needed the macros to hopefully make it easier to explain.
I just got a really crazy idea and Im not sure if it can actually be impemented.
To create a byte object in which every bit corresponds to a certain Pin on a port?
I'm not sure if Im using the right words here but an example should help:
create some object, maybe a structure (?) that looks like this:
object {Bit0 = Portb bit 3
Bit1 = Portc bit 1
...
Bit7 = Portb bit 0
}
so when you store a value into this object it will assign the respective value to those pins
for example,
object = 0xFF
would set Portb bit 3 high, Portc bit 1 high etc.
just wondering, maybe by doing a complicated macro or somethig?
To create a byte object in which every bit corresponds to a certain Pin on a port?
Search in this very forum for "bitfield". The bottom line is that struct members can be defined to be 1 bit long and so you can conglomerate 8 on a single byte address. Anyway read the tutorial.
Posted by bigmessowires: Sat. May 14, 2011 - 05:20 AM
1
2
3
4
5
Total votes: 0
I've read this whole thread, and one topic that's not mentioned regarding port bit twiddling (with or without macros) is interrupts.
Is it considered good practice to disable interrupts when modifying a port pin? Especially if you're using some kind of bit_set() or bit_clear() macro?
The reason is that if the bit being set/cleared is not a constant expression at compile time, then the compiler will have to generate several instructions to read the current port value into a register, manipulate the value, and write it back. If an interrupt triggers after the port value is read, and that interrupt modifies another pin on the same port, when the main program resumes it will write back the stale value for that pin. This issue was previously a bug in the Arduino digitalWrite() implementation: http://code.google.com/p/arduino...
I don't see anyone disabling interrupts in their code-- why not? Is there a reason I've overlooked why it's not necessary?
Posted by JohanEkdahl: Sat. May 14, 2011 - 08:51 PM
1
2
3
4
5
Total votes: 0
Quote:
the compiler will have to generate several instructions to read the current port value into a register, manipulate the value, and write it back.
The compiler will not have to generate several instructions, if only one bit is manipulated. AVRs have single machine instructions to manipulate one bit. E.g. activate the optimizer of avr-gcc and see what
PORTB |= 1;
generates.
If several bits are modified, then a read-modify-write sequence will be generated, and you will need to turn off interrupts if the port that is manipulated is shared with ISR code. The subject has been discussed in length here at 'freaks. The search words you need are e.g. "re modify write", "atomic" etc...
Ther are also tutorials on interrupt handling in general IIRC.
The avr-gcc support library avrlibc has stuff contributed by Dean Camera ('abcminiuser') that makes atomic sequences, saving and restoring state etc easy to code.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Posted by abcminiuser: Sun. May 15, 2011 - 04:15 AM
1
2
3
4
5
Total votes: 0
Quote:
The compiler will not have to generate several instructions, if only one bit is manipulated.
It will generate several instructions for RMW if the extended IO space or SRAM is used, which can indeed lead to atomicity issues. Note that the XMEGA and AVR32s have a larger register address space with dedicated SET and CLEAR registers that allow for single-cycle RMW sequences.
On the older AVRs, you'll need to protect against interrupts if you're writing anything but a single bit to the regular IO space.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
Posted by bigmessowires: Mon. May 16, 2011 - 11:55 PM
1
2
3
4
5
Total votes: 0
Thanks, that makes sense, and I'll search for the atomic write threads. And to clarify, the situation I was asking about is when the bit being set/cleared is not a constant expression at compile time. I've looked at the disassembly for contant expressions like PORTB |= 1 and it is a single sbi machine instruction, as JohanEkdahl said.
Posted by JohanEkdahl: Tue. May 17, 2011 - 07:27 AM
1
2
3
4
5
Total votes: 0
Quote:
And to clarify, the situation I was asking about is when the bit being set/cleared is not a constant expression at compile time.
Oh, I missed that vital part of the question. Yes, in that case you are at risk even with single bit operations.
Sorry for any confusion.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
Posted by jjmcousineau: Tue. Jun 14, 2011 - 02:26 PM
1
2
3
4
5
Total votes: 0
Hello, this is a very good tutorial and thank you but I was wondering if some one could explain something.
When I learned this stuff in school a few years back we only ever masked like you did in the 1st half (ie. foo &= 0x01). Why and when is it necessary to use these shift masks? I was taught using motorola micro's and I was wondering if it was some architecture thing? But as far as I can see they both do the same thing.
Why and when is it necessary to use these shift masks? I was taught using motorola micro's and I was wondering if it was some architecture thing?
Nothing says you HAVE to use bitnumbers with shifts. Some would argue that if you are only setting bit 5 of a DDR register to be an output that:
DDRB |= 0x20;
is almost as readable as:
DDRB |= (1<<5);
(thought the former may make the engineer count on his fingers to remember that 0x20 is bit 5! ;-))
However where this bit shifting comes into play is to make SFR bit usage more self-documenting. For example in many AVRs bit 5 of the UCSRB register is the bit to enable the UART data register empty interrupt. Now if you read code that says:
UCSRB |= 0x20;
or
UCSRB |= (1<<UDRIE);
many engineers (at least those with a passing knowledge of the AVR) will instantly recognise that the second of those is enabling the UDRE interrupt. However it would require a VERY fastidious reader to know that 0x20 (or even (1<<5)) happens to be the UDRIE bit in that register.
Now one might then ask why do I have to use 1<<, if Atmel had written the XML file that is used for Assembler and C header file generation such that:
#define UDRIE 0x20
rather than
#define UDRIE 5
then the usage in C would just be:
UCSRB |= UDRIE;
but the reason they defined the bit names as 0..7 is so that the number can be used with the AVR SBI and CBI opcodes (assuming UCSRB is at the right location). This introduces the minor inconvenience of having to use (1<<UDRIE) to convert 5 into 0x20. In at least one C compiler there is a macro defined as:
#define _BV(x) (1<<x)
so that at least:
UCSRB |= _BV(UDRIE);
can be used which maybe looks a little less "complex" than (1<<UDRIE). However *all* C programmers will recognise the (1<<UDRIE) version but not all are going to know what _BV() achieves without digging into header files - which kind of destroys the readability "gain" in using it.
Remember that at the end of the day all C (and Asm) code should be written with the "next reader" in mind - which could either be the poor sap who has to fix your code 3 years after you left the company or it could simply be you in 9 months when you've forgotten that setting 0x20 in UCSRB is setting the UDRIE bit! (1<<UDRIE) tells you which bit is being set without looking it up (assuming you can at least remember the purpose of "UDRIE")
Posted by JohanEkdahl: Tue. Jun 14, 2011 - 02:58 PM
1
2
3
4
5
Total votes: 0
Quote:
Why and when is it necessary to use these shift masks? [...] But as far as I can see they both do the same thing.
They do. It is just about clarity of code. And it is opinous.
Which is clearer? This
something &= (1<<4) | (1<<3);
or this
something &= 0x18;
?
In the next step, e.g. when dealing with bits in a special purpose register (like a timer control register) it helps a lot to use the symbolic bit numbers rather than some magic numerical constants). Since the bit numbers are, uhmmm..., bit numbers rather than bit masks we need to construct the masks from the numbers. To do this, the shift operator is used.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
That means, that nr 1 is shifted left as many times as it is needed to reach bit named CS10. Where does the compiler know that CS10 is that? well you give him the AVR's name and it's smart enough to know such things thanks to some smart programmers on the GCC side ;)
What is the difference between
TCCR1B |= (1 << CS10);
and
TCCR1B = (1 << CS10);
Is OR ('|') really needed there or both will work the same.
Posted by JohanEkdahl: Wed. Jun 15, 2011 - 12:05 PM
1
2
3
4
5
Total votes: 0
Quote:
Is OR ('|') really needed there
That depends on the circumstances.
Quote:
or both will work the same
Definitively not.
TCCR1B |= (1 << CS10);
is a shorthand for the equivalent
TCCR1B = TCCR1B | (1 << CS10);
so all bits that was set before this operation will still be set.
OTOH, if you do
TCCR1B = (1 << CS10);
then only the CS10 bit will be set, and all other will be cleared.
I seriously suspect that this has been covered earlier in this thread, so you might have something to gain from browsing through the complete thread..
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
But the fact that it's not obvious kind of proves how pointless these kind of macros are in aiding readability. Think about:
bit_set(foo, 0x20);
bit_clear(foo, 0x08);
if (bit_set(foo,0x80)) {
which really says (without all the parenthesis):
foo |= 0x20;
foo &= ~0x08;
if (foo & 0x80) {
As you can see you don't want an '=' in the last one as it's used in a different context to the other two. The confusion here is that then macro names are so similar you might think they'd all be used in the same context.
Posted by nickkennedy: Mon. Jul 18, 2011 - 11:13 PM
1
2
3
4
5
Total votes: 0
OK, I see it now. It was just my poor reading. Or poor reading glasses.
But I do like these macros. I agree I should make sure I understand how they work, but think they can prevent careless errors if I understand their proper use.
No they wouldn't. The first clears all bits of PORTD.
Quote:
I just had could some one explain to me the reason this doesn't work properly
Break it down: 0<<D_I means that you are shifting the number 0 by some number of bits (whatever number D_I is). Shifting 0 by anything will always result in 0. You then AND that with PORTD. ANDing anything with 0 will always result in 0.
Quote:
And this one does work properly?
Again, break it down. 1<<D_I will shift the number 1 by D_I bits. If D_I is 2, that makes the result 4 (so in binary you went from 0b00000001 to 0b00000100). You then invert that (the ~), which in binary gives you 0b11111011. You then AND that with PORTD.
Posted by smileymicros: Wed. Sep 14, 2011 - 03:47 AM
1
2
3
4
5
Total votes: 0
Koshchi wrote:
Quote:
They would both work just fine as written.
No they wouldn't. The first clears all bits of PORTD.
Which is a perfectly valid use for that notation so I repeat: 'They would both work just fine as written'. I'd never use the first notation, but who am I to say someone shouldn't use a valid C notation? In fact I've seen (0<<XXX) used in the Atmel Butterfly code, so somebody somewhere must think is okay to do this.
Now if you want to make assumptions about the intent which is unstated, then maybe they don't do what the poster wants them to do, but is that for us to decide or should he tell us what he is trying to do?
Posted by JohanEkdahl: Wed. Sep 14, 2011 - 07:30 AM
1
2
3
4
5
Total votes: 0
Quote:
In fact I've seen (0<<XXX) used in the Atmel Butterfly code, so somebody somewhere must think is okay to do this.
Perhaps, but most likely not in a statement lacking ~ and using &= . Discussing if (0<<XXX) is meaningful or clarifying must be done in the context of the complete statement.
to make it clear that you relly want anotherBit to be clear. Not that the code actually (0<<anotherBitNumber) has the exact effect to actually clears that bit, but you are doing some documentation of intent in the code.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
where they believe that using 0 in the mask is the way to switch things off. As we all know, it isn't.
This notion should be stomped on from a great height before it confuses more beginners (especially in this thread we all point them towards to learn this stuff!).
The only use of (0 << foo) is to document that foo is not being used.
Have you tried it out? (For this kind of stuff the simulator in AVR Studio is excellent.)
But yes, that looks reasonable.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopOr you could do this:
or:
depending on endianness.
Regards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
TopThis one doesnot make sense to me,
To set bit 0 in foo and then store the result back into foo:
Code:
bit OR"|" with 0x01, we will set bit 1 in foo,,
why is it to set bit 0?
I am a newbie, forgive me if i am wrong. please explain it to me.
- Log in or register to post comments
Top[Removed as I totally mis-understood the post above. Snigelen nailed the correct interpretation and answer below.]
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopThis is because bits in a byte are usually numbered from 0 to 7. So the first bit is number 0.
- Log in or register to post comments
TopJust to add a little more to that:
- Log in or register to post comments
TopThat was useful , Thanks .
- Log in or register to post comments
TopThanks!, i was looking for this information.
- Log in or register to post comments
Tophow should i access the registers R0-R32? using c programming.
Just give me an example..
Thank you
- Log in or register to post comments
TopYou don't - the point of C is that you don't need to directly access the CPU temporary registers. They are handled by the compiler in order to implement your code.
The I/O and peripheral registers (like the timer control registers) are manipulated by you, but not the CPU scratch registers.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
- Log in or register to post comments
TopTo illustrate what Dean has said consider this program:
when built by the compiler it generates:
In this code the compiler initially uses R24 to output 0xFF to DDRB. It then reuses R24 as 'mask' and initialises it to be 0x55. It reads PORTB into R25 then exclusive-or's this with 'mask' (R24). It then checks bit 0 of PIND and if that is set it complements the contents of 'mask' (so 0x55 switches to 0xAA).
You, the programmer, need never be aware which registers the compiler has chosen to put values or variables into.
- Log in or register to post comments
TopWhat this program does not work help me
- Log in or register to post comments
Topghost800,
How does your post extend the discussion of the article in the first post of this thread?
Moderator.
- Log in or register to post comments
TopCliff!
When those post totally unrelated to the thread occur I think we should tossin an explanation of the difference between the "new topic" and the "new reply" buttons. I have a feeling that the distinction is not clear for many newcomers, or thet they even do not see the buttons and think that the only way to post on the forum is the "Quick Reply" area.
ghost800!
If you want to start a discussion on a new topic, use the "new topic" button at the top or bottom thread pages and forum listings here at AVRfreaks. Each discussion should commence in a separate "thread" (topic) or things become very confused and out of order. When creating a new thread please take the time to think out a really smart title (subject) so that it reflects the content of your post (extremely bad subjects are things like "Help!", "Why does my code not work" etc).
Hope this helps!
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
Topcan the macros be used with ports?
for eg
- Log in or register to post comments
TopI'm curious. What would make you want to type:
when you could have typed:
Do the tortuous macros really help?
(BTW do you mean to read PORTC or PINC?)
- Log in or register to post comments
Topthanks! ya my mistake it should have been PINC .sorry but am new to programming an ya thanks i guess i could use
but what i meant was does this macro
work when a pin is specified in place of variable p. Or do we have to use macro such as
- Log in or register to post comments
TopYes and my question is why obfuscate code with layers of macros when the plain C to achieve the same would actually be simpler. There seems to be a recent trend to try and wrap code in N levels of macro at the drop of a hat. As someone who has to read/maintain other programmers code I find that it very rarely aids the mainatainability/readability of the code but instead just makes it more difficult to follow. Perhaps you can explain what how your bit_get() macro makes the code easier to follow. ALL programmers know what an AND operation is!
- Log in or register to post comments
Topthanks, and well as u said it will be simpler to use plain c but the reason is that, i am working on a project and the panel where i have to present it to has a few members who have well little or no knowledge of programming so i am hoping the macros will help in making them understand more easily.
- Log in or register to post comments
TopEh? You have the option of teaching them your very specific macro or the generic C & operator. With the latter they can write 1000's of programs, with the former they are tied to some very specific code for a single situation. Why not teach them how AND works?
- Log in or register to post comments
Topwell cos i am a student myself. and i am showing a presentation to justify the funding of my project, and the people on the panel will be staff of various departments, some of who may not know programming .that's why am using the macros to give a generalized presentation. I have even broken down my whole code into functions with general names for hopeful easier understanding.
- Log in or register to post comments
TopRegards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
Topi do have some idea on the working of macros now,thanks to the tutorial. And i do know basic programming so i know what happens when u use a particular macro. I am already done with my coding using c. Just needed the macros to hopefully make it easier to explain.
- Log in or register to post comments
TopThanks for the great Tutorial, it's awsome!
I just got a really crazy idea and Im not sure if it can actually be impemented.
To create a byte object in which every bit corresponds to a certain Pin on a port?
I'm not sure if Im using the right words here but an example should help:
create some object, maybe a structure (?) that looks like this:
object {Bit0 = Portb bit 3
Bit1 = Portc bit 1
...
Bit7 = Portb bit 0
}
so when you store a value into this object it will assign the respective value to those pins
for example,
object = 0xFF
would set Portb bit 3 high, Portc bit 1 high etc.
just wondering, maybe by doing a complicated macro or somethig?
- Log in or register to post comments
TopSearch in this very forum for "bitfield". The bottom line is that struct members can be defined to be 1 bit long and so you can conglomerate 8 on a single byte address. Anyway read the tutorial.
EDIT: I meant this thread:
https://www.avrfreaks.net/index.p...
First rule of programming: simplest is best.
"simplest" rarely involves macros.
- Log in or register to post comments
TopI've read this whole thread, and one topic that's not mentioned regarding port bit twiddling (with or without macros) is interrupts.
Is it considered good practice to disable interrupts when modifying a port pin? Especially if you're using some kind of bit_set() or bit_clear() macro?
The reason is that if the bit being set/cleared is not a constant expression at compile time, then the compiler will have to generate several instructions to read the current port value into a register, manipulate the value, and write it back. If an interrupt triggers after the port value is read, and that interrupt modifies another pin on the same port, when the main program resumes it will write back the stale value for that pin. This issue was previously a bug in the Arduino digitalWrite() implementation: http://code.google.com/p/arduino...
I don't see anyone disabling interrupts in their code-- why not? Is there a reason I've overlooked why it's not necessary?
- Log in or register to post comments
TopThe compiler will not have to generate several instructions, if only one bit is manipulated. AVRs have single machine instructions to manipulate one bit. E.g. activate the optimizer of avr-gcc and see what
generates.
If several bits are modified, then a read-modify-write sequence will be generated, and you will need to turn off interrupts if the port that is manipulated is shared with ISR code. The subject has been discussed in length here at 'freaks. The search words you need are e.g. "re modify write", "atomic" etc...
Ther are also tutorials on interrupt handling in general IIRC.
The avr-gcc support library avrlibc has stuff contributed by Dean Camera ('abcminiuser') that makes atomic sequences, saving and restoring state etc easy to code.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopIt will generate several instructions for RMW if the extended IO space or SRAM is used, which can indeed lead to atomicity issues. Note that the XMEGA and AVR32s have a larger register address space with dedicated SET and CLEAR registers that allow for single-cycle RMW sequences.
On the older AVRs, you'll need to protect against interrupts if you're writing anything but a single bit to the regular IO space.
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
- Log in or register to post comments
TopThanks, that makes sense, and I'll search for the atomic write threads. And to clarify, the situation I was asking about is when the bit being set/cleared is not a constant expression at compile time. I've looked at the disassembly for contant expressions like PORTB |= 1 and it is a single sbi machine instruction, as JohanEkdahl said.
- Log in or register to post comments
TopOh, I missed that vital part of the question. Yes, in that case you are at risk even with single bit operations.
Sorry for any confusion.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopI have added some predefined names to my "sbit.h".
Then you can use "PORT_cn", "DDR_cn", "PIN_cn" direct on the code (c = A..L, n = 0..7).
E.g.:
Peter
P.S.:
The original article:
https://www.avrfreaks.net/index.p...
Attachment(s):
- Log in or register to post comments
TopHello, this is a very good tutorial and thank you but I was wondering if some one could explain something.
When I learned this stuff in school a few years back we only ever masked like you did in the 1st half (ie. foo &= 0x01). Why and when is it necessary to use these shift masks? I was taught using motorola micro's and I was wondering if it was some architecture thing? But as far as I can see they both do the same thing.
Thanks in advance
- Log in or register to post comments
TopNothing says you HAVE to use bitnumbers with shifts. Some would argue that if you are only setting bit 5 of a DDR register to be an output that:
is almost as readable as:
(thought the former may make the engineer count on his fingers to remember that 0x20 is bit 5! ;-))
However where this bit shifting comes into play is to make SFR bit usage more self-documenting. For example in many AVRs bit 5 of the UCSRB register is the bit to enable the UART data register empty interrupt. Now if you read code that says:
or
many engineers (at least those with a passing knowledge of the AVR) will instantly recognise that the second of those is enabling the UDRE interrupt. However it would require a VERY fastidious reader to know that 0x20 (or even (1<<5)) happens to be the UDRIE bit in that register.
Now one might then ask why do I have to use 1<<, if Atmel had written the XML file that is used for Assembler and C header file generation such that:
rather than
then the usage in C would just be:
but the reason they defined the bit names as 0..7 is so that the number can be used with the AVR SBI and CBI opcodes (assuming UCSRB is at the right location). This introduces the minor inconvenience of having to use (1<<UDRIE) to convert 5 into 0x20. In at least one C compiler there is a macro defined as:
so that at least:
can be used which maybe looks a little less "complex" than (1<<UDRIE). However *all* C programmers will recognise the (1<<UDRIE) version but not all are going to know what _BV() achieves without digging into header files - which kind of destroys the readability "gain" in using it.
Remember that at the end of the day all C (and Asm) code should be written with the "next reader" in mind - which could either be the poor sap who has to fix your code 3 years after you left the company or it could simply be you in 9 months when you've forgotten that setting 0x20 in UCSRB is setting the UDRIE bit! (1<<UDRIE) tells you which bit is being set without looking it up (assuming you can at least remember the purpose of "UDRIE")
Cliff
- Log in or register to post comments
TopThey do. It is just about clarity of code. And it is opinous.
Which is clearer? This
or this
?
In the next step, e.g. when dealing with bits in a special purpose register (like a timer control register) it helps a lot to use the symbolic bit numbers rather than some magic numerical constants). Since the bit numbers are, uhmmm..., bit numbers rather than bit masks we need to construct the masks from the numbers. To do this, the shift operator is used.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopCheers, Thanks both of you that makes a lot of sense. Especially since I am that sap that is fixing the code 3 years later :)
- Log in or register to post comments
TopThanks for your information.
- Log in or register to post comments
TopWhat is the difference between
TCCR1B |= (1 << CS10);
and
TCCR1B = (1 << CS10);
Is OR ('|') really needed there or both will work the same.
- Log in or register to post comments
TopThe first only sets one bit and leaves the other 7 bits in the register untouched. The second sets all 8 bits - the other 7 are set to 0.
- Log in or register to post comments
TopThat depends on the circumstances.
Definitively not.
is a shorthand for the equivalent
so all bits that was set before this operation will still be set.
OTOH, if you do
then only the CS10 bit will be set, and all other will be cleared.
I seriously suspect that this has been covered earlier in this thread, so you might have something to gain from browsing through the complete thread..
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopIn the bit manipulation macros of the orignal post:
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
... etc., should the & in the first one be &= ? Would it make any difference?
- Log in or register to post comments
TopNo,
But the fact that it's not obvious kind of proves how pointless these kind of macros are in aiding readability. Think about:
which really says (without all the parenthesis):
As you can see you don't want an '=' in the last one as it's used in a different context to the other two. The confusion here is that then macro names are so similar you might think they'd all be used in the same context.
Stay clear of macros - you know it makes sense!
- Log in or register to post comments
TopYou mean "bit_get" don't you?
Regards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
TopOK, I see it now. It was just my poor reading. Or poor reading glasses.
But I do like these macros. I agree I should make sure I understand how they work, but think they can prevent careless errors if I understand their proper use.
Nick
- Log in or register to post comments
TopIn regard to a problem I just had could some one explain to me the reason this doesn't work properly (it affects all the bits)
And this one does work properly?
- Log in or register to post comments
TopThey would both work just fine as written.
Did you read the tutorial?
What do you mean by properly?
Smiley
- Log in or register to post comments
TopRegards,
Steve A.
The Board helps those that help themselves.
- Log in or register to post comments
Topಠ_à²
- Dean :twisted:
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
- Log in or register to post comments
TopNow if you want to make assumptions about the intent which is unstated, then maybe they don't do what the poster wants them to do, but is that for us to decide or should he tell us what he is trying to do?
Smiley
- Log in or register to post comments
TopPerhaps, but most likely not in a statement lacking ~ and using &= . Discussing if (0<<XXX) is meaningful or clarifying must be done in the context of the complete statement.
E.g. you might very well do
to make it clear that you relly want anotherBit to be clear. Not that the code actually (0<<anotherBitNumber) has the exact effect to actually clears that bit, but you are doing some documentation of intent in the code.
As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here.
No guarantees, but if we don't report problems they won't get much of a chance to be fixed! Details/discussions at link given just above.
"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]
- Log in or register to post comments
TopNo, no , no. The only use of a 0<< is when you want to document the fact that something is deliberately not being set. maybe something like:
Too often we see threads here where the user has grasped the fact that to set a bit they use:
but then see variants of:
where they believe that using 0 in the mask is the way to switch things off. As we all know, it isn't.
This notion should be stomped on from a great height before it confuses more beginners (especially in this thread we all point them towards to learn this stuff!).
The only use of (0 << foo) is to document that foo is not being used.
- Log in or register to post comments
TopPages