基于stm32f407 写出ADC读取语音电信号,内部flash存储10sADC读取的语音信号,后用dac再将flash内部信号输出,实现语音回放掉电存储的代码

时间: 2024-05-09 17:14:20 浏览: 19
以下是基于stm32f407的ADC读取语音电信号,内部flash存储10sADC读取的语音信号,后用dac再将flash内部信号输出,实现语音回放掉电存储的代码: ``` c #include "stm32f4xx.h" #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_flash.h" #include "stm32f4xx_hal_dac.h" #include "stm32f4xx_hal_adc.h" #define ADC1_DR_ADDRESS ((uint32_t)0x4001204C) #define FLASH_START_ADDR ((uint32_t)0x080E0000) #define FLASH_END_ADDR ((uint32_t)0x080FFFFF) #define FLASH_PAGE_SIZE ((uint32_t)0x400) #define FLASH_SECTOR_SIZE ((uint32_t)0x4000) #define FLASH_SECTOR_NUM ((uint32_t)0x0F) #define SAMPLE_RATE ((uint32_t)8000) #define SAMPLE_TIME ((uint32_t)(1000000/SAMPLE_RATE)) #define ADC_BUF_SIZE ((uint32_t)(SAMPLE_RATE*10)) // 10s static ADC_HandleTypeDef AdcHandle; static DAC_HandleTypeDef DacHandle; static uint16_t AdcBuf[ADC_BUF_SIZE]; static uint32_t AdcBufIndex; static uint32_t FlashWriteAddr; static void SystemClock_Config(void); static void Error_Handler(void); static void ADC_Config(void); static void DAC_Config(void); int main(void) { HAL_Init(); SystemClock_Config(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_DAC_CLK_ENABLE(); __HAL_RCC_TIM6_CLK_ENABLE(); __HAL_RCC_FLASH_CLK_ENABLE(); ADC_Config(); DAC_Config(); HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)ADC1_DR_ADDRESS, 1); HAL_DAC_Start(&DacHandle, DAC_CHANNEL_1); while (1) { if (AdcBufIndex >= ADC_BUF_SIZE) { HAL_FLASH_Unlock(); FLASH_EraseInitTypeDef EraseInitStruct; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.Sector = FLASH_SECTOR_NUM; EraseInitStruct.NbSectors = 1; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; uint32_t SectorError; HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); FlashWriteAddr = FLASH_START_ADDR; for (uint32_t i = 0; i < ADC_BUF_SIZE; i++) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FlashWriteAddr, AdcBuf[i]); FlashWriteAddr += 2; } HAL_FLASH_Lock(); FlashWriteAddr = FLASH_START_ADDR; for (uint32_t i = 0; i < ADC_BUF_SIZE; i++) { HAL_DAC_SetValue(&DacHandle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, AdcBuf[i]); HAL_Delay(SAMPLE_TIME); } AdcBufIndex = 0; } } } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { AdcBuf[AdcBufIndex] = HAL_ADC_GetValue(hadc); AdcBufIndex++; } static void ADC_Config(void) { AdcHandle.Instance = ADC1; AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4; AdcHandle.Init.Resolution = ADC_RESOLUTION_12B; AdcHandle.Init.ScanConvMode = DISABLE; AdcHandle.Init.ContinuousConvMode = ENABLE; AdcHandle.Init.DiscontinuousConvMode = DISABLE; AdcHandle.Init.NbrOfDiscConversion = 0; AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT; AdcHandle.Init.NbrOfConversion = 1; AdcHandle.Init.DMAContinuousRequests = ENABLE; AdcHandle.Init.EOCSelection = DISABLE; HAL_ADC_Init(&AdcHandle); ADC_ChannelConfTypeDef sConfig; sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES; sConfig.Offset = 0; HAL_ADC_ConfigChannel(&AdcHandle, &sConfig); } static void DAC_Config(void) { DacHandle.Instance = DAC; HAL_DAC_Init(&DacHandle); DAC_ChannelConfTypeDef sConfig; sConfig.DAC_Trigger = DAC_TRIGGER_NONE; sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_1); } static void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; __HAL_RCC_PWR_CLK_ENABLE(); HAL_PWR_EnableBkUpAccess(); __HAL_RCC_BACKUPRESET_FORCE(); __HAL_RCC_BACKUPRESET_RELEASE(); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 8; RCC_OscInitStruct.PLL.PLLN = 336; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = 7; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); } ``` 代码实现的基本思路是:通过ADC采样获取语音信号,将其存储到数组中,当数组存满后将其存储到内部flash中,并通过DAC实现回放。具体实现细节如下: 1. 定义了一些常量和变量: ``` c #define ADC1_DR_ADDRESS ((uint32_t)0x4001204C) #define FLASH_START_ADDR ((uint32_t)0x080E0000) #define FLASH_END_ADDR ((uint32_t)0x080FFFFF) #define FLASH_PAGE_SIZE ((uint32_t)0x400) #define FLASH_SECTOR_SIZE ((uint32_t)0x4000) #define FLASH_SECTOR_NUM ((uint32_t)0x0F) #define SAMPLE_RATE ((uint32_t)8000) #define SAMPLE_TIME ((uint32_t)(1000000/SAMPLE_RATE)) #define ADC_BUF_SIZE ((uint32_t)(SAMPLE_RATE*10)) // 10s static ADC_HandleTypeDef AdcHandle; static DAC_HandleTypeDef DacHandle; static uint16_t AdcBuf[ADC_BUF_SIZE]; static uint32_t AdcBufIndex; static uint32_t FlashWriteAddr; ``` 2. 实现ADC和DAC的配置函数: ``` c static void ADC_Config(void) { AdcHandle.Instance = ADC1; AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4; AdcHandle.Init.Resolution = ADC_RESOLUTION_12B; AdcHandle.Init.ScanConvMode = DISABLE; AdcHandle.Init.ContinuousConvMode = ENABLE; AdcHandle.Init.DiscontinuousConvMode = DISABLE; AdcHandle.Init.NbrOfDiscConversion = 0; AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT; AdcHandle.Init.NbrOfConversion = 1; AdcHandle.Init.DMAContinuousRequests = ENABLE; AdcHandle.Init.EOCSelection = DISABLE; HAL_ADC_Init(&AdcHandle); ADC_ChannelConfTypeDef sConfig; sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES; sConfig.Offset = 0; HAL_ADC_ConfigChannel(&AdcHandle, &sConfig); } static void DAC_Config(void) { DacHandle.Instance = DAC; HAL_DAC_Init(&DacHandle); DAC_ChannelConfTypeDef sConfig; sConfig.DAC_Trigger = DAC_TRIGGER_NONE; sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; HAL_DAC_ConfigChannel(&DacHandle, &sConfig, DAC_CHANNEL_1); } ``` 3. 实现ADC采样完成中断的回调函数: ``` c void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { AdcBuf[AdcBufIndex] = HAL_ADC_GetValue(hadc); AdcBufIndex++; } ``` 4. 主程序的实现: ``` c int main(void) { HAL_Init(); SystemClock_Config(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_DAC_CLK_ENABLE(); __HAL_RCC_TIM6_CLK_ENABLE(); __HAL_RCC_FLASH_CLK_ENABLE(); ADC_Config(); DAC_Config(); HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)ADC1_DR_ADDRESS, 1); HAL_DAC_Start(&DacHandle, DAC_CHANNEL_1); while (1) { if (AdcBufIndex >= ADC_BUF_SIZE) { HAL_FLASH_Unlock(); FLASH_EraseInitTypeDef EraseInitStruct; EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.Sector = FLASH_SECTOR_NUM; EraseInitStruct.NbSectors = 1; EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; uint32_t SectorError; HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError); FlashWriteAddr = FLASH_START_ADDR; for (uint32_t i = 0; i < ADC_BUF_SIZE; i++) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, FlashWriteAddr, AdcBuf[i]); FlashWriteAddr += 2; } HAL_FLASH_Lock(); FlashWriteAddr = FLASH_START_ADDR; for (uint32_t i = 0; i < ADC_BUF_SIZE; i++) { HAL_DAC_SetValue(&DacHandle, DAC_CHANNEL_1, DAC_ALIGN_12B_R, AdcBuf[i]); HAL_Delay(SAMPLE_TIME); } AdcBufIndex = 0; } } } ``` 主程序的实现比较简单,主要就是检测采样数组是否已满,如果已满则将其存储到内部flash中,并通过DAC实现回放。具体实现细节如下: - 通过`HAL_FLASH_Unlock()`函数解锁内部flash; - 通过`HAL_FLASHEx_Erase()`函数擦除flash扇区; - 通过`HAL_FLASH_Program()`函数将采样数据存储到flash中; - 通过`HAL_FLASH_Lock()`函数锁定内部flash; - 通过`HAL_DAC_SetValue()`函数将flash中的采样数据输出到DAC; - 通过`HAL_Delay()`函数实现采样率控制,保证回放速度。 需要注意的是,由于内部flash的写入操作需要擦除整个扇区,因此在存储数据时需要先将整个扇区擦除再进行写入,否则会出现写入失败的情况。

