基于纳芯微传感器设计的传感器评估板
该项目使用了纳芯微NST461-DQNR、NSPAD1N200DR04和NSPGD1M006DT04,实现了传感器评估板的设计,它的主要功能为:采集本地温度,采集当前环境气压和表面压力。
标签
传感器
纳芯微
WeDesign
红衣踏雪入梦来
更新2025-12-02
45
KiCad文件
全屏

一、任务介绍

本次项目尝试设计一款基于纳芯微温度传感NST461-DQNR, 绝压传感器NSPAD1N200DR04和表压传感器NSPGD1M006DT04设计的传感器评估板。整个设计力图简洁方便,设计过程中对NST461-DQNR和NSPAD1N200DR04这两款封装小巧的芯片的焊盘做了特别的延长,使得只需要一把烙铁即可完成整个焊接过程。板子上引出一个2\*5的排针,可通过两组IIC总线连接该传感器评估板来读写压力和温度数据。

二、硬件介绍

这次设计的传感器评估板选用的三款芯片均支持IIC通信,所以对于硬件电路的设计可以简化很多,芯片的数据手册中也提供了完善的参考设计。

  1. 温度传感器NST461-DQNR

NST461是一款高精度低功耗的数字温度传感器,它可以同时测量本地通道和远程通道的温度。从数据手册中可以看到,其本地通道的温度测量是靠芯片内部的三极管实现的,需要测量外通道的温度时,只需要在D+与D-引脚之间外接一个三极管即可。但是由于硬件设计过程中只考虑了测量本地通道的温度,没有考虑远程通道,所以实际硬件上是无法测量远程通道的温度的。
Pasted image 20251123161621.png

  1. 表压传感器NSPGD1M

NSPGD1M是一款经过校准的表压传感器,它结合了最先进的MEMS传感器技术和CMOS混合信号处理技术,采用DIP封装并提供了IIC和模拟量输出接口简化了传感器安装和使用

  1. 绝压传感器NSPAD1N

NSPAD1N是一款高精度的压力传感器,可测量10kPa到400kPa的压力范围, 在保持十分小巧的封装的同时还提供IIC/SPI和模拟量输出接口。

三、方案设计

由于本次选择的三款传感器都支持IIC接口, 按理说硬件的设计可以十分简单,在保证芯片供电正常的情况下,只需要保证IIC接口的正确连接即可。但是在阅读芯片的数据手册之后,发现如下问题

  1. 若使用IIC接口,则表压传感器NSPGD1M和绝压传感器NSPAD1N的从机地址完全相同, 这会带来地址的冲突。
  2. 温度传感器NST461的供电和通信引脚能容忍的电影范围为2.1V到3.6V,而两款压力传感器虽然在数据手册的前半部分看到可以支持3.3V或5V供电,但在后面的订购信息中可以看到,我们选用的这两款细分型号却只支持5V的供电

这就需要我们在设计电路时考虑到这两点,所以最终硬件的结构框图如下:

Pasted image 20251123165701.png

最终板子引出了两组IIC接口和两组电源接口,可直接连接到外部的STM32核心板上,第一组IIC接口只连接NST461,第二组IIC接口经由一组拨码开关来选择连接到哪一个传感器。

四、原理图与PCB设计

由于长时间没有进行硬件的设计,以及初次使用KiCAD进行硬件设计,实际的原理图和PCB的设计存在诸多问题,这里先对一些错误进行简要说明:

  1. NST461的THERM以及ALERT引脚若软件上不打算使用,应当外接上拉电阻,但在本次设计中却连接了下拉电阻,造成芯片上电后有发热,虽然可以通过IIC总线读取温度,但温度异常。在切断PCB中的两处黄色方框的铜皮后芯片工作正常。
    Pasted image 20251123170933.png
    Pasted image 20251123171228.png
  2. 拨码开关的引脚连接失误,导致需要如图进行飞线才能正确选择压力传感器

    Pasted image 20251123171047.png

    Pasted image 20251123171744.png

五、软件硬件调试说明

硬件焊接与调试

收到成品电路板后是这样,非常的简洁,除传感器本身外只需要焊接几个电容电阻即可:

image.png

由于对较难焊接的NST461和NSPAD1N的焊盘进行了加长设计,所以焊接的难度下降了很多,只要使用流动性相对较好的焊锡和一点助焊剂,就可以用烙铁完成焊接。成品效果如下图所示。焊接完成后需要添加两根飞线,并割断红框处的走线。

