基于 MSP430 + TDC‑GP22 的激光测距

基于 MSP430 + TDC‑GP22 的激光测距


一、系统总体架构

Laser Driver
     ↓
发射激光 → 目标
     ↓
APD / PIN 接收
     ↓
TDC‑GP22(高精度时间测量)
     ↓
MSP430(SPI 读取结果)
     ↓
距离计算 + 温度补偿

TDC‑GP22 核心优势


二、硬件连接(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
多次测量取中值

 

专注于matlab/simulink,电子电路,编程