基于STM32G4利用TDC-GP22举行时间差的丈量(HAL库学习笔记) ...

打印 上一主题 下一主题

主题 1653|帖子 1653|积分 4959

我会从丈量原理 SPI通讯 到GP22读写寄存器 硬件毗连 和运行效果来给各人举行阐明
TDC-GP22各个引脚的阐明和工作原理


这是我在某宝上直接购买的模块TDC-GP22(时间数字转换器)
左边干系引脚
INT:在丈量完成之后会将此引脚电平拉低,通常接入单片机当作停止引脚.
SSN SCK SO SI:这四个引脚为SPI通信的固定引脚 后面会详细表明
RTN: 硬件复位的引脚,低电平有效,也可以选择写寄存器举行软件复位不接(建议软硬复位都加上)
右边干系引脚
SP1 START: Stop通道 1,Start 通道GP22会从这两个引脚吸收脉冲,然后内部计算这两个脉冲的时间差,计算完成后会将INT引脚拉低
在担当start,stop 脉冲之前,必须要将gp22的管脚en_start,en_stop 置高平,否则start,stop 通道则不会被选通不会触发丈量

我购买的模块STOPI STOP2通道已经拉高了,但是32引脚START通道使能端是悬空
<1>GP22可以选择利用STOP1-START获取时间差 那么你就需要在外部将DIS引脚电平拉高才气举行丈量
<2>:也可以选择发射和吸收脉冲信号是给到stop1和stop2的,给START引脚一个不到场丈量但是要触发丈量用的dummy start.因为start通道的这个信号是告诉gp2现在开始进入丈量状态了
我们选择第一种丈量方式,精度可达到90ps,开启双精度模式可以达到45ps的精度
SPI通信

TDC-GP22采用SPI的方式与单片机举行通信
我们选择硬件SPI,下面是MX的部分配置:

模拟IO口PA4来当作SPI的片选信号SSN 传输速率只管在20M以下
SPI为芯片与芯片之间的通信 常用于一主多从
SSN: 而SSN片选信号通过给高低电平来确定选择哪个从机举行通信一般SSN信号线低电平有效
SCK: 时钟信号线
MOSI MISO: M为主机 S为从机 IO就是输入输出 MOSI(主机输出从机输入)MISO(主机输入从机输出)
我们引用一下爱上半导体 UP主解说SPI时用的图片

这里SSN片选信号在通信时拉高电平还是少数情况大部分时还是低电平有效
可以看到我们在利用MOSI信号线将电平拉高传输数据1的时候 恰恰处于时钟的上升沿

CPOL(时钟极性)
Low(CPHA=0)时钟空闲状态为低电平,有效状态为高电平
High(CPOL=1)时钟空闲状态为高电平,有效状态为低电平
CPHA(时钟相位)
1Edge奇数次采样(CPHA=0)第一个跳变沿用来采样数据,第二个跳变沿发送数据
2Edge偶数次采样(CPOL=1)第二个跳变沿用来采样数据,第一个跳变沿发送数据

MODE0模式 时钟空闲时为低电平,在第一个跳变沿(上升沿)采样数据上图所示
配置为(CPHA=0)(CPHA=0)
MODE1模式 时钟空闲时为低电平,在第二个跳变沿(下降沿)采样数据上图所示
配置为(CPHA=0)(CPHA=1)
MODE2模式 时钟空闲时为高电平,在第一个跳变沿(下升沿)采样数据上图所示
配置为(CPHA=1)(CPHA=0)
MODE3模式 时钟空闲时为高电平,在第二个跳变沿(上降沿)采样数据上图所示
配置为(CPHA=1)(CPHA=1)
主装备采样 = 从装备发送
主装备在上升沿采样MISO时,实际读取的是从装备提前在下降沿准备好的数据。
从装备采样 = 主装备发送
从装备在上升沿采样MOSI时,实际读取的是主装备提前在下降沿准备好的数据。
TDC-GP22数据手册上支持的工作模式只有MODE1
TDC-GP22寄存器的配置

