基于STM32的语音控制电机

该项目利用STM32F103C8T6单片机和ASRPRO语音模块,通过语音指令控制RGB灯和五线四相步进电机。ASR模块通过天问Block开发,串口2通信,步进电机通过ULN2003驱动。代码包括主程序、初始化、系统运行、LED及电机控制等部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

📢 📢 📢 号外号外,单片机项目实战课程又更新了!!!(╯‵□′)╯炸弹! ✨ ✨ ✨
💓 大家好,我是 朽木自雕i, 一个闲暇时间用来敲敲代码,画画板子,焊焊电路,玩玩单片机,搞搞Linux,写写Blog记录成长的技术人er。 👀很高兴再次见到大家,希望大家可以继续支持我 🙏,喜欢我哦~ ❤
🏆 🏆 🏆 CSDN C/C++领域优质创作者,Blog访问人次超270万+。(╯▽╰ )好香~~
💕 当才华撑不起你梦想时,请努力!而你只管努力,剩下交给天意。
🎁 🎁 🎁 文末点赞收藏+评论,有神秘礼品相送哦~

项目功能介绍

本项目基于STM32F103C8T6单片机,语音的识别采用ASRPRO语言识别模块来处理,通过语音可以控制小灯的亮灭,以及电机的启停、正反转、运行模式、运行速度、转动角度等。

语音识别模块由上位机直接进行开发,开发环境是天问Block,可点击蓝色字体直接进行下载。

所需元件:

🍎STM32F103C8T6最小系统:

🍎ASRPRO语音模块

🍎ULN2003驱动板模块

🍎五线四相步进电机

🍎RGB灯

端口定义:

因为单片机和语音模块之间的通信由串口来完成,所以我们要选择一路串口,STM32的串口选择串口串口2,波特率为9600,引脚对应关系如下:

PA2 ------> USART2_TX

PA3 ------> USART2_RX

ASRPRO语言识别模块使用串口1,设置波特率为9600,引脚对应关系如下:

PA2 ------> USART1_TX

PA3 ------> USART1_RX

注意:串口通讯时,发送端的发送引脚要接接收端的接收引脚,发送端的接收引脚要接接收端的发送引脚。

天问Block语音识别模块设置

本项目使用STM32F103C8T6作为主控芯片,MDK keil5作为编译环境,基础配置使用STM32CubeMx生成。

程序代码:

主程序代码:

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_USART2_UART_Init();
  MX_TIM7_Init();
  /* USER CODE BEGIN 2 */
    MyInit.Peripheral_Set(); //硬件初始化
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        System.Run();    //系统运行代码
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

初始化代码:

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/

uint8_t str_buf[64];
uint8_t Rx_dat[16];

/* Private variables----------------------------------------------------------*/
static void Peripheral_Set(void); 

/* Public variables-----------------------------------------------------------*/
MyInit_t MyInit = 
{
    Peripheral_Set
};

/* Private function prototypes------------------------------------------------*/      

/*
    * @name   Peripheral_Set
    * @brief  外设设置
    * @param  None
    * @retval None      
*/
static void Peripheral_Set()
{
    HAL_UART_Receive_IT(&huart2,Rx_dat,3);  //打开串口中断
    HAL_TIM_Base_Start_IT(&htim7);          //启动定时器7

    
    Unipolar_Step_Motor.Speed = Speed_5;
    Unipolar_Step_Motor.Pulse_Cnt  = 0;
    Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)4096;
    Unipolar_Step_Motor.Drive_Mode = Drive_Mode_8_Beats;
    Unipolar_Step_Motor.Direction = Reverse_State;
    
    Unipolar_Step_Motor.Status = Stop_State;
    Unipolar_Step_Motor.Circle = 1;
}

/********************************************************
  End Of File
********************************************************/

系统运行代码:

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/
static void Run(void); 
static void Error_Handler(void);
static void Assert_Failed(void);
    

/* Public variables-----------------------------------------------------------*/
System_t System = 
{
    Run,
    Error_Handler,
    Assert_Failed
};

/* Private function prototypes------------------------------------------------*/      


/*
    * @name   Run
    * @brief  系统运行
    * @param  None
    * @retval None      
*/
static void Run()
{

}

/*
    * @name   Error_Handler
    * @brief  系统错误处理
    * @param  None
    * @retval None      
*/
static void Error_Handler()
{
    /* User can add his own implementation to report the HAL error return state */
}

/*
    * @name   Assert_Failed
    * @brief  函数参数错误处理
    * @param  None
    * @retval None      
*/
static void Assert_Failed()
{
    /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
}
/********************************************************
  End Of File
********************************************************/

