Other Parts Discussed in Thread: ADS1258
Running into persistency issues with the ADS1158, specifically regarding the SPI capabilities. MOSI and MISO do not consistently provide a reliable transmission.
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi Nikhil Ayyala,
Can you please elaborate? This is not enough information to even begin to understand your issue
Please provide a schematic, oscilloscope / logic analyzer shots of the communication, and as much information as possible as to the circumstances that lead to the issue as well as everything you have already done to diagnose it
-Bryan
Hi Bryan,
Apologies for the vague description. I am providing the description of the issues here:
We are having trouble starting up the SPI in the first place. I am attaching a table with the signals of interest below to showcase the issues.
Our primary issues include:
- the Channel Data Read Direct waveforms not matching what is provided in the datasheet as a reference
- the Register and Channel Data read not matching what is provided in the datasheet as a reference
- The SPI Data register does not seem to get loaded
Signal | Waveform |
START (yellow), CS (blue) | https://gigamove.rwth-aachen.de/en/download/072228b7a639bbd572f7008d9aeb6229 |
Vdd (Yellow), RESET (Blue) | gigamove.rwth-aachen.de/.../281898cf7bab5bb8ec04163e1ab4e8c0 |
SCLK (blue), MISO (yellow) | https://gigamove.rwth-aachen.de/en/download/f1fd584f0738de4b94fa5f508685b0eb |
MOSI (blue) | https://gigamove.rwth-aachen.de/en/download/67f989cbb00a5a75f4cc8506520e13ed |
CLOCK (blue) | gigamove.rwth-aachen.de/.../01ab5ad6cb08cf06390c4833079de664 |
CLKSEL (yellow), PDWN (blue) | gigamove.rwth-aachen.de/.../1386b2be477e7d280a13af8bbf27ec83 |
I have attached the C file with the commands to the ADS1158. If any more information is needed about the functions, let me know.
/** * \file * * \brief USB Standard I/O (stdio) Example * * Copyright (c) 2011-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * * Subject to your compliance with these terms, you may use Microchip * software and any derivatives exclusively with Microchip products. * It is your responsibility to comply with third party license terms applicable * to your use of third party software (including open source software) that * may accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /** * \mainpage * * \section intro Introduction * This example demonstrates how to configure a C-library Standard * I/O interface to the ASF common USB Device CDC service. The initialization * routines, along with board and clock configuration constants, illustrate how * to perform serial I/O via a Communication Device Class (CDC) device protocol * * \section files Main Files * - stdio_usb_example.c: the example application. * - conf_board.h: board configuration * - conf_clock.h: board configuration * - stdio_usb.h: Common USB CDC Standard I/O Implementation * - read.c : System implementation function used by standard library * - write.c : System implementation function used by standard library * * \section example_description Description of the example * - Send message on USB CDC device to a Virtual Com Port. * - Performs echo of any received character * * \section contactinfo Contact Information * For further information, visit * <A href="http://www.microchip.com/design-centers/8-bit">Atmel AVR</A>.\n */ /* * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a> */ #include <asf.h> #include "main.h" #include "correct_adc_init_steps.h" #include "ADS1158_headerFile.h" #include "spi_master.h" struct spi_device spi_device_conf_ADC1 = { //.id = IOPORT_CREATE_PIN(PORTC, 4) // DAC chip select **** Just for 1 ADS1158 to be tested .id = IOPORT_CREATE_PIN(PORTD, 0) // ADC1 chip select //.id2 = IOPORT_CREATE_PIN(PORTD, 1) // ADC2 chip select }; /** * \brief main function */ int main (void) { #if SAMD21 || SAMR21 /* Initialize basic board support features. * - Initialize system clock sources according to device-specific * configuration parameters supplied in a conf_clocks.h file. * - Set up GPIO and board-specific features using additional configuration * parameters, if any, specified in a conf_board.h file. */ //system_init(); #else /* Initialize basic board support features. * - Initialize system clock sources according to device-specific * configuration parameters supplied in a conf_clock.h file. * - Set up GPIO and board-specific features using additional configuration * parameters, if any, specified in a conf_board.h file. */ sysclk_init(); board_init(); #endif // Initialize interrupt vector table support. irq_initialize_vectors(); // Enable interrupts cpu_irq_enable(); // SPI Initialization //ioport_configure_port_pin(&PORTC, PIN4_bm, IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH); ioport_configure_port_pin(&PORTC, PIN4_bm, IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH); spi_master_init(&SPIC); spi_enable(&SPIC); /* Call a local utility routine to initialize C-Library Standard I/O over * a USB CDC protocol. Tunable parameters in a conf_usb.h file must be * supplied to configure the USB device correctly. */ //stdio_usb_init(); // Get and echo characters forever. uint8_t ch; //while (true) { // //scanf("%c",&ch); // get one input character // //if (ch) { //printf("%c",ch); // echo to output //} //} // Microcontroller initialization configurations ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC1 CS //ioport_configure_port_pin(&PORTD, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC2 CS High to prevent SPI interference. //ioport_configure_port_pin(&PORTE, PIN2_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC reset pin high //ioport_configure_port_pin(&PORTF, PIN7_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); // !!!Shutdown DDCs to stop interference on SPI!!! //ioport_configure_port_pin(&PORTD, PIN2_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); // !!!Shutdown DAC to stop interference on SPI!!! void ADC1_func_config(void){ void reset_spi_interface(void){ int x = 0; ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); while (++x){} ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); while (++x){} } void stop_converter1(void){ ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //tested and works. START pin to LOW } void reset_converter1(void){ int x = 0; ioport_configure_port_pin(&PORTE, PIN2_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); while (++x){} ioport_configure_port_pin(&PORTE, PIN2_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); while (++x){} } void clocksel_and_powerdown1(void){ //tested and works //clk_sel_low ioport_configure_port_pin(&PORTE, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //PWDM ADC Disable ioport_configure_port_pin(&PORTE, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); } void write_config_registers_ADC1() { spi_deselect_device(&SPIC , &spi_device_conf_ADC1); //Configuring ADS1158 1 uint8_t buff_write [10] = { //buff_write [1] = register_write_adc|en_multiple_reg_access, buff_write [1] = channel_read_adc|en_multiple_reg_access, buff_write [2] = CONFIG0_ADC_Set , buff_write [3] = CONFIG1_ADC_Set, buff_write [4] = MUXSCH_ADC_Set , buff_write [5] = MUXDIF_ADC_Set, buff_write [6] = MUXSG0_ADC_Set, buff_write [7] = MUXSG1_ADC_Set, buff_write [8] = SYSRED_ADC_Set, buff_write [9] = GPIOC_ADC_Set, buff_write [10] = GPIOD_ADC_Set, }; spi_select_device(&SPIC , &spi_device_conf_ADC1); //Configuring ADS1158 1 spi_write_packet(&SPIC , &buff_write, 1); spi_deselect_device(&SPIC , &spi_device_conf_ADC1); } void verify_register_data1(void){ int packet_len = 11; //volatile uint8_t buff_read[10]; volatile uint8_t* buff_read=(uint8_t*)malloc(sizeof(uint8_t)*10); volatile uint8_t buff_write = 0xE0; spi_select_device(&SPIC , &spi_device_conf_ADC1); //Verify Configuring ADS1158 1 //while (1){ //spi_write_single(&SPIC, buff_write); //} //spi_wait(&SPIC); spi_write_packet(&SPIC, &buff_write, 1); ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC START if (~ PORTE.IN && PIN3_bm){ ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); } spi_read_packet(&SPIC, buff_read, 10); spi_deselect_device(&SPIC , &spi_device_conf_ADC1); } void start_converter1(void){ ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); } void read_channel_data1(void){ } void pwm_test(void){ while(1){ int x = 0; spi_select_device (&SPIC , &spi_device_conf_ADC1); while (++x){} spi_deselect_device(&SPIC , &spi_device_conf_ADC1); while (++x){} } } reset_spi_interface(); stop_converter1(); reset_converter1(); clocksel_and_powerdown1(); write_config_registers_ADC1(); verify_register_data1(); // DO NOT USE> Issue with "Register and Channel Data (Register Format) Read" Use "Channel Data Read Direct (No Command)" start_converter1(); // } uint8_t adc1_buffer[3]; uint16_t ADC1_value= 0; uint16_t ADC2_value = 0; uint8_t ADC_status_byte=0; uint8_t ADC2_value1 = 0; uint8_t ADC2_value2 = 0; //uint32_t address_to_write = 0 ; uint16_t address_to_write_1 ; uint8_t CH_ID; uint8_t ADC1_values [252]; uint8_t ADC2_values [252]; uint8_t ADC_channel; void read_channel_ADC1() // eeprom_addr_t address_to_write) { //start_converter1(); ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC START if (~ PORTE.IN && PIN3_bm)//!!! { uint8_t adc1_buff_read[4]; uint8_t adc1_buffer_w [3] = { //adc1_buffer[0] = channel_read_adc | en_multiple_reg_access| ADC_channel , adc1_buffer[0] = channel_read_adc | en_multiple_reg_access , adc1_buffer[1] = 0x00, adc1_buffer[2] = 0x00, }; uint8_t status_byte = adc1_buff_read[0]; uint8_t new_bit = (0x80); uint8_t status_byte_ideal = (CH_ID | new_bit); CH_ID = status_byte<<3; for (int i=0; i <= 128; i=i+3) ///i<504 696 { spi_select_device(&SPIC , &spi_device_conf_ADC1); spi_write_packet(&SPIC , &adc1_buffer_w,1); //// spi_deselect_device(&SPIC , &spi_device_conf_ADC1); spi_select_device(&SPIC, &spi_device_conf_ADC1); spi_read_packet(&SPIC , &adc1_buff_read,3); //// spi_deselect_device(&SPIC , &spi_device_conf_ADC1); ADC1_values[i] = adc1_buff_read[0]; ADC1_values[i+1] = adc1_buff_read[1]; ADC1_values[i+2] = adc1_buff_read[2]; if (ADC1_values[i] == (AIN0_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if ( ADC1_values[i] == AIN0_ADC) { ADC1_read_values[0] = (ADC1_values[i+1]) ;//**** ADC1_read_values[1] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN1_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN1_ADC) { ADC1_read_values[2] = (ADC1_values[i+1]) ;//**** ADC1_read_values[3] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN2_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i]== AIN2_ADC) { ADC1_read_values[4] = (ADC1_values[i+1]) ;//**** ADC1_read_values[5] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN3_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN3_ADC) { ADC1_read_values[6] = (ADC1_values[i+1]) ;//**** ADC1_read_values[7] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN4_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN4_ADC) { ADC1_read_values[8] = (ADC1_values[i+1]) ;//**** ADC1_read_values[9] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN5_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i]== AIN5_ADC) { ADC1_read_values[10] = (ADC1_values[i+1]) ;//**** ADC1_read_values[11] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN6_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN6_ADC) { ADC1_read_values[12] = (ADC1_values[i+1]) ;//**** ADC1_read_values[13] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN7_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN7_ADC) { ADC1_read_values[14] = (ADC1_values[i+1]) ;//**** ADC1_read_values[15] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN8_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN8_ADC) { ADC1_read_values[16] = (ADC1_values[i+1]) ;//**** ADC1_read_values[17] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN9_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN9_ADC) { ADC1_read_values[18] = (ADC1_values[i+1]) ;//**** ADC1_read_values[19] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN10_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN10_ADC) { ADC1_read_values[20] = (ADC1_values[i+1]) ;//**** ADC1_read_values[21] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN11_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN11_ADC) { ADC1_read_values[22] = (ADC1_values[i+1]) ;//**** ADC1_read_values[23] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN12_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN12_ADC) { ADC1_read_values[24] = (ADC1_values[i+1]) ;//**** ADC1_read_values[25] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN13_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN13_ADC) { ADC1_read_values[26] = (ADC1_values[i+1]) ;//**** ADC1_read_values[27] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN14_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN14_ADC) { ADC1_read_values[28] = (ADC1_values[i+1]) ;//**** ADC1_read_values[29] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN15_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN15_ADC) { ADC1_read_values[30] = (ADC1_values[i+1]) ;//**** ADC1_read_values[31] = (ADC1_values[i+2]) ; } } } } //return (ADC1_read_values); } ADC1_func_config(); while(1){ ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC CS ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC START if (~ PORTE.IN && PIN3_bm){ ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); read_channel_ADC1(); } } // //return 0; }
Hi Nikhil Ayyala,
I am adding your images here so they are accessible within the post:
START (yellow), CS (blue)
CLOCK (blue)
Vdd (Yellow), RESET (Blue)
SCLK (blue), MISO (yellow)
MOSI (blue)
CLKSEL (yellow), PDWN (blue)
-Bryan
Hi Nikhil Ayyala,
If I look at the CLOCK image you provided, the clock signal looks more like a sawtooth signal instead of a square wave. Why is that? Where are you measuring this signal?
Also, if the scale is 2V, then this signal looks like it is only 1V. What is your clock source? The ADC is expecting a clock signal referenced to DVDD, which I assume is 3.3V in your case.
Can you please provide a schematic so we can review? Please post it to the e2e thread instead of providing a link to a different location. If you have have a PDF or image file you can typically just drag and drop it into the thread.
-Bryan
Hi Bryan,
To answer your questions
- we are measuring the clock signal directly at the crystal itself
- The clock source we are using is the crystal oscillator itself
I have attached a pdf of the relevant schematics.
Furthermore, we have performed measurements of some other key terminals:
- Vcc_Ref_5V: 4.18 V
- AVdd: 5V
Hi Nikhil Ayyala,
Can you try measuring the clock signal at the CLKIO pin to make sure it is a 16 MHz output? Many customers have issues getting the 32 kHz crystal to startup. You might need to enable this in the ADC register map
You can also try removing the crystal and using an external clock to see if the behavior is more consistent. This is how we recommend you operate the ADS1158 i.e. with a discrete clock oscillator instead of the crystal
You have an image showing SCLK and MISO (DOUT). However, the SCLK signal is high the entire time. What are you trying to do here? You cannot read from or write to the ADC without an SCLK signal
-Bryan
Hi Bryan,
We performed a measurement of the CLKIO pin. The output is below:
We observe the frequency of 32.7 kHz but are unable to see a peak-to-peak value exceeding 1V. Here, CLKSEL is low, so this is the signal at XTAL1, and we get the same waveform upon measuring the pads of the crystal directly. CLKIO looks fine, and is at 16 MHz regardless of CLKSEL's value.
Upon writing to the ADC register map and setting CLKSEL high, the waveform we get displays as:
This matches the expected clock output that you have mentioned in your post.
Regarding SCLK and MISO, SCLK signal being high the entire time is precisely our issue. We followed the initialization instructions for SCLK from the ADS1158 Datasheet, and haven't been able to generate a consistent SCLK. This instance of SCLK being high continuously does not constitute all observed behavior. But even with SCLK operating normally, we see no SPI transmission being carried out.
Based on our understanding the code should at least be able to carry about Channel Data Read Direct, which in turn should be able to turn on the SPI. However, we are unable to observe this behavior in our waveforms.
Hi Nikhil Ayyala,
Regarding SCLK and MISO, SCLK signal being high the entire time is precisely our issue. We followed the initialization instructions for SCLK from the ADS1158 Datasheet, and haven't been able to generate a consistent SCLK.
Now I am a bit confused: the SCLK signal is not generated by the ADC, it is generated by your controller. So if there is an issue with SCLK, it is not the ADC's fault, and I don't really have much support to offer.
Also note that the SCLK signal must idle low, not high. In other words, when not being used, SCLK must be at logic 0, not logic 1 i.e. SPI mode 01
-Bryan
Hi Bryan,
We have some updated screenshots with the correct SCLK signal provided by our microcontroller. Here are the images, as we attempt to produce the timing diagram for a Channel Data Direct Read:
DRDY - yellow, CS - green, SCLK - blue
SCLK - Blue, MISO - yellow, MOSI - green
We expect the MISO line to be active and the MOSI to be inactive
This is our code:
/** * \file * * \brief USB Standard I/O (stdio) Example * * Copyright (c) 2011-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * * \page License * * Subject to your compliance with these terms, you may use Microchip * software and any derivatives exclusively with Microchip products. * It is your responsibility to comply with third party license terms applicable * to your use of third party software (including open source software) that * may accompany Microchip software. * * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. * * \asf_license_stop * */ /** * \mainpage * * \section intro Introduction * This example demonstrates how to configure a C-library Standard * I/O interface to the ASF common USB Device CDC service. The initialization * routines, along with board and clock configuration constants, illustrate how * to perform serial I/O via a Communication Device Class (CDC) device protocol * * \section files Main Files * - stdio_usb_example.c: the example application. * - conf_board.h: board configuration * - conf_clock.h: board configuration * - stdio_usb.h: Common USB CDC Standard I/O Implementation * - read.c : System implementation function used by standard library * - write.c : System implementation function used by standard library * * \section example_description Description of the example * - Send message on USB CDC device to a Virtual Com Port. * - Performs echo of any received character * * \section contactinfo Contact Information * For further information, visit * <A href="http://www.microchip.com/design-centers/8-bit">Atmel AVR</A>.\n */ /* * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a> */ #include <asf.h> #include "main.h" #include "correct_adc_init_steps.h" #include "ADS1158_headerFile.h" #include "spi_master.h" struct spi_device spi_device_conf_ADC1 = { //.id = IOPORT_CREATE_PIN(PORTC, 4) // DAC chip select **** Just for 1 ADS1158 to be tested .id = IOPORT_CREATE_PIN(PORTD, 0) // ADC1 chip select //.id2 = IOPORT_CREATE_PIN(PORTD, 1) // ADC2 chip select }; /** * \brief main function */ int main (void) { #if SAMD21 || SAMR21 /* Initialize basic board support features. * - Initialize system clock sources according to device-specific * configuration parameters supplied in a conf_clocks.h file. * - Set up GPIO and board-specific features using additional configuration * parameters, if any, specified in a conf_board.h file. */ //system_init(); #else /* Initialize basic board support features. * - Initialize system clock sources according to device-specific * configuration parameters supplied in a conf_clock.h file. * - Set up GPIO and board-specific features using additional configuration * parameters, if any, specified in a conf_board.h file. */ sysclk_init(); board_init(); #endif // Initialize interrupt vector table support. irq_initialize_vectors(); // Enable interrupts cpu_irq_enable(); // SPI Initialization //ioport_configure_port_pin(&PORTC, PIN4_bm, IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH); ioport_configure_port_pin(&PORTC, PIN4_bm, IOPORT_DIR_OUTPUT | IOPORT_INIT_HIGH); spi_master_init(&SPIC); spi_enable(&SPIC); /* Call a local utility routine to initialize C-Library Standard I/O over * a USB CDC protocol. Tunable parameters in a conf_usb.h file must be * supplied to configure the USB device correctly. */ //stdio_usb_init(); // Get and echo characters forever. uint8_t ch; //while (true) { // //scanf("%c",&ch); // get one input character // //if (ch) { //printf("%c",ch); // echo to output //} //} // Microcontroller initialization configurations ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_HIGH| IOPORT_DIR_OUTPUT); //ADC1 CS ioport_configure_port_pin(&PORTD, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC2 CS High to prevent SPI interference. ioport_configure_port_pin(&PORTE, PIN2_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC reset pin high (common pin for both ADCs) ioport_configure_port_pin(&PORTF, PIN7_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); // !!!Shutdown DDCs to stop interference on SPI!!! ioport_configure_port_pin(&PORTD, PIN2_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); // !!!Shutdown DAC to stop interference on SPI!!! ioport_configure_port_pin(&PORTC, PIN5_bm, IOPORT_INIT_HIGH|IOPORT_DIR_OUTPUT); //MOSI ioport_configure_port_pin(&PORTC, PIN6_bm, IOPORT_DIR_INPUT); //MISO ioport_configure_port_pin(&PORTC, PIN7_bm, IOPORT_INIT_HIGH|IOPORT_DIR_OUTPUT); //SCK void ADC1_func_config(void){ void reset_spi_interface(void){ int x = 0; ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); while (++x){} ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); while (++x){} } void stop_converter1(void){ ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //tested and works. START pin to LOW } void reset_converter1(void){ int x = 0; ioport_configure_port_pin(&PORTE, PIN2_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); while (++x){} ioport_configure_port_pin(&PORTE, PIN2_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); while (++x){} } void clocksel_and_powerdown1(void){ //tested and works //clk_sel_low ioport_configure_port_pin(&PORTE, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); //PWDM ADC Disable ioport_configure_port_pin(&PORTE, PIN1_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); } void write_config_registers_ADC1() { spi_deselect_device(&SPIC , &spi_device_conf_ADC1); //Configuring ADS1158 1 uint8_t buff_write [10] = { //buff_write [1] = register_write_adc|en_multiple_reg_access, buff_write [1] = channel_read_adc|en_multiple_reg_access, buff_write [2] = CONFIG0_ADC_Set , buff_write [3] = CONFIG1_ADC_Set, buff_write [4] = MUXSCH_ADC_Set , buff_write [5] = MUXDIF_ADC_Set, buff_write [6] = MUXSG0_ADC_Set, buff_write [7] = MUXSG1_ADC_Set, buff_write [8] = SYSRED_ADC_Set, buff_write [9] = GPIOC_ADC_Set, buff_write [10] = GPIOD_ADC_Set, }; spi_select_device(&SPIC , &spi_device_conf_ADC1); //Configuring ADS1158 1 spi_write_packet(&SPIC , &buff_write, 1); spi_deselect_device(&SPIC , &spi_device_conf_ADC1); } void verify_register_data1(void){ int packet_len = 11; //volatile uint8_t buff_read[10]; volatile uint8_t* buff_read=(uint8_t*)malloc(sizeof(uint8_t)*10); volatile uint8_t buff_write = 0xE0; spi_select_device(&SPIC , &spi_device_conf_ADC1); //Verify Configuring ADS1158 1 //while (1){ //spi_write_single(&SPIC, buff_write); //} //spi_wait(&SPIC); spi_write_packet(&SPIC, &buff_write, 1); ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC START if (~ PORTE.IN && PIN3_bm){ ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); } spi_read_packet(&SPIC, buff_read, 10); spi_deselect_device(&SPIC , &spi_device_conf_ADC1); } void start_converter1(void){ ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); } void read_channel_data1(void){ } void pwm_test(void){ while(1){ int x = 0; spi_select_device (&SPIC , &spi_device_conf_ADC1); while (++x){} spi_deselect_device(&SPIC , &spi_device_conf_ADC1); while (++x){} } } reset_spi_interface(); stop_converter1(); reset_converter1(); clocksel_and_powerdown1(); write_config_registers_ADC1(); verify_register_data1(); // DO NOT USE> Issue with "Register and Channel Data (Register Format) Read" Use "Channel Data Read Direct (No Command)" start_converter1(); // } uint8_t adc1_buffer[3]; uint16_t ADC1_value= 0; uint16_t ADC2_value = 0; uint8_t ADC_status_byte=0; uint8_t ADC2_value1 = 0; uint8_t ADC2_value2 = 0; //uint32_t address_to_write = 0 ; uint16_t address_to_write_1 ; uint8_t CH_ID; uint8_t ADC1_values [252]; uint8_t ADC2_values [252]; uint8_t ADC_channel; void read_channel_ADC1() // eeprom_addr_t address_to_write) { //start_converter1(); ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC START if (~ PORTE.IN && PIN3_bm)//!!! { uint8_t adc1_buff_read[4]; uint8_t adc1_buffer_w [3] = { //adc1_buffer[0] = channel_read_adc | en_multiple_reg_access| ADC_channel , adc1_buffer[0] = channel_read_adc | en_multiple_reg_access , adc1_buffer[1] = 0x00, adc1_buffer[2] = 0x00, }; uint8_t status_byte = adc1_buff_read[0]; uint8_t new_bit = (0x80); uint8_t status_byte_ideal = (CH_ID | new_bit); CH_ID = status_byte<<3; for (int i=0; i <= 128; i=i+3) ///i<504 696 { spi_select_device(&SPIC , &spi_device_conf_ADC1); spi_write_packet(&SPIC , &adc1_buffer_w,1); //// spi_deselect_device(&SPIC , &spi_device_conf_ADC1); spi_select_device(&SPIC, &spi_device_conf_ADC1); spi_read_packet(&SPIC , &adc1_buff_read,3); //// spi_deselect_device(&SPIC , &spi_device_conf_ADC1); ADC1_values[i] = adc1_buff_read[0]; ADC1_values[i+1] = adc1_buff_read[1]; ADC1_values[i+2] = adc1_buff_read[2]; if (ADC1_values[i] == (AIN0_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if ( ADC1_values[i] == AIN0_ADC) { ADC1_read_values[0] = (ADC1_values[i+1]) ;//**** ADC1_read_values[1] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN1_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN1_ADC) { ADC1_read_values[2] = (ADC1_values[i+1]) ;//**** ADC1_read_values[3] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN2_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i]== AIN2_ADC) { ADC1_read_values[4] = (ADC1_values[i+1]) ;//**** ADC1_read_values[5] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN3_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN3_ADC) { ADC1_read_values[6] = (ADC1_values[i+1]) ;//**** ADC1_read_values[7] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN4_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN4_ADC) { ADC1_read_values[8] = (ADC1_values[i+1]) ;//**** ADC1_read_values[9] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN5_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i]== AIN5_ADC) { ADC1_read_values[10] = (ADC1_values[i+1]) ;//**** ADC1_read_values[11] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN6_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN6_ADC) { ADC1_read_values[12] = (ADC1_values[i+1]) ;//**** ADC1_read_values[13] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN7_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN7_ADC) { ADC1_read_values[14] = (ADC1_values[i+1]) ;//**** ADC1_read_values[15] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN8_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN8_ADC) { ADC1_read_values[16] = (ADC1_values[i+1]) ;//**** ADC1_read_values[17] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN9_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN9_ADC) { ADC1_read_values[18] = (ADC1_values[i+1]) ;//**** ADC1_read_values[19] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN10_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN10_ADC) { ADC1_read_values[20] = (ADC1_values[i+1]) ;//**** ADC1_read_values[21] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN11_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN11_ADC) { ADC1_read_values[22] = (ADC1_values[i+1]) ;//**** ADC1_read_values[23] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN12_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN12_ADC) { ADC1_read_values[24] = (ADC1_values[i+1]) ;//**** ADC1_read_values[25] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN13_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN13_ADC) { ADC1_read_values[26] = (ADC1_values[i+1]) ;//**** ADC1_read_values[27] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN14_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN14_ADC) { ADC1_read_values[28] = (ADC1_values[i+1]) ;//**** ADC1_read_values[29] = (ADC1_values[i+2]) ; } } if (ADC1_values[i] == (AIN15_ADC|new_bit) ) { ADC1_values[i] = ADC1_values[i]<<1; ADC1_values[i] = ADC1_values[i]>>1; if (ADC1_values[i] == AIN15_ADC) { ADC1_read_values[30] = (ADC1_values[i+1]) ;//**** ADC1_read_values[31] = (ADC1_values[i+2]) ; } } } } //return (ADC1_read_values); } ADC1_func_config(); while(1){ ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC CS ioport_configure_port_pin(&PORTE, PIN5_bm, IOPORT_INIT_HIGH | IOPORT_DIR_OUTPUT); //ADC START if (~ (PORTE.IN && PIN3_bm)){ ioport_configure_port_pin(&PORTD, PIN0_bm, IOPORT_INIT_LOW | IOPORT_DIR_OUTPUT); read_channel_ADC1(); //write_config_ADC1(); } } // //return 0; }
Hi Nikhil Ayyala,
When you are trying to read data, you need the SCLK signal to clock out that data to your controller. See the image below from the datasheet.
The images you sent just look like noise on your SCLK signal, and that noise is coupling into the rest of the communication signals
-Bryan
I should have zoomed in on the signal. We do get this waveform. Here is MISO in yellow and SCLK in blue
Hi Nikhil Ayyala,
Those signals look really bad. You are seeing volts of over / under-shoot on the DOUT line. Similarly on SCLK, when the signal is low it is dropping well below ground, at least according to your scope shots.
It is not clear what is causing these issues, it is probably a combination of poor layout and improper grounding. You will have to resolve these issues if you want to communicate with this ADC.
You can also try getting our ADS1258 EVM so you can start from a known, working solution before trying to get your solution to work
-Bryan
Hi Bryan,
We managed to find a way to generate a cleaner signal. This is our output brought into MATLAB to analyze
We are currently trying to investigate the odd offset applied to the MOSI. However, this signal is currently performing regular register reads, so the MISO and SCLK look alright.
Hi Nikhil Ayyala,
Thanks for providing this information. This looks like a "channel data read command" because you are sending 0011 0000, and then receiving 16 bits back. Is this what you intended?
If not, what issues are you currently having?
-Bryan
Hi Bryan,
is the MOSI voltage level not an issue in this image? WE've been trying to determine how to set that back to normal.
Hi Nikhil Ayyala,
I agree the DIN offset is an issue, but this is not an issue with the ADC because the controller is what generates the DIN output
-Bryan