#define DAC_DHR8R1_Address 0x40007410 // Init Structure definition
DAC_InitTypeDef DAC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
u16 GetARRValue(u16 sample); //rcc 配置时钟频率
void RCC_Configuration(void)
{
/* RCC system reset(for debug purpose) */
RCC_DeInit(); /* Enable HSE */
RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */
HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus == SUCCESS)
{
/* Enable Prefetch Buffer */
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /* Flash 2 wait state */
FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */
RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */
RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */
RCC_PCLK1Config(RCC_HCLK_Div2);//36MHz /* PLLCLK = 8MHz * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); /* Enable PLL */
RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
} /* Select PLL as system clock source */
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */
while(RCC_GetSYSCLKSource() != 0x08)
{
}
} // Enable peripheral clocks -------------------------------------------------- //dma dac sinewave
// DMA clock enable
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// AFIO and GPIOA Periph clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
// DAC Periph clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM6, ENABLE);
// TIM8 Periph clock enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
} void GPIO_Configuration(void)
{
//init gpio
GPIO_InitTypeDef GPIO_InitStructure;
//dma dac sinewave
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4| GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//DAC输出 必须要设置成 模拟输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
} int main(void)
{
RCC_Configuration();
NVIC_Configuration();
GPIO_Configuration(); //DAC output SineWave (TIM8)
/*
//1>.This example describes how to use DAC dual channel mode with DMA to generate sine
//waves on both DAC channels outputs. TIM_DeInit(TIM8); // TIM8 Configuration
// Time base configuration
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = GetARRValue(44100);//72MHz 的CPU,输出44.1KHz 的音频,设置周期为1633
TIM_TimeBaseStructure.TIM_Prescaler = 0;//分频
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); // TIM8 TRGO selection
TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update); // DAC channel1 Configuration
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T8_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; DAC_Init(DAC_Channel_1, &DAC_InitStructure); // DAC channel2 Configuration
DAC_Init(DAC_Channel_2, &DAC_InitStructure); #if 1
// DMA2 channel4 configuration
DMA_DeInit(DMA2_Channel4);
#else
// DMA1 channel4 configuration
DMA_DeInit(DMA1_Channel4);
#endif DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR8R1_Address;//DAC_DHR12RD_Address;//
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&DualSine12bit; //方向:外设是目的地,还是来源
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
//DMA_DIR_PeripheralDST 外设是目的地
//DMA_DIR_PeripheralSRC 外设是来源 DMA_InitStructure.DMA_BufferSize = 512;//
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//DMA_PeripheralInc_Enable 外设地址寄存器递增
//DMA_PeripheralInc_Disable 外设地址寄存器不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//DMA_MemoryInc_Enable 内存地址寄存器递增
//DMA_MemoryInc_Disable 内存地址寄存器不变 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//内存数据宽度
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//设置CAN SPI 的DMA 模式
//DMA_Mode_Circular 工作在循环缓存模式
//DMA_Mode_Normal 工作在正常缓存模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High;//DMA 通道优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
//enable 内存到内存输出
//disable 内存到内存输出 #if 1
DMA_Init(DMA2_Channel4, &DMA_InitStructure);
//Enable DMA2 Channel4
DMA_Cmd(DMA2_Channel4, ENABLE);
#else
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
// Enable DMA1 Channel4
DMA_Cmd(DMA1_Channel4, ENABLE);
#endif // Enable DAC Channel1
DAC_Cmd(DAC_Channel_1, ENABLE);
// Enable DAC Channel2
DAC_Cmd(DAC_Channel_2, ENABLE); // Enable DMA for DAC Channel2
DAC_DMACmd(DAC_Channel_2, ENABLE); // TIM8 enable counter
TIM_Cmd(TIM8, ENABLE); */ //2>.DAC output SineWave (TIM) single sinewave 单通道 TIM_DeInit(TIM6); /* TIM6 Configuration */
TIM_PrescalerConfig(TIM6, 0x0, TIM_PSCReloadMode_Update);
TIM_SetAutoreload(TIM6, 1633);
/* TIM6 TRGO selection */
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update); /* DAC channel1 Configuration */
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
DAC_Init(DAC_Channel_1, &DAC_InitStructure); #if 1
/* DMA2 channel3 configuration */
DMA_DeInit(DMA2_Channel3);
#else
/* DMA1 channel3 configuration */
DMA_DeInit(DMA1_Channel3);
#endif DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR8R1_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&thx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 20222;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; #if 1
DMA_Init(DMA2_Channel3, &DMA_InitStructure);
/* Enable DMA2 Channel3 */
DMA_Cmd(DMA2_Channel3, ENABLE);
#else
DMA_Init(DMA1_Channel3, &DMA_InitStructure);
/* Enable DMA1 Channel3 */
DMA_Cmd(DMA1_Channel3, ENABLE);
#endif // Enable DAC Channel1
DAC_Cmd(DAC_Channel_1, ENABLE); DAC_DMACmd(DAC_Channel_1, ENABLE); // TIM8 enable counter
TIM_Cmd(TIM6, ENABLE); while(1); } // 根据采样率获得定时器自动
// 摘自waveplayer.c
u16 GetARRValue(u16 sample)
{
u16 arrValue;
//更新OCA值以符合.WAV文件采样率
switch (sample)
{
case SAMPLE_RATE_8000 :
arrValue = (u16)(72000000/8000);
break; // 8KHz = 2x36MHz / 9000
case SAMPLE_RATE_11025:
arrValue = (u16)(72000000/11025);
break; // 11.025KHz = 2x36MHz / 6531
case SAMPLE_RATE_16000:
arrValue = (u16)(72000000/16000);
break; // 16KHz = 2x36MHz / 4500
case SAMPLE_RATE_22050:
arrValue = (u16)(72000000/22050);
break; // 22.05KHz = 2x36MHz / 2365
case SAMPLE_RATE_44100:
arrValue = (u16)(72000000/44100);
break; // 44.1KHz = 2x36MHz / 1633
case SAMPLE_RATE_48000:
arrValue = (u16)(72000000/48000);
break; // 48KHz = 2x36MHz / 1500
default:
arrValue = 0;
break;
}
return arrValue;
}

