主要硬件连接约定如下
-
STM32F103C8T6(72 MHz)
-
SU-03T 语音识别模块
-- VCC 3.3 V
-- GND
-- TX → MCU RX1 (PA10)
-- RX → MCU TX1 (PA9)
-
步进电机(28BYJ-48 + ULN2003 驱动板)
-- IN1: PB0
-- IN2: PB1
-- IN3: PB2
-- IN4: PB10
-
DHT11
-- DATA: PA1,上拉 10 kΩ
-
调试/状态 LED
-- PC13(板载 LED)
-
喂食按键 KEY1(手动触发)
-- PA0,下拉 10 kΩ
-
蜂鸣器 BEEP
-- PB11
cpp
/*------------------ main.c ------------------*/
#include "stm32f10x.h" // CMSIS
#include <string.h>
#include <stdio.h>
/*---------------- 设计加V:Niumajiuhao ----------------*/
/*---------------- 用户可调区 ----------------*/
#define SYSCLK 72000000UL
#define DHT_PIN GPIO_Pin_1
#define DHT_PORT GPIOA
#define STEP_PORT GPIOB
#define IN1_PIN GPIO_Pin_0
#define IN2_PIN GPIO_Pin_1
#define IN3_PIN GPIO_Pin_2
#define IN4_PIN GPIO_Pin_10
#define LED_PIN GPIO_Pin_13
#define LED_PORT GPIOC
#define KEY_PIN GPIO_Pin_0
#define KEY_PORT GPIOA
#define BEEP_PIN GPIO_Pin_11
#define BEEP_PORT GPIOB
/* SU-03T UART */
#define SU_UART USART1
/*----------------------------------------------*/
/*---------------- 设计加V:Niumajiuhao ----------------*/
/*-------------- 步进电机 8 拍序列 -------------*/
static const uint8_t phase[8] = {
0b0001, 0b0011, 0b0010, 0b0110,
0b0100, 0b1100, 0b1000, 0b1001
};
/*------------ 全局变量 & 原型 ---------------*/
volatile uint32_t tick = 0;
uint8_t DHT_data[5];
char uartRxBuf[32];
uint8_t uartRxIdx = 0;
void delay_ms(uint32_t ms);
void SysTick_Handler(void);
void GPIO_Config(void);
void TIM2_Config(void);
void USART1_Config(void);
void DHT11_Start(void);
uint8_t DHT11_ReadByte(void);
uint8_t DHT11_Get(void);
void Stepper_Run(uint16_t steps, uint8_t dir);
void feed(void);
void beep(uint16_t ms);
/*----------------------------------------------*/
/*---------------- 主函数 --------------------*/
int main(void)
{
SystemInit(); // 72 MHz
SysTick_Config(SYSCLK/1000);
GPIO_Config();
USART1_Config();
TIM2_Config();
printf("Pet Feeder STM32+SU-03T\r\n");
while(1)
{
/* 1. 语音指令监听(SU-03T 固定返回"FEED"字符串) */
if(strstr(uartRxBuf, "FEED") != NULL)
{
memset(uartRxBuf, 0, sizeof(uartRxBuf));
feed();
}
/* 2. 手动按键 */
if(GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_SET)
{
while(GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN) == Bit_SET);
feed();
}
/* 3. 每 5 s 采集一次温湿度并打印(可扩展为自动喂食) */
static uint32_t last = 0;
if(tick - last >= 5000)
{
last = tick;
if(DHT11_Get())
{
printf("T=%d H=%d\r\n", DHT_data[2], DHT_data[0]);
}
}
}
}
/*-------------- 功能实现 --------------------*/
void feed(void)
{
beep(100);
Stepper_Run(512, 1); // 512 步约一圈,可自行调整
beep(200);
GPIO_SetBits(LED_PORT, LED_PIN);
delay_ms(1000);
GPIO_ResetBits(LED_PORT, LED_PIN);
}
void Stepper_Run(uint16_t steps, uint8_t dir)
{
static uint8_t pos = 0;
for(uint16_t i=0; i<steps; i++)
{
if(dir) pos++; else pos--;
pos &= 0x07;
uint8_t out = phase[pos];
GPIO_WriteBit(STEP_PORT, IN1_PIN, (out & 0x01) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(STEP_PORT, IN2_PIN, (out & 0x02) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(STEP_PORT, IN3_PIN, (out & 0x04) ? Bit_SET : Bit_RESET);
GPIO_WriteBit(STEP_PORT, IN4_PIN, (out & 0x08) ? Bit_SET : Bit_RESET);
delay_ms(2); // 2 ms/步 ≈ 250 rpm
}
/* 关闭线圈 */
GPIO_ResetBits(STEP_PORT, IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN);
}
void DHT11_Start(void)
{
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin = DHT_PIN;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT_PORT, &gpio);
GPIO_ResetBits(DHT_PORT, DHT_PIN);
delay_ms(18);
GPIO_SetBits(DHT_PORT, DHT_PIN);
delay_us(30);
gpio.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT_PORT, &gpio);
}
uint8_t DHT11_ReadByte(void)
{
uint8_t i, dat = 0;
for(i=0;i<8;i++)
{
while(GPIO_ReadInputDataBit(DHT_PORT, DHT_PIN) == Bit_RESET);
delay_us(40);
if(GPIO_ReadInputDataBit(DHT_PORT, DHT_PIN) == Bit_SET)
dat |= (1<<(7-i));
while(GPIO_ReadInputDataBit(DHT_PORT, DHT_PIN) == Bit_SET);
}
return dat;
}
uint8_t DHT11_Get(void)
{
uint8_t sum;
DHT11_Start();
if(GPIO_ReadInputDataBit(DHT_PORT, DHT_PIN) == Bit_RESET)
{
while(GPIO_ReadInputDataBit(DHT_PORT, DHT_PIN) == Bit_RESET);
while(GPIO_ReadInputDataBit(DHT_PORT, DHT_PIN) == Bit_SET);
DHT_data[0] = DHT11_ReadByte();
DHT_data[1] = DHT11_ReadByte();
DHT_data[2] = DHT11_ReadByte();
DHT_data[3] = DHT11_ReadByte();
sum = DHT11_ReadByte();
if((DHT_data[0]+DHT_data[1]+DHT_data[2]+DHT_data[3]) == sum)
return 1;
}
return 0;
}
void beep(uint16_t ms)
{
GPIO_SetBits(BEEP_PORT, BEEP_PIN);
delay_ms(ms);
GPIO_ResetBits(BEEP_PORT, BEEP_PIN);
}
/*-------------- 外设初始化 ------------------*/
void GPIO_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitTypeDef gpio;
/* LED */
gpio.GPIO_Pin = LED_PIN;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT, &gpio);
/* KEY */
gpio.GPIO_Pin = KEY_PIN;
gpio.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(KEY_PORT, &gpio);
/* BEEP */
gpio.GPIO_Pin = BEEP_PIN;
gpio.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(BEEP_PORT, &gpio);
/* 步进电机 */
gpio.GPIO_Pin = IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN;
GPIO_Init(STEP_PORT, &gpio);
GPIO_ResetBits(STEP_PORT, IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN);
/* DHT11 默认为上拉输入 */
gpio.GPIO_Pin = DHT_PIN;
gpio.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT_PORT, &gpio);
}
void USART1_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);
gpio.GPIO_Pin = GPIO_Pin_10;
gpio.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &gpio);
USART_InitTypeDef usart;
usart.USART_BaudRate = 9600;
usart.USART_WordLength = USART_WordLength_8b;
usart.USART_StopBits = USART_StopBits_1;
usart.USART_Parity = USART_Parity_No;
usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(SU_UART, &usart);
USART_ITConfig(SU_UART, USART_IT_RXNE, ENABLE);
USART_Cmd(SU_UART, ENABLE);
NVIC_EnableIRQ(USART1_IRQn);
}
void TIM2_Config(void) // 1 kHz 用于蜂鸣器 PWM(可选)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef tim;
tim.TIM_Period = 71;
tim.TIM_Prescaler = 999;
tim.TIM_ClockDivision = 0;
tim.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &tim);
TIM_Cmd(TIM2, ENABLE);
}
/*-------------- 中断 ------------------------*/
void SysTick_Handler(void)
{
tick++;
}
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(SU_UART, USART_IT_RXNE) != RESET)
{
uint8_t ch = USART_ReceiveData(SU_UART);
if(ch == '\n' || uartRxIdx >= sizeof(uartRxBuf)-1)
{
uartRxBuf[uartRxIdx] = 0;
uartRxIdx = 0;
}
else
uartRxBuf[uartRxIdx++] = ch;
}
}
/*-------------- 延迟函数 --------------------*/
void delay_us(uint32_t us)
{
us *= 8;
while(us--);
}
void delay_ms(uint32_t ms)
{
uint32_t start = tick;
while(tick - start < ms);
}
/*-------------- printf 重定向 ---------------*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
USART_SendData(USART1, (uint8_t)ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return ch;
}
/*---------------- 设计加V:Niumajiuhao ----------------*/
基于 STM32 单片机的宠物喂养系统设计
一、引言
1.1 研究背景与意义
在现代社会,随着人们生活节奏的加快,越来越多的家庭选择饲养宠物来丰富生活。然而,由于工作繁忙、出差等原因,宠物的喂养问题常常困扰着宠物主人。传统的宠物喂养方式需要人工定时投放食物,一旦主人无法按时照顾,宠物可能会面临饥饿的困境,甚至影响其健康。
基于此,设计一款智能化的宠物喂养系统具有重要的现实意义。该系统能够实现自动定时定量喂食,还可通过语音指令进行控制,同时能够监测饲养环境的温湿度,为宠物提供适宜的生活环境。本研究采用 STM32 单片机作为主控制器,结合 SU-03T 语音模块、步进电机和 DHT11 温湿度传感器等器件,设计出一款性能稳定、操作便捷、成本适中的智能宠物喂养系统,旨在解决宠物主人的喂养难题,保障宠物的健康成长,具有较好的市场应用前景。
1.2 国内外研究现状
国内外在智能宠物喂养领域已有一定的研究成果。国外的一些智能宠物喂养产品功能较为完善,例如能够通过手机 APP 远程控制喂食时间和食量,部分产品还具备视频监控功能,但这些产品价格较高,且在语音交互和本地化控制方面存在一定的局限性。
国内的研究则更注重性价比和实用性。许多研究以单片机为核心,实现了基本的自动喂食功能,但在语音控制的准确性、温湿度监测的集成以及喂食量的精确控制等方面还有提升空间。近年来,随着语音识别技术和传感器技术的发展,为智能宠物喂养系统的升级提供了可能。与现有研究相比,本设计引入 SU-03T 语音模块,提高了语音控制的响应速度和识别准确率;采用步进电机控制喂食量,实现了定量喂食的精确性;集成 DHT11 温湿度传感器,能够实时监测宠物生活环境,使系统功能更加完善。
1.3 研究目标与内容
本研究的目标是设计并实现一款基于 STM32 单片机的智能宠物喂养系统,该系统能够通过语音指令和定时设置实现自动喂食,精确控制喂食量,实时监测饲养环境的温湿度,并在温湿度异常时发出提醒。
研究内容主要包括以下几个方面:
- 系统总体设计:确定系统的功能需求,设计系统的整体架构和技术方案。
- 硬件设计:包括 STM32 最小系统设计、SU-03T 语音模块接口电路设计、步进电机驱动电路设计、DHT11 温湿度传感器接口电路设计以及电源电路设计等。
- 软件设计:搭建软件开发环境,设计主程序流程,实现语音识别与指令解析程序、步进电机控制程序、DHT11 温湿度采集与处理程序以及定时喂食程序等。
- 系统测试与优化:对系统的各项功能进行测试,根据测试结果进行优化,确保系统稳定可靠运行。
二、系统总体设计方案
2.1 需求分析
用户对智能宠物喂养系统的功能需求主要包括以下几个方面:
-
语音控制功能:能够通过语音指令(如 "喂食""停止喂食""增加食量""减少食量" 等)控制喂食动作,语音识别应准确可靠,不受环境噪声的过多干扰。
-
定时定量喂食功能:可以预先设置喂食时间和每次的喂食量,到设定时间后系统能够自动按照设定食量进行喂食。
-
温湿度监测功能:实时监测宠物饲养环境的温度和湿度,并能在温湿度超出适宜范围时发出提示信息。
-
手动控制功能:在语音控制和定时控制出现故障时,可通过手动按钮进行喂食操作,保证系统的可靠性。
-
状态显示功能:能够显示当前的喂食状态、设定的喂食时间和食量以及温湿度数据等。
-
基于以上需求,确定系统设计方向为:以 STM32 单片机为核心,通过 SU-03T 语音模块实现语音指令的接收与识别,利用步进电机控制喂食机构的动作以实现定量喂食,通过 DHT11 温湿度传感器采集环境温湿度数据,同时设计定时模块和手动控制模块,配合显示模块完成系统的各项功能。
2.2 系统架构设计
系统整体架构主要由 STM32 单片机、SU-03T 语音模块、步进电机及驱动模块、DHT11 温湿度传感器、按键模块、显示模块和电源模块等组成。
STM32 单片机作为主控制器,负责协调各个模块的工作。它通过串口与 SU-03T 语音模块进行通信,接收语音指令;通过 GPIO 接口连接步进电机驱动器,控制步进电机的转动,从而实现喂食量的控制;通过单总线与 DHT11 温湿度传感器连接,采集环境温湿度数据;通过 GPIO 接口连接按键模块,接收手动控制指令;通过 I2C 或 SPI 接口连接显示模块,显示系统的各项状态信息。
SU-03T 语音模块负责采集用户的语音指令,并进行识别和解析,将解析后的指令通过串口发送给 STM32 单片机。
步进电机及驱动模块在 STM32 单片机的控制下,带动喂食机构的螺旋推进器或闸门等部件运动,实现食物的定量投放。
DHT11 温湿度传感器用于实时采集宠物饲养环境的温度和湿度数据,并将数据传输给 STM32 单片机进行处理。
按键模块包括设置键、增加键、减少键和手动喂食键等,用于手动设置喂食时间、食量以及进行手动喂食操作。
显示模块采用 LCD1602 或 OLED 显示屏,用于显示当前的时间、设定的喂食时间、喂食量、环境温湿度以及系统的工作状态等信息。
电源模块为系统中的各个组件提供稳定的工作电压,确保系统的正常运行。
2.3 技术路线选择
-
单片机选型:选择 STM32 单片机作为主控制器,原因在于其具有强大的处理能力,能够快速处理多模块的数据和指令;丰富的外设接口,便于与语音模块、电机驱动器、传感器、显示模块等进行连接;同时,STM32 系列单片机具有较低的功耗和较高的性价比,适合在嵌入式系统中应用。与 51 单片机相比,STM32 的性能更优,能够满足系统复杂控制的需求;与其他高端处理器相比,STM32 成本更低,更适合本系统的设计预算。
-
语音模块选型:选用 SU-03T 语音模块,该模块具有识别准确率高、响应速度快、支持自定义唤醒词和指令集等优点,能够满足本系统对语音控制的需求。与其他语音模块相比,如 LD3320,SU-03T 的集成度更高,使用更加简便,无需复杂的外围电路设计,降低了系统的硬件复杂度。
-
电机选型:选择步进电机作为执行机构,因为步进电机具有控制精度高、运行稳定的特点,能够精确控制转动角度,从而实现喂食量的精确控制。与直流电机相比,步进电机不需要位置传感器即可实现精确定位,简化了系统设计;与伺服电机相比,步进电机成本较低,适合本系统的成本要求。
-
温湿度传感器选型:选用 DHT11 温湿度传感器,该传感器具有体积小、功耗低、精度能够满足室内环境监测需求等优点,且采用单总线通信方式,接口简单,便于与 STM32 单片机连接。与 SHT30 等传感器相比,DHT11 成本更低,虽然精度稍低,但足以满足宠物饲养环境的温湿度监测需求。
三、系统硬件设计
3.1 STM32 最小系统设计
本系统选用 STM32F103 系列单片机作为主控制器。STM32 最小系统主要由电源电路、时钟电路、复位电路和下载接口电路等组成。
电源电路:STM32 单片机需要 3.3V 的工作电压,系统采用外部 5V 直流电源供电,通过低压差线性稳压器(如 AMS1117-3.3)将 5V 电压转换为 3.3V,为单片机及其他需要 3.3V 电压的模块(如 SU-03T 语音模块、DHT11 温湿度传感器等)供电。电源电路中加入了电解电容和陶瓷电容进行滤波,以减小电源噪声对系统的影响。
时钟电路:STM32 单片机采用外部 8MHz 的晶体振荡器作为时钟源,通过锁相环(PLL)倍频后产生 72MHz 的系统时钟,保证系统各模块的高速运行。时钟电路中还配置了合适的负载电容,确保振荡器能够稳定起振。
复位电路:采用上电复位和手动复位相结合的方式。上电复位通过 RC 电路实现,当系统上电时,电容充电,产生复位信号;手动复位通过复位按钮实现,按下按钮时,单片机复位引脚接地,产生复位信号,确保系统在异常情况下能够重新启动。
下载接口电路:采用 SWD 接口,通过下载器将程序下载到 STM32 单片机中,便于系统的调试和程序更新。
3.2 SU-03T 语音模块电路设计
SU-03T 语音模块工作电压为 3.3V,通过串口与 STM32 单片机进行通信,实现语音指令的传输。
该模块的接口电路主要包括电源接口、串口接口和麦克风接口。电源接口直接连接到系统的 3.3V 电源,为模块提供工作电压;串口接口的 TX 引脚连接到 STM32 单片机的 USART_RX 引脚,RX 引脚连接到 STM32 单片机的 USART_TX 引脚,实现模块与单片机之间的双向通信;麦克风接口连接外部驻极体麦克风,用于采集用户的语音指令。
为保证串口通信的稳定性,在模块的 TX 和 RX 引脚上分别串联一个 100Ω 左右的限流电阻,减少信号传输过程中的干扰。同时,在模块的电源引脚附近并联一个 10μF 的电解电容和一个 0.1μF 的陶瓷电容,进一步滤除电源噪声,提高模块工作的稳定性。
SU-03T 语音模块的工作原理是:麦克风采集到用户的语音信号后,经过模块内部的语音识别算法处理,将识别到的指令转换为相应的数字信号,通过串口发送给 STM32 单片机,单片机接收到指令后进行解析并执行相应的操作。
3.3 步进电机驱动电路设计
本系统选用四相八拍步进电机,步距角为 1.8 度,通过控制电机的转动角度来控制喂食量。驱动芯片选用 ULN2003,该芯片是一款高电压、大电流的达林顿晶体管阵列,能够为步进电机提供足够的驱动电流,适合驱动四相步进电机。
步进电机驱动电路的设计如下:STM32 单片机的四个 GPIO 引脚分别连接到 ULN2003 的四个输入引脚(IN1-IN4),ULN2003 的四个输出引脚(OUT1-OUT4)分别连接到步进电机的四个相绕组(A、B、C、D)。通过单片机输出不同时序的脉冲信号,控制 ULN2003 内部晶体管的导通与截止,从而改变步进电机各相绕组的通电顺序,实现电机的正转、反转和停止。
为保护驱动芯片和步进电机,在电机的各相绕组两端分别并联续流二极管(如 1N4001),以吸收电机绕组断电时产生的反向电动势,防止高电压损坏芯片。同时,在 ULN2003 的电源引脚(VCC)与地之间并联滤波电容,减少电源波动对驱动电路的影响。
步进电机的转速通过改变脉冲信号的频率来调节,脉冲频率越高,电机转速越快;反之则越慢。在喂食过程中,可根据需要设置合适的转速,以保证食物投放的均匀性。
3.4 DHT11 温湿度传感器接口电路设计
DHT11 温湿度传感器采用单总线通信方式,工作电压为 3.3V-5V,本系统中采用 3.3V 供电,与 STM32 单片机的电压兼容。
传感器的接口电路较为简单,其 DATA 引脚通过一个 4.7kΩ 的上拉电阻连接到 STM32 单片机的一个 GPIO 引脚,同时连接到 3.3V 电源。上拉电阻的作用是保证 DATA 引脚在空闲状态时为高电平,确保通信的稳定性。
DHT11 温湿度传感器的工作原理是:当 STM32 单片机发送起始信号后,传感器会响应并发送 40 位的数据,其中包括 8 位湿度整数数据、8 位湿度小数数据、8 位温度整数数据、8 位温度小数数据和 8 位校验位。单片机接收到数据后,通过校验位验证数据的正确性,然后对温度和湿度数据进行解析和处理。
3.5 其他辅助电路设计
- 按键电路:设计了多个独立按键,包括设置键、增加键、减少键和手动喂食键等。每个按键的一端连接到 STM32 单片机的 GPIO 引脚,另一端接地,同时单片机的 GPIO 引脚通过内部上拉电阻或外部上拉电阻保持高电平。当按键按下时,GPIO 引脚变为低电平,单片机通过检测电平变化识别按键操作。
- 显示电路:采用 OLED12864 显示屏,通过 I2C 接口与 STM32 单片机连接。显示屏用于显示当前时间、设定的喂食时间、喂食量、环境温湿度等信息。I2C 接口电路简单,只需要两根线(SDA 和 SCL)即可实现通信,节省了单片机的 IO 资源。
- 报警电路:当环境温湿度超出设定的适宜范围时,系统通过蜂鸣器发出报警提示。蜂鸣器的驱动电路采用三极管放大电路,STM32 单片机的 GPIO 引脚通过控制三极管的导通与截止,实现蜂鸣器的发声与关闭。
四、系统软件设计
4.1 软件开发环境搭建
本系统的软件开发环境采用 Keil MDK 5,它是一款针对 ARM 微控制器的集成开发环境,支持 STM32 系列单片机的程序开发。
搭建开发环境的步骤如下:
- 安装 Keil MDK 5 软件:从官方网站下载 Keil MDK 5 安装包,按照安装向导进行安装,在安装过程中需要输入许可证信息。
- 安装 STM32 芯片支持包:打开 Keil MDK 5 软件,进入 Pack Installer 界面,搜索并下载安装 STM32F103 系列芯片的支持包,以确保软件能够正确识别和配置所使用的单片机。
- 配置编译器:在工程设置中,选择 ARMCC 编译器作为默认编译器,该编译器能够生成高效的机器代码。
- 配置调试器:根据所使用的调试工具(如 ST-Link V2),在工程设置的 Debug 选项中选择相应的调试器,并配置调试接口和通信速率等参数,以便能够正常进行程序的下载和在线调试。
4.2 主程序流程设计
主程序是系统的核心,负责统筹协调各个模块的工作,其工作流程如下:
系统上电后,首先进行初始化操作,包括 STM32 单片机的初始化(时钟、GPIO、USART、I2C、定时器等)、SU-03T 语音模块的初始化、步进电机驱动模块的初始化、DHT11 温湿度传感器的初始化、按键模块的初始化、显示模块的初始化以及系统参数的初始化(如默认喂食时间、喂食量、温湿度阈值等)。
初始化完成后,系统进入主循环。在主循环中,系统不断检测各模块的状态:
-
检测 SU-03T 语音模块是否接收到语音指令,若接收到指令,则对指令进行解析并执行相应的操作(如喂食、调整食量等)。
-
检测定时器是否到达设定的喂食时间,若到达,则控制步进电机按照设定的喂食量进行喂食。
-
周期性地通过 DHT11 温湿度传感器采集环境温湿度数据,并在显示模块上显示,若温湿度超出设定阈值,则控制蜂鸣器报警。
-
检测按键是否被按下,若有按键操作,则根据按键功能进行相应的处理(如修改喂食时间、手动喂食等)。
-
实时更新显示模块的信息,包括当前时间、喂食状态、温湿度数据等。
-
在执行各项操作的过程中,系统还会进行错误检测和处理,如传感器通信错误、电机驱动故障等,确保系统的稳定运行。
4.3 语音识别程序设计
SU-03T 语音模块的配置和控制通过串口通信实现。首先需要使用官方提供的配置工具对模块进行参数设置,包括设置唤醒词(如 "小喂")、指令集(如 "喂食" 对应指令 0x01、"停止喂食" 对应指令 0x02、"增加食量" 对应指令 0x03、"减少食量" 对应指令 0x04 等),并将模块的波特率设置为 9600,与 STM32 单片机的 USART 接口波特率保持一致,同时启用串口输出模式,使模块在识别到有效指令后自动发送相应的指令代码。
在 STM32 单片机的程序中,语音识别程序通过 USART 中断服务函数接收 SU-03T 语音模块发送的指令数据。当模块识别到用户的语音指令后,会将对应的指令代码通过串口发送给单片机,单片机接收到数据后,将其存储在接收缓冲区中,并设置指令接收标志位。
主程序检测到指令接收标志位后,对接收缓冲区中的指令代码进行解析。例如,当接收到指令 0x01 时,判断为 "喂食" 指令,主程序控制步进电机按照当前设定的喂食量进行喂食操作;当接收到指令 0x02 时,判断为 "停止喂食" 指令,主程序控制步进电机停止转动;当接收到指令 0x03 时,判断为 "增加食量" 指令,主程序适当增加设定的喂食量,并在显示模块上更新;当接收到指令 0x04 时,判断为 "减少食量" 指令,主程序适当减少设定的喂食量,并更新显示。