一些时候,我们需要通过热电偶获取温度数据。在这里我们将讨论如何实现并使用MAX31855热电偶温度变送器的驱动问题。
MAX31855是具有冷端补偿,能将K、J、N、T或E型热电偶信号转换成数字量的热偶温度变送器。该热偶温度变送器输出14位带符号数据,通过SPI兼容接口、以只读格式输出。其引脚定义疾风传如下图所示:
MAX31855器件处理来自热电偶的读数,并通过串口发送数据。当片选信号为低电平,并在SCK端施加时钟信号,即可从SO读取结果。MAX31855器件始终在后台执行转换,只有片选信号CS为高电平时才能更新故障状态和温度数据。片选信号CS为低电平时,SO引脚将输出第一位数据。通过SPI接口读取完整的冷端补偿热电偶温度,需要14个时钟周期。读取热电偶和参考端温度需要32个时钟周期,其格式如下图所示:
在时钟下降沿读取输出位。第一位D31为热电偶温度符号位。D[30:18]位包含温度转换数据,顺序为MSB至LSB。D16位正常状态下为低电平,热电偶输入开路或对GND或VCC短路时变为高电平。参考端温度数据从D15开始。个数据位的定义如下:
MAX31855热偶温度变送器的温度分辨率为0.25℃,最高温度读数为+1800℃,最低温度读数为-270℃,对于K型热电偶,温度范围为-200℃至+700℃,保持±2℃精度。
我们已经了解了MAX31855热偶温度变送器的基本情况。接下来我们将依据MAX31855热偶温度变送器的各种配置参数设计并实现MAX31855热偶温度变送器的驱动程序。
与以前的驱动设计一样,我们依然是基于对象来设计MAX31855热偶温度变送器的驱动程序。所以我们要先抽象并定义MAX31855热偶温度变送器对象类型。一般来讲对象包括属性与操作两方面,我们将据此逐一分析MAX31855热偶温度变送器对象的属性与操作。
先考虑MAX31855热偶温度变送器对象的属性。对于MAX31855热偶温度变送器来说,每次访问返回的数据格式是固定的,这其中包括一些状态位,所以为了记录这些状态位我们定义一个状态量作为对象的属性。还有读回来的原始数据编码、解析出来的检测温度和冷端温度实际上表示了MAX31855热偶温度变送器当时所处的状态,所以我们将其定义为对象的属性。
再来考虑MAX31855热偶温度变送器对象的操作。对于MAX31855热偶温度变送器来说,操作就是获取温度检测数据,而读取数据操作本身依赖于具体的软硬件平台,所提我们将其定义为对象的操作。而MAX31855热偶温度变送器采用SPI接口需要控制片选信号,当然在总线上只有一台设备时,我们可以直接将其通过硬件选中,但为了通用性我们还是使用软件来控制片选操作,所以我们将片选动作作为对象的一个操作。
根据上述对MAX31855热偶温度变送器对象属性和操作的分析,我们可以抽象的到MAX31855热偶温度变送器的对象类型如下:
/*定义MAX31855对象类型*/
typedef struct Max31855Object {
uint8_t status;
uint32_t dataCode;
float mTemperature; //TC测量温度
float rTemperature; //冷端温度
void (*ReadData)(uint8_t *rData,uint16_t rSize);
void (*ChipSelcet)(Max31855CSType cs); //片选信号
}Max31855ObjectType;
抽象了对象类型后就可声明对象变量,可是这个对象变量必须作必要的初始化才能使用。所以我们需要一个初始化函数来对其进行初始化。在此函数中,我们将检测变量的有效性和初始状态赋值,并对设备进行必要的配置。根据这些要求我们设计MAX31855热偶温度变送器的对象初始化函数如下:
/*初始化MAX31855对象*/
void Max31855Initialization(Max31855ObjectType *tc,
Max31855ReadDataType read,
Max31855ChipSelcetType cs
)
{
if((tc==NULL)||(read==NULL))
{
return;
}
tc->ReadData=read;
if(cs!=NULL)
{
tc->ChipSelcet=cs;
}
else
{
tc->ChipSelcet=DefaultChipSelect;
}
tc->status=0;
tc->dataCode=0;
tc->mTemperature=0.0;
tc->rTemperature=0.0;
tc->ChipSelcet(Max31855CS_Disable);
}
我们之所以定义这一对象,目的是为了操作该对象。接下来我们就来考了MAX31855热偶温度变送器对象的操作问题。我们使用MAX31855热偶温度变送器就是为了测量温度。所以对MAX31855热偶温度变送器对象所要做的主要操作就是获取温度的转换数据并解析出温度值。对于MAX31855热偶温度变送器来说,除了热电偶的测量温度还有冷端的温度,这两个数据转换值都是可以读出来的,他们的格式如下:
根据前面的分析以及数据格式,我们可以设计获取温度数据的操作函数如下:
/*获取MAX31855测量数据*/
void Max31855GetDatas(Max31855ObjectType *tc)
{
uint8_t rData[4];
uint16_t tCode=0;
uint16_t rCode=0;
tc->ChipSelcet(Max31855CS_Enable);
tc->ReadData(rData,4);
tCode=(rData[0]<<8)+rData[1];
tCode=(tCode>>2);
rCode=(rData[2]<<8)+rData[3];
rCode=(rCode>>4);
tc->mTemperature=CalcMeasureTemperature(tCode);
tc->rTemperature=CalcColdEndTemperature(rCode);
tc->dataCode=(rData[0]<<24)+(rData[1]<<16)+(rData[2]<<8)+rData[3];
tc->ChipSelcet(Max31855CS_Disable);
}
我们已经设计并实现了MAX31855热偶温度变送器对象的驱动程序。这一驱动程序的设计还需要验证,所以我们需要设计一个简单的应用来验证这一驱动程序的正确性。
为了基于对象操作MAX31855热偶温度变送器,我们还是需要声明并初始化MAX31855热偶温度变送器对象变量。
Max31855ObjectType max31855;
声明了这个对象变量,我们还需要使用前面设计的Max31855Initialization对象初始化函数对这个变量进行初始化。这个变量有几个参数:
Max31855ObjectType *tc, //MAX31855对象变量
Max31855ReadDataType read, //读MAX31855函数指针
Max31855ChipSelcetType cs //片选操作函数指针
其中第一个参数为需要初始化的对象变量,后面两个为操作回调函数的指针,这几个函数我们是炫耀实现的,其原型定义如下:
typedef void (*Max31855ReadDataType)(uint8_t *rData,uint16_t rSize);
typedef void (*Max31855ChipSelcetType)(Max31855CSType cs); //片选信号
这些函数的实现依赖于具体的软硬件平台,我们这里实现基于STM32F103的操作函数,依据原型定义我们实现如下:
/*SPI1读数据操作*/
static void BmtcReadData(uint8_t *rData,uint16_t rSize)
{
HAL_SPI_Receive (&hspi1, rData, rSize, 1000);
}
/*SPI1片选操作函数*/
static void BmtcChipSelcet(Max31855CSType cs)
{
if(Max31855CS_Enable == cs)
{
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
return;
}
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
}
这要初始化函数的全部参数皆已定义,我们可以初始化MAX31855热偶温度变送器对象如下:
/*初始化MAX31855对象*/
Max31855Initialization(&max31855,
BmtcReadData,
BmtcChipSelcet
);
事实上,这个驱动程序我们已经应用于具体的项目当中,并且使用正常。所以在这个验证中,我们直接将项目中的实现代码节选如下:
/*获取MAX31855测量数据*/
Max31855GetDatas(&max31855);
aPara.phyPara.temperature=max31855.mTemperature;
aPara.phyPara.rTemperature=max31855.rTemperature;
在我们的项目中,我们使用驱动实现了热电偶的温度采集,在使用过程中运行很稳定,数据获取及解析也没有问题,所以驱动程序的设计应该是符合要求的。
在使用驱动程序的时候要注意,MAX31855热偶温度变送器SPI端口的时钟频率有要求,主设备输出的串行时钟最大不要超过5MHz,我们设置为2.5MHz时运行比较稳定。
在使用驱动时需注意,采用SPI接口的器件需要考虑片选操作的问题。如果片选信号是通过硬件电路来实现的,我们在初始化时给其传递NULL值。如果是软件操作片选则传递我们编写的片选操作函数。
全部0条评论
快来发表一下你的评论吧 !