相关推荐

最新推荐

recommend-type

基于Selenium的Java爬虫实战(内含谷歌浏览器Chrom和Chromedriver版本116.0.5808.0)

资源包括: 1.Java爬虫实战代码 2.selenium学习笔记 3.代码演示视频 4.谷歌浏览器chrom116.0.5808.0 chrome-linux64.zip chrome-mac-arm64.zip chrome-mac-x64.zip chrome-win32.zip chrome-win64.zip 5.谷歌浏览器驱动器Chromedriver116.0.5808.0 chromedriver-linux64.zip chromedriver-mac-arm64.zip chromedriver-mac-x64.zip chromedriver-win32.zip chromedriver-win64.zip 特别说明:Chrome 为测试版(不会自动更新) 仅适用于自动测试。若要进行常规浏览,请使用可自动更新的标准版 Chrome。)
recommend-type

2024消费趋势报告.pdf

2024消费趋势报告.pdf
recommend-type

PCB的电磁兼容设计+电子设计领域

1、EMC由EMI和EMS组成 2、EMS常见的整改措施 3、干扰=共模干扰+差模干扰 4、元器件的摆放 5、缝隙影响
recommend-type

给排水施工图全套.xdw.pdf

给排水施工图全套.xdw
recommend-type

基于微信小程序的旅游出行必备(后端接口ssm框架实现)-毕设项目

