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