image.png

用手边空余的STM32H503核心板进行软件调试,板子两个I2C接口分别接STM32的I2C1和I2C2

image.png

1. NST461初始化与温度读取

// NST461初始化
void nst461_init(void)
{
uint8_t temp;
uint8_t channel_en = 0x1; // only enable the local channel
uint32_t status = 0;
do
{
// Read the ID register, if it read succcess, that means the device can work.
status = HAL_I2C_Mem_Read(&hi2c1, NST461_ADDR, ID_REG, NST461_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x\r\n", status);
break;
}
// write the channel enable register, to disable the remote channel because we didn't have a remote transistor.
status = HAL_I2C_Mem_Write(&hi2c1, NST461_ADDR, CHANNAL_EN_REG, NST461_REG_LENGTH, &channel_en, sizeof(channel_en), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C write failed, the status is 0x%x\r\n", status);
break;
}
// read back the channel enable register, it should be 0b1.
status = HAL_I2C_Mem_Read(&hi2c1, NST461_ADDR, CHANNAL_EN_REG, NST461_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x\r\n", status);
break;
}
if(temp != channel_en)
{
printf("The channel config failed, can't disable the remote channel!\r\n");
break;
}
}while(0);
}
// NST461温度读取
double nst461_get_local_temperature(void)
{
uint32_t status;
uint8_t temp;
uint8_t raw_temperature[2];
double final_temperature;
do
{
// polling the busy bit when it clear.
status = HAL_I2C_Mem_Read(&hi2c1, NST461_ADDR, STATUS_REG, NST461_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x\r\n", status);
break;
}
HAL_Delay(2);
}while ((temp & 0x80) == 0x80);

status = HAL_I2C_Mem_Read(&hi2c1, NST461_ADDR, LOCAL_TEMP_H_REG, NST461_REG_LENGTH, &raw_temperature[0], sizeof(raw_temperature[0]), I2C_DFEUALT_TIMEOUT);
status = HAL_I2C_Mem_Read(&hi2c1, NST461_ADDR, LOCAL_TEMP_L_REG, NST461_REG_LENGTH, &raw_temperature[1], sizeof(raw_temperature[0]), I2C_DFEUALT_TIMEOUT);
// printf("raw temperature is 0x%x, 0x%x\r\n", raw_temperature[0], raw_temperature[1]);

final_temperature = (double) raw_temperature[0] + (raw_temperature[1] >> 4) * 0.0625L;
printf("Current temperature is %f\r\n", final_temperature);

return final_temperature;
}
  1. NSPGD1M和NSPAD1N的数据读取:
// NSPGD1M和NSPAD1N的数据读取规则基本相同,只是最后的数据转换的公式不同
//NSPGD1M数据读取:
void nspgd1m_start_conversion(void)
{
uint8_t temp = NSPGD1M_START_COVERSION; // write 0xA to start conversion
uint32_t status = 0;
status= HAL_I2C_Mem_Write(&hi2c2, NSPGD1M_ADDR, CONVERSION_STATE_REG, NSPGD1M_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x, %s\r\n", status, __func__);
}
}

bool nspgd1m_conversion_finished(void)
{
uint8_t temp;
uint32_t status = 0;
status= HAL_I2C_Mem_Read(&hi2c2, NSPGD1M_ADDR, CONVERSION_STATE_REG, NSPGD1M_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x, %s\r\n", status, __func__);
}
printf("The Status Register value is 0x%x\r\n", temp);
return (temp == NSPGD1M_COVERSION_FINISHED) ? true : false;
}

