当前位置: 首页 > news >正文

TDC7201与TDC7200芯片寄存器功能概述及main.c代码

TDC7201 全部寄存器完整功能手册
前置说明
1. TDC7201 内部包含两路独立 TDC 内核(TDC1 / TDC2),两套寄存器完全独立,通过 CSB1 / CSB2 片选区分,下文统一前缀 TDCx_ 代表任意一路内核寄存器;
2. 寄存器地址范围 00h ~ 1Ch,分为配置寄存器、中断寄存器、溢出阈值寄存器、STOP 屏蔽寄存器、测量结果寄存器、校准寄存器六大类;
3. 8 位寄存器:单字节读写;24 位寄存器(TIME/CLOCK_COUNT/CALIBRATION):3 字节 SPI 读取,Bit23 为奇偶校验位,Bit22~0 为有效计数值。

/////////////////////////////////////////////////////////////////////////////////////////////////////////
一、基础配置寄存器(00h / 01h,8 位可读写)
1. 地址 00h: TDCx_CONFIG1 主配置寄存器(复位 00h)
位 位名称 详细功能
D7 FORCE_CAL 强制校准使能0:测量正常结束自动校准;溢出 / 无 STOP 中断时不校准1:无论测量是否异常终止,强制执行自校准
D6 PARITY_EN 奇偶校验开关0:TIME/CLOCK_COUNT/CALIBRATION 寄存器校验位恒 01:开启偶校验,读取可校验数据传输错误
D5 TRIGG_EDGE TRIGG 输出脉冲边沿0:上升沿输出触发信号1:下降沿输出触发信号
D4 STOP_EDGE STOP 信号触发边沿0:上升沿停止计时(推荐高精度场景)1:下降沿停止计时
D3 START_EDGE START 信号触发边沿0:上升沿启动计时(推荐)1:下降沿启动计时
D2~D1 MEAS_MODE 测量模式选择00:模式 1(12ns~2000ns 短测距,仅环振计数)01:模式 2(250ns~8ms 长测距,推荐通用)10/11:硬件保留,禁止使用
D0 START_MEAS 测量启动位写 1:清空所有测量寄存器、输出 TRIG 触发脉冲、启动一次完整测量测量完成后硬件自动清零

2. 地址 01h:TDCx_CONFIG2 高级配置寄存器(复位 40h)
位 位名称 详细功能
D7~D6 CALIBRATION2_PERIODS 二次校准时钟周期数(决定校准精度)00=2 个外部时钟;01=10(默认);10=20;11=40
D5~D3 AVG_CYCLES 多周期平均次数(低功耗 MCU 休眠模式)000:单次测量(关闭平均)001=2 / 010=4 / 011=8 / 100=16 / 101=32 / 110=64 / 111=128平均模式下 CLOCK_COUNT 读取后需右移 log2 (次数) 再计算 TOF
D2~D0 NUM_STOP 可采集 STOP 脉冲最大数量000:单 STOP;001=2;010=3;011=4;100=5101/110/111:无效,强制单路 STOP


/////////////////////////////////////////////////////////////////////////////////////////////////////////
二、中断控制寄存器(02h / 03h,8 位)
3. 地址 02h:TDCx_INT_STATUS 中断状态寄存器(复位 00h,写 1 清零标志)
存储所有测量 / 溢出事件状态,仅写 1 可清除对应标志,只读不会清零
位 位名称 详细功能
D7~D5 Reserved 硬件保留,固定 0
D4 MEAS_COMPLETE_FLAG 测量完成总标志1:一组平均 / 单次测量全部结束;写 1 清零
D3 MEAS_STARTED_FLAG 测量启动标志1:已捕获 START 脉冲,计时开始;写 1 清零
D2 CLOCK_CNTR_OVF_INT 时钟粗计数器溢出中断1:外部时钟计数超限,测量立即终止;写 1 清零
D1 COARSE_CNTR_OVF_INT 环振粗计数器溢出中断1:短时间环振计数超限,测量终止;写 1 清零
D0 NEW_MEAS_INT 新测量完成主中断(INTB 引脚触发源)1:全部 STOP 采集完成,拉低 INTB;写 1 清零


