主题中讨论的其他器件: ADS1258
ADS1158遇到持久性问题、具体而言涉及 SPI 功能。 MOSI 和 MISO 无法始终提供可靠的传输。
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.
您好、Bryan:
对于模糊的描述很抱歉。 我在此提供问题的说明:
我们一开始就无法启动 SPI。 我将随附一张具有以下重要信号的表格、以展示这些问题。
我们的主要问题包括:
-通道数据直接读取波形与作为参考的数据表中提供的不匹配
-寄存器和通道数据读取与数据表中作为参考提供的数据不匹配
- SPI 数据寄存器似乎没有被加载
信号 | 波形 |
启动(黄色)、CS (蓝色) | https://gigamove.rwth-aachen.de/en/download/072228b7a639bbd572f7008d9aeb6229 |
VDD (黄色)、RESET (蓝色) | gigamove.rwth-aachen.de/.../281898cf7bab5bb8ec04163e1ab4e8c0 |
SCLK (蓝色)、MISO (黄色) | https://gigamove.rwth-aachen.de/en/download/f1fd584f0738de4b94fa5f508685b0eb |
MOSI (蓝色) | https://gigamove.rwth-aachen.de/en/download/67f989cbb00a5a75f4cc8506520e13ed |
时钟(蓝色) | gigamove.rwth-aachen.de/.../01ab5ad6cb08cf06390c4833079de664 |
CLKSEL (黄色)、PDWN (蓝色) | gigamove.rwth-aachen.de/.../1386b2be477e7d280a13af8bbf27ec83 |
我已经将 C 文件和命令附加到 ADS1158。 如果需要有关函数的更多信息、请告诉我。
/** * \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="">www.microchip.com/.../8-bit">Atmel AVR</A>.\n */ /* * Support and FAQ: visit <a href="">www.microchip.com/.../">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(&***); spi_enable(&***); /* 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(&*** , &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(&*** , &spi_device_conf_ADC1); //Configuring ADS1158 1 spi_write_packet(&*** , &buff_write, 1); spi_deselect_device(&*** , &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(&*** , &spi_device_conf_ADC1); //Verify Configuring ADS1158 1 //while (1){ //spi_write_single(&***, buff_write); //} //spi_wait(&***); spi_write_packet(&***, &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(&***, buff_read, 10); spi_deselect_device(&*** , &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 (&*** , &spi_device_conf_ADC1); while (++x){} spi_deselect_device(&*** , &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(&*** , &spi_device_conf_ADC1); spi_write_packet(&*** , &adc1_buffer_w,1); //// spi_deselect_device(&*** , &spi_device_conf_ADC1); spi_select_device(&***, &spi_device_conf_ADC1); spi_read_packet(&*** , &adc1_buff_read,3); //// spi_deselect_device(&*** , &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; }
尊敬的 Nikhil Ayyala:
如果我查看您提供的时钟图像、会发现时钟信号更像锯齿形信号、而不是方波。 为什么会这样呢? 您将在何处测量这个信号?
此外、如果刻度为2V、则该信号看起来仅为1V。 您的时钟源是什么? ADC 需要一个参考 DVDD 的时钟信号、在本例中、我假设该信号为3.3V。
您能否提供原理图以便我们进行审阅? 请将其发布到 e2e 主题帖、而不是提供指向其他位置的链接。 如果你有一个 PDF 或图像文件、你通常只需将其拖放到线程中即可。
-Bryan
您好、Bryan:
来回答您的问题
-我们直接在晶振本身处测量时钟信号
-我们使用的时钟源是晶体振荡器本身
我已随附相关原理图的 pdf 文件。
e2e.ti.com/.../ADC-Schematics-pdf.pdf
此外、我们还对其他一些关键端子进行了测量:
Vcc_Ref_:4.18 V
- AVDD:5V
尊敬的 Nikhil Ayyala:
您能否尝试测量 CLKIO 引脚上的时钟信号以确保它是16 MHz 输出? 许多客户在启动32kHz 晶体时遇到问题。 您可能需要在 ADC 寄存器映射中启用
您还可以尝试移除晶体并使用外部时钟来查看行为是否更加一致。 这就是我们建议您操作 ADS1158的方式、即用离散时钟振荡器代替晶体
图像显示 SCLK 和 MISO (DOUT)。 不过、SCLK 信号 在整个过程中都处于高电平。 "你干嘛啊? 如果没有 SCLK 信号、您无法对 ADC 进行读取或写入
-Bryan
您好、Bryan:
我们执行了 CLKIO 引脚测量。 输出如下:
我们观察到频率为32.7kHz、但无法看到峰峰值超过1V。 这里、CLKSEL 为低电平、所以这是 XTAL1的信号、我们在直接测量晶体的焊盘时会得到相同的波形。 CLKIO 看起来很好、并且无论 CLKSEL 的值如何、都处于16 MHz 状态。
写入 ADC 寄存器映射并将 CLKSEL 设置为高电平后、我们得到的波形显示为:
这与您在帖子中提到的预期时钟输出相匹配。
关于 SCLK 和 MISO、SCLK 信号始终处于高电平正是我们的问题。 我们按照 ADS1158数据表中针对 SCLK 的初始化说明进行操作、但无法生成一致的 SCLK。 SCLK 持续为高电平的这种情况并不构成所有观察到的行为。 但即使 SCLK 正常运行、也不会执行 SPI 传输。
根据我们的理解、代码至少应能够进行通道数据直接读取、反过来应能够开启 SPI。 但是、我们无法在波形中观察到这种行为。
尊敬的 Nikhil Ayyala:
关于 SCLK 和 MISO, SCLK 信号是高电平整个时间正是我们的问题。 我们按照 ADS1158数据表中 SCLK 的初始化说明进行操作,但无法生成一致的 SCLK。
现在我有点困惑:SCLK 信号不是由 ADC 生成、而是由您的控制器生成。 因此、如果 SCLK 有问题、它不是 ADC 的故障、我实际上无法提供太多支持。
另请注意、SCLK 信号必须空闲低电平、而不是高电平。 换句话说、当不被使用时、SCLK 必须为逻辑0、而不是逻辑1、即 SPI 模式01。
-Bryan
您好、Bryan:
我们更新了一些截图、其中包含了我们的微控制器提供的正确 SCLK 信号。 当我们尝试生成通道数据直接读取的时序图时、以下是图像:
DRDY -黄色、CS -绿色、SCLK -蓝色
SCLK -蓝色、MISO -黄色、MOSI -绿色
我们希望 MISO 线路处于活动状态、MOSI 处于非活动状态
这是我们的准则:
e2e.ti.com/.../2654.main.c
尊敬的 Nikhil Ayyala:
这些信号看起来真的很糟糕。 您正在 DOUT 线路上看到过冲/下冲电压。 同样、在 SCLK 上、当信号为低电平时、信号下降到远低于地电平、至少根据您的示波器截图所示。
目前尚不清楚是什么导致了这些问题、这可能是布局不佳和接地不当的组合。 如果您想与此 ADC 通信、就必须解决这些问题。
您也可以尝试获取我们的 ADS1258 EVM、以便在尝试使您的解决方案正常工作之前从已知且有效的解决方案着手。
-Bryan