毕业设计基于微信小程序的旅游出行必备(后端接口ssm框架实现)-毕设项目.zip 个人经导师指导并认可通过的高分设计项目,评审分98分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 项目介绍: 旅游出行必备项目, 前端为微信小程序,后端接口为ssm框架实现,项目包含源码、数据库毕业设计基于微信小程序的旅游出行必备(后端接口ssm框架实现)-毕设项目.zip 个人经导师指导并认可通过的高分设计项目,评审分98分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 项目主要功能: 该项目是一个基于微信小程序的旅游出行应用,结合后端SSM(Spring MVC + Spring + MyBatis)框架提供服务。主要功能包括行程规划、景点信息查询、在线预订等,旨在为用户提供便捷的旅游出行体验。特点在于利用微信小程序的便捷性,实现即用即走,同时通过后端强大的数据处理能力保证服务稳定性。技术栈涵盖微信小程序开发、Java SSM框架、数据库管理等,适合学习和作为毕业设计参考。
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

MATLAB正态分布协方差分析:揭示正态分布变量之间的协方差

![MATLAB正态分布协方差分析:揭示正态分布变量之间的协方差](https://site.cdn.mengte.online/official/2021/11/20211128213137293.png) # 1. 正态分布概述 正态分布,又称高斯分布,是统计学中最重要的连续概率分布之一。它广泛应用于自然科学、社会科学和工程领域。 正态分布的概率密度函数为: ``` f(x) = (1 / (σ√(2π))) * exp(-(x - μ)² / (2σ²)) ``` 其中: - μ:正态分布的均值 - σ:正态分布的标准差 - π:圆周率 正态分布具有以下特性: - 对称性:
recommend-type

我正在开发一款个人碳足迹计算app,如何撰写其需求分析文档,请给我一个范例

为了更全面、清晰地定义个人碳足迹计算app的需求,需求分析文档应该包含以下内容: 1.项目简介:对该app项目的概述及目标进行说明。 2.用户分析:包括目标用户群、用户需求、行为等。 3.功能需求:对app的基本功能进行定义,如用户登录、数据录入、数据统计等。 4.非功能需求:对使用app的性能和质量等进行定义,如界面设计、数据安全、可扩展性等。 5.运行环境:包括app的开发环境和使用环境。 下面是一个范例: 需求分析文档 1. 项目简介 该app项目旨在为用户提供一款方便、易用、可定制的个人碳足迹计算平台,以促进环保和可持续性发展。 2. 用户分析 目标用户群:全球关
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。