0 前言
🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 STM32录音笔设计与实现
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:5分
🧿 项目分享:见文末!
设计功能:
- ✨本系统STM32、IDS1820模块、按键组成
- ✨按键可以进行录音、播放、播放设置
- ✨按下1按键进行录音并且状态指示灯常亮
- ✨录音完成后,可按下2进行语音播放
- ✨录音完成后,可按下3进行循环播放
1 设计方案
STM32单片机录音笔语音录放存储回放系统
本系统由STM32F103C8T6单片机核心板、IDS1820模块、按键组成。
- 1、按键可以设置该设备进行录音、播放、播放设置。
- 2、按下录音按键不送进行录音,录音过程中状态指示灯常亮。
- 3、录音完成后,可以通过播放按键在按键模式下触发播放。
- 4、播放设置按键可以进行自动播放选择和按键触发播放选择,上电默认按键触发;自动模式下,循环播报录制的声音。
2 实现效果
毕业设计 STM32录音笔设计与实现
3 硬件设计
4 软件设计
部分关键代码
//main前面
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#define KEY0 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)
#define KEY1 HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)
#define val_count_max 5000 //最大采样个数
uint16_t val_count=0; //实际采样个数
uint16_t val_data[val_count_max]={0};
uint16_t val_data_buff[val_count_max]={0};
#define DAC_Count 4096
uint8_t DAC_Data[5000]={0};
uint16_t DAC_F=2;
volatile uint16_t Time_Count=0;
char* ch_tab="12345";
char read_buff[100]={0};
FATFS fs; //文件系统工作区指针
FIL fp; //文件对象结构指针
FRESULT f_res; //函数放回结果
uint16_t fnum; /* 文件成功读写数量 */
uint16_t fp_num; //文件大小
UINT fp_rw_num; //实际文件读写字节数
uint8_t fp_wriet_flag=0; //SD卡写标志
uint8_t sound_record_flag=0; //录音标志
uint8_t fp_read_flag=0; //SD卡读标志
uint8_t play_record_flag=0; //播音标志
uint8_t key0_down_flag=0; //按键按下一次标志,
uint8_t key1_down_flag=0; //按键按下一次标志,
uint16_t fp_memory=0;
char Read_Data[DAC_Count]={0};
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
void KEY_Scanf()
{
if(KEY0 == 0) //录音开始和停止
{
HAL_Delay(10);
if(KEY0==0)
{
while(!KEY0);
key0_down_flag=0;
sound_record_flag = !sound_record_flag; //0:停止 1:开始
}
}
if(KEY1 == 0)
{
HAL_Delay(10);
if(KEY1==0)
{
while(!KEY1);
key1_down_flag=0;
play_record_flag = !play_record_flag;
}
}
}
void KEY_Handle(void)
{
if((sound_record_flag != 0) && (key0_down_flag==0)) //开始录音
{
key0_down_flag=1;
val_count=0;
HAL_TIM_Base_Start_IT(&htim3);
HAL_ADC_Start(&hadc1);
}
else if((sound_record_flag == 0) && (key0_down_flag==0)) //停止录音
{
key0_down_flag=1;
HAL_TIM_Base_Stop_IT(&htim3);
HAL_ADC_Stop(&hadc1);
f_close(&fp);
f_mount(NULL,"0:",1); //取消挂载
}
if((play_record_flag !=0) && (key1_down_flag==0)) //开始播音
{
key1_down_flag=1;
HAL_TIM_Base_Start_IT(&htim3);
HAL_ADC_Start(&hadc1);
//在外部 SD 卡挂载文件系统,文件系统挂载时会对 SD 卡初始化
f_res = f_mount(&fs, "0:", 1);
f_res = f_open(&fp, "0:ADC_DATA.txt", FA_OPEN_EXISTING | FA_READ);
if(f_res==FR_OK)
{
f_lseek(&fp, 44); //偏移文件起始位置44个字节,后面的就是所需要的数据
fp_memory=f_size(&fp);
printf("文件大小:%d\r\n",fp_memory);
}
}
else if((play_record_flag ==0) && (key1_down_flag==0))
{
key1_down_flag=1;
HAL_TIM_Base_Stop_IT(&htim3);
HAL_ADC_Stop(&hadc1);
f_close(&fp);
f_mount(NULL,"0:",1); //取消挂载
}
}
void FILE_RW_Test(void) //文件系统读写测试
{
printf("挂载SD卡驱动\r\n");
f_res=f_mount(&fs,"0:",1);
f_unlink("0:ADC_DATA.txt");
if(f_res == FR_OK)
{
printf("挂载成功\r\n");
f_res=f_open(&fp,"0:ADC_DATA.txt",FA_WRITE | FA_OPEN_ALWAYS);
if(f_res == FR_OK)
{
printf("文件打开成功\r\n");
f_res=f_write(&fp,tab,10,&fp_rw_num);
if(f_res == FR_OK)
{
printf("写入成功\r\n实际写入字节数:%d\r\n",fp_rw_num);
}
}
}
f_close(&fp);
f_res=f_open(&fp,"0:ADC_DATA.txt",FA_READ | FA_OPEN_ALWAYS);
if(f_res == FR_OK)
{
printf("文件打开成功\r\n");
f_res=f_read(&fp,read_buff,5,&fp_rw_num);
if(f_res == FR_OK)
{
printf("读取成功\r\n");
printf("%s\r\n",read_buff);
}
}
}
void Audio_SD_Write(void)
{
if(fp_wriet_flag == 1)
{
fp_wriet_flag = 0;
f_res=f_mount(&fs,"0:",1);
if(f_res == FR_OK)
{
printf("挂载成功\r\n");
}
else
printf("挂载失败\r\n");
f_res=f_open(&fp,"0:ADC_DATA.txt",FA_OPEN_ALWAYS | FA_WRITE);
if(f_res == FR_OK)
printf("文件打开成功\r\n");
else
printf("打开失败\r\n");
f_lseek(&fp, f_size(&fp));//确保写词写入不会覆盖之前的数据
f_res=f_write(&fp,val_data_buff,4096,&fp_rw_num);
if(f_res == FR_OK)
{
memset(val_data_buff,0,5000);
printf("写入成功\r\n实际写入字节数:%d\r\n",fp_rw_num);
}
else
printf("写入失败\r\n");
}
f_close(&fp);
f_mount(NULL,"0:",1); //取消挂载
}
void Audio_SD_Read(void)
{
if(Time_Count>=fnum){ //当DAC输出的字节大于等于读取到的字节数
Time_Count = 0;
memset(DAC_Data,0,sizeof(DAC_Data)); //清空数组
f_res=f_read(&fp,Read_Data,4096,(UINT*)&fnum);//读出4096个字节
memcpy(DAC_Data,Read_Data,fnum); //数组复制
}
if(f_eof(&fp)) //已经读取完了
{
f_lseek(&fp, 44); //跳过前面44个字节
}
}
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
int wd4;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3)
{
if((sound_record_flag !=0) && (play_record_flag ==0))
{
val_data[val_count]=HAL_ADC_GetValue(&hadc1);
val_count++;
if(val_count == 2048)
{
memcpy(val_data_buff,val_data,sizeof(val_data));
val_count=0;
fp_wriet_flag=1;
}
}
if((sound_record_flag ==0) && (play_record_flag !=0))
{
Time_Count += DAC_F;
wd4 = ((DAC_Data[Time_Count-1]-0x80)<<8)|(DAC_Data[Time_Count-2]); //将16位的音频数据转为12位。
wd4 = 0xfff & (wd4>>4);
HAL_DAC_SetValue(&hdac,DAC_CHANNEL_2,DAC_ALIGN_12B_R,wd4);//12位右对齐数据格式设置DAC值
}
}
}
//main里面
HAL_DAC_Start(&hdac,DAC_CHANNEL_2);
HAL_TIM_Base_Stop_IT(&htim3);
HAL_ADC_Stop(&hadc1);
HAL_Delay(1);
// FILE_RW_Test(); //测试函数
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
KEY_Scanf();
KEY_Handle();
if((sound_record_flag !=0) && (play_record_flag ==0))
Audio_SD_Write(); //录音
else if((sound_record_flag ==0) && (play_record_flag !=0))
Audio_SD_Read(); //播音
}
/* USER CODE END WHILE */
5 最后
包含内容
🧿 项目分享:见文末!
**项目分享: ** https://blog.csdn.net/m0_984093