| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				| DAC80501 code support |  
				|  Posted: Fri Apr 05, 2024 11:16 am |   |  
				| 
 |  
				| Hello, 
 I want to interface the PIC18F2520 with external 16 bit DAC (Example: DAC80501ZDQFR). Please can you support how to send data to the external DAC. Any code snippets to understand.
 
 Internal Voltage reference: +2.5V
 
 uC PIN SDO is connected to SDA
 uC PIN SCK is connected to SCLK
 uC PIN B1 is connected to SYNC/A0
 
 Earlier I posted a topic for different DAC, but now would like to use this finally.
 
 Thanks in advance.
 |  | 
	
		|  | 
	
		| dyeatman 
 
 
 Joined: 06 Sep 2003
 Posts: 1968
 Location: Norman, OK
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Apr 05, 2024 12:25 pm |   |  
				| 
 |  
				| Are you going to keep changing DACs then asking us for help with each one? If you got the other one going, the same basic code should work for this one with changes to the command byte.
 
 Starting out:
 Read the datasheet...the interface is very similar to the earlier DAC.
 
 Next:
 For SPI you must tie SPI2C Low
 Power on device
 Set SYNC High
 
 Then:
 If needed, set/change bits in 8 bit command byte (0x08 for DAC output)
 set SYNC Low
 Output 8 bit command byte
 Output 8 bit MSB SPI data
 Output 8 bit LSB SPI data
 Set SYNC High
 Rinse and repeat...
 _________________
 Google and Forum Search are some of your best tools!!!!
 |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon May 20, 2024 2:25 am |   |  
				| 
 |  
				| I tried the below code but it is not working. Any comments please. 
  	  | Code: |  	  | #include "18F2520.h" #fuses HS
 #use delay(clock=12000000)
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 // Define SPI pins for DAC80501
 #define DAC_CS    PIN_C2
 #define DAC_SCLK PIN_C3
 #define DAC_MOSI PIN_C5
 
 // Function to initialize SPI for DAC80501
 void init_spi(void) {
 setup_spi(SPI_MASTER | SPI_CLK_DIV_16 | SPI_H_TO_L | SPI_XMIT_L_TO_H);
 output_high(DAC_CS); // Deselect the DAC
 }
 
 // Function to write data to the DAC80501
 void write_dac80501(unsigned int16 value) {
 unsigned int8 high_byte, low_byte;
 
 // Split the 16-bit value into two 8-bit values
 high_byte = (value >> 8) & 0xFF;
 low_byte = value & 0xFF;
 
 // Send the data to the DAC80501 over SPI
 output_low(DAC_CS); // Select the DAC
 spi_write(high_byte); // Send the high byte
 spi_write(low_byte); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 }
 
 void main() {
 unsigned int16 dac_value = 0x8000; // Example value to set DAC to mid-scale
 
 // Initialize SPI
 init_spi();
 
 // Main loop
 while(TRUE) {
 // Write the example value to the DAC
 write_dac80501(dac_value);
 
 // Delay for demonstration purposes
 delay_ms(1000);
 }
 }
 
 | 
 |  | 
	
		|  | 
	
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon May 20, 2024 5:24 am |   |  
				| 
 |  
				| You're not sending the necessary 'command byte' as previous poster posted !!! Curious , I downloaded the datasheet and it does say that you need to send 24 bits ( cmd,hsdb,lsdb) to the chip.
 There's also a LOT of critical hardware design (PCB layout,opamp,parts,etc.) necessary to get accurate, repeatable 16 bit data.
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon May 20, 2024 9:37 am |   |  
				| 
 |  
				| Lets give a hint: 
  	  | Code: |  	  | #define DACREG 0x80 //command byte to select the data register
 // Function to write data to the DAC80501
 void write_dac80501(unsigned int16 value)
 
 // Send the data to the DAC80501 over SPI
 output_low(DAC_CS); // Select the DAC
 spi_write(DACREG);
 spi_write(make8(value,1)); // Send the high byte
 spi_write(make8(value,0)); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 }
 
 | 
 
 This should write the value to the data register. However you will
 probably have to program the configurations first. Turn on the reference
 and the DAC itself (two bits in the CONFIG register), and also program
 the gain of the reference and the DAC itself (GAIN register).
 Also I have not checked that the mode you are setting up in the
 setup, is what this DAC requires. There also may be a problem with your
 use of spi_write for the last byte. By default this command returns as soon
 as the byte is loaded, it does not wait for the byte to actually be sent. So
 as shown the CS (SYNC) signal may be raised too soon. It must not be
 raised till the byte has finished transferring.
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon May 20, 2024 9:38 am |   |  
				| 
 |  
				| Lets give a hint: 
  	  | Code: |  	  | #define DACREG 0x80 //command byte to select the data register
 // Function to write data to the DAC80501
 void write_dac80501(unsigned int16 value)
 
 // Send the data to the DAC80501 over SPI
 output_low(DAC_CS); // Select the DAC
 spi_write(DACREG); //select to write to the data register
 spi_write(make8(value,1)); // Send the high byte
 spi_write(make8(value,0)); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 }
 
 | 
 
 This should write the value to the data register. However you will
 probably have to program the configurations first. Turn on the reference
 and the DAC itself (two bits in the CONFIG register), and also program
 the gain of the reference and the DAC itself (GAIN register).
 Also I have not checked that the mode you are setting up in the
 setup, is what this DAC requires. There also may be a problem with your
 use of spi_write for the last byte. By default this command returns as soon
 as the byte is loaded, it does not wait for the byte to actually be sent. So
 as shown the CS (SYNC) signal may be raised too soon. It must not be
 raised till the byte has finished transferring.
 |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed May 22, 2024 11:03 pm |   |  
				| 
 |  
				| Thanks Ttelmah. It's really helpful  |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jun 20, 2024 11:24 am |   |  
				| 
 |  
				| I tried the below code. Measured DAC output is +5V. I used internal reference 2.5V. Why the output is +5V? What should I modify to get the output of 2.5V at 65535. 
 Please help. 	  | Code: |  	  | #include "18F2520.h" #fuses HS
 #use delay(clock=12000000)
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 // Define SPI pins for DAC80501
 #define DAC_CS   PIN_C2
 #define DAC_SCLK PIN_C3
 #define DAC_MOSI PIN_C5
 
 #define DACREG 0x08 //command byte to select the data register
 
 // Function to initialize SPI for DAC80501
 void init_spi(void) {
 setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64);
 output_high(DAC_CS);  // Deselect DAC
 }
 
 // Function to write data to the DAC80501
 void write_dac80501(unsigned int16 value)
 {
 // Send the data to the DAC80501 over SPI
 output_low(DAC_CS); // Select the DAC
 spi_write(DACREG);
 spi_write(make8(value,1)); // Send the high byte
 spi_write(make8(value,0)); // Send the l     ow byte
 output_high(DAC_CS); // Deselect the DAC
 }
 
 void main() {
 unsigned int16 dac_value;
 
 // Initialize SPI
 init_spi();
 
 // Send the data to the DAC80501 over SPI
 value1 = 0x000A;   // Soft reset
 output_low(DAC_CS); // Select the DAC
 spi_write(0x05);   // TRIGGER Register
 spi_write(make8(value1,1)); // Send the high byte
 spi_write(make8(value1,0)); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 
 // Send the data to the DAC80501 over SPI
 value1 = 0x0100;   // REF-DIV divided by 2; Gain set to 1
 output_low(DAC_CS); // Select the DAC
 spi_write(0x04);   // Gain register
 spi_write(make8(value1,1)); // Send the high byte
 spi_write(make8(value1,0)); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 
 dac_value = 65535;
 
 // Main loop
 while(TRUE) {
 // Write the example value to the DAC
 write_dac80501(dac_value);
 
 // Delay for demonstration purposes
 delay_ms(1000);
 }
 }
 
 | 
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jun 20, 2024 11:39 am |   |  
				| 
 |  
				| You need a delay after sending reset. Minimum 250uSec. |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jun 20, 2024 12:03 pm |   |  
				| 
 |  
				| Brilliant. But where it is mentioned in the datasheet? Just curious. |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jun 20, 2024 1:09 pm |   |  
				| 
 |  
				| You have to put two things together. 
 8.3.3 Power-On-Reset (POR) where is says it takes 250uSec before a
 command can be accepted.
 
 Then the note in 8.3.4, "A software reset initiates a POR event."
 |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Jun 20, 2024 2:18 pm |   |  
				| 
 |  
				| Thank you Ttelmah  |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jun 21, 2024 7:27 am |   |  
				| 
 |  
				| I'm also using the 24 bit ADC LTC2410 in the same project. ADC code is working fine separately. When the ADC measured after the line
 
 DAC init
 
 Then the ADC measurement is not correct. 	  | Code: |  	  | setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64); | 
 
 ADC code:
 Any suggestions 	  | Code: |  	  | signed int32 Read_A2D(void) {
 int x;
 signed int32 data = 0;
 
 output_high(A2D_SCLK);
 delay_us(200);
 output_high(A2D_CSI);
 output_low(A2D_SCLK);
 output_low(A2D_CSI);
 
 data = 0;
 
 while((input(A2D_SDO))==1); //wait for /EOC to go low...
 
 for (x = 32; x!=0; x--)
 {
 output_high(A2D_SCLK); //clock hi
 delay_us(15);      //   15us it was
 if (input(A2D_SDO))
 bit_set(Data, x - 1);
 output_low(A2D_SCLK); //clock low
 delay_us(15);
 //      delay_us(10);
 }
 
 output_high(A2D_CSI);
 
 return data;
 }
 | 
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jun 21, 2024 9:40 am |   |  
				| 
 |  
				| What pins are used for the ADC connection?. You do realise just how good the electrical design is going to need to be
 to work at these levels.
 Are any interrupts enabled?.
 Why the delays in the ADC sampling loop?. The times for this are nSec, not
 uSec.
 |  | 
	
		|  | 
	
		| hemnath 
 
 
 Joined: 03 Oct 2012
 Posts: 242
 Location: chennai
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jun 21, 2024 9:47 am |   |  
				| 
 |  
				| Testing code. But capturing ADC issue.  	  | Code: |  	  | #include "18F2520.h" #fuses HS
 #use delay(clock=12000000)
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 // ADC PIN Assignments
 #define A2D_CSI      PIN_C1
 #define A2D_SCLK    PIN_C3
 #define A2D_SDO      PIN_C4
 
 // Define SPI pins for DAC80501
 #define DAC_CS   PIN_C2
 #define DAC_MOSI PIN_C5
 
 #define RS485_EN   PIN_B1
 
 #define DACREG 0x08 //command byte to select the data register
 
 signed int32 A2D_value = 0;
 
 // Function to initialize SPI for DAC80501
 void init_spi(void) {
 setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64);
 output_high(DAC_CS);  // Deselect DAC
 }
 
 // Function to write data to the DAC80501
 void write_dac80501(unsigned int16 value)
 {
 // Send the data to the DAC80501 over SPI
 output_low(DAC_CS); // Select the DAC
 spi_write(DACREG);
 spi_write(make8(value,1)); // Send the high byte
 spi_write(make8(value,0)); // Send the l     ow byte
 output_high(DAC_CS); // Deselect the DAC
 }
 
 signed int32 Read_A2D(void)
 {
 int x;
 signed int32 data = 0;
 
 output_high(A2D_SCLK);
 delay_us(200);
 output_high(A2D_CSI);
 output_low(A2D_SCLK);
 output_low(A2D_CSI);
 
 data = 0;
 
 while((input(A2D_SDO))==1); //wait for /EOC to go low...
 
 for (x = 32; x!=0; x--)
 {
 output_high(A2D_SCLK); //clock hi
 delay_us(15);      //   15us it was
 if (input(A2D_SDO))
 bit_set(Data, x - 1);
 output_low(A2D_SCLK); //clock low
 delay_us(15);
 }
 
 output_high(A2D_CSI);
 
 return data;
 }
 
 
 void main() {
 unsigned int16 dac_value, value1;
 
 delay_ms(1000);
 
 output_high(RS485_EN);
 output_high(A2D_CSI);
 output_high(DAC_CS); // Deselect the DAC
 
 // Initialize SPI
 init_spi();
 
 // Send the data to the DAC80501 over SPI
 value1 = 0x000A;   // Soft reset
 output_low(DAC_CS); // Select the DAC
 spi_write(0x05);   // TRIGGER Register
 spi_write(make8(value1,1)); // Send the high byte
 spi_write(make8(value1,0)); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 
 delay_ms(500);
 
 // Send the data to the DAC80501 over SPI
 value1 = 0x0100;   // REF-DIV divided by 2; Gain set to 1
 output_low(DAC_CS); // Select the DAC
 spi_write(0x04);   // Gain register
 spi_write(make8(value1,1)); // Send the high byte
 spi_write(make8(value1,0)); // Send the low byte
 output_high(DAC_CS); // Deselect the DAC
 delay_ms(100);
 
 dac_value = 65535;
 
 // Main loop
 while(TRUE) {
 
 
 A2D_value = Read_A2D();
 delay_ms(200);
 
 write_dac80501(dac_value);
 
 printf("\r\naverage: %8Ld", A2D_value);
 delay_ms(1000);
 }
 }
 
 | 
 |  | 
	
		|  | 
	
		|  |