一种基于四线制去耦的高精度测温电路
采用四线制测阻电路,可以有效抑制引线阻抗及自热功率带来的测量误差,整体模块的功能运行代码如下:
//发布日期: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(C31)
{
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------------------------------------///