4. 地址 03h:TDCx_INT_MASK 中断屏蔽寄存器(复位 07h)
控制中断是否输出到硬件INTB引脚;寄存器状态位不受屏蔽影响
位 位名称 详细功能
D7~D3 Reserved 硬件保留,固定 0
D2 CLOCK_CNTR_OVF_MASK 时钟溢出中断屏蔽1:溢出时 INTB 拉低输出中断;0:仅寄存器置位,引脚无电平变化
D1 COARSE_CNTR_OVF_MASK 环振溢出中断屏蔽1:溢出触发 INTB;0:仅内部记录,无硬件中断
D0 NEW_MEAS_MASK 测量完成主中断屏蔽1:测量结束拉低 INTB 唤醒 MCU;0:仅寄存器标记,无引脚中断

/////////////////////////////////////////////////////////////////////////////////////////////////////////
三、计数器溢出阈值寄存器(04h~07h,8 位读写)
作用:设置最大计时上限,计数超过阈值立刻终止测量并触发溢出中断;16 位阈值 = 高 8 位 <<8 | 低 8 位
5. 04h TDCx_COARSE_CNTR_OVF_H 环振溢出阈值高 8 位(复位 FFh)
6. 05h TDCx_COARSE_CNTR_OVF_L 环振溢出阈值低 8 位(复位 FFh)
组合 COARSE_CNTR_OVF = H<<8 | L:模式 1 专用上限,环振计数值超过则溢出停机;手册禁止低 8 位设为 1。
7. 06h TDCx_CLOCK_CNTR_OVF_H 时钟计数器溢出高 8 位(复位 FFh)
8. 07h TDCx_CLOCK_CNTR_OVF_L 时钟计数器溢出低 8 位(复位 FFh)
组合 CLOCK_CNTR_OVF = H<<8 | L:模式 2 专用上限,外部时钟周期计数超限触发中断。

/////////////////////////////////////////////////////////////////////////////////////////////////////////
四、STOP 噪声屏蔽寄存器(08h / 09h,8 位读写)
近端杂波过滤:START 之后前 N 个外部时钟周期内,所有 STOP 脉冲全部忽略,屏蔽近距离反射干扰
9. 08h TDCx_CLOCK_CNTR_STOP_MASK_H 屏蔽窗口高 8 位(复位 00h)
10. 09h TDCx_CLOCK_CNTR_STOP_MASK_L 屏蔽窗口低 8 位(复位 00h)
组合 MASK = H<<8 | L;约束:MASK 数值必须小于时钟溢出阈值,否则未到有效窗口就溢出报错


/////////////////////////////////////////////////////////////////////////////////////////////////////////
五、TOF 时间原始计数值寄存器(10h / 12h / 14h / 16h / 18h / 1Ah,24 位只读)
命名 TDCx_TIMEn(n=1~6):存储 START 到第 n 路 STOP 之间环形振荡器小数计数值
寄存器统一格式:
Bit23: 奇偶校验位(PARITY_EN=1 时有效)
Bit22~0: 23 位原始环振计数
| 地址 | 寄存器名 | 功能 |
|------|----------|------|
| 10h | TDCx_TIME1 | START → 第 1 路 STOP 环振计数值(模式 2TOF 计算公式基准项) |
| 12h | TDCx_TIME2 | START → 第 2 路 STOP 环振计数值 |
| 14h | TDCx_TIME3 | START → 第 3 路 STOP 环振计数值 |
| 16h | TDCx_TIME4 | START → 第 4 路 STOP 环振计数值 |
| 18h | TDCx_TIME5 | START → 第 5 路 STOP 环振计数值 |
| 1Ah | TDCx_TIME6 | 5 路 STOP 模式下备用计时缓存