上面是 双通道,单通道的DAC 音频输出

需要注意的是数据,一定要是wave的格式, 下面就有检测wave格式是否正确的代码

/** @defgroup WAVEPLAYER_Private_Defines
* @{
*/
#define CHUNK_ID 0x52494646 /* correspond to the letters 'RIFF' */
#define FILE_FORMAT 0x57415645 /* correspond to the letters 'WAVE' */
#define FORMAT_ID 0x666D7420 /* correspond to the letters 'fmt ' */
#define DATA_ID 0x64617461 /* correspond to the letters 'data' */
#define FACT_ID 0x66616374 /* correspond to the letters 'fact' */
#define WAVE_FORMAT_PCM 0x01
#define FORMAT_CHNUK_SIZE 0x10
#define CHANNEL_MONO 0x01
#define SAMPLE_RATE_8000 8000
#define SAMPLE_RATE_11025 11025
#define SAMPLE_RATE_22050 22050
#define SAMPLE_RATE_44100 44100
#define BITS_PER_SAMPLE_8 8
#define WAVE_DUMMY_BYTE 0xA5
#define DAC_DHLCD_REG_8LCD_REG_1_ADDRESS 0x40007410 static ErrorCode WavePlayer_WaveParsing()
{
uint32_t Temp = 0x00;
uint32_t ExtraFormatBytes = 0;
__IO uint32_t err = 0; memcpy(Wavebuffer,0,20250-1);//在这里固定了数组,实际中再用其他的buffer
memcpy(Wavebuffer,thx,20222); // Read chunkID, must be 'RIFF' ----------------------------------------------
Temp = ReadUnit(Wavebuffer, 0, 4, BigEndian);
if (Temp != CHUNK_ID)
{
return(Unvalid_RIFF_ID);
} // Read the file length ----------------------------------------------------
WAVE_Format.RIFFchunksize = ReadUnit(Wavebuffer, 4, 4, LittleEndian); // Read the file format, must be 'WAVE' ------------------------------------
Temp = ReadUnit(Wavebuffer, 8, 4, BigEndian);
if (Temp != FILE_FORMAT)
{
return(Unvalid_WAVE_Format);
} // Read the format chunk, must be'fmt ' --------------------------------------
Temp = ReadUnit(Wavebuffer, 12, 4, BigEndian);
if (Temp != FORMAT_ID)
{
return(Unvalid_FormatChunk_ID);
}
// Read the length of the 'fmt' data, must be 0x10 -------------------------
Temp = ReadUnit(Wavebuffer, 16, 4, LittleEndian);
if (Temp != 0x10)
{
ExtraFormatBytes = 1;
}
// Read the audio format, must be 0x01 (PCM) -------------------------------
WAVE_Format.FormatTag = ReadUnit(Wavebuffer, 20, 2, LittleEndian);
if (WAVE_Format.FormatTag != WAVE_FORMAT_PCM)
{
return(Unsupporetd_FormatTag);
} // Read the number of channels, must be 0x01 (Mono) ------------------------
WAVE_Format.NumChannels = ReadUnit(Wavebuffer, 22, 2, LittleEndian);
if (WAVE_Format.NumChannels != CHANNEL_MONO)
{
return(Unsupporetd_Number_Of_Channel);
} // Read the Sample Rate ----------------------------------------------------
WAVE_Format.SampleRate = ReadUnit(Wavebuffer, 24, 4, LittleEndian);
// Update the OCA value according to the .WAV file Sample Rate
switch (WAVE_Format.SampleRate)
{
case SAMPLE_RATE_8000 :
TIM6ARRValue = 4500;
break; // 8KHz = 36MHz / 4500
case SAMPLE_RATE_11025:
TIM6ARRValue = 3265;
break; // 11.025KHz = 36MHz / 3265
case SAMPLE_RATE_22050:
TIM6ARRValue = 1632;
break; // 22.05KHz = 36MHz / 1632
case SAMPLE_RATE_44100:
TIM6ARRValue = 816;
break; // 44.1KHz = 36MHz / 816
default:
return(Unsupporetd_Sample_Rate);
} // Read the Byte Rate ------------------------------------------------------
WAVE_Format.ByteRate = ReadUnit(Wavebuffer, 28, 4, LittleEndian); // Read the block alignment ------------------------------------------------
WAVE_Format.BlockAlign = ReadUnit(Wavebuffer, 32, 2, LittleEndian); // Read the number of bits per sample --------------------------------------
WAVE_Format.BitsPerSample = ReadUnit(Wavebuffer, 34, 2, LittleEndian);
if (WAVE_Format.BitsPerSample != BITS_PER_SAMPLE_8)
{
return(Unsupporetd_Bits_Per_Sample);
}
SpeechDataOffset = 36;
// If there is Extra format bytes, these bytes will be defined in "Fact Chunk"
if (ExtraFormatBytes == 1)
{
// Read th Extra format bytes, must be 0x00 ------------------------------
Temp = ReadUnit(Wavebuffer, 36, 2, LittleEndian);
if (Temp != 0x00)
{
return(Unsupporetd_ExtraFormatBytes);
}
// Read the Fact chunk, must be 'fact' -----------------------------------
Temp = ReadUnit(Wavebuffer, 38, 4, BigEndian);
if (Temp != FACT_ID)
{
return(Unvalid_FactChunk_ID);
}
// Read Fact chunk data Size ---------------------------------------------
Temp = ReadUnit(Wavebuffer, 42, 4, LittleEndian); SpeechDataOffset += 10 + Temp;
}
// Read the Data chunk, must be 'data' ---------------------------------------
Temp = ReadUnit(Wavebuffer, SpeechDataOffset, 4, BigEndian);
SpeechDataOffset += 4;
if (Temp != DATA_ID)
{
return(Unvalid_DataChunk_ID);
} // Read the number of sample data ------------------------------------------
WAVE_Format.DataSize = ReadUnit(Wavebuffer, SpeechDataOffset, 4, LittleEndian);
SpeechDataOffset += 4;
wavecounter = SpeechDataOffset;
return(Valid_WAVE_File);
}

