一种基于四线制去耦的高精度测温电路

该博客介绍了一种基于四线制测阻电路的高精度温度测量系统,通过STM32微控制器实现,结合ADS1248芯片进行温度转换。系统使用CAN总线进行数据传输,具备自检、超量程报警功能,并通过串口输出温度信息。此外,还详细描述了系统的初始化、定时器设置、中断处理和CAN总线滤波配置。
摘要由CSDN通过智能技术生成

一种基于四线制去耦的高精度测温电路

采用四线制测阻电路,可以有效抑制引线阻抗及自热功率带来的测量误差,整体模块的功能运行代码如下:

//发布日期:2022.10.17------------------------------------///
/* Includes ------------------------------------------------------------------*/
#include “main.h”
#include “stm32f1xx_hal.h”
#include “spi.h”
#include “tim.h”
#include “usart.h”
#include “wwdg.h”
#include “gpio.h”
#include “ADS.h”
#include “math.h”

#define SWITCH HAL_GPIO_ReadPin(GPIOA,Switch_Pin)
#define KEYLED HAL_GPIO_ReadPin(GPIOB,Keyled_Pin)

static uint8_t table[]={‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’};
uint8_t DisStr[8];
uint8_t TxData[13];//T1=+025.132/t

double REF2=806.0;//799.51;//802.0;//ADS1248参考电阻
double RTD2;

double R0=1000.0;

double Temperature;
float Trans_F;
char ss[4];
char ss_num;
char p_F;

double C1=0;//Keyled 开始0.5S闪烁一次,自检
double C3=0;//Keyled 开始4S闪烁一次,超量程
double C4=0;//Keyled 开始0.5S闪烁一次,闪烁8次
double Num_beat=0;
double Num_C3=3;
double Flash_num=8;

char state;
char error;
uint32_t RxID;
CAN
CAN_HandleTypeDef hcan;
static CanTxMsgTypeDef TxMessage;
static CanRxMsgTypeDef RxMessage;

void MX_CAN_Init(void);
void HAL_CAN_MspInit(CAN_HandleTypeDef
canHandle);
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle);
void CanTransTemp(void);
void CanTransState(char s);
void CanTransError(char s);

double RTDToTemperature(double R);
void Num2Char(uint8_t str, double number, unsigned int g, unsigned int l);

