0

I want to take 2 different outputs from my DAC from void setDacOutput function (and it should be switching with/like the timer for both outputs. One output of 2.9375V for 0.9ms from ISR if statement and other of 2.5V for 1.6ms from else statememt) but my DAC only gives one output (in ISR - interrupt service routine only one of the if statement dacfunction or the else statement's (when if statement is commented) runs, not both). I want the DAC to give value for both if and else statement in ISR. For the given code it is only giving 2.9375Volts (called in isr-if statement). Not giving 2.5V (called in isr-else statement).

My timer is giving correct output when I connect oscilloscope to Pin9 and gnd (0.9ms on and 1.6ms off).I am using TLV5616 DAC from TI. And I’ve tried to print something in both if and else of ISR and they work but Dacfunction runs only once giving only one output. Maybe something wrong with SPI. Any help will be extremely appreciated please.

This is my code:

// TLV5616 DAC communication using SPI
#include <SPI.h>

/*  TI TLV5616CP (2.7 to 5.5V) LP 12-Bit Digital to Analog Converter
For sensor details see: http://www.ti.com/lit/ds/sbas415c/sbas415c.pdf


Circuit:
TLV attached to Uno pins as follows:
TLV Pin         Uno Pin
1 (DIN)         11 (MOSI - Output)
2 (SCLK)        13 (SCK - Output)
3 (/CS)          8 (Chip selec8t - Output)
4 (FS)          10 (SS - Output)


Note: TLV5616 has no provision for MISO pin 12, output is in volts



// Pin 8 = /CS, Pin 10 = SS
const int chipSelect = 8;
const int slaveSelect = 10;


// Variables for TLV5616 Testing
const unsigned int control = 0x4000;
const unsigned int msbMask = 0xFF00;
const unsigned int lsbMask = 0x00FF;
unsigned int command, data;
byte commandMsb, commandLsb;


//Variables for timers setting
uint16_t timerOneVal[] = {14400, 25600}; 
uint8_t timerTwoVal[] = {90, 160};
bool timerOneItr = 0;
bool timerTwoItr = 0;


void setup(void)
{
  Serial.begin(9600);
  /* To "condition" the hardware we begin with the call: SPI.begin()
  which configures the SPI pins (SCK, MOSI, SS) as outputs. It sets
  SCK and MOSI low and SS high. It then enables SPI mode with the
  hardware in master mode which has a side effect of setting MISO as
  an input.

  The SPI.transfer call does the actual transfer of bytes. I must
  set /CS and SS at the appropriate time */



  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV2);       // Freq SPI_CLK = 8MHz
  SPI.setDataMode(SPI_MODE1);                // CPOL = 0, CPHA = 1
  pinMode(chipSelect, OUTPUT);
  pinMode(slaveSelect, OUTPUT);


  pinMode(9, OUTPUT);


  digitalWrite(9, LOW);

  setTimers();

}


void setTimers()
{
  cli();

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;
  OCR1A = 0xFFFF;                   // set compare match register first time to full value (change values later on in the Interrupt service routine - ISR)
  TCCR1A = 0x40;                    // toggle OC1A on compare
  TCCR1B = 0x09;                    // Set CS10 and WGM12 bits for no prescaling and turning on CTC mode                                   
  TIMSK1 = 0x02;                    // enable timer compare interrupt

  sei();

}

void setDacOutput(unsigned int dacValue)
{
    digitalWrite(chipSelect, LOW);             // Enable TLV5616 /CS
    digitalWrite(slaveSelect, LOW);            // Enable TLV5616 FS


    /* The TLV5616 control bits are D14 and D13, D15 and D12 is don't care. The data
    to be written to the TLV5616 is in Bits D11 to D0. commandMsb is the (8-bit) MSB
    and commandLsb is the (8-bit) LSB of the 16-bit TLV5616 control word */


    command = control | dacValue;
    commandMsb = (command & msbMask) >> 8;
    commandLsb = command & lsbMask;
    SPI.transfer(commandMsb);
    SPI.transfer(commandLsb);
    delayMicroseconds(1);
    digitalWrite(slaveSelect, HIGH);            // Disable TLV5616 FS
    digitalWrite(chipSelect, HIGH);             // Disable TLV5616 /CS
//    SPI.end(); 
}



ISR(TIMER1_COMPA_vect)
{

  OCR1A = timerOneVal[timerOneItr];

  if(!timerOneItr){
    setDacOutput(0x0966);     // 2406/0x0966 for 2.9375V; 2045/0x0800 for 2.500V;
    timerOneItr = !timerOneItr; 
  }
  else{
    setDacOutput(0x0800);
    timerOneItr = !timerOneItr;
  }

}
  • Majenko I accidentally deleted your answer. Can you kindly post again please? – Muhammad Uzair Arif Mar 19 at 22:57
  • Majenko Sir, I accidentally deleted your answer before even being able to read. Can you please post it again kindly? – Muhammad Uzair Arif Mar 19 at 23:10
  • 2
    you are mistaken about the answer from @Majenko .... you cannot delete someone's answer ... the answer would still be here – jsotola Mar 20 at 4:28
  • Perhaps Majenko removed the answer because it was not right? to be honest, you're asking about Dacfunction running once, but since there's no function called Dacfunction or even just Dac only you could possibly guess what you are referring to – Jaromanda X Mar 20 at 8:45
  • @MuhammadUzairArif I did not write an answer. I edited your question to place your code in a code block. That is all. – Majenko Mar 20 at 10:59

Your Answer

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

Browse other questions tagged or ask your own question.