STM32F405作为主控,ADS1110作为温度采样,通过DAC输出模拟量,无论怎么进行PID整定,当达到目标值的时候,采样值会出现剧烈波动。结果如图:

代码如下:
#ifndef __ADS1110_I2C_H__
#define __ADS1110_I2C_H__
#include "main.h"
#define ADS1110_ADDR_A0 0x48
#define ADS1110_ADDR_A1 0x49
#define ADS1110_ADDR_A2 0x4A
#define ADS1110_ADDR_A3 0x4B
#define ADS1110_ADDR_A4 0x4C
#define ADS1110_ADDR_A5 0x4D
#define ADS1110_ADDR_A6 0x4E
#define ADS1110_ADDR_A7 0x4F
// 设备类型
typedef enum {
ADC_TYPE_ADS1110 = 0,
ADC_TYPE_ADS1115 = 1,
ADC_TYPE_UNKNOWN = 2
} ADC_Type;
// 模式
typedef enum {
ADS1110_MODE_CONTINUOUS = 0x00,
ADS1110_MODE_SINGLE = 0x10
} ADS1110_Mode;
// 数据速率
typedef enum {
ADS1110_DR_240SPS = 0x00,
ADS1110_DR_60SPS = 0x01,
ADS1110_DR_30SPS = 0x02,
ADS1110_DR_15SPS = 0x03
} ADS1110_DataRate;
// 增益
typedef enum {
ADS1110_PGA_1 = 0x00,
ADS1110_PGA_2 = 0x01,
ADS1110_PGA_4 = 0x02,
ADS1110_PGA_8 = 0x03
} ADS1110_Gain;
// ADS1110状态枚举
typedef enum {
ADS1110_STATE_IDLE = 0,
ADS1110_STATE_WAITING_DATA,
ADS1110_STATE_DATA_READY,
ADS1110_STATE_ERROR
} ADS1110_StateTypeDef;
// 数据结构用于存储读取结果
typedef struct {
uint8_t rx_buf[3];
int16_t raw_buf[5];
uint8_t raw_index;
int16_t raw_data;
float voltage;
uint8_t gain_setting;
uint8_t data_ready;
} ADS1110_Data;
extern ADS1110_Data ads1110_data;
extern ADC_Type adc_type;
extern ADS1110_StateTypeDef state;
ADC_Type Detect_ADC_Type(I2C_HandleTypeDef *hi2c, uint8_t dev_addr);
void ADS1110_Init(I2C_HandleTypeDef *hi2c, uint8_t dev_addr,
ADS1110_Mode mode, ADS1110_DataRate dr, ADS1110_Gain gain);
uint8_t ADS1110_IsDataReady(I2C_HandleTypeDef *hi2c, uint8_t dev_addr);
// DMA读取函数
HAL_StatusTypeDef ADS1110_StartRead_DMA(I2C_HandleTypeDef *hi2c, uint8_t dev_addr);
void ADS1110_ProcessData(void);
void TestDevice(void);
void USE_ADS1110(void);
void USE_ADS1110_DMA(void);
#endif
#include "ads1110_i2c.h"
#include "i2c.h"
#include "stdio.h"
#include "tempctrl.h"
ADS1110_StateTypeDef state = ADS1110_STATE_IDLE;
ADC_Type adc_type = ADC_TYPE_UNKNOWN;
ADS1110_Data ads1110_data;
ADC_Type Detect_ADC_Type(I2C_HandleTypeDef *hi2c, uint8_t dev_addr)
{
uint8_t rx_data[3];
HAL_StatusTypeDef status;
uint8_t success_cnt = 0;
printf("[ADS1110] 检测设备: 0x%02X\r\n", dev_addr);
// 先检查设备是否响应
if(HAL_I2C_IsDeviceReady(hi2c, dev_addr << 1, 3, 100) != HAL_OK) {
printf("[ADS1110] 设备未响应\r\n");
return ADC_TYPE_UNKNOWN;
}
for(int i = 0; i < 3; i++) {
status = HAL_I2C_Master_Receive(hi2c, (dev_addr << 1) | 0x01, rx_data, 3, 100);
if(status == HAL_OK) {
success_cnt++;
}
}
if(success_cnt == 3) {
printf("[ADS1110] 连续3次读取成功,判定为ADS1110\r\n");
return ADC_TYPE_ADS1110;
}
printf("[ADS1110] 读取失败或设备不匹配\r\n");
return ADC_TYPE_UNKNOWN;
}
void ADS1110_Init(I2C_HandleTypeDef *hi2c, uint8_t dev_addr,
ADS1110_Mode mode, ADS1110_DataRate dr, ADS1110_Gain gain)
{
printf("[ADS1110] 初始化...\r\n");
uint8_t config = 0x00;
// 构建配置字节
config |= (mode & 0x10); // 模式位(位4)
config |= ((dr & 0x03) << 2); // 数据速率位(位2-3)
config |= (gain & 0x03); // 增益位(位0-1)
printf("[ADS1110] 发送配置: 0x%02X\r\n", config);
if(HAL_I2C_Master_Transmit(hi2c, dev_addr << 1, &config, 1, 100) != HAL_OK)
{
printf("[ADS1110] 配置发送失败\r\n");
}
else
{
printf("[ADS1110] 配置发送成功\r\n");
}
HAL_Delay(10);
printf("[ADS1110] 初始化完成\r\n");
ads1110_data.data_ready = 0;
state = ADS1110_STATE_IDLE;
}
uint8_t ADS1110_GetConfig(I2C_HandleTypeDef *hi2c, uint8_t dev_addr)
{
uint8_t rx_buf[3];
if(HAL_I2C_Master_Receive(hi2c, (dev_addr << 1) | 0x01, rx_buf, 3, 100) != HAL_OK)
{
return 0xFF;
}
return rx_buf[2];
}
uint8_t ADS1110_IsDataReady(I2C_HandleTypeDef *hi2c, uint8_t dev_addr)
{
uint8_t rx_buf[3];
if(HAL_I2C_Master_Receive(hi2c, (dev_addr << 1) | 0x01, rx_buf, 3, 100) != HAL_OK)
{
return 0;
}
// 第7位为0表示数据就绪
return (rx_buf[2] & 0x80) ? 0 : 1;
}
// DMA读取
HAL_StatusTypeDef ADS1110_StartRead_DMA(I2C_HandleTypeDef *hi2c, uint8_t dev_addr)
{
if(state == ADS1110_STATE_WAITING_DATA)
{
printf("[ADS1110] 已经在等待数据\r\n");
return HAL_BUSY;
}
state = ADS1110_STATE_WAITING_DATA;
ads1110_data.data_ready = 0;
return HAL_I2C_Master_Receive_DMA(hi2c, (dev_addr << 1) | 0x01, ads1110_data.rx_buf, 3);
}
static void ADS1110_UpdateBuffer(ADS1110_Data *p_data) {
p_data->raw_buf[p_data->raw_index] = p_data->raw_data;
p_data->raw_index = (p_data->raw_index + 1) % 5; // 循环索引
}
static float ADS1110_CalculateAverage(const ADS1110_Data *p_data) {
int32_t sum = 0;
for (int i = 0; i < 5; i++) {
sum += p_data->raw_buf[i];
}
return (float)sum / 5.0f;
}
// 处理DMA读取完成的数据
void ADS1110_ProcessData(void)
{
if(state != ADS1110_STATE_WAITING_DATA)
{
return;
}
if(ads1110_data.rx_buf[0] == 0xFF && ads1110_data.rx_buf[1] == 0xFF)
{
printf("[ADS1110] 接收到无效数据\r\n");
state = ADS1110_STATE_ERROR;
return;
}
ads1110_data.raw_data = (int16_t)((ads1110_data.rx_buf[0] << 8) | ads1110_data.rx_buf[1]);
ads1110_data.gain_setting = ads1110_data.rx_buf[2] & 0x03;
float gain_value;
switch(ads1110_data.gain_setting)
{
case ADS1110_PGA_1: gain_value = 1.0f; break;
case ADS1110_PGA_2: gain_value = 2.0f; break;
case ADS1110_PGA_4: gain_value = 4.0f; break;
case ADS1110_PGA_8: gain_value = 8.0f; break;
default: gain_value = 1.0f;
}
if (ads1110_data.raw_data < 0) ads1110_data.raw_data = 0;
ADS1110_UpdateBuffer(&ads1110_data);
float raw_avg = ADS1110_CalculateAverage(&ads1110_data);
// ads1110_data.voltage = (float)ads1110_data.raw_data / 32768.0f * 2.048f / gain_value;
float voltage_avg = raw_avg / 32768.0f * 2.048f / gain_value;
ads1110_data.data_ready = 1;
state = ADS1110_STATE_DATA_READY;
if (raw_avg < 0) raw_avg = 0;
else if (raw_avg > 65535) raw_avg = 65535;
adc_value = (uint16_t)(raw_avg + 0.5f);
adc_conv_complete = 1;
}
void TestDevice(void)
{
adc_type = Detect_ADC_Type(&hi2c1, ADS1110_ADDR_A0);
printf("[ADS1110] 检测到设备类型: %d\r\n", adc_type);
if(adc_type == ADC_TYPE_ADS1110)
{
ADS1110_Init(&hi2c1, ADS1110_ADDR_A0,
ADS1110_MODE_CONTINUOUS,
ADS1110_DR_240SPS,
ADS1110_PGA_1);
uint8_t config = ADS1110_GetConfig(&hi2c1, ADS1110_ADDR_A0);
printf("[ADS1110] 当前配置: 0x%02X\r\n", config);
printf("[ADS1110] 初始化完成\r\n");
}
else
{
printf("[ADS1110] 不支持的设备类型\r\n");
}
}
void USE_ADS1110_DMA(void)
{
switch(state)
{
case ADS1110_STATE_IDLE:
if(ADS1110_StartRead_DMA(&hi2c1, ADS1110_ADDR_A0) == HAL_OK)
{
// printf("[ADS1110] DMA读取已启动\r\n");
}
break;
case ADS1110_STATE_DATA_READY:
// 处理已读取的数据
if(ads1110_data.data_ready)
{
// adc_conv_complete = 1;
// printf("%d,%d\n",
// ads1110_data.raw_data, adc_value);
ads1110_data.data_ready = 0;
state = ADS1110_STATE_IDLE;
}
break;
case ADS1110_STATE_WAITING_DATA:
// printf("[ADS1110] 等待数据中...\r\n");
break;
case ADS1110_STATE_ERROR:
printf("[ADS1110] 错误状态,重置\r\n");
state = ADS1110_STATE_IDLE;
break;
}
}
// I2C传输完成回调函数
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c == &hi2c1)
{
ADS1110_ProcessData();
// printf("[ADS1110] DMA读取完成\r\n");
// HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_4);
}
}
// I2C错误回调函数
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c == &hi2c1)
{
printf("[ADS1110] I2C通信错误\r\n");
state = ADS1110_STATE_ERROR;
}
}
#ifndef TEMPCTRL_H
#define TEMPCTRL_H
#include "main.h"
#include "dac.h"
#include "usart.h"
#include <stdio.h>
/* PID参数配置 */
#define KP 15.0f
#define KI 0.01f
#define KD 0.05f
/* 积分限幅 */
#define INTEGRAL_LIMIT 500.0f
/* DAC参数 */
#define DAC_RESOLUTION 4095
#define DAC_MAX_VOLTAGE 3.0f
#define OUTPUT_MIN_VOLTAGE 0.0f
#define OUTPUT_MAX_VOLTAGE 3.0f
/* 函数声明 */
void TemCtrl_Init(void);
void TempCtrl(void);
float PID_Calculate(float setPoint, float actualInput);
void Update_DAC_Output(float output);
void Update_DAC_Voltage(float voltage_output);
/* 外部变量声明 */
extern uint16_t adc_value;
extern uint8_t rx_buffer[2];
extern uint8_t uart3_rec_flag;
extern uint8_t adc_conv_complete;
extern uint16_t setPoint;
#endif /* TEMPCTRL_H */
#include "tempctrl.h"
#include "ads1110_i2c.h"
#include "tim.h"
#include "usart.h"
#include "i2c.h"
uint16_t adc_value = 0;
uint8_t rx_buffer[2];
uint8_t uart3_rec_flag = 0;
uint8_t adc_conv_complete = 0;
uint16_t setPoint = 0x0498;
/* PID控制变量 */
float actualInput, lastInput, error, integral, derivative;
float pidOutput;
float lastError = 0;
float PID_Calculate(float setPoint, float actualInput)
{
error = setPoint - actualInput;
integral += error;
if (integral > INTEGRAL_LIMIT) integral = INTEGRAL_LIMIT;
if (integral < -INTEGRAL_LIMIT) integral = -INTEGRAL_LIMIT;
derivative = error - lastError;
lastError = error;
pidOutput = KP * error + KI * integral + KD * derivative;
// 输出限幅及积分抗饱和
if (pidOutput > 100.0f) {
pidOutput = 100.0f;
// if (error > 0) integral -= error;
} else if (pidOutput < 0.0f) {
pidOutput = 0.0f;
// if (error < 0) integral -= error;
}
lastInput = actualInput;
return pidOutput;
}
void Update_DAC_Output(float output)
{
float voltage_output;
uint16_t dac_value;
voltage_output = (output / 100.0f) * OUTPUT_MAX_VOLTAGE;
if (voltage_output < OUTPUT_MIN_VOLTAGE) voltage_output = OUTPUT_MIN_VOLTAGE;
if (voltage_output > OUTPUT_MAX_VOLTAGE) voltage_output = OUTPUT_MAX_VOLTAGE;
dac_value = (uint16_t)((voltage_output / DAC_MAX_VOLTAGE) * DAC_RESOLUTION);
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, dac_value);
}
void TemCtrl_Init(void)
{
/* 启动DAC通道 */
HAL_DAC_Start(&hdac, DAC_CHANNEL_2);
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, 2048);
/* 初始化PID变量 */
error = 0;
integral = 0;
derivative = 0;
lastInput = 0;
lastError = 0;
HAL_UART_Receive_IT(&huart3, rx_buffer, sizeof(rx_buffer));
printf("Temperature Control Initialized with DAC Output\r\n");
printf("Default Setpoint: 0x%04X\r\n", setPoint);
}
void TempCtrl(void)
{
static uint32_t last_pid_time = 0;
uint32_t current_time = HAL_GetTick();
if(adc_conv_complete == 1)
{
adc_conv_complete = 0;
// if(current_time - last_pid_time >= 100)
// {
// last_pid_time = current_time;
// HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_4);
// if (adc_value > 0x0490)
// {
pidOutput = PID_Calculate((float)setPoint, (float)adc_value);
if (pidOutput < 0.0f) pidOutput = 0.0f;
if (pidOutput > 100.0f) pidOutput = 100.0f;
Update_DAC_Output(pidOutput);
printf("%d,%d,%.2f\n",
adc_value, setPoint, pidOutput);
// }
// else
// {
//// Update_DAC_Output(0.0);
// printf("0x%04X\n", adc_value);
// }
// }
}
if (uart3_rec_flag)
{
uart3_rec_flag = 0;
uint16_t new_setpoint = (rx_buffer[0] << 8) | rx_buffer[1];
setPoint = (float)new_setpoint;
integral = 0;
printf("New setpoint received: 0x%04X\r\n", new_setpoint);
HAL_UART_Receive_IT(&huart3, rx_buffer, sizeof(rx_buffer));
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART3)
{
uart3_rec_flag = 1;
}
}
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_DAC_Init();
MX_USART3_UART_Init();
MX_TIM6_Init();
MX_USART6_UART_Init();
MX_TIM8_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
TestDevice();
TemCtrl_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
USE_ADS1110_DMA();
TempCtrl();
// 短暂延时
HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
有没有佬支支招啊(大哭),已经调了快两个星期了