How to write hexadecimal variables to PORTA of Arduino Mega 2560 ?

Hi! everybody,

I am working with a simple function, this function obtain some integer variables, So it's where I have a doubt.
I want to write hexadecimal variables towards the PORTA due the instruction of the LM629N-8 controller's guide programming. I only understand how to print hexadecimal values through Serial port. But I don't know write Hex values to PORTA of Arduino Mega 2560.

let you an example of sintaxis:

PORTA = 0x00; where 0x00 is not a constant in my sketch, I need to write a hexadecimal variable.
:frowning:

Assuming x is the byte variable holding your data you just do PORTA = x; hexadécimal is just a screen representation, the PORT register does not care one minute about that, it wants a byte (8 bits)

Hi! JML,
Thanks! for your response, mmm.. the variable is of unsigned long int type. for example the variable can give me a 63,000 as integer value.

:confused:

It's ok. I understand your idea about the PORTA wants a byte, and the hexadecimal is only a screen representation.

Thanks! for your help! JML.

You can write a byte to a 8 bit port.

unsigned long is 4 bytes.

Thank you! larryd. mmmm. I will use the [Bitwise Operators] and write byte per byte from my data variable.

If you have unsigned long x = 0xAABBCC[color=red]DD[/color]; and do PORTA = x; the compiler knows PORTA is a byte and thus will do the masking for you and only get 0x[color=red]DD[/color]; automagically into PORTA

The true question is why the h*ll are you using 32 bits to handle something that needs to go into 8 bits though :slight_smile: and secondly how does whatever system is on the other side of PORTA know that the data is there to read ?

Oh! excellent questions,

I have some fuctions into my sketch to enable the lines control to read/write to Host I/O parallel communication port by extarnal hardware. I will try to use the Bitshiftright operator to write a unsigned long variable. Because it's right the controller has some registers of 32 bits.

Ok so you would do

const byte clockPin = 3; // whatever you use for signaling
unsigned long x = 0xAABBCCDD;
....
pinMode(clockPin, OUPUT);
DDRA = 0xFF; // PORTA as ouput
...

unsigned long xCopy = x; // thé copy will get modified
for (byte i=0; i<4; i++) {
   digitalWrite(clockPin, HIGH); // tell host controller data is not safe anymore
   PORTA = xCopy & 0xFF; // masking un-necessary technically but for sake of clarity
   digitalWrite(clockPin, LOW); // signal data ready
   delay(1); // wait a bit - could be more effective in microseconds 
   xCopy>>=8; // shift the bits;
}
1 Like

mmm.. To be honest I'm pretty excited for your code JML, I understood it, it's simple and good.

I'll be working with the sketch, Thank you for your time and suggestions.

:slight_smile:

If you have unsigned long x = 0xAABBCCDD; and do PORTA = x; the compiler knows PORTA is a byte and thus will do the masking for you and only get 0xDD; automagically into PORTA

Is it logically correct to write 32-bit data into an 8-bit destination though it is physically correct because the compiler does the necessary adjustment?

What is about using a union?

void setup() 
{
  Serial.begin(9600);
  union {
          byte dataArray[4];       //dataArray[0] contains 0xDD
          unsigned long data = 0xAABBCCDD;
       } myData;

  for (int i=0; i<4; i++)
  {
    PORTA = myData.dataArray[i];
    //wait for ACK before sending the next byte
  }
}

void loop() 
{
  
}

GolamMostafa:
Is it logically correct to write 32-bit data into an 8-bit destination though it is physically correct because the compiler does the necessary adjustment?

What is about using a union?

Yes Implicit conversions are automatically performed when a value is copied to a compatible type. Some of these conversions may imply a loss of precision, which the compiler can signal with a warning. This warning can be avoided with an explicit conversion. So Unless you actually cast the value with PORTA = (uint8_t) (xCopy & 0xFF);you will get a warning. (which i intentionally left for OP :slight_smile: )

Your union approach is actually compiler dependent and not guaranteed to work all the time depending on how you build the union or the compiler you use. The spec mentions

The union is only as big as necessary to hold its largest data member. The other data members are allocated in the same bytes as part of that largest member. The details of that allocation are implementation-defined, and it's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union.

so my advice (although I know your example would work with GCC for an arduino) would be to stay away from reading from the inactive member and use pointers into the unsigned long bytes if you want to avoid shifting the bits - which is basically what the compiler does for you using your 4 bytes array

uint32_t x = 0xAABBCCDD;
uint8_t * ptr = (uint8_t*) &x; // pointer to the first  byte
for (byte i=0; i<4; i++) {
   digitalWrite(clockPin, HIGH); // tell host controller data is not safe anymore
   PORTA = *ptr;
   digitalWrite(clockPin, LOW); // signal data ready
   delay(1); // wait a bit - could be more effective in microseconds 
   ptr++; // Go to next byte in memory
}

The art of getting good answers lies in asking good questions.

  • @ J-M-L