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: 1933 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: 9221 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: 19495
|
|
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: 19495
|
|
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.
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);
}
}
| Please help. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
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: 19495
|
|
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
Code: | setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64); | Then the ADC measurement is not correct.
ADC code: 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;
} | Any suggestions |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
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);
}
}
|
|
|
|
|