stm32通过NTC采集温度,二分法查表,精度0.1℃

NTC是指负温度系数的电阻器,电阻值会随着温度上升而减少,我们可以利用该特性,对温度进行采集和计算。

下面是NTC的规格和温度阻值表

标称阻值:10kΩ @ 25℃

精度公差:±1%

B值:3435K at 25/85℃

B值公差:±1%

我用的是查表法,所以在计算中不使用B值,B值直接忽略,只关心精度和温度阻值表。

我们先看看电路

STM32的ADC是12位的,我们根据电路图可以得到公式

 我们把温度阻值表代入公式,可借助EXCEL计算,可以得到温度对应的ADC值大小,然后定义数组,用于查表计算温度。

温度阻值表快速转化为C语言数组的方法如下链接:

NTC温度传感器R-T表格数据批量转换成C语言数组-CSDN博客

我选取的温度范围是-20℃~120℃,生成下列数组。

#ifndef _NTC_H
#define _NTC_H
#include "user_define.h"

#define NTC_HIGH_PRECISION 	1//1=0.1℃ 0=1℃

#define NUM 141

//-20℃~120℃ 
static uc16 NTC3435_10K[NUM]=
{
	3581,3559,3535,3511,3486,3461,3435,3408,3381,3353,
	3324,3295,3266,3234,3203,3171,3138,3105,3072,3037,
	3003,                                             //0                                      
	2968,2932,2896,2859,2823,2785,2748,2710,2672,2633,
	2595,2556,2517,2478,2438,2399,2360,2321,2281,2242,
	2203,2164,2125,2086,2048,2009,1971,1933,1896,1858,
	1822,1785,1749,1713,1678,1643,1608,1574,1540,1507,
	1475,1436,1411,1380,1349,1319,1289,1260,1231,1203,
	1176,1149,1122,1096,1070,1045,1021,997,974,951,
	928,906,885,864,843,823,803,784,766,747,
	729,712,695,678,662,646,631,616,601,587,
	573,559,546,533,520,508,496,484,473,462,
	451,440,430,420,410,400,391,382,373,365,
	356,348,340,332,325,317,310,303,296,290,
	283,277,271,265,259,253,247,242,237,231,
};

extern s16 Read_NTC_Temperature(uc16 *list,u16 rADC,s16 BaseValue);

#endif

二分法查表,可以用循环的方法或者递归函数查找,我采用的是循环的方法,查找出ADC在列表中的位置,就可以知道对应的索引号,进而计算温度值,代码如下:

//输入参数:ADC值表  ADC值
//返回值:查表后的索引号
u16 NTC_Lookup(uc16 *list,u16 data)
{
	u16 middle=0;
	u16 indexL=0;
	u16 indexR=NUM-1;
	if(data>=*(list+0))
    	return 0;
	if(data<=*(list+NUM-1))
   		return NUM-1;
   	
	while((indexR-indexL)>1)
	{
		middle=(indexL+indexR)>>1;
		if(data==*(list+middle))
			return middle;
		else if(data>*(list+middle))
       indexR=middle;
    else if(data<*(list+middle))
    	indexL=middle;
	}
	return indexL;
}

//例如我们采集到的ADC值是3000,经过二分法查找到的索引号是20,我们就可以知道温度在NTC3435_10K[20](0℃)和NTC3435_10K[21](1℃)之间。

二分法查找的值是表中的索引号,我们还需要根据索引号和ADC值进一步计算温度值(精度0.1℃),代码如下:

//输入参数:ADC表  采集的ADC值   ADC表的起始温度值(-20℃=-200)
//返回值:温度值 单位0.1℃ 例如返回值是100,对应的就是100*0.1℃=10℃。
s16 Read_NTC_Temperature(uc16 *list,u16 rADC,s16 BaseValue)
{
	u16 index=0;
	u16 deta=0;
	u16 t=0;
	s16 result=0;
	if(rADC>=list[0])
		return BaseValue;
	if(rADC<=*(list+NUM-1))
	{
		result=((NUM-1)*10+BaseValue);
		return result;
	}
	index=NTC_Lookup(list,rADC);
#if NTC_HIGH_PRECISION
	deta=list[index]-list[index+1];
	t=10*(list[index]-rADC)/deta;
#endif
	result=(BaseValue+index*10+t);
	return result;
}

main.c代码

int main()
{
  int temp;//
  temp=Read_NTC_Temperature(NTC3435_10K,3010,-200);//温度ADC表 ADC值 ADC表的起始温度(-20℃)
  printf("ntc = %d\n",temp);
  return 0;
}

我输入ADC值3010,输出值为-3,也就是-3*0.1℃=-0.3℃,

我用ADC换算成电阻值再去推算温度也是-0.3℃,算法正确,大家放心使用。

NTC(Negative Temperature Coefficient)是指负温度系数,是一种用于测量温度的元件。在STM32中,我们可以通过ADC模块来测量NTC的电压值,进而计算出温度值。下面是一个简单的NTC测温程序: ```c #include "stm32f10x.h" #include "stdio.h" #define ADC1_DR_Address ((u32)0x4001244C) float temp; void ADC1_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_ADC1, ENABLE); /* Configure PB0 as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure and enable DMA */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&temp; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Float; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); /* Configure and enable ADC */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_28Cycles5); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); /* Enable DMA channel */ DMA_Cmd(DMA1_Channel1, ENABLE); /* Start ADC conversion */ ADC_SoftwareStartConvCmd(ADC1, ENABLE); } int main(void) { ADC1_Init(); while (1) { printf("Temperature: %.2f\n", temp); delay_ms(1000); } } void delay_ms(uint32_t ms) { uint32_t i, j; for (i = 0; i < ms; i++) { for (j = 0; j < 7200; j++); } } ``` 在这个程序中,我们使用了ADC模块和DMA模块来获取NTC的电压值,并将其转化为温度值。具体的实现步骤如下: 1. 首先,我们需要初始化ADC模块和DMA模块。在ADC初始化中,我们将PC0配置为模拟输入,并且开启了DMA传输。在DMA初始化中,我们将DMA传输的方向设置为从ADC数据寄存器到内存中的temp变量,传输的数据大小为半字(16位),传输的数据个数为1个。在ADC配置中,我们将ADC配置为连续转换模式,开启了DMA传输,并且将通道8配置为输入源。 2. 在程序的主循环中,我们使用了printf函数来输出温度值,并且使用了delay_ms函数来进行延时。在delay_ms函数中,我们使用了一个简单的循环来进行延时。 3. 最后,在main函数中调用ADC1_Init函数来初始化ADC和DMA模块,并进入主循环。 需要注意的是,NTC的电压值与温度值之间的关系是非线性的,因此我们需要根据NTC的特性曲线来进行温度的计算。在这个例子中,我们没有考虑这一点,只是将ADC读取到的电压值直接转化为温度值输出。如果需要更准确的温度测量结果,需要考虑NTC的特性曲线。
评论 50
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值