在处理wave 音频数据的时候

实际数据20222 byte

RIFFchunksize 是20214

Read the number of sample data 20108 (SpeechDataOffset为44 )

前面offset 是44, 而总sample data 是20108,

20222 -44 -20108 = 70

70就是不要的数据尾, 为了DAC 不发出杂音(爆音是接近 0或255的曲线, 128是中音)

实际处理数据的时候 前offset +44, 后offset -(114 -44) 就可以了

这样就没有爆音了,哈哈

stm32 DAC输出音频的更多相关文章

  1. Keil MDK STM32系列(八) STM32F4基于HAL的PWM和定时器输出音频

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  2. STM32 DAC的配置与使用

    本博文转自:http://blog.chinaunix.net/uid-24219701-id-4101802.html STM32 的 DAC 模块(数字/模拟转换模块)是 12 位数字输入,电压输 ...

  3. stm32 dac 配置过程

    DAC模块的通道1来输出模拟电压,其详细设置步骤如下: 1)开启PA口时钟,设置PA4为模拟输入. STM32F103ZET6的DAC通道1是接在PA4上的,所以,我们先要使能PORTA的时钟,然后设 ...

  4. STM32—DAC配置

    文章目录 一.DAC介绍 二.主要寄存器说明 三.代码及配置 一.DAC介绍 ADC是模数转换器,可以将模拟电压转换位数字信号:DAC是数模转换器,可以将数字信号转换为模拟电压. STM32F103Z ...

  5. stm32 dac库函数解读

    1.简述: 12位数字输入,电压输出,DAC可以配置为8位或12位模式.有2个输出通道.在双DAC模式下,两个通道可以独立地工作. 特殊功能: 噪声波形生成,三角波形生成,外部触发转换,双DAC同时或 ...

  6. STM32 精确输出PWM脉冲数控制电机(转)

    STM32 精确输出PWM脉冲数控制电机 发脉冲两种目的1)速度控制2)位置控制 速度控制目的和模拟量一样,没有什么需要关注的地方发送脉冲方式为PWM,速率稳定而且资源占用少 stm32位置控制需要获 ...

  7. 【转】STM32定时器输出比较模式中的疑惑

    OCx与OCxREF和CCxP之间的关系 初学STM32,我这个地方卡了很久,现在终于有些明白了,现在把我的理解写下与大家共享,如果有不对的地方,还请指出. OCxREF就是一个参考信号,并且约定: ...

  8. [SimplePlayer] 5. 向音频设备输出音频

    两种SDL音频输出方式 我们这里采用SDL来进行音频输出.SDL提供两种音频输出的方式: 如果在SDL_OpenAudio时不指定callback,那么可以调用SDL_QueueAudio主动地向音频 ...

  9. stm32定时器输出移相PWM(非主从模式)

    背景:由于项目需要,需要stm32输出任意相角度的PWM 前提知识: 1.stm32定时器的Tim,一般有多个OC.具体差别根据型号来定. 2.定时器的使能,理论上是多个通道同时使能 3.TIM_OC ...

