|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Fri Jun 21, 2024 11:10 am |
|
|
The answer is very obvious. You are using the hardware SPI for the DAC.
This uses pins C3, C4 & C5. You then try to use C5 for the software SPI to
the ADC. No wonder it gives problems.
WHY????
Use the hardware SPI for both devices. Separate CS lines. If they need
different modes, then setup two configurations (use #use SPI not
setup_spi, and give these different stream names). |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri Jun 21, 2024 11:23 am |
|
|
how to use #use spi |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Fri Jun 21, 2024 11:28 am |
|
|
Read the manual, and look at the examples.
Unless you have a very old compiler, this is the preferred way to configure
SPI now. Beware though you need to use spi_xfer instead of spi_read or
spi_write. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri Jun 21, 2024 12:36 pm |
|
|
Something like this, Code: | #define DAC_CS PIN_C2
#define ADC_CS PIN_C1
#use SPI(MASTER, SPI1, MODE=0, BITS=32, STREAM=SPI_ADC)
#use SPI(MASTER, SPI1, MODE=0, BITS=16, STREAM=SPI_DAC) |
It would be helpful if you help me to modify the earlier code.
How to receive 32 bit from ADC? |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Fri Jun 21, 2024 4:13 pm |
|
|
Does the below code is fine. Please comment.
Code: | #include <18F2520.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, ERRORS)
// Define your DAC and ADC chip select pins
#define DAC_CS PIN_C2
#define ADC_CS PIN_C1
#define SDI PIN_C4
#use SPI(MASTER, MODE=0, FORCE_HW, BITS=24, STREAM=DAC) //defaults to maximum speed
#use SPI(MASTER, MODE=0, BITS=32, STREAM=ADC) //defaults to maximum speed
void main() {
unsigned int16 dac_value = 0;
int32 dummy;
int32 adc_value;
delay_ms(2000);
printf("\r\nmain");
// Example DAC initialization
output_high(ADC_CS); // Ensure ADC chip select is initially high
output_high(DAC_CS); // Ensure DAC chip select is initially high
printf("\r\nWelcome");
delay_ms(500);
// DAC configuration steps
output_low(DAC_CS); // Select the DAC
dummy=spi_xfer(DAC,0x05000A,24);
output_high(DAC_CS); // Deselect the DAC
delay_ms(500);
printf("\r\nDAC step 1 done");
delay_ms(500);
output_low(DAC_CS); // Select the DAC
dummy=spi_xfer(DAC,0x040000,24);
output_high(DAC_CS); // Deselect the DAC
printf("\r\nDAC step 2 done");
delay_ms(500);
dac_value = 65535;
// Main loop for DAC operation
while (1) {
printf("\r\nwhile loop");
delay_ms(500);
// Example DAC write operation
output_low(DAC_CS); // Select DAC
dummy = spi_xfer(DAC,0x8, 8); // Write data to DAC
dummy = spi_xfer(DAC,dac_value, 16); // Write data to DAC
output_high(DAC_CS); // Deselect DAC
// Example ADC read operation (if ADC is connected and configured)
// Uncomment and complete ADC functionality if needed
output_low(ADC_CS); // Select ADC
spi_xfer(ADC, 0xFFFFFFFF, 32); // Send dummy data to start conversion
// adc_value = spi_xfer(ADC, 0x00000000, 32); // Read ADC value
output_high(ADC_CS); // Deselect ADC
while((input(SDI))==1); //wait for /EOC to go low...
output_low(ADC_CS); // Select ADC
adc_value = spi_xfer(ADC, 0x00000000, 32); // Read ADC value
output_high(ADC_CS); // Deselect ADC
printf("\r\nADC Value: %ld", adc_value);
printf("\r\nDAC Value: %lu", dac_value);
delay_ms(500); // Example delay
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Sat Jun 22, 2024 4:12 am |
|
|
A couple of comments/questions:
Are you sure of the mode numbers. Need to check the data sheet for both
devices.
Will both support the maximum SPI rate?. Again need to check the data
sheet.
Code: |
#use SPI(MASTER, MODE=0, SPI1, BITS=24, STREAM=DAC) //defaults to maximum speed
#use SPI(MASTER, SPI1, MODE=0, BITS=32, STREAM=ADC) //defaults to maximum speed
|
You need to tell it what SPI port or pins to use. SPI1 says to use the SPI1
hardware port. Also forces hardware.
If both devices do support the same mode, you can just use one #use,
and the same stream name. The point about using separate streams is
it allows different modes/speeds for the two devices. Leave bits=32,
since you specify the bits used in each transfer.. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Sun Jun 23, 2024 8:24 am |
|
|
I modified the code. DAC is working good. But ADC is not working as expected. Receiving 0 in ADC.
Please support.
Code: |
#include "18F2520.h"
#fuses HS
#use delay(clock=12000000)
#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#define A2D_CSI PIN_C1
#define A2D_SCLK PIN_C3
#define A2D_SDO PIN_C4
#use spi(MASTER, DI=PIN_C4, CLK=A2D_SCLK, MODE=0, BAUD=19200, stream=LTC)
#use spi(MASTER, FORCE_HW, MODE=0, stream=DAC)
// DAC PIN Assignments
#define DAC_CS PIN_C2
#define DAC_MOSI PIN_C5
#define RS485_EN PIN_B1 // RS485 transmit or receive enable pin
#define OUT_CNTRL PIN_B3 // Voltage or current output selection pin
signed int32 A2D_value = 0;
void main()
{
unsigned int32 dummy = 0;
unsigned int32 dac_value = 0;
signed int32 adc_value = 0;
output_high(RS485_EN);
delay_ms(50);
printf("\n\r");
printf("\r\nMain loop\r\n");
output_low(RS485_EN);
delay_ms(50);
output_low(OUT_CNTRL);
// Initialize SPI
output_low(DAC_CS); // Select the DAC
dummy=spi_xfer(DAC,0x05000A,24);
output_high(DAC_CS); // Deselect the DAC
delay_ms(500);
printf("\r\nDAC step 1 done");
delay_ms(500);
output_low(DAC_CS); // Select the DAC
dummy=spi_xfer(DAC,0x040000,24);
output_high(DAC_CS); // Deselect the DAC
dac_value = 16383;
while(1)
{
// DAC TEST
output_low(DAC_CS); // Select DAC
dummy = spi_xfer(DAC,0x8, 8); // Write data to DAC
dummy = spi_xfer(DAC,dac_value, 16); // Write data to DAC
output_high(DAC_CS); // Deselect DAC
output_high(RS485_EN);
delay_ms(50);
printf("\n\r");
printf("\r\nDAC Value = %6lu\r\n", dac_value);
output_low(RS485_EN);
delay_ms(50);
delay_ms(500);
// ADC TEST
adc_value = 0;
output_low(A2D_CSI); // Select ADC
while (input(A2D_SDO) == 1);
adc_value = spi_xfer(LTC, 0x00000000, 32); // Read ADC value
output_high(A2D_CSI); // Deselect ADC
output_high(RS485_EN);
delay_ms(50);
printf("\n\r");
printf("\r\nADC Value = %9ld\r\n", adc_value);
output_low(RS485_EN);
delay_ms(50);
delay_ms(500); // Example delay
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Jun 23, 2024 2:16 pm |
|
|
curious... so....I got the LTCdatasheet
possible problems
1) wrong SPI 'mode'
2) wrong connections
3) grounded ADC input pin
4) SPI speed too fast
I notice you didn't parse the 32 data from the ADC. That should be done !
testing should be done with a known, stable Vin to the ADC, say from a Vreg chip ( 1.2500000000 volts ). That way you know what it's supposed to be.
24 bit ADC is mighty 'tricky' to get good ,let alone GREAT results from. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Sun Jun 23, 2024 2:45 pm |
|
|
Connections are good. Now I can able to see positive results. But will do full testing and confirm. Final modified code. any problems do you see visually.
Code: | #include "18F2520.h"
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP // Internal oscillator
#use delay(clock=12000000) // 12Mhz
#use rs232(baud=9600, xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#define A2D_CSI PIN_C1
#define A2D_SCLK PIN_C3
#define A2D_SDO PIN_C4
#define RS485_EN PIN_B1
#define DAC_CS PIN_C2
#define OUT_CNTRL PIN_B3
#use spi(MASTER, DI=A2D_SDO, CLK=A2D_SCLK, BAUD=100000, BITS=32, MODE=1, stream=LTC)
#use spi(MASTER, DO=PIN_C5, CLK=A2D_SCLK, MODE=0, BAUD=100000, stream=DAC)
signed int32 Read_A2D(void)
{
int1 eoc;
union
{
signed int32 rval;
unsigned int32 raw;
} temp=0;
do
{
output_low(A2D_CSI);
eoc = input_state(A2D_SDO);
output_high(A2D_CSI); //clock in the EOC bit
} while (eoc); //wait for EOC to drop
output_low(A2D_CSI); //now drop select for the transfer
temp.raw=spi_xfer(LTC,0,32); //get 32bits
output_high(A2D_CSI);
//Now need to sign extend the value
if (bit_test(temp.raw,29))
{
//-ve value
temp.raw |=0xE0000000; //turn on top 3 bits
}
else
{
temp.raw &=0x01FFFFFFF; //only use low 29bits
}
return temp.rval/32;
}
void main(void)
{
signed int32 A2D_value;
signed int32 oversample;
int8 ctr;
setup_adc_ports(NO_ANALOGS|VSS_VDD); // No analogs
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
output_high(A2D_CSI);
setup_comparator (NC_NC_NC_NC); // Disable comparator
unsigned int32 dummy = 0;
unsigned int32 dac_value = 0;
output_high(RS485_EN);
delay_ms(50);
printf("\n\r");
printf("\r\nMain loop\r\n");
output_low(RS485_EN);
delay_ms(50);
output_low(OUT_CNTRL);
// Initialize SPI
output_low(DAC_CS); // Select the DAC
dummy=spi_xfer(DAC,0x05000A,24);
output_high(DAC_CS); // Deselect the DAC
delay_ms(500);
printf("\r\nDAC step 1 done");
delay_ms(500);
output_low(DAC_CS); // Select the DAC
dummy=spi_xfer(DAC,0x040000,24);
output_high(DAC_CS); // Deselect the DAC
dac_value = 16383;
//Now need to trigger a dummy read to start the conversion
A2D_value=Read_A2D();
while(1)
{
delay_ms(200); //delay before reading the first time
A2D_value=Read_A2D();
A2D_value = A2D_value/8;
output_high(RS485_EN);
delay_ms(50);
printf("ADC: %8Ld\r\n", A2D_value);
printf("\n\r");
output_low(RS485_EN);
delay_ms(50);
// DAC TEST
output_low(DAC_CS); // Select DAC
dummy = spi_xfer(DAC,0x8, 8); // Write data to DAC
dummy = spi_xfer(DAC,dac_value, 16); // Write data to DAC
output_high(DAC_CS); // Deselect DAC
output_high(RS485_EN);
delay_ms(50);
// printf("\n\r");
// printf("\r\nDAC Value = %6lu\r\n", dac_value);
output_low(RS485_EN);
delay_ms(50);
delay_ms(500);
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Sun Jun 23, 2024 4:02 pm |
|
|
you need to mask off the top 3 bits as they're NOT part of the reading.
you can also eliminate the lower 5 bits. what's left is the 24 bits of the A2D voltage, using bit29 as the 'sign' bit. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19495
|
|
Posted: Mon Jun 24, 2024 1:04 am |
|
|
Also, the baud rate is wrong.
19200 is the frequency of it's internal SCK. External SCK, supports rates
up to 2MHz. Select this. or close to it (1Mhz say).
The mode number is wrong. Thought it was likely.
The LTC says it outputs data on the falling edge of the clock, and expects
it to be sampled on the rising edge. This is MODE3.
For this look at the Wikipedia entry, and particularly the table under the
section 'mode numbers.
The DAC actually wants MODE1. That it works on 0, suggests a lot of
luck (actually that the PIC has it's clock very slightly delayed compared
to the data). |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|