一、LDC1614芯片简介
LDC1614是德州仪器(TI)推出的4通道电感式传感控制器,通过检测电感线圈的频率变化,实现对导电物体(如金属)的距离、位置或材质的高精度测量。其核心特性包括:
-
4个独立传感通道,支持多目标检测;
-
I2C接口(地址0x2A,7位),兼容标准/快速模式;
-
可编程驱动电流(1.5mA~32mA),适配不同线圈;
-
分辨率达28位,测量精度±1%;
-
低功耗模式,适合电池供电场景。
二、硬件连接
2.1 核心连接表
| LDC1614引脚 | STM32F103C8T6引脚 | 功能说明 |
|---|---|---|
| SCL | PB6 (I2C1_SCL) | I2C时钟线 |
| SDA | PB7 (I2C1_SDA) | I2C数据线 |
| VDD | 3.3V | 电源 (2.3V~3.6V) |
| GND | GND | 地线 |
| INTB | PA0 (可选) | 中断输出(低有效) |
| CLKIN | 悬空(内部RC振荡) | 外部时钟输入(可选) |
2.2 线圈连接
LDC1614需外接电感线圈(如PCB螺旋线圈,直径5~20mm),线圈两端接LDC1614的CH0-CH3引脚(每个通道对应一个线圈)。
三、STM32 I2C配置(标准库)
3.1 I2C初始化函数
c
#include "stm32f10x.h"
#include "i2c.h"
void I2C1_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
// 配置PB6(SCL)、PB7(SDA)为复用开漏输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 复用开漏
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// I2C1配置
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 2:1占空比
I2C_InitStructure.I2C_OwnAddress1 = 0x00; // 主机地址(可忽略)
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // 使能ACK
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7位地址
I2C_InitStructure.I2C_ClockSpeed = 100000; // 100kHz(标准模式)
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE); // 使能I2C1
}
3.2 I2C读写函数
c
// I2C发送数据(寄存器地址+数据)
void I2C_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint16_t data) {
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); // 等待总线空闲
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // EV5
// 发送设备地址(写)
I2C_Send7bitAddress(I2C1, dev_addr<<1, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // EV6
// 发送寄存器地址
I2C_SendData(I2C1, reg_addr);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // EV8
// 发送数据(16位分两次发送)
I2C_SendData(I2C1, (uint8_t)(data >> 8)); // 高8位
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1, (uint8_t)(data & 0xFF)); // 低8位
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// 发送停止信号
I2C_GenerateSTOP(I2C1, ENABLE);
}
// I2C读取数据(寄存器地址+读取数据)
uint16_t I2C_ReadReg(uint8_t dev_addr, uint8_t reg_addr) {
uint16_t data = 0;
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
// 发送起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // EV5
// 发送设备地址(写)
I2C_Send7bitAddress(I2C1, dev_addr<<1, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // EV6
// 发送寄存器地址
I2C_SendData(I2C1, reg_addr);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // EV8
// 发送重复起始信号
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // EV5
// 发送设备地址(读)
I2C_Send7bitAddress(I2C1, dev_addr<<1, I2C_Direction_Receiver);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); // EV6
// 读取数据(16位)
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7
data = I2C_ReceiveData(I2C1) << 8; // 高8位
I2C_AcknowledgeConfig(I2C1, DISABLE); // 最后一次读取关闭ACK
I2C_GenerateSTOP(I2C1, ENABLE); // 发送停止信号
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); // EV7
data |= I2C_ReceiveData(I2C1); // 低8位
I2C_AcknowledgeConfig(I2C1, ENABLE); // 恢复ACK
return data;
}
四、LDC1614初始化与配置
4.1 寄存器定义(关键寄存器)
c
// LDC1614寄存器地址(部分)
#define LDC1614_DEV_ADDR 0x2A // 7位I2C地址
#define REG_DATA_CH0 0x00 // 通道0数据寄存器(28位)
#define REG_DATA_CH1 0x02 // 通道1数据寄存器(28位)
#define REG_DATA_CH2 0x04 // 通道2数据寄存器(28位)
#define REG_DATA_CH3 0x06 // 通道3数据寄存器(28位)
#define REG_RCOUNT_CH0 0x08 // 通道0转换计数寄存器
#define REG_OFFSET_CH0 0x0C // 通道0偏移寄存器
#define REG_SETTLECOUNT_CH0 0x10 // 通道0稳定计数寄存器
#define REG_CLOCK_DIVIDERS_CH0 0x14 // 通道0时钟分频寄存器
#define REG_CONFIG 0x1A // 全局配置寄存器
#define REG_MUX_CONFIG 0x1B // 多路复用配置寄存器
#define REG_DRIVE_CURRENT 0x1E // 驱动电流寄存器
4.2 LDC1614初始化函数
c
void LDC1614_Init(void) {
// 1. 复位芯片(写入CONFIG寄存器,bit15=1)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_CONFIG, 0x8000);
delay_ms(10); // 等待复位完成
// 2. 配置全局参数(CONFIG寄存器)
// bit15=0(正常工作), bit14=1(启用INTB), bit13=0(连续转换模式)
// bit12-10=000(分频系数1), bit9-0=0x000(保留)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_CONFIG, 0x4000);
// 3. 配置多路复用(MUX_CONFIG寄存器)
// bit15-13=000(通道序列0-3), bit12=0(自动扫描), bit11-8=0x0F(所有通道使能)
// bit7-6=00(SETTLECOUNT分频), bit5-0=0x00(保留)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_MUX_CONFIG, 0x0F00);
// 4. 配置驱动电流(DRIVE_CURRENT寄存器)
// CH0-CH3驱动电流:0x1F(约16mA,根据线圈调整)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_DRIVE_CURRENT, 0x1F1F1F1F);
// 5. 配置通道0参数(以CH0为例)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_RCOUNT_CH0, 0x0FFF); // 转换计数(最大值)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_SETTLECOUNT_CH0, 0x0400); // 稳定计数(1024 cycles)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_CLOCK_DIVIDERS_CH0, 0x1001); // 时钟分频(1:1)
I2C_WriteReg(LDC1614_DEV_ADDR, REG_OFFSET_CH0, 0x0000); // 偏移量0
}
参考代码 STM32F103C8T6驱动LDC1614测试程序 www.youwenfan.com/contentcss/183148.html
五、数据读取与处理
5.1 读取通道数据
LDC1614每个通道数据为28位,存储在2个16位寄存器中(高12位+低16位),需拼接后转换为实际频率值。
c
// 读取通道0数据(28位)
uint32_t LDC1614_ReadCh0(void) {
uint16_t data_high = I2C_ReadReg(LDC1614_DEV_ADDR, REG_DATA_CH0); // 高12位(bit15-4)
uint16_t data_low = I2C_ReadReg(LDC1614_DEV_ADDR, REG_DATA_CH0+1); // 低16位(bit15-0)
uint32_t data_28bit = ((uint32_t)(data_high & 0x0FFF) << 16) | data_low; // 拼接28位
return data_28bit;
}
5.2 数据转换为频率
LDC1614的输出频率为:
fOUT=fREF×228RCOUNT×DATAf_{OUT}=\frac{f_{REF}×2^{28}}{RCOUNT×DATA}fOUT=RCOUNT×DATAfREF×228
其中:
-
fREFf_{REF}fREF:参考频率(由CLKIN或内部RC决定,默认4MHz);
-
RCOUNTRCOUNTRCOUNT:转换计数值(REG_RCOUNT_CH0,如0x0FFF=4095);
-
DATADATADATA:28位数据(LDC1614_ReadCh0()返回值)。
c
float LDC1614_DataToFreq(uint32_t data_28bit) {
const float f_ref = 4000000; // 参考频率4MHz
const uint16_t rcount = 0x0FFF; // RCOUNT值(4095)
float freq = (f_ref * (1UL << 28)) / (rcount * data_28bit); // 计算频率(Hz)
return freq;
}
六、主程序测试流程
c
#include "stm32f10x.h"
#include "i2c.h"
#include "ldc1614.h"
#include "usart.h" // 串口初始化(用于打印数据)
int main(void) {
SystemInit(); // 系统时钟初始化(72MHz)
USART1_Init(115200); // 串口初始化(波特率115200)
I2C1_Init(); // I2C初始化
LDC1614_Init(); // LDC1614初始化
printf("LDC1614 Test Start...\r\n");
while (1) {
// 读取通道0数据
uint32_t data_ch0 = LDC1614_ReadCh0();
float freq_ch0 = LDC1614_DataToFreq(data_ch0);
// 打印结果(串口)
printf("CH0 Data: 0x%08lX, Freq: %.2f Hz\r\n", data_ch0, freq_ch0);
delay_ms(500); // 500ms刷新一次
}
}
七、测试结果与分析
7.1 预期输出
通过串口助手(如XCOM)可观察到类似以下数据:
c
LDC1614 Test Start...
CH0 Data: 0x07A1203F, Freq: 123456.78 Hz
CH0 Data: 0x079F3045, Freq: 123987.65 Hz
...
当金属物体靠近线圈时,频率会降低 (电感增大),远离时频率升高(电感减小)。
7.2 常见问题排查
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 无数据输出 | I2C通信失败 | 检查接线(SCL/SDA是否接反)、上拉电阻(4.7kΩ) |
| 数据全0或全F | 线圈未连接或损坏 | 用万用表测量线圈电阻(应<10Ω) |
| 频率值异常(如0Hz) | RCOUNT或DRIVE_CURRENT配置错误 | 检查REG_RCOUNT_CH0和REG_DRIVE_CURRENT寄存器值 |
八、总结
本测试程序实现了STM32F103C8T6对LDC1614的基础驱动,包括I2C通信、寄存器配置、数据读取与转换。通过串口打印的28位数据和频率值,可验证LDC1614的正常工作。实际应用中,需根据线圈参数(电感、Q值)调整驱动电流 和RCOUNT,以优化测量范围和精度。
扩展方向:
-
添加多通道数据读取(CH1-CH3);
-
实现距离-频率校准曲线(通过实验数据拟合);
-
结合中断功能(INTB引脚)实现低功耗检测。