0
\$\begingroup\$

I bought the DAC7612 and would like to make it communicate with a PIC18F26K80 microcontroller. It is specified on the Farnell website that you can use SPI communication, but there is nothing about SPI in the DAC7612 datasheet.

Indeed, the microcontroller must send 14 bits to the DAC (2 to choose the output of the DAC and 12 data bits). The SPI communication allows to send 8 bits at a time. It is therefore not possible to use it I guess.

So I decided to use bit banging but I don't get any voltage at the output of the DAC7612. However, I can observe with the oscilloscope the signals sent by the microcontroller (CLK, SDI, CS, LOADDACs). Here is the code:

void loadDAC(uint16_t d)
{
uint16_t dac;
uint8_t i;
 
dac = d | 0x2000;           // DAC Port A
LOADDACS_SetHigh();
CS_DAC_SetLow();            // CS_DAC low level
__delay_us(0.03); 
 
for(i = 0; i < 14u; i++)
 {
 if(dac & 0x2000)
      SDO_DAC_SetHigh();        // SDO high level
 else
      SDO_DAC_SetLow();         // SDO low level
 
 CLK_DAC_SetHigh();             // SCK high level
 __delay_us(0.1);
 CLK_DAC_SetLow();              // SCK low level 

 dac <<= 1;  
 }
__delay_us(0.03); 
CS_DAC_SetHigh();           // CS_DAC high level
LOADDACS_SetLow();
__delay_us(0.03);
LOADDACS_SetHigh();
}

Thank you for reading.


Code for SPI Communication but still nothing:

        dac_value =0xFFF;   // 12 bits resolution
        
        LOADDACS_SetHigh();
        SPI_Open(SPI_DEFAULT);
        CS_DAC_SetLow();
        SSPBUF = (uint8_t)(dac_value >> 6)| 0x80; // 0x80 : select DAC Port A and send 4 MSB
        while(!SSPSTATbits.BF);
        SSPBUF = (uint8_t)(dac_value << 2 & 0x00FF);    // Send 8 LSB
        while(!SSPSTATbits.BF);
        CS_DAC_SetHigh();
        SPI_Close();
        LOADDACS_SetLow();
        __delay_us(0.03);
        LOADDACS_SetHigh();
\$\endgroup\$
8
  • \$\begingroup\$ What makes you think that the SPI peripheral would not be suitable? Is it because 14 is not divisible by 8? \$\endgroup\$
    – polwel
    Jun 21 at 11:23
  • \$\begingroup\$ If I send two SPI frames, the DAC will receive 16 bits and not 14. I tried this code for the SPI communication but I still have nothing in output: \$\endgroup\$
    – Untitled07
    Jun 21 at 12:03
  • \$\begingroup\$ If you send 16 bits, then the very first two will be clocked out and discarded. \$\endgroup\$
    – polwel
    Jun 21 at 12:15
  • \$\begingroup\$ Well @polwel , by sending two frames of 8 bits in SPI, I read a voltage in output but it is the mess. The output is either A and B (dac_value=0xPXXX where P ={0 - 2 - 4 - 6 - 8 - A - C - E}) or only B (dac_value=0xPXXX where P ={1 - 3 - 5 - 7 - 9 - B - D - F}). Thanks for your time. \$\endgroup\$
    – Untitled07
    Jun 21 at 15:08
  • 1
    \$\begingroup\$ I don't follow your reasoning, but it is entirely irrelevant how many bits you send. The only thing that matters are the last 14 bits the moment LOADDACS is strobed. There is no reason why the SPI peripheral cannot be made to work here. \$\endgroup\$
    – polwel
    Jun 21 at 15:55
0
\$\begingroup\$

In the bit-banged code you seem to be missing a delay between setting the output and setting the clock high (\$t_{DS}\$ in the datasheet and also \$t_{CL}\$). Not sure if this is significant though.

Your 0.03 us delay (but how accurate is that delay function and does it actually take a float argument?) is also exactly the minimum value and should be increased a bit. Maybe start with 1 us delays everywhere -- or even 10 us, then fine-tune.

You may also be missing a first high-to-low clock transition before the first iteration of the loop (clock should idle high), which would offset everything by one bit.


In your SPI code, you've left-aligned the 14 bits instead of right-aligning them, so everything is off by two bits and the device would use the 2 MSB of the value for output selection instead of A1 and A0 (which get shifted out). The first word for output A should be (dac >> 8) | 0x20 and the second word dac & 0xFF.

But, your SPI clock phase and polarity settings also look wrong -- I think it should be SPI_CPHA1 | SPI_CPOL1 instead of SPI_DEFAULT. As you've set it, the DAC will be off by one bit in the other direction.

So the net effect of the two mistakes is that everthing is shifted by one bit, just like for the bit-banged code! It will read A0 for A1 and the MSB of the value for A0. This produces the behaviour you describe: your A1 input doesn't matter, A0 = 1 (P odd) combines with the MSB of 0xFFF to give you register B (H-H in the truth table), and A0 = 0 (P even) combines with the MSB of 0xFFF to give you register A and B (L-X in the truth table).

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for your reply. Well it seems to work but with the same problems as the SPI communication that I explained in a comment. This is very weird. \$\endgroup\$
    – Untitled07
    Jun 21 at 15:14
  • \$\begingroup\$ @Untitled07 I've updated the answer according to that new info. \$\endgroup\$
    – DamienD
    Jun 21 at 22:31
  • \$\begingroup\$ Thank you @DamienD ! It works much better when the code is correct ^^ SPI_Default was created by the MCC plugin in which I configured the SPI bus, it corresponds to CPHA = CPOL = 1 \$\endgroup\$
    – Untitled07
    Jun 22 at 8:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.