double nspgd1m_get_pressure()
{
uint32_t status;
uint8_t raw_pressure[3];
uint32_t pressure_code = 0;
double final_pressure;
bool conversion = false;

nspgd1m_start_conversion();
do {
conversion = nspgd1m_conversion_finished();
HAL_Delay(100);
} while (conversion != true);

status = HAL_I2C_Mem_Read(&hi2c2, NSPGD1M_ADDR, OUTPUT_DATA_H_REG, NSPGD1M_REG_LENGTH, &raw_pressure[0], sizeof(raw_pressure[0]), I2C_DFEUALT_TIMEOUT);
status = HAL_I2C_Mem_Read(&hi2c2, NSPGD1M_ADDR, OUTPUT_DATA_M_REG, NSPGD1M_REG_LENGTH, &raw_pressure[1], sizeof(raw_pressure[0]), I2C_DFEUALT_TIMEOUT);
status = HAL_I2C_Mem_Read(&hi2c2, NSPGD1M_ADDR, OUTPUT_DATA_L_REG, NSPGD1M_REG_LENGTH, &raw_pressure[2], sizeof(raw_pressure[0]), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x, %s\r\n", status, __func__);
}
pressure_code = (raw_pressure[0] << 16) | (raw_pressure[1] << 8) | raw_pressure[2];

printf("Raw pressure is %d\r\n", pressure_code);
final_pressure = (pressure_code / 8388607.0000L - NSPGD1M_GAIN_OFFSET_B) / NSPGD1M_GAIN_OFFSET_A;

printf("Current pressure is %lf\r\n", final_pressure);
return final_pressure;
}
//NSPAD1N数据读取:
void nspad1n_start_conversion(void)
{
uint8_t temp = 0xA; // write 0xA to start conversion
uint32_t status = 0;
status= HAL_I2C_Mem_Write(&hi2c2, NSPAD1N_ADDR, CONVERSION_STATE_REG, NSPAD1N_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x, %s\r\n", status, __func__);
}
}

bool nspad1n_conversion_finished(void)
{
uint8_t temp;
uint32_t status = 0;
status= HAL_I2C_Mem_Read(&hi2c2, NSPAD1N_ADDR, CONVERSION_STATE_REG, NSPAD1N_REG_LENGTH, &temp, sizeof(temp), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x, %s\r\n", status, __func__);
}
printf("The Status Register value is 0x%x\r\n", temp);
return (temp == 0x02) ? true : false;
}

double nspad1n_get_pressure()
{
uint32_t status;
uint8_t raw_pressure[3];
uint32_t pressure_code = 0;
double final_pressure;
bool conversion = false;

nspad1n_start_conversion();
do {
conversion = nspad1n_conversion_finished();
HAL_Delay(1);
} while (conversion != true);

status = HAL_I2C_Mem_Read(&hi2c2, NSPAD1N_ADDR, OUTPUT_DATA_H_REG, NSPAD1N_REG_LENGTH, &raw_pressure[0], sizeof(raw_pressure[0]), I2C_DFEUALT_TIMEOUT);
status = HAL_I2C_Mem_Read(&hi2c2, NSPAD1N_ADDR, OUTPUT_DATA_M_REG, NSPAD1N_REG_LENGTH, &raw_pressure[1], sizeof(raw_pressure[0]), I2C_DFEUALT_TIMEOUT);
status = HAL_I2C_Mem_Read(&hi2c2, NSPAD1N_ADDR, OUTPUT_DATA_L_REG, NSPAD1N_REG_LENGTH, &raw_pressure[2], sizeof(raw_pressure[0]), I2C_DFEUALT_TIMEOUT);
if(HAL_OK != status)
{
printf("The I2C read failed, the status is 0x%x, %s\r\n", status, __func__);
}
pressure_code = (raw_pressure[0] << 16) | (raw_pressure[1] << 8) | raw_pressure[2];

final_pressure = NSPAD1N_GAIN_OFFSET_A * pressure_code / 8388607 + NSPAD1N_GAIN_OFFSET_B;

printf("Current pressure is %lf\r\n", final_pressure);
return final_pressure;
}

六、数据波形采集和分析

由于两款压力传感器不需要进行配置,就可以直接进行数据读取,所以此处不对其波形进行分析。但由于硬件上没有连接温度传感器NST461的外部通道,所以在使用过程中需要在NST461初始化时关闭远程通道,其操作相对复杂,下面对其波形进行简要分析:

NST461.jpg

NST461_2.jpg

七、心得与体会

从五年前第一次参加Funpack的活动知道电子森林开始,就经常关注电子森林的活动,也做了不少次”股东“。虽然现在的工作和电子类关系不大,但是还是会关注一些电子设计类的公众号,用还剩下的一点专业知识去体会电路设计的艺术。自从正式工作后已经有四年多没有接触硬件的设计了,实际操作的要点早忘得一干二净。导致这次Wedesign的活动虽然简单,但最后还是出了两个致命的问题,还好飞线还可以抢救一下,才没有再做一次”股东“。非常感谢电子森林和纳芯微的这次活动,让我能够重温硬件的设计,并且在短时间内学会了KiCAD的使用方法。


附件下载
设计资源 - 附件.zip
传感器驱动工程
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号