void SystemClock_Config1(void);
void MX_CAN_Init(void);
void CAN_SetTxMsg(void);
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef hcan);
void SystemClock_Config(void);
static void MX_NVIC_Init(void);
/

  • @brief The application entry point.

  • @retval None
    */

    int main(void)
    {
    HAL_Init();
    SystemClock_Config();
    HAL_Delay(100);

    MX_GPIO_Init();
    HAL_GPIO_WritePin(GPIOB,Keyled_Pin,GPIO_PIN_SET);//程序开启,指示灯初始化常灭,IO输出高电平

    MX_TIM1_Init();//设置定时器,周期0.5S(分频3600,周期5000)
    MX_NVIC_Init();//中断优先级初始化
    HAL_TIM_Base_Start_IT(&htim1);//打开定时器

    C1=1;//Keyled开始闪烁,周期0.5S,开始自检

    state=5;//自检中
    MX_CAN_Init();
    MX_SPI1_Init();
    MX_USART2_UART_Init();

    InitADS();
    while(InitADS_RTDChannle())
    {
    HAL_Delay(100);
    }
    HAL_Delay(2000);

    while(GainSetCal())
    {
    HAL_Delay(100);
    }
    HAL_Delay(100);

    while(OffSetCal())
    {
    HAL_Delay(100);
    }
    HAL_Delay(100);

    while(InitADS_RTDChannle())
    {
    HAL_Delay(100);
    }
    HAL_Delay(10000);

    C1=0;//ADS初始化,校准通过后,系统自检通过;
    state=1;

    HAL_GPIO_WritePin(GPIOB,Keyled_Pin,GPIO_PIN_RESET);//指示灯常亮,IO输出低电平
    HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);

    while(1)
    {
    HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
    RTD2=(double)ReadOnceAD()/8388607.0*REF2/4;//读取阻值
    Temperature=RTDToTemperature(RTD2);//温度转换

    if(Temperature>150.0||Temperature<(-70.0))//超量程,2S周期闪烁,正常量程后指示灯常量                      
    {							            
    	C4=0;
    	C3=1;//超量程提示,调用中断,期间指示灯闪烁周期:2S/次
    	TxData[0]='O';TxData[1]='v';TxData[2]='e';TxData[3]='r';TxData[4]='R';TxData[5]='a';
    	TxData[6]='n';TxData[7]='g';TxData[8]='e';TxData[9]='?';TxData[10]=0x0a;
    
    	HAL_UART_Transmit(&huart2,TxData,11,100);//串口输出"OverRange? " 
    
    	error=0x45;
    	CanTransError(error);//报警	
    	state=4;
    	CanTransState(state);//发送状态
    }
    else
    {
    	C3=0;
        if(C4==0)
        {
    		HAL_GPIO_WritePin(GPIOB,Keyled_Pin,GPIO_PIN_RESET);//指示灯常亮 
        }                
    	state=1;
    	error=0;
    	
    	Num2Char(DisStr, Temperature, 3, 3);	
    	TxData[0]='T';TxData[1]='1';TxData[2]='='; 
    	TxData[11]='?';  TxData[12]=0x0a;                                 
    	if(Temperature>=0)
    	{
    		TxData[3]='+';
    	}
    	else
    	{
    		TxData[3]='-';
    	}
    	for(int i=0;i<=7;i++)
    	{
    		TxData[4+i]=DisStr[i];                            
    	}	
    }
    
    if(SWITCH==0)//按下触发键
    {  
    	HAL_Delay(400*100);//延迟400ms//加延迟,防止抖动
    	HAL_Delay(400*100);//延迟200ms
    	if(SWITCH==0)
    	{                    
    		TxData[0]='T';TxData[1]='2';TxData[2]='=';              
    		//HAL_UART_Transmit(&huart2,TxData,13,100);//串口输出“T2=±***.***?”                   
    		Flash_num=8;//闪烁次数
    		C4=1;//闪烁8次                     
    	}               					
    	CanTransTemp();//发送温度数值							
    } 
    else
    {
    		;
    }
    HAL_UART_Transmit(&huart2,TxData,13,100);             
    			
    Num_beat=Num_beat-1;
    if(Num_beat<=0)
    {  
    	Num_beat=60;				
    	hcan.pTxMsg->ExtId=0x18395058;//扩展ID,心跳包
    	hcan.pTxMsg->IDE=CAN_ID_EXT;//扩展帧
    	hcan.pTxMsg->RTR=CAN_RTR_DATA;//发送为数据
    	hcan.pTxMsg->DLC=0;//数据长度0
    	HAL_CAN_Transmit(&hcan,100);
    }
    

    }
    }

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //定时器中断函数
{
if(htim==&htim1)
{
if(C11)//POwerled翻转,0.5S
{
HAL_GPIO_WritePin(GPIOB,Keyled_Pin,(KEYLED^1)?(GPIO_PIN_SET):(GPIO_PIN_RESET));//指示灯翻转
}

if(C3
1)
{
Num_C3=Num_C3-1;
if(Num_C3<=0)
{
HAL_GPIO_WritePin(GPIOB,Keyled_Pin,(KEYLED^1)?(GPIO_PIN_SET):(GPIO_PIN_RESET));//指示灯翻转
Num_C3=3;//1S闪烁一次
}
}

if(C4==1)
{
Flash_num=Flash_num-1;

	if(Flash_num>=0)//Keyled翻转   
	{   					
		HAL_GPIO_WritePin(GPIOB,Keyled_Pin,(KEYLED^1)?(GPIO_PIN_SET):(GPIO_PIN_RESET));//指示灯翻转[异或判断实现状态翻转]                          					               
	}
	else
	{
		HAL_GPIO_WritePin(GPIOB,Keyled_Pin,GPIO_PIN_RESET);//灭灯
		C4=0;
	}
}                        

}
}

