can you read or write 8 bits at once?

I'm trying to interface a Mega2560 to 3 Siemens DL3416 alpha numeric displays. Since there are no libraries written for these displays, I'm trying to learn some details of how things work in the libraries. Being a likely good example, I read through the LiquidCrystal library .cpp file and the .h file, but I'm not seeing what I expected. I confess I'm not real good at any programming language, especially C or C++.

Right now I can do simple things like turn on the cursor in any given character position, so timing is not an issue, but it's very tedious addressing the displays using the bit wise I/O. Is there a way to read or write an entire 8 bit "port" or do I have to shift array values and write a bit at a time? I've searched the forums for bytewise, bytewide, etc., but didn't find the right thread I guess. I'm sure this has been a topic before.

If all of the wires are on the same port, then yes you can.

For example if all of your data pins were on Port C, you could use:

PORTC = 21; //set bits 0,2,4 to a 1, the rest to 0.

can you read or write 8 bits at once?

Yes if they are in the same byte. Otherwise no.

Uh-oh. Unless I'm unbelievably lucky, I probably don't have them aligned that way.
I'll have to check it. Thanks a LOT for the answers.

I don't know your particular device but those devices typically don't "read" the data pins until they are "strobed", ie. a particular pin is going through a transition. In that case, no atomicity of writing to the data pins makes zero difference.

Yes you can directly manipulate the I/O 'ports' to read or write all bits in a given I/O port in a single instruction. However depending on which arduino board type you have not all 8 bits for each port are avalible for use.

So here is the software methods

And here is a pin mapping diagram to associate arduino pin numbers to port/bit numbers for the 168/328 chips and the 1280/2560 chips:

https://spreadsheets.google.com/pub?key=rtHw_R6eVL140KS9_G8GPkA&gid=0

Lefty

PORTC = 21; //set bits 0,2,4 to a 1, the rest to 0.

A far better way to accomplish this would be to use binary. Typically it is the bits that are important, not the numerical value. When you try to do the conversion yourself the very best you can do is get it correct. The compiler gets it correct every time.

PORTC = B00010101; //set bits 0,2,4 to a 1, the rest to 0.

For some unfathomable reason this is not possible with some C compilers but as far as I know it works ok with the Arduino.

Don

1 Like

In Arduno it works fine (as there are #defines in the Binary.h file which define all of the 8bit binary numbers). However in C, binary literals are not part of the specification so the strictest of compilers just spit them out.
With GCC, there is built in support for binary literals, so you can use things like 0b or 0B to denote a binary number. It is beyond me why the people at Arduino decided to define there own binary numbers rather than use the GCC ones.

I read that all 8 bit binary numbers had been explicitly defined in Arduino and was surprised that they were not "natively" supported in C/C++. But I have a question. I just tried this: int x = B01001100; and the compiler didn't complain. Then I tried adding 8 more bits and it squawked. I guess that makes sense if only the first 256 binary numbers are defined, but doesn't it take 16 bits to be an integer type? Does this mean you can access only the low byte in an integer using binary?

sellonoid:
I read that all 8 bit binary numbers had been explicitly defined in Arduino and was surprised that they were not "natively" supported in C/C++. But I have a question. I just tried this: int x = B01001100; and the compiler didn't complain. Then I tried adding 8 more bits and it squawked. I guess that makes sense if only the first 256 binary numbers are defined, but doesn't it take 16 bits to be an integer type? Does this mean you can access only the low byte in an integer using binary?

Try using the 0b syntax that is built into gcc, e.g. int x = 0b10101010101010

The microcontroller itself works in binary and has not problems using 16bit binary numbers - in fact all decimal and hex numbers are converted to binary anyway. The problem is just telling the compiler that the number you have written should be treated as if it is already in binary and that is what is missing from the C specification.
When you try and save an 8 bit number to a 16bit int, the microcontroller simply assumes the upper 8 bits are all zero (unsigned) or all one (both are signed and the 8bit number is negative).

That's cool, it worked! if you can do that, why would they explicitly define 00000000 - 11111111? That's rhetorical as I don't expect you to defend it.

My preference is to use a "bit" macro that defines a constant for an individual bit
then OR them together to create other constants.
I also like to use individual defines for each bit because usually the bits mean something
and you can assign them mnemonic names for clarity.

It makes the code easier to read and much less prone to errors since when typing in
binary constants it is easy to miscount the bits and create incorrect constants.

For example all these assignements to "mask" are the same
yet at least in my in my view the last one is the easiest to tell what
is going on:

#define BIT(x) (1 <<x)
#define RED BIT(0)
#define GREEN BIT(1)
#define BLUE BIT(2)
#define YELLOW (RED |  GREEN)
#define LED_ON BIT(15)

const int mask = 0b1000000000000011;
const int mask = BIT(15) | BIT(1) | BIT(0);
const int mask = LED_ON | GREEN | RED;
const int mask = LED_ON | YELLOW;

Note: The AVR tools define _BV() the same as BIT() above
but it is non standard. If you define it yourself, then the code
will work on any C compiler.

--- bill


floresta:

PORTC = B00010101; //set bits 0,2,4 to a 1, the rest to 0.

For some unfathomable reason this is not possible with some C compilers but as far as I know it works ok with the Arduino.

Don

This is not a C compiler issue but rather a self created issue by
team Wiring/Arduino

All C compilers support binary constants.
The problem is what I can only describe as what appears to be a NIH (not invented here) mindset in team Wiring/Arduino
which often decides that having a similar yet proprietary way of doing things
is better than simply explaining the real way of doing things in the language being used: C/C++
In this case the team Wiring/Arduino guys invented their own binary constants.
This kind of deliberate duplication of functionality
has always frustrated and annoyed me particularly because just like in this
case it isn't a complete replacement for the built in solution.

I mean why not simply explain that the binary syntax is

0bxxxxxxxx

How is that any harder than
Bxxxxxxxx

Which is non standard, requires a custom header file and
a define for every single Bxxxxxxxx define?
Today's Arduino solution only works for 8 bit values.
Take a look at binary.h down in the core directory
sometime. It is comical and yet sad at the same time.

The method they have used does not scale beyond 8 bits.

Think of the size of that header file if it needs to support
16 bit numbers or the impossibility of using it for
32 bit binary constants for something like DUE?

bperrybap:
All C compilers support binary constants.

ANSI C has no support for binary literals.

The 0bxxxxx format is something GCC adds as an extension to the standard. I think a couple of other compilers have similar extensions as well, but not all by any means.

I stand corrected. Thank you for that clarification.
I feel silly for not verifying it first. I'm so used to gcc (been using it since the late 80's)
I forget to check on what the real standard supports.
Kind of odd that there is no support for binary literals in ANSI C.
Oddly enough in over 30 years of embedded C programming I have yet to ever
use binary literals.

--- bill

Kind of odd that there is no support for binary literals in ANSI C.

No not odd at all.
Binary constants are only used by people who are scared of Hex. The Hex constant is a much easier thing to use. If I had my way I would ban binary constants.

I agree, once you get used to hex there is little need for binary.

For those that don't know, here is a little tip for Binary to hex conversion:

Take a binary number (works for any number of bits, but lets choose 13 to demonstrate):

0b1101101101010

Split it into groups of four bits starting from right to left

   1   1011   0110   1010

If there arent a multiple of four bits, then pad with zeros until there are (now you see why I chose 13)

0001   1011   0110   1010

Now convert each group into decimal [base 10] (you can skip this step when you get used to it)

  1      11      6     10

Now convert each group into hex [base 16]

  1       B      6     A

Finally, stick it back together, and you have your hexadecimal number:

0x1B6A