
📢 📢 📢 号外号外,单片机项目实战课程又更新了!!!(╯‵□′)╯炸弹! ✨ ✨ ✨
💓 大家好,我是 朽木自雕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