void CAN_SetTxMsg(void)
{
hcan.pTxMsg->ExtId=0x0001; //扩展ID
hcan.pTxMsg->IDE=CAN_ID_EXT; //扩展帧

hcan.pTxMsg->RTR=CAN_RTR_DATA;//发送为数据
hcan.pTxMsg->DLC=2; 					//数据长度2 
hcan.pTxMsg->Data[0]=0x01;
hcan.pTxMsg->Data[1]=0x02;

}
CAN接收中断
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef *hcan)
{
RxID=RxMessage.ExtId;

if(RxID==0x0C635850)
{
	CanTransTemp();
}
if(RxID==0x0C615850)
{
	CanTransError(error);
}
HAL_CAN_Receive_IT(hcan, CAN_FIFO0);

}
//CAN中断处理函数,原发送内容+1
void CanTransTemp(void)
{
Trans_F=Temperature;
p_F=(char )&Trans_F;
for(ss_num=0;ss_num<4;ss_num++)
{
ss[ss_num]=
(p_F+ss_num);
}
hcan.pTxMsg->ExtId=0x18455058;//扩展ID
hcan.pTxMsg->IDE=CAN_ID_EXT;//扩展帧

hcan.pTxMsg->RTR=CAN_RTR_DATA;//发送为数据
hcan.pTxMsg->DLC=8;//数据长度8
hcan.pTxMsg->Data[0]=ss[0];
hcan.pTxMsg->Data[1]=ss[1];
hcan.pTxMsg->Data[2]=ss[2];
hcan.pTxMsg->Data[3]=ss[3];
hcan.pTxMsg->Data[4]=0xFF;
hcan.pTxMsg->Data[5]=0xFF;
hcan.pTxMsg->Data[6]=0xFF;
hcan.pTxMsg->Data[7]=0xFF;
HAL_CAN_Transmit(&hcan,100);

}

void CanTransState(char s)
{
hcan.pTxMsg->ExtId=0x18435058;//扩展ID
hcan.pTxMsg->IDE=CAN_ID_EXT;//扩展帧
hcan.pTxMsg->RTR=CAN_RTR_DATA;//发送为数据
hcan.pTxMsg->DLC=2;//数据长度8
hcan.pTxMsg->Data[0]=s;
hcan.pTxMsg->Data[1]=0x00;
HAL_CAN_Transmit(&hcan,100);
}

void CanTransError(char s)
{
hcan.pTxMsg->ExtId=0x18425058;//扩展ID
hcan.pTxMsg->IDE=CAN_ID_EXT;//扩展帧
hcan.pTxMsg->RTR=CAN_RTR_DATA;//发送为数据
hcan.pTxMsg->DLC=2;//数据长度8
hcan.pTxMsg->Data[0]=s;
hcan.pTxMsg->Data[1]=0x00;
HAL_CAN_Transmit(&hcan,100);
}

/**

  • @brief System Clock Configuration
  • @retval None
    */
    void SystemClock_Config(void)
    {

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;

/**Initializes the CPU, AHB and APB busses clocks 
*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}

/**Initializes the CPU, AHB and APB busses clocks 
*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}

/**Configure the Systick interrupt time 
*/

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000/100);//10us

/**Configure the Systick 
*/

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 1);
}

/**

  • @brief NVIC Configuration.
  • @retval None
    /
    static void MX_NVIC_Init(void)
    {
    /
    USB_LP_CAN1_RX0_IRQn interrupt configuration /
    HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
    /
    TIM1_UP_IRQn interrupt configuration */
    HAL_NVIC_SetPriority(TIM1_UP_IRQn, 0, 2);
    HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
    }