/////////////////////////////////////////////////////////////////////////////////////////////////////////
六、外部时钟整数计数寄存器(11h / 13h / 15h / 17h / 19h,24 位只读)
命名 TDCx_CLOCK_COUNTn(n=1~5):仅测量模式 2 有效,记录 START 到第 n 路 STOP 之间完整外部时钟周期整数
寄存器统一格式:
Bit23: 奇偶校验位
Bit22~16: 多周期平均扩展位,存放累加余数
Bit15~0: 16 位有效时钟周期计数值
| 地址 | 寄存器名 | 功能 |
|------|----------|------|
| 11h | TDCx_CLOCK_COUNT1 | 第 1 路 STOP 对应的外部时钟整数计数 |
| 13h | TDCx_CLOCK_COUNT2 | 第 2 路 STOP 对应的外部时钟整数计数 |
| 15h | TDCx_CLOCK_COUNT3 | 第 3 路 STOP 对应的外部时钟整数计数 |
| 17h | TDCx_CLOCK_COUNT4 | 第 4 路 STOP 对应的外部时钟整数计数 |
| 19h | TDCx_CLOCK_COUNT5 | 第 5 路 STOP 对应的外部时钟整数计数 |

/////////////////////////////////////////////////////////////////////////////////////////////////////////
七、自校准基准寄存器(1Bh / 1Ch,24 位只读)
MCU 读取后计算真实 LSB 皮秒分辨率,补偿温漂、电压漂移,是 TOF 换算核心参数
22. 1Bh TDCx_CALIBRATION1 单时钟周期校准值
存储1 个外部时钟周期对应的环振计数值(校准点 1)
23. 1Ch TDCx_CALIBRATION2 多周期校准值
存储 CONFIG2.CALIBRATION2_PERIODS 设定数量的外部时钟对应的环振计数值(校准点 2)
校准计算公式:
calCount = (CALIBRATION2 - CALIBRATION1) / (CALIBRATION2_PERIODS - 1)
normLSB = 外部时钟周期 / calCount

/////////////////////////////////////////////////////////////////////////////////////////////////////////
标准测量寄存器操作流程
1.SPI 写 CONFIG1 / CONFIG2 配置模式、平均次数、STOP 数量;
2.配置溢出阈值、STOP 屏蔽窗口寄存器;
3.置位 CONFIG1.START_MEAS 启动测量;
4.等待 INTB 硬件中断;
5.读取 CALIBRATION1 / CALIBRATION2 计算 LSB 分辨率;
6.读取 TIMEx / CLOCK_COUNTx,代入对应模式公式算出真实飞行时间 TOF;
7.写 1 清除 INT_STATUS 中断标志,重复下一次测量。


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

TDC7200寄存器功能整理
一、基础配置寄存器(00h-01h)
1.地址00h:CONFIG1 主配置寄存器 (复位 00h,8位读写)
位 位名 功能说明
D7 FORCE_CAL 强制校准:0 = 测量中断(溢出 / 无 STOP)时不校准;1 = 无论测量是否正常结束,强制执行一次自校准
D6 PARITY_EN 奇偶校验使能:0 = 测量寄存器无校验位;1=TIME/CLOCK_COUNT/CALIBRATION 寄存器开启偶校验
D5 TRIGG_EDGE TRIGG 触发输出边沿:0 = 上升沿输出;1 = 下降沿输出
D4 STOP_EDGE STOP 信号触发边沿:0 = 上升沿停止计时;1 = 下降沿停止计时(推荐上升沿保证精度)
D3 START_EDGE START 信号触发边沿:0 = 上升沿启动计时;1 = 下降沿启动计时(推荐上升沿)
D2~D1 MEAS_MODE 测量模式选择:00 = 模式 1(12ns~500ns 短时间测量,仅环形振荡器计数)01 = 模式 2(250ns~8ms 长距离,外部时钟粗计数 + 环振小数,通用推荐)10/11 = 保留禁用
D0 START_MEAS 测量启动位:写 1 立即触发新测量,清空所有结果寄存器、产生 TRIGG 脉冲;测量完成硬件自动清 0

2.地址01h:CONFIG2 高级配置寄存器 (复位 40h,8位读写)
位 位名 功能说明
D7~D6 CALIBRATION2_PERIODS 二次校准时钟周期数(校准精度基准):00=2 个外部时钟;01=10 个(默认);10=20 个;11=40 个
D5~D3 AVG_CYCLES 多周期平均次数(低功耗,MCU 休眠自动多次测量):001=2 次、010=4 次、011=8 次、100=16 次、101=32 次、110=64 次、111=128 次;000 = 关闭平均,单次测量
D2~D0 NUM_STOP 支持的 STOP 通道数量:000 = 单 STOP;001=2 路;010=3 路;011=4 路;100=5 路;101/110/111 = 无效,强制单路