LED灯代码:

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/
static void LED_ON(uint8_t);     //打开
static void LED_OFF(uint8_t);    //关闭
static void LED_Flip(uint8_t);   //翻转

/* Public variables-----------------------------------------------------------*/
LED_t LED = 
{
    LED_ON,
    LED_OFF,
    LED_Flip
};

/* Private function prototypes------------------------------------------------*/      

/*
    * @name   LED_ON
    * @brief  打开LED
    * @param  Num -> 编号
    * @retval None      
*/
static void LED_ON(uint8_t LED_Num)
{
    //条件选择语句
    switch(LED_Num)
    {
        case LED1: HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);break;
        case LED2: HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);break;
        case LED3: HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);break;
        default: System.Assert_Failed();
    }
}

/*
    * @name   LED_OFF
    * @brief  关闭LED
    * @param  Num -> 编号
    * @retval None      
*/
static void LED_OFF(uint8_t LED_Num)
{
    //条件选择语句
    switch(LED_Num)
    {
        case LED1: HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);break;
        case LED2: HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);break;
        case LED3: HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);break;
        default: System.Assert_Failed();
    }
}

/*
    * @name   LED_Flip
    * @brief  取反LED
    * @param  Num -> 编号
    * @retval None      
*/
static void LED_Flip(uint8_t LED_Num)
{
    //条件选择语句
    switch(LED_Num)
    {
        case LED1: HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); break;
        case LED2: HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin); break;
        case LED3: HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin); break;
        default: System.Assert_Failed();
    }
}
/********************************************************
  End Of File
********************************************************/

步进电机控制代码:

/* Includes ------------------------------------------------------------------*/
#include "MyApplication.h"

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/

/* Private function prototypes------------------------------------------------*/      
static void Direction_Adjust(void);        //步进电机方向调整
static void Speed_Adjust(Speed_Change_t);  //步进电机速度调整
static void Step_One_Pulse(void);          //步进电机步进一个脉冲

/* Public variables-----------------------------------------------------------*/

//定义结构体类变量
Unipolar_Step_Motor_t Unipolar_Step_Motor = 
{
  Stop_State,
    Forward_State, 
    Speed_6,
    1,
    Drive_Mode_8_Beats,
    0,
    (uint16_t)4096,
    
    Direction_Adjust,
    Speed_Adjust,
    Step_One_Pulse
};

/*
    * @name   Direction_Adjust
    * @brief  直流电机方向调整
    * @param  None
    * @retval None      
*/
static void Direction_Adjust(void)
{
    if(Unipolar_Step_Motor.Status == Start_State)
    {
        //调整电机运行方向
        if(Unipolar_Step_Motor.Direction == Reverse_State)
        {
            Unipolar_Step_Motor.Direction = Forward_State;
        }
        else
        {
            Unipolar_Step_Motor.Direction = Reverse_State;
        }
        
        Unipolar_Step_Motor.Circle = Circle_Set_Value;
        Unipolar_Step_Motor.Pulse_Cnt = 0;
    }
}

/*
    * @name   Speed_Adjust
    * @brief  直流电机速度调整
    * @param  Speed_Change -> 速度变化
    * @retval None      
*/
static void Speed_Adjust(Speed_Change_t Speed_Change)
{

    if(Unipolar_Step_Motor.Status == Start_State)
    {
        if(Speed_Change == Speed_up)
        {
            //增大电机速度
            switch(Unipolar_Step_Motor.Speed)
            {
                case Speed_1: Unipolar_Step_Motor.Speed = Speed_2; break;
                case Speed_2: Unipolar_Step_Motor.Speed = Speed_3; break;
                case Speed_3: Unipolar_Step_Motor.Speed = Speed_4; break;
                case Speed_4: Unipolar_Step_Motor.Speed = Speed_5; break;
                case Speed_5: Unipolar_Step_Motor.Speed = Speed_6; break;
                case Speed_6: Unipolar_Step_Motor.Speed = Speed_7; break;
                case Speed_7: Unipolar_Step_Motor.Speed = Speed_8; break;
                case Speed_8: Unipolar_Step_Motor.Speed = Speed_9; break;
                case Speed_9: Unipolar_Step_Motor.Speed = Speed_9;  break;
                default:Unipolar_Step_Motor.Speed = Speed_6; 
            }
        }
        else
        {
            //减小电机速度
            switch(Unipolar_Step_Motor.Speed)
            {
                case Speed_1: Unipolar_Step_Motor.Speed = Speed_1; break;
                case Speed_2: Unipolar_Step_Motor.Speed = Speed_1; break;
                case Speed_3: Unipolar_Step_Motor.Speed = Speed_2; break;
                case Speed_4: Unipolar_Step_Motor.Speed = Speed_3; break;
                case Speed_5: Unipolar_Step_Motor.Speed = Speed_4; break;
                case Speed_6: Unipolar_Step_Motor.Speed = Speed_5; break;
                case Speed_7: Unipolar_Step_Motor.Speed = Speed_6; break;
                case Speed_8: Unipolar_Step_Motor.Speed = Speed_7; break;
                case Speed_9: Unipolar_Step_Motor.Speed = Speed_8; break;
                default:Unipolar_Step_Motor.Speed = Speed_6;
            }
        }
        
        //更新定时器7的计时重装载寄存器
        TIM7 ->ARR = Unipolar_Step_Motor.Speed;
    
    }
}

