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.
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)
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 and secondly how does whatever system is on the other side of PORTA know that the data is there to read ?
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.
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;
}
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 )
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
}