/////////////////////////////////////////////////////////////////////////////////////////////////////////
二、中断控制寄存器(02h ~ 03h)
3. 地址 02h:INT_STATUS 中断状态寄存器(复位 00h,8 位读写清标志)
存储所有中断事件标志,写 1 清零对应位,只读标志不可自动清除
位 位名 功能说明
D7~D5 Reserved 保留位,固定 0
D4 MEAS_COMPLETE_FLAG 测量完成总标志:1 = 一组平均 / 单次测量全部结束;写 1 清零
D3 MEAS_STARTED_FLAG 测量启动标志:1 = 已捕获 START 信号,计时开始;写 1 清零
D2 CLOCK_CNTR_OVF_INT 时钟粗计数器溢出中断:1 = 外部时钟计数超限,测量立即终止;写 1 清零
D1 COARSE_CNTR_OVF_INT 环振粗计数器溢出中断:1 = 短时间计数超限,测量立即终止;写 1 清零
D0 NEW_MEAS_INT 新测量完成中断(主中断):1 = 有效 STOP 全部采集完毕;INTB 引脚拉低输出中断;写 1 清零


4. 地址 03h:INT_MASK 中断屏蔽寄存器(复位 07h,8 位读写)
控制中断是否输出到硬件引脚 INTB;寄存器内标志位不受屏蔽影响,仅屏蔽引脚电平
位 位名 功能说明
D7~D3 Reserved 保留位,固定 0
D2 CLOCK_CNTR_OVF_MASK 时钟溢出中断屏蔽:1 = 允许引脚输出;0 = 仅寄存器置位,引脚无中断
D1 COARSE_CNTR_OVF_MASK 环振溢出中断屏蔽:1 = 允许引脚输出;0 = 屏蔽引脚
D0 NEW_MEAS_MASK 测量完成主中断屏蔽:1 = 允许 INTB 拉低;0 = 仅寄存器记录,MCU 无硬件中断

/////////////////////////////////////////////////////////////////////////////////////////////////////////
三、计数器溢出阈值寄存器(04h ~ 07h)
作用:设置最大计时时长,超过则触发溢出中断并终止测量,分高低 8 位组成 16 位阈值
5. 04h COARSE_CNTR_OVF_H 环振溢出阈值高 8 位(FFh)
6. 05h COARSE_CNTR_OVF_L 环振溢出阈值低 8 位(FFh)
组合 COARSE_CNTR_OVF = H<<8 | L,模式 1 计时超过该值直接停止测量。
7. 06h CLOCK_CNTR_OVF_H 时钟计数器溢出高 8 位(FFh)
8. 07h CLOCK_CNTR_OVF_L 时钟计数器溢出低 8 位(FFh)
组合 CLOCK_CNTR_OVF = H<<8 | L,模式 2 外部时钟计数超限触发中断


/////////////////////////////////////////////////////////////////////////////////////////////////////////
四、STOP 屏蔽窗口寄存器(08h ~ 09h)
9. 08h CLOCK_CNTR_STOP_MASK_H 屏蔽窗口高 8 位(00h)
10. 09h CLOCK_CNTR_STOP_MASK_L 屏蔽窗口低 8 位(00h)
组合 MASK = H<<8 | L:
START 后前 MASK 个外部时钟周期内,所有 STOP 脉冲全部忽略,用于过滤近距离杂波、超声波近端反射噪声;
要求 MASK 值必须小于 CLOCK 溢出阈值,否则未到有效窗口就溢出报错。


/////////////////////////////////////////////////////////////////////////////////////////////////////////
五、TOF 测量结果寄存器(10h ~ 1Ah,全部 24 位只读)
格式:Bit23 = 奇偶校验位,Bit22~0=23 位原始计数值;存储 START 与各 STOP 之间的环振计数值。
11. 10h TIME1
START 到第 1 路 STOP 的环振原始计数;模式 2 公式计算 TOF 的基准时间项。
12. 12h TIME2
START 到第 2 路 STOP 环振计数
13. 14h TIME3
START 到第 3 路 STOP 环振计数
14. 16h TIME4
START 到第 4 路 STOP 环振计数
15. 18h TIME5
START 到第 5 路 STOP 环振计数
16. 1Ah TIME6
最大 5 路 STOP 场景下备用计时缓存

