#include "spi.h" #include "APPDEF.H" #include "math.h" // AD7190寄存器地址定义 #define AD7190_REG_COMM 0x00 << 3 #define AD7190_REG_STAT 0x00 << 3 #define AD7190_REG_MODE 0x01 << 3 #define AD7190_REG_CONF 0x02 << 3 #define AD7190_REG_DATA 0x03 << 3 #define AD7190_REG_GPOC 0x05 << 3 // AD7190命令定义 #define AD7190_CMD_NOP 0xFF #define AD7190_CMD_WR 0x00 #define AD7190_CMD_RD 0x40 // AD7190配置寄存器位掩码 #define AD7190_CONF_CH_MASK 0x000F #define AD7190_CONF_BURNOUT 0x0800 #define AD7190_CONF_REFSEL 0x0400 #define AD7190_CONF_GAIN_MASK 0x0038 #define AD7190_CONF_MODE_MASK 0x0C00 // AD7190配置寄存器增益定义 #define AD7190_CONF_GAIN_1 0x00 #define AD7190_CONF_GAIN_8 0x08 #define AD7190_CONF_GAIN_16 0x10 #define AD7190_CONF_GAIN_32 0x18 #define AD7190_CONF_GAIN_64 0x20 #define AD7190_CONF_GAIN_128 0x28 #define AD7190_CONF_GAIN_256 0x30 // AD7190配置寄存器工作模式定义 #define AD7190_CONF_MODE_CONT 0x000000 #define AD7190_CONF_MODE_ZEROSEL 0x800000 #define AD7190_CONF_MODE_FullSEL 0xA00000 #define AD7190_CONF_MODE_FS9_0 0x0003FF // AD7190 电桥开关 #define AD7190_GPOCON_BDPSW 0x40 void AD7190_WriteRegister(uint8_t regAddr, uint32_t regValue) { SPI1_ReadWrite(AD7190_CMD_WR | regAddr); SPI1_ReadWrite((regValue >> 16) & 0xFF); SPI1_ReadWrite((regValue >> 8) & 0xFF); SPI1_ReadWrite(regValue & 0xFF); } uint32_t AD7190_ReadRegister(uint8_t regAddr) { uint32_t regValue = 0; SPI1_ReadWrite(AD7190_CMD_RD | regAddr); regValue = SPI1_ReadWrite(0xFF); regValue = (regValue << 8) + SPI1_ReadWrite(0xFF); regValue = (regValue << 8) + SPI1_ReadWrite(0xFF); return regValue; } void AD7190_WriteRegisterOnce(uint8_t regAddr, uint8_t regValue) { SPI1_ReadWrite(AD7190_CMD_WR | regAddr); SPI1_ReadWrite(regValue); } uint8_t AD7190_ReadRegisterOnce(uint8_t regAddr) { uint32_t regValue = 0; SPI1_ReadWrite(AD7190_CMD_RD | regAddr); regValue = SPI1_ReadWrite(0xFF); return regValue; } bool AD7190_WaitForReady(uint32_t timeout) { uint32_t count = 0; // SPI1_ReadWrite(AD7190_CMD_RD | AD7190_REG_STAT); // while ((SPI1_ReadWrite(0xFF) & 0x80) && (count < timeout)) { // delay_us(1); // count++; // } while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) && (count < timeout)) { delay_us(1); count++; } if (count >= timeout) { return false; } else { return true; } } //extern uint16_t Read_Internal_Temperature(); //// AD7190函数:读取AD转换结果 //float V25 = 1.43; // 25 度时的传感器电压(mV) // float Avg_Slope = 4.3; // 传感器电压与温度之间的平均斜率(mV/°C) // // 获取 ADC 参考电压值(一般为 3.3V) // float Vref = 3.3; // 参考电压值(V) //float TemperatureIn; uint8_t ErrCount; uint32_t AD7190_ReadData() { uint32_t data = 0; //uint16_t TempI; if(AD7190_WaitForReady(50000)) { data = AD7190_ReadRegister(AD7190_REG_DATA); // TempI = Read_Internal_Temperature(); // // 将 ADC 值转换为电压值 // float V_ADC = (TempI * Vref) / 4095; // // 计算温度值(摄氏度) // TemperatureIn = ((V25 - V_ADC)*1000 / Avg_Slope) + 25.0; if(data > 15000000) { ErrCount++; } else { ErrCount = 0; } } else { ErrCount++; } if(ErrCount > 10) { SPI1_Configuration(); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); osDelay(50); uint32_t modeReg; // 配置寄存器:通道选择、参考电压源、增益和工作模式 // 打开PSW uint8_t GPOC = AD7190_ReadRegisterOnce(AD7190_REG_GPOC); GPOC |= AD7190_GPOCON_BDPSW; AD7190_WriteRegisterOnce(AD7190_REG_GPOC, GPOC); osDelay(5); uint32_t config = 0x0000011F; AD7190_WriteRegister(AD7190_REG_CONF, config); osDelay(5); modeReg |= AD7190_CONF_MODE_FS9_0; // 滤波器最低速率输出 AD7190_WriteRegister(AD7190_REG_MODE, modeReg); osDelay(5); // 执行上电校准 modeReg = AD7190_ReadRegister(AD7190_REG_MODE); modeReg &= ~0x00E00000; modeReg |= AD7190_CONF_MODE_ZEROSEL; AD7190_WriteRegister(AD7190_REG_MODE, modeReg); osDelay(5); AD7190_WaitForReady(1000000); modeReg &= ~0x00E00000; modeReg |= AD7190_CONF_MODE_FullSEL; AD7190_WriteRegister(AD7190_REG_MODE, modeReg); osDelay(5); AD7190_WaitForReady(1000000); // 校准完成 切换回连续转换模式 modeReg = 0x000803FF; AD7190_WriteRegister(AD7190_REG_MODE, modeReg); ErrCount = 0; osDelay(500); if(AD7190_WaitForReady(50000)) { data = AD7190_ReadRegister(AD7190_REG_DATA); } } return data; } // AD7190函数:读取AD转换结果并转换为实际电压值 // static void bubbleSort2(float *num) //{ // float temp; // int i, j; // for (i = 0; i < 5; i++) { // for (j = 0; j < 5 - i; j++) { // if (num[j] > num[j + 1]) { // // 交换相邻元素的值 // temp = num[j]; // num[j] = num[j + 1]; // num[j + 1] = temp; // } // } // } //} // 定义卡尔曼滤波器的参数结构体 typedef struct { float x; // 状态估计值 float P; // 状态协方差 float Q; // 过程噪声协方差 float R; // 观测噪声协方差 float K; // 卡尔曼增益 } KalmanFilter; KalmanFilter kf2; // 初始化卡尔曼滤波器 void kalman_filter_init2(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_update2(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; // 更新状态协方差 } float WeightData2 = 0.0f; float ADvalue2filter = 0.0f; // static float bufferdata2[5]; // static float dataout2[5]; static float WeightData2Temp = 0.0f; int32_t ADvalue2filterOld = 0; int32_t ADvalue2 = 0; uint8_t ic2 = 0; uint8_t i; int32_t data2 = 0; struct uCalibrateWeight CalibrateWeight2; uint8_t FollowCount = 0; uint8_t TimeCount = 0; int32_t WeightZeroOld = 0; uint32_t modeRega; uint32_t configa; uint32_t configao; bool weightChanging = false; #include "APPDEF.H" void AD7190_Run(const void *p_arg) { osDelay(600); ADvalue2 = AD7190_ReadData(); osDelay(200); ADvalue2 = AD7190_ReadData(); ADvalue2filterOld = ADvalue2filter = ADvalue2; kalman_filter_init2(&kf2, ADvalue2, 1.0, 0.001, 0.1); WeightZeroOld = CalibrateWeight2.WeightZero; uint8_t FilterQOld, SensorQOld, ZeroTrackOld, RuBianLiangOld, ruBianTimeOld; int8_t RubianLiang, RubianTime; float ZeroTrackTime, ZeroTrackRange; for (;;) { if (FilterQOld != Set.FilterQ) { FilterQOld = Set.FilterQ; switch (Set.FilterQ) // 滤波器信任度 信任度越高 反应越慢数据显示越稳定 { case 0: kf2.Q = 0.1; break; case 1: kf2.Q = 0.08; break; case 2: kf2.Q = 0.06; break; case 3: kf2.Q = 0.04; break; case 4: kf2.Q = 0.02; break; case 5: kf2.Q = 0.009; break; case 6: kf2.Q = 0.007; break; case 7: kf2.Q = 0.005; break; case 8: kf2.Q = 0.003; break; case 9: kf2.Q = 0.001; break; default: break; } } if (SensorQOld != Set.SensorQ) { SensorQOld = Set.SensorQ; switch (Set.SensorQ) // 传感器信任度 信任度越高 反应越迅速,数据波动越大 显示越不稳定 { case 0: kf2.R = 0.5; break; case 1: kf2.R = 0.3; break; case 2: kf2.R = 0.1; break; case 3: kf2.R = 0.08; break; case 4: kf2.R = 0.06; break; case 5: kf2.R = 0.04; break; case 6: kf2.R = 0.02; break; case 7: kf2.R = 0.009; break; case 8: kf2.R = 0.005; break; case 9: kf2.R = 0.001; break; default: break; } } if (ZeroTrackOld != Set.ZeroTrack) // 零点跟踪 跟踪级别越高 原始数据发生缓慢变化时,最终数据不会发生变化的可能性越大。例如 当跟踪级别设置为9时,那么如果原始数据在4秒内变化小于2.5mg,那么最终数据不会发生变化。原理是cpu会将这4秒内变化的数据叠加到零点上,相当于动态调零了。 { ZeroTrackOld = Set.ZeroTrack; switch (ZeroTrackOld) { case 0: ZeroTrackTime = 20; ZeroTrackRange = 0; break; case 1: ZeroTrackTime = 15; ZeroTrackRange = 0.0005; break; case 2: ZeroTrackTime = 10; ZeroTrackRange = 0.0005; break; case 3: ZeroTrackTime = 7; ZeroTrackRange = 0.0005; break; case 4: ZeroTrackTime = 4; ZeroTrackRange = 0.0005; break; case 5: ZeroTrackTime = 4; ZeroTrackRange = 0.0008; break; case 6: ZeroTrackTime = 4; ZeroTrackRange = 0.001; break; case 7: ZeroTrackTime = 4; ZeroTrackRange = 0.0015; break; case 8: ZeroTrackTime = 4; ZeroTrackRange = 0.002; break; case 9: ZeroTrackTime = 4; ZeroTrackRange = 0.0025; break; default: break; } } if (ruBianTimeOld != Set.RuBianTime) // 蠕变时间 级别越高 蠕变时间越短,蠕变越快 零为不蠕变 { ruBianTimeOld = Set.RuBianTime; switch (Set.RuBianTime) { case 0: RubianTime = 100; break; case 1: RubianTime = 60; break; case 2: RubianTime = 30; break; case 3: RubianTime = 20; break; case 4: RubianTime = 15; break; case 5: RubianTime = 10; break; case 6: RubianTime = 8; break; case 7: RubianTime = 6; break; case 8: RubianTime = 4; break; case 9: RubianTime = 2; break; default: break; } } if (RuBianLiangOld != Set.RuBianLiang) //蠕变量 可分正向蠕变和反向蠕变 零为不蠕变 当零点跟踪为0时 调零后观察一段时间的数据变化 如果数据持续变化为负数 则为负蠕变。反之为正蠕变。 负蠕变调整蠕变量为负数级别(谨慎调整 建议不调整) { RuBianLiangOld = Set.RuBianLiang; switch (Set.RuBianLiang) { case 0: RubianLiang = -5; break; case 1: RubianLiang = -4; break; case 2: RubianLiang = -3; break; case 3: RubianLiang = -2; break; case 4: RubianLiang = -1; break; case 5: RubianLiang = 0; break; case 6: RubianLiang = 1; break; case 7: RubianLiang = 2; break; case 8: RubianLiang = 3; break; case 9: RubianLiang = 4; break; case 10: RubianLiang = 5; break; default: break; } } osDelay(190); ADvalue2 = AD7190_ReadData(); kalman_filter_update2(&kf2, ADvalue2); // 更新步骤 ADvalue2filter = kf2.x; WeightData2Temp = CalibrateWeight2.WeightSlope * ((int32_t)ADvalue2filter - (int32_t)CalibrateWeight2.WeightZero); if( RubianLiang != 0 ) { if (TimeCount++ > 4 * RubianTime) // 动态称重时蠕变跟踪 { TimeCount = 0; if (CalibrateWeight2.WeightZero == WeightZeroOld) { CalibrateWeight2.WeightZero += RubianLiang; } WeightZeroOld = CalibrateWeight2.WeightZero; } } if (fabs(WeightData2 - WeightData2Temp) < ZeroTrackRange) { if (FollowCount++ > 4 * ZeroTrackTime) // 零点动态跟踪 { FollowCount = 0; TimeCount = 0; CalibrateWeight2.WeightZero += ADvalue2filter - ADvalue2filterOld; ADvalue2filterOld = ADvalue2filter; } } else { FollowCount = 0; ADvalue2filterOld = ADvalue2filter; } if (fabs(WeightData2 - WeightData2Temp) > 0.01f) { weightChanging = 1; } else { weightChanging = 0; } if (fabs(WeightData2 - WeightData2Temp) > 0.001f) // 数据滤波 { WeightData2Temp = (int32_t)(WeightData2Temp * 10000) / 10000.0f; WeightData2 = WeightData2Temp; } } } osThreadDef(AD7190_Run, osPriorityNormal, 1, 0); // AD7190函数:初始化AD7190 void AD7190_Init() { SPI1_Configuration(); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); SPI1_ReadWrite(0xFF); osDelay(50); uint32_t modeReg; // 配置寄存器:通道选择、参考电压源、增益和工作模式 // 打开PSW uint8_t GPOC = AD7190_ReadRegisterOnce(AD7190_REG_GPOC); GPOC |= AD7190_GPOCON_BDPSW; AD7190_WriteRegisterOnce(AD7190_REG_GPOC, GPOC); osDelay(5); uint32_t config = 0x0000011F; AD7190_WriteRegister(AD7190_REG_CONF, config); osDelay(5); modeReg |= AD7190_CONF_MODE_FS9_0; // 滤波器最低速率输出 AD7190_WriteRegister(AD7190_REG_MODE, modeReg); osDelay(5); // 执行上电校准 modeReg = AD7190_ReadRegister(AD7190_REG_MODE); modeReg &= ~0x00E00000; modeReg |= AD7190_CONF_MODE_ZEROSEL; AD7190_WriteRegister(AD7190_REG_MODE, modeReg); osDelay(5); AD7190_WaitForReady(1000000); modeReg &= ~0x00E00000; modeReg |= AD7190_CONF_MODE_FullSEL; AD7190_WriteRegister(AD7190_REG_MODE, modeReg); osDelay(5); AD7190_WaitForReady(1000000); // 校准完成 切换回连续转换模式 modeReg = 0x000803FF; AD7190_WriteRegister(AD7190_REG_MODE, modeReg); CalibrateWeight2.WeightSlope = 0.0000818f; CalibrateWeight2.WeightZero = 745430; osThreadCreate(osThread(AD7190_Run), NULL); }