随机推荐

  1. js时间格式的转换

    function System_dateInit(value) {     if (value != null) {         var d = new Date(value);          ...

  2. 【BZOJ3196】Tyvj 1730 二逼平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的 ...

  3. 关于mapreduce过程中出现的错误:Too many fetch-failures

    Reduce task启动后第一个阶段是shuffle,即向map端fetch数据.每次fetch都可能因为connect超时,read超时,checksum错误等原因而失败.Reduce task为 ...

  4. Xcode界面简介

    创建 Object-C 程序 进入主界面方式 : 打开 Xcode 之后, 可以使用 Xcode 菜单, 但是必须创建一个 Object-C 工程 或者 导入 一个 Object-C 工程才可以进入主 ...

  5. 1199: [HNOI2005]汤姆的游戏 - BZOJ

    Description 汤姆是个好动的孩子,今天他突然对圆规和直尺来了兴趣.于是他开始在一张很大很大的白纸上画很多很多的矩形和圆.画着画着,一不小心将他的爆米花弄撒了,于是白纸上就多了好多好多的爆米花 ...

  6. springMVC+MyBatis+Spring 整合(3)

    spring mvc 与mybatis 的整合. 加入配置文件: spring-mybaits.xml <?xml version="1.0" encoding=" ...

  7. bzoj 3676: [Apio2014]回文串 回文自动机

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 844  Solved: 331[Submit][Status] ...

  8. 关​于​h​i​b​e​r​n​a​t​e​中​双​向​外​键​关​联​o​n​e​-​t​o​-​o​n​e​的​p​r​o​p​e​r​t​y​-​r​e​f​=​的​问​题(转)

    大家都知道hibernate中的one-to-one映射主要有两种策略,(1)一对一主键关联(单向和双向).(2)一对一外键映射(单项和双向).本文主要讲解一下,一对一外键映射中的双向问题,在此前先通 ...

  9. 论MOBA类游戏五号位的重要性

    观众朋友们,也许你对题目很好奇,才打开这篇文章.为什么技术圈中会出现游戏类的软文?如果时间充足,可以继续往下看. MOBA 类游戏的兴起,逐渐吞噬游戏市场,以病毒式的扩张方式肆意改变着游戏玩家内心对游 ...

  10. 电商安全无小事,如何有效地抵御 CSRF 攻击?

    现在,我们绝大多数人都会在网上购物买东西.但是很多人都不清楚的是,很多电商网站会存在安全漏洞.比如乌云就通报过,国内很多家公司的网站都存在 CSRF 漏洞.如果某个网站存在这种安全漏洞的话,那么我们在 ...