/*
    * @name   Step_One_Pulse
    * @brief  步进电机步进一个脉冲
    * @param  Speed_Change -> 速度变化
    * @retval None      
*/
static void Step_One_Pulse(void)
{
    static uint8_t Position = 0;
    
    //单四拍
    if(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Single_4_Beats)
    {
        if(Unipolar_Step_Motor.Direction == Forward_State)
        {
            //正向步进  A - D - C - B
            switch(Position)
            {
                case 0: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 1: CLR_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                case 2: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 3: CLR_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                default: System.Error_Handler();
            }
        }
        else
        {
            //反向步进  A - B - C - D
            switch(Position)
            {
                case 0: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 1: CLR_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 2: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 3: CLR_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                default: System.Error_Handler();
            }
        }
        
        //更新位置信息
        if((++Position) == 4)
                Position = 0;
    }
    
    //双四拍
    if(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Double_4_Beats)
    {
        if(Unipolar_Step_Motor.Direction == Forward_State)
        {
            //正向步进  DA - CD - BC - AB
            switch(Position)
            {
                case 0: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                case 1: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; SET_Motor_D; break;
                case 2: CLR_Motor_A; SET_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 3: SET_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                default: System.Error_Handler();
            }
        }
        else
        {
            //反向步进  DA - AB - BC - CD
            switch(Position)
            {
                case 0: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                case 1: SET_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 2: CLR_Motor_A; SET_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 3: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; SET_Motor_D; break;
                default: System.Error_Handler();
            }
        }
        
        //更新位置信息
        if((++Position) == 4)
                Position = 0;
    }
    
    //单八拍
    if(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_8_Beats)
    {
        if(Unipolar_Step_Motor.Direction == Forward_State)
        {
            //正向步进 A - DA - D - CD - C - BC - B - AB
            switch(Position)
            {
                case 0: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 1: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                case 2: CLR_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                case 3: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; SET_Motor_D; break;
                case 4: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 5: CLR_Motor_A; SET_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 6: CLR_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 7: SET_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                default:System.Error_Handler();
            }
        }
        else
        {
            //反向步进 A - AB - B - BC - C -CD - D - DA 
            switch(Position)
            {
                case 0: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 1: SET_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break; 
                case 2: CLR_Motor_A; SET_Motor_B; CLR_Motor_C; CLR_Motor_D; break;
                case 3: CLR_Motor_A; SET_Motor_B; SET_Motor_C; CLR_Motor_D; break;
                case 4: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; CLR_Motor_D; break; 
                case 5: CLR_Motor_A; CLR_Motor_B; SET_Motor_C; SET_Motor_D; break;
                case 6: CLR_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                case 7: SET_Motor_A; CLR_Motor_B; CLR_Motor_C; SET_Motor_D; break;
                default: System.Error_Handler();
            }
        }
        
        //更新位置信息
        if((++Position) == 8)
                Position = 0;
    }
}
/********************************************************
  End Of File
********************************************************/

定时器回调函数:

