基于 MSP430 + TDC‑GP22 的激光测距
一、系统总体架构
Laser Driver
↓
发射激光 → 目标
↓
APD / PIN 接收
↓
TDC‑GP22(高精度时间测量)
↓
MSP430(SPI 读取结果)
↓
距离计算 + 温度补偿
TDC‑GP22 核心优势
- 时间分辨率:45 ps
- 测量范围:3.5 ns ~ 4 ms
- 功耗极低(适合 MSP430)
二、硬件连接(MSP430 + TDC‑GP22)
1、SPI 接口(强制 4 线)
| TDC‑GP22 | MSP430 |
|---|---|
| SCK | P1.5 |
| SI | P1.6 |
| SO | P1.7 |
| CSN | P2.0 |
| INTN | P2.1 |
| EN_RESET | P2.2 |
2、激光与接收
| 信号 | 说明 |
|---|---|
| LASER_TX | MSP430 GPIO → MOS 驱动 |
| STOP | APD 比较器 → TDC STOP |
| START | 激光触发 → TDC START |
三、TDC‑GP22 寄存器配置(核心)
1、寄存器一览
| 地址 | 名称 | 作用 |
|---|---|---|
| 0x00 | CONFIG1 | 测量模式 |
| 0x01 | CONFIG2 | 校准 |
| 0x02 | CONFIG3 | 中断 |
| 0x03 | CONFIG4 | 测温 |
| 0x04 | CALIB | 校准值 |
| 0x05 | RESULT1 | 时间结果 |
2、CONFIG1(最重要)
#define CONFIG1_DEFAULT 0x000000
/*
Bit[1:0] = 01 → 模式 1(START→STOP1)
Bit[3] = 0 → 单次测量
Bit[7] = 1 → 使能中断
*/
四、MSP430 SPI 驱动(基础)
#include <msp430.h>
#define CSN_LO P2OUT &= ~BIT0
#define CSN_HI P2OUT |= BIT0
#define EN_RESET_LO P2OUT &= ~BIT2
#define EN_RESET_HI P2OUT |= BIT2
void SPI_Init(void)
{
P1SEL |= BIT5 | BIT6 | BIT7; // SCK, MISO, MOSI
P1DIR |= BIT5 | BIT6;
P1DIR &= ~BIT7;
UCB0CTL1 |= UCSWRST;
UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCSYNC;
UCB0CTL1 = UCSSEL_2 | UCSWRST;
UCB0BR0 = 0x02; // SPI 时钟
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST;
}
五、TDC‑GP22 读写函数
uint8_t SPI_Transfer(uint8_t data)
{
UCB0TXBUF = data;
while (!(UCB0IFG & UCRXIFG));
return UCB0RXBUF;
}
void TDC_WriteReg(uint8_t addr, uint32_t data)
{
CSN_LO;
SPI_Transfer(addr & 0x7F);
SPI_Transfer((data >> 24) & 0xFF);
SPI_Transfer((data >> 16) & 0xFF);
SPI_Transfer((data >> 8) & 0xFF);
SPI_Transfer(data & 0xFF);
CSN_HI;
}
uint32_t TDC_ReadReg(uint8_t addr)
{
uint32_t data = 0;
CSN_LO;
SPI_Transfer(addr | 0x80);
data |= SPI_Transfer(0xFF) << 24;
data |= SPI_Transfer(0xFF) << 16;
data |= SPI_Transfer(0xFF) << 8;
data |= SPI_Transfer(0xFF);
CSN_HI;
return data;
}
六、TDC‑GP22 初始化
void TDC_Init(void)
{
EN_RESET_HI;
__delay_cycles(16000);
TDC_WriteReg(0x00, 0x000001); // CONFIG1
TDC_WriteReg(0x01, 0x000000); // CONFIG2
TDC_WriteReg(0x02, 0x000000); // CONFIG3
}
七、一次完整测距流程
float Laser_Range(void)
{
uint32_t time_raw;
float time_ns, distance;
// 1. 触发激光
P1OUT |= BIT0; // 激光发射
__delay_cycles(10);
P1OUT &= ~BIT0;
// 2. 等待测量完成
while (P2IN & BIT1); // INTN 拉低表示完成
// 3. 读取时间
time_raw = TDC_ReadReg(0x05);
// 4. 换算时间(ns)
time_ns = time_raw * 0.045; // 45ps/LSB
// 5. 计算距离(米)
distance = (time_ns / 2.0f) * 0.299792458f;
return distance;
}
八、温度补偿(工程级必加)
float Temp_Compensation(float d)
{
uint32_t temp_raw = TDC_ReadReg(0x04);
float temp = temp_raw * 0.01f;
// 温度系数(需标定)
float k = -0.0012f;
return d + k * (25.0f - temp);
}
九、主函数
void main(void)
{
WDTCTL = WDTPW | WDTHOLD;
DCOCTL = CALDCO_8MHZ;
BCSCTL1 = CALBC1_8MHZ;
P1DIR |= BIT0; // 激光控制
P2DIR |= BIT0 | BIT2;
SPI_Init();
TDC_Init();
while (1)
{
float dist = Laser_Range();
dist = Temp_Compensation(dist);
__delay_cycles(8000000); // 1s
}
}
参考代码 激光测距程序 www.youwenfan.com/contentcsu/69864.html
十、调试要点
START 与 STOP 必须同电平基准
电源噪声要小(LC 滤波)
激光脉宽 ≤ 10 ns
多次测量取中值