/////////////////////////////////////////////////////////////////////////////////////////////////////////
六、 外部时钟粗计数寄存器(11h、13h、15h、17h、19h,24 位只读)

仅测量模式 2 有效,记录 START 至对应 STOP 之间完整外部时钟周期数:
Bit23 = 校验位,Bit22~16 = 多周期平均扩展位,Bit15~0=16 位时钟计数值;
计算 TOF 时需根据 AVG_CYCLES 右移平均次数 log2 位。
17. 11h CLOCK_COUNT1 第 1 路 STOP 时钟周期数
18. 13h CLOCK_COUNT2 第 2 路 STOP 时钟周期数
19. 15h CLOCK_COUNT3 第 3 路 STOP 时钟周期数
20. 17h CLOCK_COUNT4 第 4 路 STOP 时钟周期数
21. 19h CLOCK_COUNT5 第 5 路 STOP 时钟周期数

/////////////////////////////////////////////////////////////////////////////////////////////////////////
七、自校准基准寄存器(1Bh、1Ch,24 位只读)
用于实时计算 LSB(单环振皮秒分辨率),补偿温漂、电压漂移,是 TOF 换算核心参数。
22. 1Bh CALIBRATION1
单外部时钟周期对应的环振计数值(校准点 1)
23. 1Ch CALIBRATION2
N 个外部时钟周期对应的环振计数值(N 由 CONFIG2 的 CALIBRATION2_PERIODS 设定)

补充:寄存器分组功能总览
1. 配置组 (00/01h):工作模式、平均次数、STOP 通道、信号边沿、启动测量
2. 中断组 (02/03h):读取测量 / 溢出状态,控制硬件中断引脚输出
3. 阈值组 (04~09h):设置最大计时时长、近端噪声屏蔽窗口
4. 测量数据组 (10~19h,1Ah):存储每一路 STOP 的环振小数计数 + 外部时钟整数计数
5. 校准组 (1Bh/1Ch):芯片自校准原始数据,MCU 读取后换算真实皮秒 TOF 时间

关键使用流程补充
1. SPI 写入 CONFIG1/CONFIG2 配置模式、平均次数;
2. 配置溢出阈值与 STOP 屏蔽窗口;
3. 置位 CONFIG1.0 启动测量;
4. 等待 INTB 硬件中断;
5. SPI 读取 CALIBRATION1/CALIBRATION2 计算标准 LSB;
6. 读取 TIMEx、CLOCK_COUNTx,代入公式算出真实飞行时间 TOF;
7. 写 1 清除 INT_STATUS 中断标志,开启下一次测量

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2026 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"
#include <stdio.h>
#include <string.h>

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/*外部晶振8MHz*/
#define CLOCKperiod 1.0f/(8000000.0f)


/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi1;

TIM_HandleTypeDef htim1;

UART_HandleTypeDef huart1;

/* USER CODE BEGIN PV */


typedef enum{
blank = 100,
start,
read,
calculate,
processing,
send
}state;