/* USER CODE BEGIN 4 /
void MX_CAN_Init(void)
{
hcan.Instance = CAN1;
hcan.Init.Prescaler = 9;
hcan.Init.Mode = CAN_MODE_NORMAL;
hcan.Init.SJW = CAN_SJW_2TQ;
hcan.Init.BS1 = CAN_BS1_8TQ;
hcan.Init.BS2 = CAN_BS2_7TQ;
hcan.Init.TTCM = DISABLE;
hcan.Init.ABOM = ENABLE;
hcan.Init.AWUM = ENABLE;
hcan.Init.NART = DISABLE;
hcan.Init.RFLM = DISABLE;
hcan.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK)
{
_Error_Handler(FILE, LINE);
}
CAN_FilterConfTypeDef sFilterConfig;
hcan.pTxMsg = &TxMessage;
hcan.pRxMsg = &RxMessage;
/CAN过滤器初始化/
sFilterConfig.FilterNumber = 0; //过滤器组0
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; //工作在标识符屏蔽位模式
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //过滤器位宽为单个32位。
/
使能报文标示符过滤器按照标示符的内容进行比对过滤,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。 */

sFilterConfig.FilterIdHigh = (((uint32_t)0x1314<<3)&0xFFFF0000)>>16; //要过滤的ID高位
sFilterConfig.FilterIdLow = (((uint32_t)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //要过滤的ID低位
sFilterConfig.FilterMaskIdHigh = 0x0000; //过滤器高16位每位必须匹配
sFilterConfig.FilterMaskIdLow = 0x0000; //过滤器低16位每位必须匹配
sFilterConfig.FilterFIFOAssignment = 0; //过滤器被关联到FIFO 0
sFilterConfig.FilterActivation = ENABLE; //使能过滤器
sFilterConfig.BankNumber = 14;
HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
}

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

GPIO_InitTypeDef GPIO_InitStruct;
if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */

/* USER CODE END CAN1_MspInit 0 /
/
CAN1 clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();

/**CAN GPIO Configuration    
PA11     ------> CAN_RX
PA12     ------> CAN_TX 
*/
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN CAN1_MspInit 1 */

/* USER CODE END CAN1_MspInit 1 */
}
}

void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{

if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspDeInit 0 */

/* USER CODE END CAN1_MspDeInit 0 /
/
Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();

/**CAN GPIO Configuration    
PA11     ------> CAN_RX
PA12     ------> CAN_TX 
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);

/* CAN1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);

/* USER CODE BEGIN CAN1_MspDeInit 1 */

/* USER CODE END CAN1_MspDeInit 1 /
}
}
/
USER CODE END 4 /
/
*

  • @brief This function is executed in case of error occurrence.
  • @param file: The file name as string.
  • @param line: The line in file as a number.
  • @retval None
    */
    void _Error_Handler(char file, int line)
    {
    /
    USER CODE BEGIN Error_Handler_Debug /
    /
    User can add his own implementation to report the HAL error return state /
    while(1)
    {
    }
    /
    USER CODE END Error_Handler_Debug */
    }

#ifdef USE_FULL_ASSERT
/**

  • @brief Reports the name of the source file and the source line number
  •     where the assert_param error has occurred.
    
  • @param file: pointer to the source file name
  • @param line: assert_param error line source number
  • @retval None
    /
    void assert_failed(uint8_t
    file, uint32_t line)
    {
    /* USER CODE BEGIN 6 /
    /
    User can add his own implementation to report the file name and line number,
    tex: printf(“Wrong parameters value: file %s on line %d\r\n”, file, line) /
    /
    USER CODE END 6 /
    }
    #endif /
    USE_FULL_ASSERT */

/**

  • @}
    */

/**

  • @}
    */

/************************ © COPYRIGHT STMicroelectronics *END OF FILE/
//发布日期:2022.10.17------------------------------------///

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值