12位ADC SPI驱动代码读取应变传感器数据始终返回0问题排查
LTC1296CCN ADC采样全0故障排查
系统配置与故障现象
- 信号链路:INA128P仪表放大器 + LTC1296CCN 12位ADC,采集额定输出2mV/V的应变式称重传感器信号
- ADC通信规则:拉低CS片选引脚后,先向Din引脚发送8位配置字,随后Dout引脚依次输出1个无效空比特、12位有效采样数据,后续持续输出低电平,直到CS引脚拉高结束通信;器件支持半双工模式,官方推荐3线双向连接架构
- 故障表现:分别尝试全双工、半双工SPI通信实现,读取结果始终为全0,无有效采样值
- 硬件实现:面包板搭建电路,采用STM32作为主控
现有实现代码
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2022 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <stdio.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ SPI_HandleTypeDef hspi1; UART_HandleTypeDef huart2; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); static void MX_SPI1_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ char uart_buf[100]; char boofer[100]; uint8_t ADC_buf[2]; uint8_t input_word[2]; int uart_buf_len; int length; uint16_t testdata[100]; uint8_t i = 0; uint16_t sample; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART2_UART_Init(); MX_SPI1_Init(); /* USER CODE BEGIN 2 */ // CS pin should default high HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); uart_buf_len = sprintf(uart_buf, "SPI test\r\n"); HAL_UART_Transmit(&huart2, (uint8_t *)uart_buf, uart_buf_len, 100); //input word is 10100110 input_word[0] = 167; /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); //HAL_SPI_Transmit(&hspi1, input_word, 1, 100); //HAL_SPI_Receive(&hspi1, ADC_buf, 2, 100); HAL_SPI_TransmitReceive(&hspi1, input_word, ADC_buf, 2, 100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); sample = (((uint16_t) ADC_buf[0] << 9)|(((uint16_t)ADC_buf[1] << 1))) >> 4; testdata[i] = sample; length =sprintf(boofer,"%d\n",testdata[i]) + 1; HAL_UART_Transmit(&huart2, boofer, length, 100); i++; /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
故障点定位
代码逻辑硬错误
- 配置字数值错误:注释标注配置字应为
10100110,换算十进制为166(十六进制0xA6),但代码中input_word[0]赋值为167(二进制10100111),最后一位配置位错误会导致ADC无法识别启动指令,直接输出低电平。 - SPI传输长度不足:按照时序要求,拉低CS后总共需要21个SCK时钟周期(8个发配置字 + 1个空比特 +12个读有效数据)才能完成一次采样,对应3字节传输。现有代码一次仅传输2字节共16个时钟,还未等ADC输出完有效数据就结束传输,之后拉高CS直接终止通信,自然读不到有效数据。
- 数据移位拼接逻辑完全错位:8个配置字发送周期内ADC的Dout为高阻态,接收到的第一个字节全为无效值;空比特出现在第9个时钟周期,12位有效数据分布在第10-21个时钟周期,现有移位逻辑从无效的第一个字节取数,拼出的结果必然是错误的0值。
- 数组越界风险:定义
uint8_t i作为testdata数组(长度100)的索引,循环中i持续自增无归零逻辑,i溢出后会篡改其他内存数据,导致程序运行异常。
SPI配置必查项(现有代码未贴SPI初始化部分,以下为高频错误点)
- 模式不匹配:LTC1296要求SPI空闲时SCK为低电平,数据在SCK上升沿锁存,对应SPI模式0(CPOL=0,CPHA=0),如果配置为其他模式,通信时序完全错位。
- 波特率过高:LTC1296最高支持SPI时钟为8MHz,面包板接线寄生电容大,调试阶段需将SPI波特率降到1MHz以下,时钟过高会导致采样边沿错位。
- 半双工接线错误:采用3线半双工模式时,必须将STM32的MISO、MOSI引脚短接后再连接ADC的双向DATA引脚;如果用全双工模式,需将MOSI接ADC的Din、MISO接ADC的Dout,两种模式接线不能混淆,否则会出现引脚电平冲突,读不到数据。
- CS引脚配置错误:采用软件控制CS时,需将SPI硬件NSS功能关闭,对应PB6引脚配置为推挽输出模式。
硬件连接排查项
- 电源与基准电压异常:LTC1296需要稳定5V单电源供电,Vref参考电压引脚必须接独立高精度基准源,不能直接接电源Vcc,否则电源纹波会导致ADC不工作;用万用表实测Vcc、Vref引脚电压,确认AGND、DGND可靠共地。
- 前端放大器输出异常:断开ADC输入,实测INA128的输出电压,确认传感器受压时输出电压在0~Vref范围内,无负电压、超量程输出情况。
- 接触不良:检查面包板接线,确认SCK、DATA、CS引脚无虚接、错接,CS拉低/拉高时引脚电平符合0V/5V要求。
修正后核心采样逻辑参考
uint8_t tx_buf[3] = {0xA6, 0x00, 0x00}; // 正确配置字10100110 uint8_t rx_buf[3] = {0}; uint16_t adc_val = 0; // 采样循环逻辑 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); HAL_Delay(1); // 等待CS电平稳定 HAL_SPI_TransmitReceive(&hspi1, tx_buf, rx_buf, 3, 100); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); // 按实际时序拼接12位有效数据 adc_val = ((uint16_t)(rx_buf[1] & 0x7F) << 5) | (rx_buf[2] >> 3);
内容的提问来源于stack exchange,提问作者Νίκος Χαλκιάς
相关产品推荐
相关产品推荐

