基于stm32的恒温箱的代码
时间: 2023-09-01 11:08:43 浏览: 217
基于 STM32 的恒温箱的代码需要实现以下功能:
1. 读取传感器数据:使用 ADC 模块读取温度传感器的数据,并将其转换为实际温度值。
2. 控制加热器和风扇:使用 PWM 输出控制加热器和风扇的电压,从而实现温度控制。
3. 显示温度数据:使用 OLED 显示屏或者 LCD 屏幕显示当前的温度值和设定值。
4. 设置温度范围:使用按键或者旋转编码器等输入设备,设置温度范围和设定温度值。
下面是基于 STM32 的恒温箱的代码示例,供您参考:
```c
#include "stm32f10x.h"
#include "stdio.h"
// 温度传感器引脚定义
#define TEMPERATURE_SENSOR_PIN GPIO_Pin_0
#define TEMPERATURE_SENSOR_GPIO GPIOA
// 按键引脚定义
#define BUTTON_PIN GPIO_Pin_1
#define BUTTON_GPIO GPIOA
// OLED 显示屏引脚定义
#define OLED_SCL_PIN GPIO_Pin_5
#define OLED_SDA_PIN GPIO_Pin_7
#define OLED_RST_PIN GPIO_Pin_6
#define OLED_GPIO GPIOB
// PWM 输出引脚定义
#define HEATER_PIN GPIO_Pin_8
#define HEATER_GPIO GPIOA
#define FAN_PIN GPIO_Pin_9
#define FAN_GPIO GPIOA
// 温度范围和设定温度值
#define MIN_TEMPERATURE 20
#define MAX_TEMPERATURE 50
#define DEFAULT_TEMPERATURE 25
// 温度控制参数
#define KP 0.5
#define KI 0.1
#define KD 0.2
// 全局变量定义
volatile float temperature = 0;
volatile float set_temperature = DEFAULT_TEMPERATURE;
volatile float integral = 0;
volatile float derivative = 0;
volatile float last_error = 0;
volatile uint32_t last_time = 0;
// 函数声明
void ADC_Init(void);
void GPIO_Init(void);
void PWM_Init(void);
void TIM2_Init(void);
void OLED_Init(void);
void OLED_WriteCmd(uint8_t cmd);
void OLED_WriteData(uint8_t data);
void OLED_SetPos(uint8_t x, uint8_t y);
void OLED_Clear(void);
void OLED_ShowString(uint8_t x, uint8_t y, char *str);
void Delay_ms(uint32_t ms);
float PID_Controller(float set_value, float actual_value);
int main(void)
{
// 初始化
GPIO_Init();
ADC_Init();
PWM_Init();
TIM2_Init();
OLED_Init();
// 温度控制循环
while (1)
{
// 读取传感器数据
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
temperature = ADC_GetConversionValue(ADC1) * 3.3 / 4096.0 * 100.0;
// 控制温度
float output = PID_Controller(set_temperature, temperature);
// 设置 PWM 输出
if (output > 0)
{
TIM_SetCompare1(TIM1, output);
TIM_SetCompare2(TIM1, 0);
}
else
{
TIM_SetCompare1(TIM1, 0);
TIM_SetCompare2(TIM1, -output);
}
// 显示温度数据
char str[16];
sprintf(str, "Temp: %.1f C", temperature);
OLED_ShowString(0, 0, str);
sprintf(str, "Set: %.1f C", set_temperature);
OLED_ShowString(0, 2, str);
// 延时 500ms
Delay_ms(500);
}
}
// ADC 初始化函数
void ADC_Init(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能 ADC1 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// 配置 ADC1 通道 0 的 GPIO 引脚
GPIO_InitStructure.GPIO_Pin = TEMPERATURE_SENSOR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(TEMPERATURE_SENSOR_GPIO, &GPIO_InitStructure);
// 配置 ADC1
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
// 配置 ADC1 通道 0
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
// 使能 ADC1
ADC_Cmd(ADC1, ENABLE);
}
// GPIO 初始化函数
void GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 使能 GPIOA 和 GPIOB 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
// 配置温度传感器引脚
GPIO_InitStructure.GPIO_Pin = TEMPERATURE_SENSOR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(TEMPERATURE_SENSOR_GPIO, &GPIO_InitStructure);
// 配置按键引脚
GPIO_InitStructure.GPIO_Pin = BUTTON_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(BUTTON_GPIO, &GPIO_InitStructure);
// 配置 OLED 显示屏引脚
GPIO_InitStructure.GPIO_Pin = OLED_SCL_PIN | OLED_SDA_PIN | OLED_RST_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(OLED_GPIO, &GPIO_InitStructure);
// 配置 PWM 输出引脚
GPIO_InitStructure.GPIO_Pin = HEATER_PIN | FAN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HEATER_GPIO, &GPIO_InitStructure);
GPIO_Init(FAN_GPIO, &GPIO_InitStructure);
}
// PWM 初始化函数
void PWM_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
// 使能 TIM1 时钟和 GPIOA 时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA, ENABLE);
// 配置 GPIOA 引脚为 PWM 输出
GPIO_InitStructure.GPIO_Pin = HEATER_PIN | FAN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(HEATER_GPIO, &GPIO_InitStructure);
GPIO_Init(FAN_GPIO, &GPIO_InitStructure);
// 配置 TIM1 时钟和周期
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// 配置 TIM1 通道 1 和通道 2 为 PWM 输出
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
// 启动 TIM1
TIM_Cmd(TIM1, ENABLE);
}
// 定时器初始化函数
void TIM2_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
// 使能 TIM2 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 配置 TIM2 时钟和周期
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 配置 TIM2 中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 启动 TIM2
TIM_Cmd(TIM2, ENABLE);
}
// OLED 初始化函数
void OLED_Init(void)
{
GPIO_SetBits(OLED_GPIO, OLED_RST_PIN);
Delay_ms(100);
GPIO_ResetBits(OLED_GPIO, OLED_RST_PIN);
Delay_ms(100);
GPIO_SetBits(OLED_GPIO, OLED_RST_PIN);
Delay_ms(100);
OLED_WriteCmd(0xAE);
OLED_WriteCmd(0xD5);
OLED_WriteCmd(0x80);
OLED_WriteCmd(0xA8);
OLED_WriteCmd(0x3F);
OLED_WriteCmd(0xD3);
OLED_WriteCmd(0x00);
OLED_WriteCmd(0x40);
OLED_WriteCmd(0x8D);
OLED_WriteCmd(0x14);
OLED_WriteCmd(0x20);
OLED_WriteCmd(0x00);
OLED_WriteCmd(0xA1);
OLED_WriteCmd(0xC8);
OLED_WriteCmd(0xDA);
OLED_WriteCmd(0x12);
OLED_WriteCmd(0x81);
OLED_WriteCmd(0xCF);
OLED_WriteCmd(0xD9);
OLED_WriteCmd(0xF1);
OLED_WriteCmd(0xDB);
OLED_WriteCmd(0x40);
OLED_WriteCmd(0xA4);
OLED_WriteCmd(0xA6);
OLED_WriteCmd(0xAF);
OLED_Clear();
}
// OLED 写命令
void OLED_WriteCmd(uint8_t cmd)
{
uint8_t i;
GPIO_ResetBits(OLED_GPIO, OLED_SCL_PIN);
GPIO_ResetBits(OLED_GPIO, OLED_SDA_PIN);
for (i = 0; i < 8; i++)
{
if ((cmd & 0x80) == 0x80)
{
GPIO_SetBits(OLED_GPIO, OLED_SDA_PIN);
}
else
{
GPIO_ResetBits(OLED_GPIO, OLED_SDA_PIN);
}
cmd <<= 1;
GPIO_SetBits(OLED_GPIO, OLED_SCL_PIN);
GPIO_ResetBits(OLED_GPIO, OLED_SCL_PIN);
}
}
// OLED 写数据
void OLED_WriteData(uint8_t data)
{
uint8_t i;
GPIO_ResetBits(OLED_GPIO, OLED_SCL_PIN);
GPIO_SetBits(OLED_GPIO, OLED_SDA_PIN);
for (i = 0; i < 8; i++)
{
if ((data & 0x80) == 0x80)
{
GPIO_SetBits(OLED_GPIO, OLED_SDA_PIN);
}
else
{
GPIO_ResetBits(OLED_GPIO, OLED_SDA_PIN);
}
data <<= 1;
GPIO_SetBits(OLED_GPIO, OLED_SCL_PIN);
GPIO_ResetBits(OLED_GPIO, OLED_SCL_PIN);
}
}
// OLED 设置位置
void OLED_SetPos(uint8_t x, uint8_t y)
{
OLED_WriteCmd(0xb0 + y);
OLED_WriteCmd(((x & 0xf0) >> 4) | 0x10);
OLED_WriteCmd(x & 0x0f);
}
// OLED 清屏
void OLED_Clear(void)
{
uint8_t i, j;
for (i = 0; i < 8; i++)
{
OLED_WriteCmd(0xb0 + i);
OLED_WriteCmd(0x00);
OLED_WriteCmd(0x10);
for (j = 0; j < 128; j++)
{
OLED_WriteData(0x00);
}
}
}
// OLED 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, char *str)
{
uint8_t i = 0;
while (str[i] != '\0')
{
OLED_SetPos(x, y);
OLED_WriteData(str[i]);
x += 8;
i++;
}
}
// 延时函数
void Delay_ms(uint32_t ms)
{
uint32_t i, j;
for (i = 0; i < ms; i++)
{
for (j = 0; j < 2000; j++);
}
}
// PID 控制器
float PID_Controller(float set_value, float actual_value)
{
uint32_t current_time = TIM_GetCounter(TIM2);
float error = set_value - actual_value;
float output = KP * error + KI * integral + KD * derivative;
integral += error * (current_time - last_time) / 1000.0;
derivative = (error - last_error) / (current_time - last_time) * 1000.0;
last_error = error;
last_time = current_time;
if (output > 100) output = 100;
if (output < -100) output = -100;
return output;
}
// 定时器中断处理函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2,
阅读全文