文章目录

  • 0 前言
  • 1 注意事项
  • 1.1 参考电阻
  • 1.2 SPI时序图
  • 1.3 寄存器
  • 2 将RTD数据寄存器值转换为温度
  • 2.1 线性化温度数据
  • 2.2 RTD温度计算(PT100)
  • 3 示例代码
  • 0 前言

    本文主要介绍MAX31865 测温注意事项,并写出读取温度的示例代码,模块详细参数可以查阅相关手册,

    1 注意事项

    1.1 参考电阻

    电阻温度检测器(RTD)是一种阻值随温度变化的电阻。铂是最常见、精度最高的测温金属丝材料。铂RTD称为PT-RTD,镍、铜和其它金属亦可用来制造RTD。RTD具有较宽的测温范围,最高达+800°C,具有较高精度和较好的可重复性,线性度适中。

    为测量RTD阻值,接入参考电阻(RREF),该电阻与RTD串联,偏置电压作用在RREF上端,3线制典型应用电路如下图所示,


    参考电阻的电流同样流过RTD。参考电阻两端的电压为ADC基准电压。RTD电压连接至ADC差分输入(RTDIN+和RTDIN-)。所以ADC产生的数字输出等于RTD电阻与参考电阻的比值。对于铂电阻RTD,选择阻值等于RTD 0°C阻值的4倍的参考电阻最为合适。因此,针对PT100选用400Ω参考电阻;针对PT1000则选用4kΩ参考电阻

    1.2 SPI时序图

    读取寄存器数据,先写入要读的地址,再读取数据,时序图如下,
    在这里插入图读时序片描述

    写数据到寄存器,先写入要写的地址,再写入数据, 如下图所示,

    时钟极性和相位

    1.3 寄存器

    MAX3186主要有8个寄存器,如下表所示,

    0x00:配置寄存器,需要配置2/3/4线,故障检测周期等
    0x01-0x02:RTD电阻寄存器,由两个8位的寄存器组成,包含15位有效数据,RTD LBS 的bit0为故障位,表示检测到任意RTD故障,应用软件中需要做故障判断处理
    0x03-0x06:故障上限和故障下限寄存器用于选择RTD故障检测的触发门限。
    0x07:故障状态寄存器锁存所有检测到的故障位;向配置寄存器中的故障状态清除位写1时,将全部故障状态位清零。

    2 将RTD数据寄存器值转换为温度

    首先,利用下面公式确定RTD的阻值,

    ADC编码 = RTD数据寄存器(01h – 02h)中的15位ADC转换结果,RREF = 基准电阻的阻值
    如果RTD的阻值已知、电阻特性定义良好,则可通过计算或查找表确定温度值。

    2.1 线性化温度数据

    对于-100°C至+100°C温度范围,简单利用RTD数据可以很好地实现温度逼近,如下所示:
    温度(°C) ≈  (ADC编码/32) – 256
    从该式可以得出:0°C时,误差为0°C; -100°C时,误差为-1.75°C; +100°C时,误差为-1.4°C (假 设采用IEC751RTD,RREF等于0°C RTD电阻的四倍)。

    PT100实际测量发现,50°环境中,计算值和实际值相差1.8°左右,这样无法直接用到项目中,那就看看第2种转换方式

    2.2 RTD温度计算(PT100)

    查阅了网上大量资料,都是用线性化处理的方式,最后在Github项目中,发现采用下面公式转化温度和实际测量值保持一致

    更多详细说明请参考芯片手册《AN-709 APPLICATION NOTE》

    3 示例代码

    下图是某个项目中的MAX31865的设计图,这里参考电阻为402欧/1%,采用3线制接入PT100,主控芯片是STM32F107

    温度采集的示例代码

    // 定义结构体,用于读取整个模块数据
    struct rtd_max31865
    {
        uint8_t config_reg;
        uint16_t rtd_reg;
        uint16_t hft_reg;
        uint16_t lft_reg;
        uint8_t  status_reg;
    };
    
    void spi_delay( uint32_t delay )
    {
    	while( delay--);
    }
    
    void send_byte( uint8_t data )
    {
        uint8_t i;
    	uint32_t delay = 0xff;
    	
        for (i = 0; i < 8; i++)
        {
    		SPI3_SCLK_L();
    		spi_delay(delay);
    		
    		if( data & 0x80 )
    		{
    			SPI3_MOSI_H();
    		}
    		else
    		{
    			SPI3_MOSI_L();
    		}
    
            spi_delay(delay);
    		
    		SPI3_SCLK_H();
    		spi_delay(delay);
    
            data <<= 1;
        }
    }
    
    uint8_t read_byte( void )
    {
        uint8_t i;
    	uint8_t read = 0;
    	uint32_t delay = 0xff;
    
        for (i = 0; i < 8; i++)
        {        
    		SPI3_SCLK_L();
    		spi_delay(delay);
    		
            read = read << 1;
    
    		if ( SPI3_READ_BIT() ) 
    		{
    			read += 1;
    		}
    		else
    		{
    			read += 0;
    		}
    
            SPI3_SCLK_H();
            spi_delay(delay);
        }
        return read;
    }
    
    void max31865_config( uint8_t addr, uint8_t data )
    {
    	send_byte( addr );
    	send_byte( data );
    }
    void max31865_read( struct rtd_max31865* max31865 )
    {
    	uint8_t i, read_data[8];
    	
    	send_byte( 0 );
    	
    	for ( i = 0; i < 8; i++ )
    	{
    		read_data[i] = read_byte();
    		
    	}
    	
    	max31865->config_reg = read_data[0];
    	max31865->rtd_reg = ((read_data[1] << 8) | read_data[2]) >> 1;
    	max31865->hft_reg = ((read_data[3] << 8) | read_data[4]) >> 1;    
        max31865->lft_reg = (read_data[5] << 8) | read_data[6];            
        max31865->status_reg = read_data[7];                                  
    }
    
    float max31865_read_temp( struct rtd_max31865* max31865 )
    { 
    	uint8_t i;
    	uint32_t adc_val = 0;
    	float rtd;
    	unsigned int data;
    	float Rt;
    	float Rt0 = 100;  //PT100	
    	float Z1,Z2,Z3,Z4,temp;
    	float a = 3.9083e-3;
    	float b = -5.775e-7;
    	float rpoly;
    
    	for ( i = 0; i < 10; i++ )
    	{
    		max31865_read(max31865);
    		
    		adc_val += max31865->rtd_reg;
    	
    		HAL_Delay(2);
    	}
    	
    	Rt = (double)( adc_val * 402) / (32768 * 10);
    	
    	Z1 = -a;
    	Z2 = a*a-4*b;
    	Z3 = 4*b/Rt0;
    	Z4 = 2*b;
    	temp = Z2+Z3*Rt;
    	temp = (sqrt(temp)+Z1)/Z4;
    	
    	
    	// 温度大于0
    	if(temp>=0)
    	{
    		return temp;
    	}
    
    	// 温度小于0
    	rpoly = Rt;
    	temp = -242.02;
    	temp += 2.2228 * rpoly;
    	rpoly *= Rt;  // square
    	temp += 2.5859e-3 * rpoly;
    	rpoly *= Rt;  // ^3
    	temp -= 4.8260e-6 * rpoly;
    	rpoly *= Rt;  // ^4
    	temp -= 2.8183e-8 * rpoly;
    	rpoly *= Rt;  // ^5
    	temp += 1.5243e-10 * rpoly;
    
    	return temp;
    }
    
    void max31865_init( void )
    {
    	max31865_config( 0x80, 0xD0);
    }
    

    作者:九斗嵌入式

    物联沃分享整理
    物联沃-IOTWORD物联网 » MAX31865模块温度测量

    发表回复