TDC-GP22有7个32位的配置寄存器 此中高8位是地点 低24位是参数
GP22的寄存器比力复杂,详细配置对应的功能需要参考数据手册,这里只是简单列出和本次丈量有关的配置:
写寄存器的配置
参数值为32位数据,高8位为地点,低24位为配置参数

如果想要改变寄存器参数和手册请详细阅读寄存器举行更改对应的配置
读寄存器的配置

读寄存器的操纵码是0xBx
这里我只解说我们本次丈量能用到的操纵符0,4,5
0xB0是我们丈量结束后举行存储的效果寄存器,通过写入0xB0会返回一个32位的数据,高16 位整数部分,低16 位小数部分
0xB4用来验证TDC单元是否溢出
0xB5用来验证SPI是否可以大概正常通信,通过写入0XB5会返回寄存器1的高8位
如果你寄存器1配置为0x014100,那么就会返回01
0x50软件复位操纵符
0x70初始化丈量,通知 gp22进入丈量准备状态,每次丈量前都要开启一次
STM32与GP22的硬件毗连

初始化TDC-GP22举行测试通讯

干系代码:
  1. #define ENABLE_TDC HAL_GPIO_WritePin(TDC_NSS_GPIO_Port,TDC_NSS_Pin,GPIO_PIN_RESET);
  2. #define DISABLE_TDC HAL_GPIO_WritePin(TDC_NSS_GPIO_Port,TDC_NSS_Pin,GPIO_PIN_SET);
  3. //定义片选信号
  4. extern SPI_HandleTypeDef hspi1;
  5. void Tdc_Reset(void)
  6. {
  7.     HAL_GPIO_WritePin(TDC_RTN_GPIO_Port, TDC_RTN_Pin, GPIO_PIN_SET);
  8.     HAL_Delay(10);
  9.     HAL_GPIO_WritePin(TDC_RTN_GPIO_Port, TDC_RTN_Pin, GPIO_PIN_RESET);
  10.     HAL_Delay(10);
  11.     HAL_GPIO_WritePin(TDC_RTN_GPIO_Port, TDC_RTN_Pin, GPIO_PIN_SET);
  12. }
  13. void Tdc_test(void)
  14. {
  15.     int Reset = 0x50;
  16.     uint32_t REG0 = 0;
  17.     Tdc_Reset();//硬件复位
  18.     HAL_Delay(10);
  19.     ENABLE_TDC;
  20.     DWT_DelayUs(1);
  21.     Spi_send_byte(Reset);//软件复位
  22.     DISABLE_TDC;
  23.     ENABLE_TDC;
  24.     DWT_DelayUs(1);
  25.     SPIwrite32(0x80009620);
  26.     DISABLE_TDC;
  27.     ENABLE_TDC;
  28.     DWT_DelayUs(1);
  29.     SPIwrite32(0x81014100);
  30.     DISABLE_TDC;
  31.     ENABLE_TDC;
  32.     DWT_DelayUs(1);
  33.     SPIwrite32(0x82E00000);
  34.     DISABLE_TDC;
  35.     ENABLE_TDC;
  36.     DWT_DelayUs(1);
  37.     SPIwrite32(0x83180000);
  38.     DISABLE_TDC;
  39.     ENABLE_TDC;
  40.     DWT_DelayUs(1);
  41.     SPIwrite32(0x84200000);
  42.     DISABLE_TDC;
  43.     ENABLE_TDC;
  44.     DWT_DelayUs(1);
  45.     SPIwrite32(0x85080000);
  46.     DISABLE_TDC;
  47.     ENABLE_TDC;
  48.     DWT_DelayUs(1);
  49.     SPIwrite32(0x86010000);
  50.     DISABLE_TDC;
  51.     HAL_Delay(10);
  52.     ENABLE_TDC;
  53.     DWT_DelayUs(1);
  54.     REG0=Tdc_Read32Bits(0xB5);//这里使用的写入8位读取32位的函数,实际上在测试的时候返回8位就可以了,这里不做修改了
  55.     u1_printf_nonblocking("0x%08x\r\n", REG0);
  56.         DISABLE_TDC;  //验证寄存器
  57. };
  58. uint32_t Tdc_Read32Bits(uint8_t command)//写8读32
  59. {
  60.     uint8_t rx_buffer[4] = {0};
  61.     uint32_t result = 0;
  62.     ENABLE_TDC;                          // 拉低片选使能
  63.     Spi_send_byte(command);               // 发送8位命令
  64.     // 连续接收4个字节
  65.     if (HAL_SPI_Receive(&hspi1, rx_buffer, 4, 1000) == HAL_OK)
  66.     {
  67.         // 组合为32位数据(大端模式)
  68.         result = ((uint32_t)rx_buffer[0] << 24) |
  69.                  ((uint32_t)rx_buffer[1] << 16) |
  70.                  ((uint32_t)rx_buffer[2] << 8)  |
  71.                  (uint32_t)rx_buffer[3];
  72.         //u1_printf_nonblocking("rx_buffer: 0x%02x 0x%02x 0x%02x 0x%02x\r\n",
  73.         //                rx_buffer[0], rx_buffer[1], rx_buffer[2], rx_buffer[3]);  测试使用
  74.     }
  75.     else
  76.     {
  77.         // 错误处理
  78.         u1_printf_nonblocking("SPI Read Error\r\n");
  79.     }
  80.     DISABLE_TDC;                         // 拉高片选禁用
  81.     return result;
  82. }
  83. void SPIwrite32(uint32_t data)//写32
  84. {
  85.     uint8_t bytes[4];
  86.     bytes[0] = (data >> 24) & 0xFF;  // 地址 + 高8位
  87.     bytes[1] = (data >> 16) & 0xFF;
  88.     bytes[2] = (data >> 8)  & 0xFF;
  89.     bytes[3] = data & 0xFF;
  90.     HAL_SPI_Transmit(&hspi1, bytes, 4, HAL_MAX_DELAY);
  91. }