uint8_t spi_INT_status;
uint32_t time1;
uint32_t time2;
uint32_t clock_count1;
uint32_t CALIBRATION1;
uint32_t CALIBRATION2;
float TOF1;
float distance_buf[10];
uint8_t measure_cnt = 0;
float normLSB;
float calCount;
state state1 = blank;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);
static void MX_TIM1_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
void TDC7200_Init(void){
uint8_t config1[2] = {0x40,0x00};/*写,地址第六位置1*/
uint8_t config2[2] = {0x41,0x40};/*Calibration10clock,single stop*/
uint8_t INT_MASK[2] = {0x43,0x01};/*使能measurement interrupt*/
uint8_t COARSE_H[2] = {0x44,0xFF};/*默认*/
uint8_t COARSE_L[2] = {0x45,0x00};/*默认*/
/*配置config1*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_Transmit(&hspi1, config1, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
/*配置config2*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_Transmit(&hspi1, config2, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
/*配置INT_MASK*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_Transmit(&hspi1, INT_MASK, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
/*配置coarse_h*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_Transmit(&hspi1, COARSE_H, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
/*配置coarse_h*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_Transmit(&hspi1, COARSE_L, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
}
void startfunction(void){
uint8_t start[2] = {0x40,0x01};/*准备开始一次测量*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_Transmit(&hspi1, start, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
HAL_TIM_OnePulse_Start(&htim1,TIM_CHANNEL_1);//给到激光器和TDC的start引脚上
}

void readfunction(void){
uint8_t byte1[4];
uint8_t byte2[4];
uint8_t byte3[4];
uint8_t byte4[4];
uint8_t byte5[4];
uint8_t TxData[2] = {0x02,0xff};
uint8_t spi_INT_status[2];
/*读INT_STATUT*/
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_TransmitReceive(&hspi1, TxData, spi_INT_status, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);

/*读tim1*/
uint8_t Tim1[4] = {0x10, 0xff, 0xff, 0xff};/*读的话第六位为0即可*/
if(spi_INT_status[1]&0x01){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_TransmitReceive(&hspi1, Tim1, byte1, 4, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
time1 = (uint32_t)byte1[1] <<16 | (uint32_t)byte1[2] <<8 | (uint32_t)byte1[3];
}

/*读tim2*/
uint8_t Tim2[4] = {0x12, 0xff, 0xff, 0xff};
if(spi_INT_status[1]&0x01){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_TransmitReceive(&hspi1, Tim2, byte2, 4, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
time2 = (uint32_t)byte2[1] <<16 | (uint32_t)byte2[2] <<8 | (uint32_t)byte2[3];
}

/*读CLOCK_COUNT1*/
uint8_t CLOCK_COUNT1_tx[4] = {0x11, 0xff, 0xff, 0xff};
if(spi_INT_status[1]&0x01){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_TransmitReceive(&hspi1, CLOCK_COUNT1_tx, byte3, 4, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
clock_count1 = (uint32_t)byte3[1] <<16 | (uint32_t)byte3[2] <<8 | (uint32_t)byte3[3];
}

/*读CALIBRATION1*/
uint8_t CALIBRATION1_tx[4] = {0x1B, 0xff, 0xff, 0xff};
if(spi_INT_status[1]&0x01){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_TransmitReceive(&hspi1, CALIBRATION1_tx, byte4, 4, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
CALIBRATION1 = (uint32_t)byte4[1] <<16 | (uint32_t)byte4[2] <<8 | (uint32_t)byte4[3];
}

/*读CALIBRATION2*/
uint8_t CALIBRATION2_tx[4] = {0x1C, 0xff, 0xff, 0xff};
if(spi_INT_status[1]&0x01){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 0);
HAL_SPI_TransmitReceive(&hspi1, CALIBRATION2_tx, byte5, 4, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, 1);
CALIBRATION2 = (uint32_t)byte5[1] <<16 | (uint32_t)byte5[2] <<8 | (uint32_t)byte5[3];
}
}

void processingfunction(void){
for(int i=0; i<=8; i++){
for(int j=i+1; j<=9; j++){
if(distance_buf[i]>distance_buf[j]){
float m = distance_buf[i];
distance_buf[i] = distance_buf[j];
distance_buf[j] = m;
}
}
}
}

/* 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 */

/* 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_SPI1_Init();
MX_TIM1_Init();
MX_USART1_UART_Init();
TDC7200_Init();
/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1){
/* USER CODE END WHILE */
switch(state1){
case start:
startfunction();
break;
case read:
readfunction();
state1 = calculate;
break;
case processing:
processingfunction();
state1 = send;
break;
default: break;
}

if(state1 == calculate){
calCount = (float)(CALIBRATION2 - CALIBRATION1) / 9.0f;
normLSB = CLOCKperiod / calCount;
TOF1 = (time1*normLSB)+(clock_count1*CLOCKperiod)-(time2*normLSB);
distance_buf[measure_cnt] = (TOF1/2.0f)*(3e8f);
if(measure_cnt < 9){
measure_cnt++;
state1 = start;
}
else{
state1 = processing;
measure_cnt = 0;
}
}

if(state1 == send){
char tx[50];
sprintf(tx,"%.3f\r\n",distance_buf[5]);
HAL_UART_Transmit(&huart1, (uint8_t *)tx, strlen(tx), 100);
state1 = blank;
}

}
}
/* USER CODE BEGIN 3 */
/* USER CODE END 3 */

/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}

