【STM32G431实战】模拟SPI驱动ADS1118实现四通道电压采集(附代码)_ads1118例程 c语言
一、项目背景
最近做了用ADS1118芯片轮询采集四个通道电压值的一个项目,在网上找了好久也没发现可以实现多通道采集的,大部分都是在讲单通道使用。本文通过STM32G431的GPIO模拟SPI协议,实现四通道轮询电压采集。
二、ADS1118芯片解析
1. 核心特性概览
ADS1118是TI推出的16位高精度ΔΣ型ADC,集成了关键外围组件,特别适合工业传感应用:
-
分辨率:16位无失码(0.0078% FSR)
-
输入类型:4路单端/2路差分通道
-
内置PGA:可编程增益放大器(1~8倍)
-
基准电压:内部2.048V±0.05%(温漂10ppm/℃)
-
采样速率:8SPS~860SPS(可编程)
-
片上温度传感器:±2℃精度(-40~125℃)
-
工作电压:2.0~5.5V(兼容3.3V/5V系统)
-
封装:X2QFN(10) 1.50mm×2.00mm;VSSOP(10) 3.00mm×3.00mm;
2. 寄存器配置详解
通过16位配置寄存器控制工作模式:
配置字示例(AIN0单端输入):
1 100 010 1 100 0 1011 // 二进制表示 │ │ │ │ │ └─ TS_MODE=0(ADC) │ │ │ │ └────── DR=100(128SPS) │ │ │ └───────── MODE=1(单次) │ │ └─────────── PGA=010(±2.048V) │ └─────────────── MUX=100(AIN0) └────────────────── OS=1(启动转换)→ 十六进制值:0xC58B
3. 数据格式解析
ADC模式(16位数据)
-
数据格式:二进制补码
-
有效位:高12位(低4位为状态位)
-
电压换算:V = Code× LSB
LSB:当前量程最小分辨率(如两成为±2.048V时,LSB=62.5μV)Code:实际ADC值
温度模式
-
数据格式:14位补码(高位在前)
-
换算公式:Temperature(℃) = (RAW_DATA >> 4) × 0.03125 - 50
分辨率:0.03125℃/LSB
-
注意:读取温度时会自动禁用ADC通道
-
4. SPI通信特性
-
时钟模式:SPI Mode 1(CPOL=0, CPHA=1)
-
数据帧:16位全双工传输
-
MOSI:发送配置字
-
MISO:返回转换结果
-
-
关键时序参数:
参数 最小值 典型值 t_CSSCLK (CS到SCLK) 200ns - SCLK周期 400ns 1μs 转换时间(128SPS) - 8ms
5. 设计注意事项
-
输入保护
-
// 推荐电路VIN ──┬── 10kΩ电阻 ──┬── ADS1118_AINx │ │ └── 5.1V齐纳 ─┘ │ └── 100pF电容 ── GND
-
功耗管理:
-
单次转换后自动休眠(功耗降至0.5μA)
-
唤醒方式:发送新配置字时自动启动转换
-
-
通道切换延迟:
-
切换通道后需等待1/DR时间(128SPS时≥8ms)
-
温度传感器启用后需100ms稳定时间
-
三、硬件设计
本次设计选用了STM32G431KBU3型号单片机,电路图及连接关系如下所示。
STM32G431 ADS1118PA4(CS) ------> CSPA5(SCLK) ------> SCLKPA6(MISO) ------> DOUTPA7(MOSI) ------> DIN3.3V ------> VDDGND ------> GND
四、软件实现
1. ADS1118初始化
初始化软件SPI通信接口,并设置好ADS1118的配置字,具体配置模式可以参照datasheet或者上一章节。
void ADS1118_Init(void) //ADS1118初始化{uint16_t config = ADS1118_CONFIG_SS_START_OFF | // ADS1118_CONFIG_MODE_CONTIN | //连续转换模式 ADS1118_CONFIG_DR_128SPS | // 转换 速率 SPS ADS1118_CONFIG_TS_MODE_ADC | // 读取ADC,而不是温度 ADS1118_CONFIG_PULL_UP_ON | //上拉电阻启用 ADS1118_CONFIG_NOP_VALID | // this is valid data (default)ADS1118_CONFIG_PGA_4_096V | // FSR is ±4.096 VADS1118_CONFIG_MUX_SINGLE_0| //AINP is AIN0 and AINN is GND//单端 ADS1118_CONFIG_RESV; // reserved bits must be set to 1GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIOA_CLK_ENABLE();// 开启GPIOC时钟//CS -> D9SCLK -> D11DIN(MOSI) -> D13----推挽輸出 GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //推挽輸出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //MISO -> D15----开漏輸出 GPIO_InitStruct.Pin = GPIO_PIN_6;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;//开漏輸出 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);MISO_H;SCLK_L;MOSI_L;Write_ADS1118(config,1,0);//设置ads1118}
SPI的IO口以及配置字宏定义如下:
#define READ_MISO HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)#define SCLK_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)#define SCLK_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)/*单片机为主机*/#define MOSI_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_SET) //主机出从机入#define MOSI_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_7,GPIO_PIN_RESET)#define MISO_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET) //主机入从机出#define MISO_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET)#define CS_H HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4 ,GPIO_PIN_SET)#define CS_L HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4 ,GPIO_PIN_RESET)//单次转换开始#define ADS1118_CONFIG_SS_START_MASK 0x8000#define ADS1118_CONFIG_SS_START_ON 0x8000 //开始单次转换#define ADS1118_CONFIG_SS_START_OFF 0x0000 // 无效 //输入多路复用器配置#define ADS1118_CONFIG_MUX_MASK 0x7000#define ADS1118_CONFIG_MUX_DIFF_0_1 0x0000 //AINP is AIN0 and AINN is AIN1 //差分#define ADS1118_CONFIG_MUX_DIFF_0_3 0x1000 //AINP is AIN0 and AINN is AIN3#define ADS1118_CONFIG_MUX_DIFF_1_3 0x2000 //AINP is AIN1 and AINN is AIN3#define ADS1118_CONFIG_MUX_DIFF_2_3 0x3000 //AINP is AIN2 and AINN is AIN3#define ADS1118_CONFIG_MUX_SINGLE_0 0x4000 //AINP is AIN0 and AINN is GND//单端#define ADS1118_CONFIG_MUX_SINGLE_1 0x5000 //AINP is AIN1 and AINN is GND#define ADS1118_CONFIG_MUX_SINGLE_2 0x6000 //AINP is AIN2 and AINN is GND#define ADS1118_CONFIG_MUX_SINGLE_3 0x7000 //AINP is AIN3 and AINN is GND//可编程增益放大器配置#define ADS1118_CONFIG_PGA_MASK 0x0E00 //FSR is ±0.256 V#define ADS1118_CONFIG_PGA_6_144V 0x0000 //FSR is ±6.144 V#define ADS1118_CONFIG_PGA_4_096V 0x0200 //FSR is ±4.096 V#define ADS1118_CONFIG_PGA_2_048V 0x0400 //FSR is ±2.048 V#define ADS1118_CONFIG_PGA_1_024V 0x0600 //FSR is ±1.024 V#define ADS1118_CONFIG_PGA_0_512V 0x0800 //FSR is ±0.512 V#define ADS1118_CONFIG_PGA_0_256V 0x0A00 //FSR is ±0.256 V//设备操作模式#define ADS1118_CONFIG_MODE_MASK 0x0100#define ADS1118_CONFIG_MODE_CONTIN 0x0000 //连续转换模式#define ADS1118_CONFIG_MODE_SINGLE 0x0100 //掉电,单次转换模式//数据速率#define ADS1118_CONFIG_DR_MASK 0x00E0 //860SPS#define ADS1118_CONFIG_DR_8SPS 0x0000#define ADS1118_CONFIG_DR_16SPS 0x0020#define ADS1118_CONFIG_DR_32SPS 0x0040#define ADS1118_CONFIG_DR_64SPS 0x0060#define ADS1118_CONFIG_DR_128SPS 0x0080 #define ADS1118_CONFIG_DR_250SPS 0x00A0#define ADS1118_CONFIG_DR_475SPS 0x00C0#define ADS1118_CONFIG_DR_860SPS 0x00E0//温度传感器模式#define ADS1118_CONFIG_TS_MODE_MASK 0x0010#define ADS1118_CONFIG_TS_MODE_ADC 0x0000 //ADC模式#define ADS1118_CONFIG_TS_MODE_TEMP 0x0010 //温度传感器模式//上拉使能//仅当CS为高电平时,此位使能DOUT / DRDY引脚上的内部弱上拉电阻。 启用后,内部400kΩ电阻器将总线线路连接到电源。 禁用时,DOUT / DRDY引脚悬空。#define ADS1118_CONFIG_PULL_UP_MASK 0x0008#define ADS1118_CONFIG_PULL_UP_ON 0x0008 //上拉电阻启用#define ADS1118_CONFIG_PULL_UP_OFF 0x0000 //上拉电阻禁用//控制是否将数据写入配置寄存器#define ADS1118_CONFIG_NOP_MASK 0x0006#define ADS1118_CONFIG_NOP_VALID 0x0002 // 有效数据,更新Config寄存器#define ADS1118_CONFIG_NOP_INVALID 0x0006 //无效数据,不更新Config寄存器的内容//#define ADS1118_CONFIG_RESV 0x0001 // default, required//#define ADS1118_CONST_C_PER_BIT (0.03125)#define ADS1118_CONST_BIT_PER_C 32//#define ADS1118_CONST_6_144V_LSB_mV (0.1875)#define ADS1118_CONST_4_096V_LSB_mV (0.125)#define ADS1118_CONST_2_048V_LSB_mV (0.0625)#define ADS1118_CONST_1_024V_LSB_mV (0.03125)#define ADS1118_CONST_0_512V_LSB_mV (0.015625)#define ADS1118_CONST_0_256V_LSB_mV (0.0078125)
2. 写入配置字函数
/*******************************************************************************函数名称:Write_ADS1118()函数功能:设置1118寄存器输 入:config:寄存器配置 discardData: 是否更新读回数据 0读回 1不读回返 回: 16位ad转换数据备 注: *******************************************************************************/int16_t Write_ADS1118(uint16_t config,uint8_t discardData){uint8_t i=0; static int16_t read=0;CS_L;if(discardData==0) {read=0;}delay_us(1); for(i=0;i<16;i++) // 循环16次 {if(config & 0x8000)MOSI_H;else MOSI_L;config <<= 1;delay_us(1);SCLK_H;delay_us(1);SCLK_L;delay_us(1);if(discardData==0){read<<=1;if(READ_MISO)read ++;}else{delay_us(2);}}CS_H;delay_us(2);CS_L;//SCLK_L;//MOSI_L;//MISO_H;return read;}
3. 读取通道值函数
/*******************************************************************************函数名称:ADS_SEL_Read()函数功能:读取各路电压,通过两个switch选择读取不同的通道输 入:road:增益放大器两端的电压选择,并选择测几路电压 Ref: 选择参考电压,有6种选择 mode: 是否更新读回数据 0读回 1不读回输 出:dat:16位ad转换数据备 注:这一次读出的转换数据是上一次的转换数据,不要混淆.这里选择的是单次 转换电压值,当然,也可以选择多次转换,通过寄存器的第8位可以设置*******************************************************************************/int16_t ADS_SEL_Read(uint8_t road,uint8_t Ref,uint8_t mode) //测几路电压{ int dat = 0;uint16_t config = ADS1118_CONFIG_SS_START_OFF | // ADS1118_CONFIG_MODE_CONTIN | //连续转换模式 ADS1118_CONFIG_DR_128SPS | // 转换 速率 SPS ADS1118_CONFIG_TS_MODE_ADC | // 读取ADC,而不是温度 ADS1118_CONFIG_PULL_UP_ON | //上拉电阻启用 ADS1118_CONFIG_NOP_VALID | // this is valid data (default) ADS1118_CONFIG_RESV; // reserved bits must be set to 1 switch(road) //选择有效转换的路数 {case 0: config |= ADS1118_CONFIG_MUX_DIFF_0_1;break; //AINP = AIN0 and AINN = AIN1 (default)case 1: config |= ADS1118_CONFIG_MUX_DIFF_0_3;break; //AINP = AIN0 and AINN = AIN3case 2: config |= ADS1118_CONFIG_MUX_DIFF_1_3;break; //AINP = AIN1 and AINN = AIN3case 3: config |= ADS1118_CONFIG_MUX_DIFF_2_3;break; //AINP = AIN2 and AINN = AIN3case 4: config |= ADS1118_CONFIG_MUX_SINGLE_0;break; //AINP = AIN0 and AINN = GNDcase 5: config |= ADS1118_CONFIG_MUX_SINGLE_1;break; //AINP = AIN1 and AINN = GNDcase 6: config |= ADS1118_CONFIG_MUX_SINGLE_2;break; //AINP = AIN2 and AINN = GNDcase 7: config |= ADS1118_CONFIG_MUX_SINGLE_3;break; //AINP = AIN3 and AINN = GNDdefault : break; } switch(Ref) {case 0: config |= ADS1118_CONFIG_PGA_6_144V;break; //000 : FS = ±6.144V(1)case 1: config |= ADS1118_CONFIG_PGA_4_096V;break; //001 : FS = ±4.096V(1)case 2: config |= ADS1118_CONFIG_PGA_2_048V;break; //002 : FS = ±2.048V(1)case 3: config |= ADS1118_CONFIG_PGA_1_024V;break; //003 : FS = ±1.024V(1)case 4: config |= ADS1118_CONFIG_PGA_0_512V;break; //004 : FS = ±0.512V(1)case 5: case 6: case 7: config |= ADS1118_CONFIG_PGA_0_256V;break; //005 : FS = ±0.256V(1)default : break; } dat = Write_ADS1118(config,mode); return dat;}
4. 主函数
/** * @brief The application entry point. * @retval int */int main(void){ /* USER CODE BEGIN 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_USART1_UART_Init();ADS1118_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ Volt_Value[0] = ADS_SEL_Read(5,0,0)*ADS1118_CONST_4_096V_LSB_mV/1000 Volt_Value[0] = ADS_SEL_Read(5,0,0)*ADS1118_CONST_4_096V_LSB_mV/1000; HAL_Delay(15); //AN2 Volt_Value[1] = ADS_SEL_Read(6,0,0)*ADS1118_CONST_4_096V_LSB_mV/1000; Volt_Value[1] = ADS_SEL_Read(6,0,0)*ADS1118_CONST_4_096V_LSB_mV/1000; HAL_Delay(15); delay_ms(100); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */}
需要注意的是,ADS1118本次读取的值是上次的转换数据,所以在多通道连续读取时,可以连续对一个通道读取两次,保证取到的数据为本通道值。如果不连续读取两次,而是单次错位取出数据的方式,一定要注意等待时间,建议加上/DRDY判断,不然很容易产生通道错位。
源码下载地址:https://download.csdn.net/download/qq_46671207/91645040?spm=1001.2014.3001.5503