126 lines
3.5 KiB
C
126 lines
3.5 KiB
C
#include "BSP.H"
|
||
|
||
#define MAX6675_SCK_GPIO GPIOB
|
||
#define MAX6675_SCK_PIN GPIO_Pin_5
|
||
|
||
#define MAX6675_CS_GPIO GPIOB
|
||
#define MAX6675_CS_PIN GPIO_Pin_4
|
||
|
||
#define MAX6675_SO_GPIO GPIOB
|
||
#define MAX6675_SO_PIN GPIO_Pin_3
|
||
|
||
uint16_t MAX6675_ReadData(void)
|
||
{
|
||
uint16_t data = 0;
|
||
int8_t i = 0;
|
||
// 选中传感器
|
||
GPIO_ResetBits(MAX6675_CS_GPIO, MAX6675_CS_PIN);
|
||
|
||
// 从SO引脚读取数据
|
||
for (i = 15; i >= 0; i--) {
|
||
// 将SCK引脚拉低
|
||
GPIO_ResetBits(MAX6675_SCK_GPIO, MAX6675_SCK_PIN);
|
||
|
||
// 延时一段时间
|
||
delay_us(1);
|
||
|
||
// 读取SO引脚状态
|
||
if (GPIO_ReadInputDataBit(MAX6675_SO_GPIO, MAX6675_SO_PIN)) {
|
||
data |= (1 << i); // 设置对应位为1
|
||
}
|
||
|
||
// 将SCK引脚拉高
|
||
GPIO_SetBits(MAX6675_SCK_GPIO, MAX6675_SCK_PIN);
|
||
|
||
// 延时一段时间
|
||
delay_us(1);
|
||
}
|
||
|
||
// 解除传感器选中状态
|
||
GPIO_SetBits(MAX6675_CS_GPIO, MAX6675_CS_PIN);
|
||
|
||
return data;
|
||
}
|
||
float Temperature;
|
||
// 定义卡尔曼滤波器的参数结构体
|
||
typedef struct {
|
||
float x; // 状态估计值
|
||
float P; // 状态协方差
|
||
float Q; // 过程噪声协方差
|
||
float R; // 观测噪声协方差
|
||
float K; // 卡尔曼增益
|
||
} KalmanFilter;
|
||
KalmanFilter kf;
|
||
|
||
// 初始化卡尔曼滤波器
|
||
void kalman_filter_init(KalmanFilter *kf, float initial_x, float initial_P, float process_noise, float measurement_noise)
|
||
{
|
||
kf->x = initial_x;
|
||
kf->P = initial_P;
|
||
kf->Q = process_noise;
|
||
kf->R = measurement_noise;
|
||
}
|
||
|
||
// 更新卡尔曼滤波器状态
|
||
void kalman_filter_update(KalmanFilter *kf, float measurement)
|
||
{
|
||
// 预测步骤
|
||
float x_pred = kf->x; // 预测的状态值
|
||
float P_pred = kf->P + kf->Q; // 预测的状态协方差
|
||
|
||
// 更新步骤
|
||
kf->K = P_pred / (P_pred + kf->R); // 计算卡尔曼增益
|
||
kf->x = x_pred + kf->K * (measurement - x_pred); // 更新状态估计值
|
||
kf->P = (1 - kf->K) * P_pred; // 更新状态协方差
|
||
}
|
||
#include "APPDEF.H"
|
||
void MAX6675_ConvertTemperature(const void *P_arg)
|
||
{
|
||
kalman_filter_init(&kf, 0.0, 1.0, 0.01, 0.3);
|
||
|
||
for (;;) {
|
||
osDelay(250);
|
||
uint16_t data = MAX6675_ReadData();
|
||
// 提取温度数据部分(高位14位)
|
||
uint16_t temperatureData = data >> 3;
|
||
|
||
// 判断正负号位
|
||
uint8_t sign = (data & 0x04) >> 2;
|
||
|
||
// 温度转换为摄氏度
|
||
float temperature = (float)temperatureData * 0.25f;
|
||
|
||
// 如果为负温度,取补码并添加负号
|
||
if (sign == 1) {
|
||
temperature = -((~temperatureData + 1) * 0.25f);
|
||
}
|
||
kalman_filter_update(&kf, temperature); // 更新步骤
|
||
Temperature = kf.x + Set.TempDelta;
|
||
/* code */
|
||
}
|
||
}
|
||
osThreadDef(MAX6675_ConvertTemperature, osPriorityNormal, 1, 0);
|
||
|
||
void MAX6675_Init(void)
|
||
{
|
||
// 初始化CS引脚为高电平(不选中传感器)
|
||
GPIO_SetBits(MAX6675_CS_GPIO, MAX6675_CS_PIN);
|
||
// 初始化GPIO引脚和延时函数
|
||
GPIO_InitTypeDef GPIO_InitStruct;
|
||
GPIO_InitStruct.GPIO_Pin = MAX6675_SCK_PIN;
|
||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_Init(MAX6675_SCK_GPIO, &GPIO_InitStruct);
|
||
|
||
GPIO_InitStruct.GPIO_Pin = MAX6675_CS_PIN;
|
||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_Init(MAX6675_CS_GPIO, &GPIO_InitStruct);
|
||
|
||
GPIO_InitStruct.GPIO_Pin = MAX6675_SO_PIN;
|
||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_Init(MAX6675_SO_GPIO, &GPIO_InitStruct);
|
||
osThreadCreate(osThread(MAX6675_ConvertTemperature), NULL);
|
||
}
|