/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}

/**
* @brief SPI1 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI1_Init(void)
{

/* USER CODE BEGIN SPI1_Init 0 */

/* USER CODE END SPI1_Init 0 */

/* USER CODE BEGIN SPI1_Init 1 */

/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */

/* USER CODE END SPI1_Init 2 */

}

/**
* @brief TIM1 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM1_Init(void)
{

/* USER CODE BEGIN TIM1_Init 0 */

/* USER CODE END TIM1_Init 0 */

TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

/* USER CODE BEGIN TIM1_Init 1 */

/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 65535;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OnePulse_Init(&htim1, TIM_OPMODE_SINGLE) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */

/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);

}

/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{

/* USER CODE BEGIN USART1_Init 0 */

/* USER CODE END USART1_Init 0 */

/* USER CODE BEGIN USART1_Init 1 */

/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */

/* USER CODE END USART1_Init 2 */

}

/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */

/* USER CODE END MX_GPIO_Init_1 */

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(start_GPIO_Port, start_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);

/*Configure GPIO pins : PA0 PA2 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/*Configure GPIO pins : start_Pin CS_Pin */
GPIO_InitStruct.Pin = start_Pin|CS_Pin;
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);

/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);

/* USER CODE BEGIN MX_GPIO_Init_2 */

/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if(GPIO_Pin == GPIO_PIN_0){/*GPIO0中断是用来TDC计数结束*/
state1 = read;
}
if(GPIO_Pin == GPIO_PIN_2){/*GPIO2中断是用来开始一次测量*/
state1 = start;
}
}
/* USER CODE END 4 */

/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


http://www.jsqmd.com/news/1112725/

相关文章:

  • 服务器内存与CPU协同工作知识测试题
  • 阿里terway源码分析
  • likeadmin-api 怎么做计费?从余额查询到点数消耗的接口设计
  • 2026年优选指南:探寻最佳服务的苦荞全麦片品牌
  • HAL库代码基础介绍
  • 每日技术推荐(全栈/游戏/应用开发)
  • 从 has.showToast 看 ASCF 的 API 调用链路
  • 一些碎碎念qjl--6
  • 手写 MCP Server 连数据库:50 行代码让 AI 学会查 SQL
  • 企业AI转型困境与能力建设实战指南
  • 聊一聊 Linux 上对函数进行 hook 的两种方式
  • CPT外汇:注重效率的使用者更在意的工具可用性,这里做个维度观察
  • 交叉熵损失函数实战指南:原理、陷阱与工业级调优
  • 千万不能忽视!选择防盗门时必须知道的5个关键点
  • 好用的看广告供应商哪个公司好
  • foo2zjs打印机驱动架构解析:从ZJ-Stream协议到企业级部署的完整技术方案
  • Windows10Debloater终极指南:轻松打造纯净高效的Windows 10系统
  • Java毕设选题推荐:基于 SpringBoot 的线上选课学习考核教育平台的设计与实现 智慧远程教育资源发布管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 三进制太玄经·八十一首(坤至乾·每行一卦标准版)
  • Loki MCP Server -支持Claude Desktop/Claude Code/Cursor 等客户端通过自然语言查询日志
  • 机器学习模型生产化落地:从Notebook到稳定服务的七步实战
  • 从寄存器映射到Modbus TCP组网:硬核拆解工业数据采集卡的通信协议架构
  • WebSocket 重连后 K 线还缺?Python 检测缺口 + REST 回补 + gap_report 留痕**
  • tModCodeAssist:泰拉瑞亚模组开发者的智能代码助手终极指南
  • Java计算机毕设之基于 SpringBoot 的中药饮片采购入库出库管控系统的设计与实现 基于 SpringBoot 的中药材供应商与采购订单管理系统(完整前后端代码+说明文档+LW,调试定制等)
  • ML模型服务化实战:从Notebook到稳定生产的五大关键
  • 2026最新8款平替AI团队编程软件实测 适配多仓库规范统一
  • AI科研效率革命:用Claude技能包重构论文写作与数据分析流程
  • 多维聚合数据操作:维度对齐、度量校准与空值治理实战
  • 数据湖介绍