/*
    * @name   HAL_TIM_PeriodElapsedCallback
    * @brief  定时器中断回调函数
    * @param  *htim -> 处理定时器的结构体指针
    * @retval None      
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    //控制步进电机
    if(htim->Instance == htim7.Instance)
    {
        //没转完指定的圈数
        if((Unipolar_Step_Motor.Circle > 0)&&(Unipolar_Step_Motor.Status == Start_State))
        {
            //电机转动一个脉冲
            Unipolar_Step_Motor.Step_One_Pulse();
            
            //根据脉冲计数判断是否转动了一圈
            if(++Unipolar_Step_Motor.Pulse_Cnt == Unipolar_Step_Motor.One_Circle_Pulse)
            {
                Unipolar_Step_Motor.Pulse_Cnt = 0;
                //转动圈数减一
                Unipolar_Step_Motor.Circle--;
            }
        }
        //已转完指定的圈数
        else
        {
            Unipolar_Step_Motor.Status = Stop_State;
            CLR_Motor_A;
            CLR_Motor_B;
            CLR_Motor_C;
            CLR_Motor_D;
        }    
    }
}

串口接收中断回调函数:

/*
    * @name   HAL_UART_RxCpltCallback
    * @brief  串口中断接收中断回调函数
    * @param  huart -> 处理串口的结构体指针
    * @retval None      
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART2)
    {
        if(Rx_dat[0] == 0xBF && Rx_dat[2] == 0xFB)
        {
            switch(Rx_dat[1])
            {
                case 0xa1:LED.LED_ON(LED3); break;  //打开红灯  R
                case 0xa2:LED.LED_OFF(LED3);break;  //关闭红灯
                case 0xa3:LED.LED_ON(LED1); break;  //打开绿灯  G
                case 0xa4:LED.LED_OFF(LED1);break;  //关闭绿灯
                case 0xa5:LED.LED_ON(LED2); break;  //打开蓝灯  B
                case 0xa6:LED.LED_OFF(LED2);break;  //关闭蓝灯
            
                case 0xb1: Unipolar_Step_Motor.Direction = Reverse_State;break;   //电机正转
                case 0xb2: Unipolar_Step_Motor.Direction = Forward_State;break;   //电机反转        
                    
                case 0x04: Unipolar_Step_Motor.Speed = Speed_1;TIM7 ->ARR = Unipolar_Step_Motor.Speed; break;   //低速模式
                case 0x05: Unipolar_Step_Motor.Speed = Speed_5;TIM7 ->ARR = Unipolar_Step_Motor.Speed; break;   //中速模式
                case 0x06: Unipolar_Step_Motor.Speed = Speed_9;TIM7 ->ARR = Unipolar_Step_Motor.Speed; break;   //高速模式
                
                case 0xb5:Unipolar_Step_Motor.Drive_Mode = Drive_Mode_Single_4_Beats; break; //单四拍模式
                case 0xb6:Unipolar_Step_Motor.Drive_Mode = Drive_Mode_Double_4_Beats; break; //双四拍模式
                case 0xb7:Unipolar_Step_Motor.Drive_Mode = Drive_Mode_8_Beats;        break; //单八拍模式
                
                case 0xb8: Unipolar_Step_Motor.Status = Start_State;  break;   //打开电机
                case 0xb9: Unipolar_Step_Motor.Status = Stop_State;   break;   //关闭电机
                
                case 0x00:   //电机转动15度
                    if((Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Single_4_Beats)||(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Double_4_Beats))
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)86;
                    else 
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)171;
                    
                    Unipolar_Step_Motor.Circle = 1;
                    Unipolar_Step_Motor.Status = Start_State;
                break;
                
                case 0x01:   //电机转动30度
                    if((Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Single_4_Beats)||(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Double_4_Beats))
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)171;
                    else 
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)341;
                    
                    Unipolar_Step_Motor.Circle = 1;
                    Unipolar_Step_Motor.Status = Start_State;
                
                break;
                
                case 0x02:   //电机转动45度
                    if((Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Single_4_Beats)||(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Double_4_Beats))
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)256;
                    else 
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)512;
                    
                    Unipolar_Step_Motor.Circle = 1;
                    Unipolar_Step_Motor.Status = Start_State;
                break;
                
                case 0x03:   //电机转动90度
                    if((Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Single_4_Beats)||(Unipolar_Step_Motor.Drive_Mode == Drive_Mode_Double_4_Beats))
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)512;
                    else 
                        Unipolar_Step_Motor.One_Circle_Pulse = (uint16_t)1024;
                    
                    Unipolar_Step_Motor.Circle = 1;
                    Unipolar_Step_Motor.Status = Start_State;
                break;
                default:

                    break;
            }
            HAL_UART_Transmit(&huart2,str_buf,sizeof(str_buf),10000);
            HAL_UART_Receive_IT(&huart2,Rx_dat,3);
        }
    }
}

重写接收字符函数:

int fgetc(FILE *f)
{
    uint8_t ch;
    HAL_UART_Receive(&huart2,&ch,1,0xffff);
    return ch;
}    

完整项目链接:

链接:https://pan.baidu.com/s/1tDo5k4rsIQQMUwlYxGYBbQ

提取码:61qc

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

朽木自雕i

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值