复制代码
代码块中:
写8位读32位用于获取丈量效果
写32位用来配置寄存器


颠末测试后确实返回了0x81寄存器的高8位01,证明通讯成功
如果碰到返回值不绝为0x55可以看看SPI四根线打仗是否准确,工作模式是否利用模式1,是否成功复位,可以在复位函数后加个小延时包管启动,微妙级别的延时函数可以在CSDN的博客里找找,我也是用别人的开源代码,我每次写入寄存器值的时候都会拉低再拉高片选信号,包管写入进寄存器。
利用TDC-GP22举行时间差的丈量

我们采用的方案是用两个IO口模拟出START和STOP1的脉冲触发信号

不需要配置下拉上拉 初始低电平 引脚速度选择Very High
下面提供IO口模拟两个有时间差的脉冲信号代码
  1. uint32_t Generate_1us_Pulse_Pair(void)
  2. {
  3.     uint32_t REG0=0;
  4.     ENABLE_TDC;
  5.     Spi_send_byte(0x70); // Init   
  6.     DISABLE_TDC;
  7.     START_GPIO_Port->BSRR = (uint32_t)START_Pin << 16;//保证低电平
  8.     STOP1_GPIO_Port->BSRR = (uint32_t)STOP1_Pin << 16;//保证低电平
  9.     DWT_DelayUs(1);
  10.        
  11.     START_GPIO_Port->BSRR = START_Pin;  //拉高START
  12.     for (uint8_t i = 0; i < 1; i++) {}
  13.     START_GPIO_Port->BSRR = (uint32_t)START_Pin << 16;
  14.                        
  15.     for (uint8_t i = 0; i < 8; i++) {} //时间差
  16.                        
  17.     STOP1_GPIO_Port->BSRR = STOP1_Pin; //拉高STOP1
  18.     for (uint8_t i = 0; i < 1; i++) {}
  19.     STOP1_GPIO_Port->BSRR = (uint32_t)STOP1_Pin << 16;
  20.     while(HAL_GPIO_ReadPin(TDC_INT_GPIO_Port, TDC_INT_Pin)==1) {}
  21.     ENABLE_TDC;
  22.     REG0=Tdc_Read32Bits(0xB0);//读取结果寄存器REG0
  23.     //u1_printf_nonblocking("0x%08x\r\n", REG0);
  24.     DISABLE_TDC;
  25.     return         REG0;        //返回寄存器获取的测量值
  26. }
