lowByte highByte, separating 32-bits

I am trying to program a DDS board (AD9959) with an Arduino Uno and need to set a frequency tuning word. The frequency tuning word is 32 bits long, but using SPI.transfer, I can only write 8 bits at a time.

Ideally I would like to enter a decimal number, and have the code figure out the appropriate bytes to send. I have attempted to do this using lowByte. However when I upload the code to view the bitstream on an oscilloscope, no data is being sent. Which means I am probably not using lowByte correctly.

  //Generating decimal Freq. Tuning Word (FTW)
    unsigned long _ftw = freqOut*RESOLUTION/refClk; //32 bits long
  
    //Splitting into 4 bytes for writing
    byte ftw[] = {lowByte(_ftw >>24), lowByte(_ftw >>16), lowByte(_ftw >>8), lowByte(_ftw)};

    digitalWrite(SS, LOW);
    
      //Writes the data in each register for each byte contained within
      for(int i = 0; i < registerInfo[1]; i++){
    
          SPI.transfer(ftw[i]);
        
      }
    
    digitalWrite(SS, HIGH);

When I feed the exact same code the expected binary numbers instead of the line with the lowBytes:

byte ftw[] = {1000000, 00000000, 00000000, 00000000};

The program I am running works just fine.

Any suggestions on how to fix, or alternative methods to split up 32-bits into 4 bytes?
~Thanks

union
Discussed a few times on this forum.

(type punning is bad)

but using SPI.transfer, I can only write 8 bits at a time.

There is also this command

SPI.transfer(buffer, size)

this should work

SPI.transfer((uint8_t*)&_ftw, 4);
byte ftw[] = { B01000000, B00000000, B00000000, B00000000 };
byte ftw[] = { B1000000, 0, 0, 0 };

cattledog:
There is also this command

SPI.transfer(buffer, size)

this should work

SPI.transfer((uint8_t*)&_ftw, 4);

Wrong endianess. Think again...

    unsigned long _ftw = freqOut*RESOLUTION/refClk; //32 bits long

What are the definitions of freqOut, RESOLUTION, and refClk?

I'm suspecting that freqOut and/or refClk are not actually 32bit numbers, and therefore the expression is being computer in 16bit ("int") math, giving unexpected results.

#defined Constants for integers to be used in 32bit calculations should get a "L" or "UL" suffix. Or a decimal point, if you want the compiler to do intermediate calculations in floating point.

westfw:

    unsigned long _ftw = freqOut*RESOLUTION/refClk; //32 bits long

What are the definitions of freqOut, RESOLUTION, and refClk?

I'm suspecting that freqOut and/or refClk are not actually 32bit numbers, and therefore the expression is being computer in 16bit ("int") math, giving unexpected results.

#defined Constants for integers to be used in 32bit calculations should get a "L" or "UL" suffix. Or a decimal point, if you want the compiler to do intermediate calculations in floating point.

All of the variables in that expression are unsigned longs. freqOut is 80000000 (80Mhz), refClk is 500000000 (500Mhz), and Resolution is 2^32. So they should all be nearly 32 bits.

    unsigned long _ftw = freqOut*RESOLUTION/refClk; //32 bits long
// freqOut is 80000000 (80Mhz), refClk is 500000000 (500Mhz), and Resolution is 2^32.

Wait; RESOLUTION is what, exactly?
In C, "(2^32)" would be zero, since "^" is the XOR operator.
In AVR-C, 232 will overflow 32bits, and your math will go wonky. (max value for 32bit number is 232-1)
In LOTS of cases, 80000000* will overflow 32bits.

Please post all of the relevant code, including the actual definitions of the constants...

Maybe you DO need to do the calculations with float, or "long long"; As long as the result of the calculations is less than 32bits, and somewhat integer-like, the assignment to long should work OK in the end...
(As an example, the avr-libc _delay_ms() function uses a floating point argument, and does a bunch of floating point calculations internally, all of which are supposed to be constants and disappear into integers by the time the binary is actually produced.

#include "SPI.h"
#include "arduino.h"
#include "BigNumber.h"


//Defining important tester variables
const long refClk = 500000000L; //currently including multiplier, will need to change in the future
const long freqOut = 80000000L; //Desired output freq. temporary soln.
const long RESOLUTION = 4294967296L;

void setup() {
  // put your setup code here, to run once:

      pinMode(SS, OUTPUT);
      pinMode(MOSI, OUTPUT);
      pinMode(SCK, OUTPUT);
    
    //Starting SPI communication
    SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));

    digitalWrite(SS, HIGH);    //Turn off data communication
}

void loop() {
  // put your main code here, to run repeatedly:

  //Generating decimal Freq. Tuning Word (FTW)
    long _ftw = (freqOut*RESOLUTION)/refClk; //00101000 11110101 11000010 10001111
    //long _ftw = 1073741824;

  
    //Splitting into 4 bytes for writing
    byte ftw[] = {lowByte(_ftw >> 24), lowByte(_ftw >> 16), lowByte(_ftw >> 8), lowByte(_ftw)};
    
    digitalWrite(SS, LOW);
     
          SPI.transfer(ftw[0]);
          SPI.transfer(ftw[1]);
          SPI.transfer(ftw[2]);
          SPI.transfer(ftw[3]);
    
    digitalWrite(SS, HIGH);

}

RESOLUTION is the number representing 2^32. (Just faster to type 2^32);

I figured out how to get lowByte to work. I swapped my unsigned longs for longs and the bitstream appeared as expected. However, I found a new problem.

This line:

long _ftw = (freqOut*RESOLUTION)/refClk;

does not work.

When I do the calculation myself (seen in the commented out line below it) and run the code, the program works fine. What is going on here? Have I reached a limitation on the arduino's math skills?

I think I figured out the problem. When trying to do multiplication with longs, multiplying the two longs together created an overflow. I swapped all of those variables in the equation for type long long, and then set my _ftw as type long, and everything started working.

I think I figured out the problem. When trying to do multiplication with longs, multiplying the two longs together created an overflow.

//Defining important tester variables

const long refClk = 500000000L; //currently including multiplier, will need to change in the future
const long freqOut = 80000000L; //Desired output freq. temporary soln.
const long RESOLUTION = 4294967296L;

While I don't like to "lecture", I feel a bit compelled to point out here that if your initial post had been more complete, and included those definitions, we would have come to this conclusion a lot more quickly...