我是直接在开发板的PA4引脚和一个GND引脚上接的一个8欧0.5瓦的小喇叭,喇叭上还串联了一个105的电容,播放的WAV文件是8位22KHz单声道PCM格式的文件,DMA代码是这样的
DMA_DeInit(DMA2_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR8R1_Address; // 单通道8位右对齐 数据的来源
DMA_InitStructure.DMA_BufferSize = BUFF_SIZE; // 缓冲大小
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 8位数据宽度
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; // 8位数据宽度
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Wavebuffer; // 内存基址 数据要写到哪里去
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // 外设作为数据传输的目的地
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址寄存器递增
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 工作在正常缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道x拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // DMA通道x没有设置为内存到内存传输
DMA_Init(DMA2_Channel3, &DMA_InitStructure);
DMA_Cmd(DMA2_Channel3, ENABLE); //使能DMA2通道3
DMA_ITConfig(DMA2_Channel3, DMA_IT_TC | DMA_IT_HT, ENABLE);
TIM6的代码是这样的:
TIM_DeInit(TIM6);
TIM_SetAutoreload(TIM6, TIM6ARRValue); //TIM6ARRValue的值是72000000/22050
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
TIM_Cmd(TIM6, ENABLE);
DAC的代码是这样的
DAC_DeInit();
DAC_StructInit(&DAC_InitStructure);
DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO; //选择定时器6做外部触发源
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; // 无波形产生
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; // 禁止输出缓冲
DAC_Init(DAC_Channel_1, &DAC_InitStructure); //DAC通道1初始化
DAC_Cmd(DAC_Channel_1, ENABLE); //使能DAC通道1:一旦使能了DAC通道1,PA.04将自动连接到DAC转换器
DAC_DMACmd(DAC_Channel_1, ENABLE); //使能DMA用于DAC通道1
DAC_Init(DAC_Channel_2, &DAC_InitStructure); //DAC通道2初始化
DAC_Cmd(DAC_Channel_2, ENABLE); //使能DAC通道2:一旦使能了DAC通道2,PA.05将自动连接到DAC转换器
DAC_DMACmd(DAC_Channel_2, ENABLE); //使能DMA用于DAC通道2
然后使用了中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =3;//NVIC_PriorityGroup_1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;// NVIC_PriorityGroup_4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
在中断函数中写数据
void PlayReadBlock(u16 offset)
{
FRESULT res;
res = f_read(&fp, Wavebuffer + offset, 512, &br);
if((res!=FR_OK) || (br==0))
{
f_close(&fp);
}
else if (br < 512)
{
f_close(&fp);
TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE); //禁止TIM6更新中断
TIM_Cmd(TIM6, DISABLE); //禁止TIM6
}
}
void DMA2_Channel3_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_IT_HT3) == SET)
{
DMA_ClearITPendingBit(DMA2_IT_HT3);
DMA_ClearFlag(DMA2_FLAG_HT3);
//检查过半标志,有效,清除标志,处理前半段数据
PlayReadBlock(0);
}
LED3 = !LED3;
if (DMA_GetITStatus(DMA2_IT_TC3) == SET)
{
DMA_ClearITPendingBit(DMA2_IT_TC3);
DMA_ClearFlag(DMA2_FLAG_TC3);
//检查完成标志,有效,清除标志,处理后半段数据
PlayReadBlock(BUFF_SIZE>>1);
}
}
基本上就是这些了,代码都能正常运行中断也能正常进入,不知道是不是我的配置有问题,或者是计算有问题,本人是菜鸟才入门STM32请教坛子里的各位朋友,谢谢了!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
---------------------------------
如果您说的是单独的f_read的读取SD卡文件的时间的话,我测试过每秒有200K以上。
您说的双缓冲是这样吗?
res = f_read(&fp, Wavebuffer2, BUF_SIZE, &br);
if((res!=FR_OK) || (br==0))
{
f_close(&fp);
//LED1 = !LED1;
return Invalid_WAVE_File;
}
if(WaveDataLength)
{
WaveDataLength -= BUF_SIZE;
}
if(WaveDataLength < BUF_SIZE)
{
WaveDataLength = 0;
}
while(DMA_GetFlagStatus(DMA2_FLAG_TC3) == RESET) //转换完成标志
{
tmp=(u16)((u32)((WAVE_Format.DataSize-WaveDataLength)*400)/WAVE_Format.DataSize);
LCD_DrawYLine(tmp, 202, 213);
}
DMA2->IFCR = DMA2_FLAG_TC3; // 清除DMA2中断标志
DMA2_Channel3->CCR = 0x0; // 清除DMA2通道3设置寄存器配制
DMA2_Reconfig((u32)&Wavebuffer2);
res=f_read(&fp, Wavebuffer, BUF_SIZE, &br);
if((res!=FR_OK) || (br==0))
{
f_close(&fp);
return Invalid_WAVE_File;
}
if(WaveDataLength)
{
WaveDataLength -= BUF_SIZE;
}
if(WaveDataLength < BUF_SIZE)
{
WaveDataLength = 0;
}
while(DMA_GetFlagStatus(DMA2_FLAG_TC3) == RESET)
{
tmp=(u16)((u32)((WAVE_Format.DataSize-WaveDataLength)*400)/WAVE_Format.DataSize);
LCD_DrawYLine(tmp, 202, 213);
}
DMA2->IFCR = DMA2_FLAG_TC3; // 清除DMA2中断标志
DMA2_Channel3->CCR = 0x0; // 清除DMA2通道3设置寄存器配制
DMA2_Reconfig((u32)&Wavebuffer);
不知道会不会是喇叭的问题我之前用网上找到的一个代码,并且他介绍了直接移植的方法,编译通过后输出到喇叭上的声音也是哒哒哒的声音,我看人家都是接的音响或者耳机,不知道能不能驱动起来这个喇叭
---------------------------------
原子大哥,1:使用DMA+DAC+TIM6这样的传输方式,因为外设地址不变,有木有可能DMA之前传送的一个数据还未数模转换,DMA传送的数据又到了将之前的数据覆盖了???
2:DMA使用正常模式(即不使用循环传送),缓冲区数据传送完成后将停止DMA传送,如果再次启动DMA,是不是又是从缓冲区首地址开始传送?
求解,谢谢原子大哥!
一周热门 更多>