复制代码

我们选择的丈量方式的两个通道单边沿敏感,可以大抵观察出两个脉冲信号高电平之间的时间差大概是3.2个单元格左右,也就是320ns的时间间隔
本次实验只是模拟利用GP22这个模块举行时间差的丈量,单片机的GPIO驱动能力不敷强,内阻较大,如果想得到准确到pf的丈量效果建议处置惩罚一下发出的脉冲信号
丈量完成时,INT引脚会拉低电平,我们在这个时候读取寄存器REG0的数据就可以获取丈量值,高16位为整数,低16位为小数,(如果SPI通信确认正常而停止引脚始终无法拉低那么很有可能是芯片的问题大概查看两边引脚是否都供电)
获取的数据转化为浮点型之后,我们GP22的晶振是4M二分频2M赫兹,转化为周期就是500ns记一次数,转化部分不再赘述了,直接给各人看丈量效果

能看出来还是有一些偏差的,但基本稳定在321.1ns左右
利用的串口发送函数是我上一篇博客中介绍的
4.17日调试改动:
丈量模拟IO口引脚发送两个ns级别时间差的脉冲信号仅仅只是为了测试GP22的功能,由于IO驱动能力不敷,引脚最高速度固定在50M,所以丈量的数据在飘动是正常征象,我决定利用TDR时序反射法丈量同轴电缆的长度去体现出GP22的功能
这个脉冲信号是我单片机引脚反转发出的高低高的脉冲信号,再颠末非门处置惩罚之后变成低高低的脉冲信号,可以看出确实比上图中只有引脚反转的效果要好不少

同轴电缆,将外壳的铜丝接地,内里的铜芯当作输出引脚,我们将上面的脉冲信号接入同轴电缆,我们会在这个点接入示波器会观察到:

第一个脉冲是上图脉冲衰减之后的,峰值在2V左右,第二个小脉冲信号是同轴电缆反射返来的,详细TDR时域反射法各人可以去相知趣识,这两个脉冲之间的时间黑白是取决于电缆的属性的,我手上的这根电缆大概是8ns一米的换算关系。
我这里以为能量守恒定理好明白一点,毕竟打入电缆的脉冲只有3.3V,所以图中有衰减很正常
但这两个小脉冲再加上其他的小尖峰的峰值一定是3.3V
我这里采用的是单片机引脚发出脉冲->颠末非门增长驱动能力接入电缆->再利用高速比力器拉高电缆反射小脉冲
颠末高速比力器后的波形:

将两个脉冲信号都举行拉高处置惩罚,一定要利用高速比力器,低速处置惩罚不了高频信号
这时候再用GP22去丈量两个上升沿的时间就非常稳了

效果为77.18ns左右,几乎符合我们上图的时间差。
我在学习GP22的时候遇见不少困难,在网上很少能看到一些有效的资料,所以我干系的讲述可能存在很多错误,希望各人一起交流学习。我也推荐几篇非常良好的文章关于GP22的
2023年电赛B题《同轴线缆长度与终端负载检测装置》,基于立创开发板天空星STM32F407VET6的方案
STM32F4 HAL库 调试TDC-GP22[测试SPI通信]

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

大号在练葵花宝典

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表