STM32F103C8T6单片机软件实现按键1进入设置温度;按键2控制水泵水过滤的开停;按键3控制LED灯的开关;按键4负责温度值的具体设置
时间: 2024-04-05 14:07:45 浏览: 282
stm32单片机状态机,stm32单片机程序,C,C++
5星 · 资源好评率100%
以下是一个可能的实现:
```c
#include "stm32f10x.h"
#include "stdio.h"
#define LED_PIN GPIO_Pin_13
#define LED_PORT GPIOC
#define PUMP_PIN GPIO_Pin_12
#define PUMP_PORT GPIOB
#define TEMP_SET_PIN GPIO_Pin_11
#define TEMP_SET_PORT GPIOB
#define TEMP_READ_PIN GPIO_Pin_10
#define TEMP_READ_PORT GPIOB
#define TEMP_THRESHOLD 25.0f
volatile uint8_t setting_temp_mode = 0;
volatile float target_temp = 25.0f;
volatile uint8_t pump_on = 0;
volatile uint8_t led_on = 0;
void init_gpio() {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef gpio_init;
gpio_init.GPIO_Pin = LED_PIN;
gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT, &gpio_init);
gpio_init.GPIO_Pin = PUMP_PIN;
gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(PUMP_PORT, &gpio_init);
gpio_init.GPIO_Pin = TEMP_SET_PIN;
gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(TEMP_SET_PORT, &gpio_init);
gpio_init.GPIO_Pin = TEMP_READ_PIN;
gpio_init.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(TEMP_READ_PORT, &gpio_init);
}
void init_timer() {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef timer_init;
timer_init.TIM_Prescaler = 7200 - 1;
timer_init.TIM_CounterMode = TIM_CounterMode_Up;
timer_init.TIM_Period = 1000 - 1;
timer_init.TIM_ClockDivision = TIM_CKD_DIV1;
timer_init.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &timer_init);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM3_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 0;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
TIM_Cmd(TIM3, ENABLE);
}
void TIM3_IRQHandler() {
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
float current_temp = 0.0f;
for (int i = 0; i < 8; i++) {
current_temp += ((float)ADC_GetConversionValue(ADC1) / 4096.0f) * 3.3f;
}
current_temp /= 8.0f;
current_temp = (current_temp - 0.76f) / 0.0025f;
if (setting_temp_mode) {
target_temp = current_temp;
printf("Target temperature set to %.1f C\n", target_temp);
} else {
if (current_temp >= target_temp) {
GPIO_ResetBits(PUMP_PORT, PUMP_PIN);
} else {
GPIO_SetBits(PUMP_PORT, PUMP_PIN);
}
if (current_temp >= TEMP_THRESHOLD) {
GPIO_SetBits(LED_PORT, LED_PIN);
} else {
GPIO_ResetBits(LED_PORT, LED_PIN);
}
}
}
}
void init_adc() {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_InitTypeDef adc_init;
adc_init.ADC_Mode = ADC_Mode_Independent;
adc_init.ADC_ScanConvMode = DISABLE;
adc_init.ADC_ContinuousConvMode = ENABLE;
adc_init.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
adc_init.ADC_DataAlign = ADC_DataAlign_Right;
adc_init.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &adc_init);
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
}
int main() {
init_gpio();
init_adc();
init_timer();
printf("System initialized\n");
while (1) {
if (GPIO_ReadInputDataBit(TEMP_SET_PORT, TEMP_SET_PIN) == RESET) {
setting_temp_mode = 1;
printf("Entering temperature setting mode\n");
while (setting_temp_mode) {
if (GPIO_ReadInputDataBit(TEMP_SET_PORT, TEMP_SET_PIN) == RESET) {
setting_temp_mode = 0;
printf("Exiting temperature setting mode\n");
}
if (GPIO_ReadInputDataBit(TEMP_READ_PORT, TEMP_READ_PIN) == RESET) {
target_temp -= 1.0f;
printf("Target temperature set to %.1f C\n", target_temp);
while (GPIO_ReadInputDataBit(TEMP_READ_PORT, TEMP_READ_PIN) == RESET);
}
if (GPIO_ReadInputDataBit(TEMP_READ_PORT, TEMP_READ_PIN) == SET) {
target_temp += 1.0f;
printf("Target temperature set to %.1f C\n", target_temp);
while (GPIO_ReadInputDataBit(TEMP_READ_PORT, TEMP_READ_PIN) == SET);
}
Delay(100);
}
}
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == RESET) {
pump_on = !pump_on;
if (pump_on) {
printf("Turning on water pump\n");
GPIO_SetBits(PUMP_PORT, PUMP_PIN);
} else {
printf("Turning off water pump\n");
GPIO_ResetBits(PUMP_PORT, PUMP_PIN);
}
while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == RESET);
}
if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == RESET) {
led_on = !led_on;
if (led_on) {
printf("Turning on LED\n");
GPIO_SetBits(LED_PORT, LED_PIN);
} else {
printf("Turning off LED\n");
GPIO_ResetBits(LED_PORT, LED_PIN);
}
while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2) == RESET);
}
Delay(100);
}
}
```
解释:
- `init_gpio()` 初始化 GPIO 端口和引脚,设置 LED 灯、水泵、温度设定按键和温度读取引脚的模式和初始状态。
- `init_timer()` 初始化定时器 TIM3,在该定时器的中断处理函数中读取温度传感器的值并根据需要控制水泵和 LED 灯的状态。
- `init_adc()` 初始化 ADC1 并启用连续转换模式,以便在中断处理函数中读取温度传感器的值。
- 在 `main()` 函数中首先执行初始化函数,并进入一个无限循环体。
- 如果温度设定按键被按下,进入温度设定模式。在该模式下,判断按键状态以增加或减少设定温度的值,并在控制台输出新的设定值。按下温度设定按键以退出该模式。
- 如果水泵控制按键被按下,切换水泵的开关状态,并在控制台输出相应信息。按下水泵控制按键以切换水泵的开关状态。
- 如果 LED 控制按键被按下,切换 LED 灯的开关状态,并在控制台输出相应信息。按下 LED 控制按键以切换 LED 灯的开关状态。
- `Delay()` 函数用于简单的延时,可以使用 `SysTick` 定时器或其他方式实现。
需要注意的一些问题:
- 为了提高温度读取的精度,可以在中断处理函数中对 ADC 进行多次采样并取平均值。
- 为了避免温度读取的抖动,可以在中断处理函数中对新的温度值进行滤波,例如使用简单的移动平均或滑动窗口平均等算法。
- 为了避免按键的抖动,可以在按键处理中加入一定的软件去抖动,例如使用计数器或状态机等方式。
- 为了简化代码和提高可读性,可以使用宏定义或枚举类型等方式定义一些常量和状态标志。
阅读全文