专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
谁用过,stm32的DAC直接播放声音,不知道音质如何???
2019-07-20 23:12
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
18495
29
1646
谁用过,stm32的DAC直接播放声音,不知道音质如何???
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
29条回答
lxj19901115
2019-07-22 14:05
/*
核心思想,配置定时器,DA,频率为16K,32K等
在读取数据的时候,使用双BUFFER切换,两个缓冲区的大小为64字节,
主循环一直填充BUFFER里面的数据
定时器中断则在BUFFER里面,读取数据
双通道
*/
//idx 要播放的文件编号
//DA_ChNum 要使用的PCM通道编号
void 
cm_PlayInit(unsigned int idx,unsigned int DA_ChNum)
{
/*
首先获取要播放的PCM音频的数据的起始地址和文件长度
*/
g_ReadSpiStartAdd[DA_ChNum] = 
cm_PlayInitAddr(idx);
g_ReadSpiEndAdd[DA_ChNum] = 
cm_PlayInitAddr(idx + 1);
/*
判断DA通道,将两个BUFFER都读取数据
*/
if(!DA_ChNum)
{
SPI_ReadNWords(gb_PCMBuffer1,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch1);
g_ReadSpiOffset[DA_ChNum]+=c_ReadSpiSize_Byte;
SPI_ReadNWords(gb_PCMBuffer2,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch1);
}
else
{
SPI_ReadNWords(R_DataBuffer1,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch2);
g_ReadSpiOffset[DA_ChNum]+=c_ReadSpiSize_Byte;
SPI_ReadNWords(R_DataBuffer2,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch2);
}
g_ReadSpiOffset[DA_ChNum] = c_BitClear;
/*
判断是否有DA播放正在进行,
*/
if(!(g_PcmDA_Sts[c_PCM_ID_CH1] | g_PcmDA_Sts[c_PCM_ID_CH2]))//无播放任务,初始化定时器
{
SACM_PCM_Init();
SACM_A1800_DAC_Timer_X1();
}
g_PcmDA_Sts[DA_ChNum] = c_PCM_Playing;//设置某个通道为播放状态
g_FlagPcmEn |= (c_BitSet << DA_ChNum);//使能某个播放通道,为DA输出
}
/*
此函数为主程序调用
*/
void 
cm_ChangeBuffer(void)
{
if(!g_FlagPcmEn)//判断是否有DA播放那个使能
{
g_FlagPcmEn = c_BitClear;
}
if(g_FlagBufferPcmInit & c_PCM_UpdataCH1)//DA通道1
{
g_FlagBufferPcmInit &=~c_PCM_UpdataCH1;//清楚数据更新标记
g_ReadSpiOffset[c_PCM_ID_CH1]+=c_ReadSpiSize_Byte;//文件长度偏移
g_PcmDA_Sts[c_PCM_UpdataCH1] = c_PCM_Playing;//设置为播放状态
if(g_SendBufferIdx[c_PCM_ID_CH1] == 0)//双BUFFER切换,读取
{
SPI_ReadNWords(gb_PCMBuffer2,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch1);
}
else
{
SPI_ReadNWords(gb_PCMBuffer1,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch1);
}
}
if(g_FlagBufferPcmInit & c_PCM_UpdataCH2)
{
g_FlagBufferPcmInit &=~c_PCM_UpdataCH2;
g_ReadSpiOffset[c_PCM_ID_CH2]+=c_ReadSpiSize_Byte;
g_PcmDA_Sts[c_PCM_UpdataCH2] = c_PCM_Playing;
if(g_SendBufferIdx[c_PCM_ID_CH2] == 0)
{
SPI_ReadNWords(R_DataBuffer2,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch2);
}
else
{
SPI_ReadNWords(R_DataBuffer1,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch2);
}
}
}
void 
cm_MainLoop(void)
{
Pcm_ChangeBuffer();
}
void SendIrqBuffer(void)
{
if(!g_FlagPcmEn)
{
g_FlagPcmEn = c_BitClear;
}
if(g_FlagPcmEn & c_PCM_DA_En_Ch1)
{
//大于文件长度,设置播放状态为停止
if(g_ReadSpiOffset[c_PCM_ID_CH1] + g_ReadSpiStartAdd[c_PCM_ID_CH1] >= g_ReadSpiEndAdd[c_PCM_ID_CH1])
{
g_ReadSpiOffset[c_PCM_ID_CH1] = c_BitClear;
g_PcmDA_Sts[0] = c_PCM_Stop;
return;
}
if(g_IrqSendBufferIdx[c_PCM_ID_CH1] >= c_SendPCM_BufferSize)//数据发送
{//双BUFFER切换
g_IrqSendBufferIdx[c_PCM_ID_CH1] = c_BitClear;
g_SendBufferIdx[c_PCM_ID_CH1]++;
if(g_SendBufferIdx[c_PCM_ID_CH1] >= c_BufferNum)
{
g_SendBufferIdx[c_PCM_ID_CH1] = c_BitClear;
}
g_FlagBufferPcmInit = c_BitSet;
}
if(g_SendBufferIdx[c_PCM_ID_CH1] == 1)
{
*P_DAC_CH1_Data = gb_PCMBuffer2[g_IrqSendBufferIdx[c_PCM_ID_CH1]];//往DA输出数据
}
else
{
*P_DAC_CH1_Data = gb_PCMBuffer1[g_IrqSendBufferIdx[c_PCM_ID_CH1]];
}
g_IrqSendBufferIdx[c_PCM_ID_CH1]++;
}
//ch2
if(g_FlagPcmEn & c_PCM_DA_En_Ch2)
{
if(g_ReadSpiOffset[c_PCM_ID_CH2] + g_ReadSpiStartAdd[c_PCM_ID_CH2] >= g_ReadSpiEndAdd[c_PCM_ID_CH2])
{
g_ReadSpiOffset[c_PCM_ID_CH2] = c_BitClear;
g_PcmDA_Sts[1] = c_PCM_Stop;
return;
}
if(g_IrqSendBufferIdx[c_PCM_ID_CH2] >= c_SendPCM_BufferSize)
{
g_IrqSendBufferIdx[c_PCM_ID_CH2] = c_BitClear;
g_SendBufferIdx[c_PCM_ID_CH2]++;
if(g_SendBufferIdx[c_PCM_ID_CH2] >= c_BufferNum)
{
g_SendBufferIdx[c_PCM_ID_CH2] = c_BitClear;
}
g_FlagBufferPcmInit |= 2;
}
if(g_SendBufferIdx[c_PCM_ID_CH2] == 1)
{
*P_DAC_CH2_Data = R_DataBuffer2[g_IrqSendBufferIdx[c_PCM_ID_CH2]];
}
else
{
*P_DAC_CH2_Data = R_DataBuffer1[g_IrqSendBufferIdx[c_PCM_ID_CH2]];
}
g_IrqSendBufferIdx[c_PCM_ID_CH2]++;
}
}
加载中...
查看其它29个回答
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
核心思想,配置定时器,DA,频率为16K,32K等
在读取数据的时候,使用双BUFFER切换,两个缓冲区的大小为64字节,
主循环一直填充BUFFER里面的数据
定时器中断则在BUFFER里面,读取数据
双通道
*/
//idx 要播放的文件编号
//DA_ChNum 要使用的PCM通道编号
void cm_PlayInit(unsigned int idx,unsigned int DA_ChNum)
{
/*
首先获取要播放的PCM音频的数据的起始地址和文件长度
*/
g_ReadSpiStartAdd[DA_ChNum] = cm_PlayInitAddr(idx);
g_ReadSpiEndAdd[DA_ChNum] = cm_PlayInitAddr(idx + 1);
/*
判断DA通道,将两个BUFFER都读取数据
*/
if(!DA_ChNum)
{
SPI_ReadNWords(gb_PCMBuffer1,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch1);
g_ReadSpiOffset[DA_ChNum]+=c_ReadSpiSize_Byte;
SPI_ReadNWords(gb_PCMBuffer2,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch1);
}
else
{
SPI_ReadNWords(R_DataBuffer1,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch2);
g_ReadSpiOffset[DA_ChNum]+=c_ReadSpiSize_Byte;
SPI_ReadNWords(R_DataBuffer2,c_ReadSpiSize_Byte,ReadSpiPcmOffset_Ch2);
}
g_ReadSpiOffset[DA_ChNum] = c_BitClear;
/*
判断是否有DA播放正在进行,
*/
if(!(g_PcmDA_Sts[c_PCM_ID_CH1] | g_PcmDA_Sts[c_PCM_ID_CH2]))//无播放任务,初始化定时器
{
SACM_PCM_Init();
SACM_A1800_DAC_Timer_X1();
}
g_PcmDA_Sts[DA_ChNum] = c_PCM_Playing;//设置某个通道为播放状态
g_FlagPcmEn |= (c_BitSet << DA_ChNum);//使能某个播放通道,为DA输出
}
/*
此函数为主程序调用
*/
void cm_ChangeBuffer(void)
{
if(!g_FlagPcmEn)//判断是否有DA播放那个使能
{
g_FlagPcmEn = c_BitClear;
}
if(g_FlagBufferPcmInit & c_PCM_UpdataCH1)//DA通道1
{
g_FlagBufferPcmInit &=~c_PCM_UpdataCH1;//清楚数据更新标记
g_ReadSpiOffset[c_PCM_ID_CH1]+=c_ReadSpiSize_Byte;//文件长度偏移
g_PcmDA_Sts[c_PCM_UpdataCH1] = c_PCM_Playing;//设置为播放状态
if(g_SendBufferIdx[c_PCM_ID_CH1] == 0)//双BUFFER切换,读取
{
SPI_ReadNWords(gb_PCMBuffer2,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch1);
}
else
{
SPI_ReadNWords(gb_PCMBuffer1,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch1);
}
}
if(g_FlagBufferPcmInit & c_PCM_UpdataCH2)
{
g_FlagBufferPcmInit &=~c_PCM_UpdataCH2;
g_ReadSpiOffset[c_PCM_ID_CH2]+=c_ReadSpiSize_Byte;
g_PcmDA_Sts[c_PCM_UpdataCH2] = c_PCM_Playing;
if(g_SendBufferIdx[c_PCM_ID_CH2] == 0)
{
SPI_ReadNWords(R_DataBuffer2,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch2);
}
else
{
SPI_ReadNWords(R_DataBuffer1,c_SendPCM_BufferSize,ReadSpiPcmOffset_Ch2);
}
}
}
void cm_MainLoop(void)
{
Pcm_ChangeBuffer();
}
void SendIrqBuffer(void)
{
if(!g_FlagPcmEn)
{
g_FlagPcmEn = c_BitClear;
}
if(g_FlagPcmEn & c_PCM_DA_En_Ch1)
{
//大于文件长度,设置播放状态为停止
if(g_ReadSpiOffset[c_PCM_ID_CH1] + g_ReadSpiStartAdd[c_PCM_ID_CH1] >= g_ReadSpiEndAdd[c_PCM_ID_CH1])
{
g_ReadSpiOffset[c_PCM_ID_CH1] = c_BitClear;
g_PcmDA_Sts[0] = c_PCM_Stop;
return;
}
if(g_IrqSendBufferIdx[c_PCM_ID_CH1] >= c_SendPCM_BufferSize)//数据发送
{//双BUFFER切换
g_IrqSendBufferIdx[c_PCM_ID_CH1] = c_BitClear;
g_SendBufferIdx[c_PCM_ID_CH1]++;
if(g_SendBufferIdx[c_PCM_ID_CH1] >= c_BufferNum)
{
g_SendBufferIdx[c_PCM_ID_CH1] = c_BitClear;
}
g_FlagBufferPcmInit = c_BitSet;
}
if(g_SendBufferIdx[c_PCM_ID_CH1] == 1)
{
*P_DAC_CH1_Data = gb_PCMBuffer2[g_IrqSendBufferIdx[c_PCM_ID_CH1]];//往DA输出数据
}
else
{
*P_DAC_CH1_Data = gb_PCMBuffer1[g_IrqSendBufferIdx[c_PCM_ID_CH1]];
}
g_IrqSendBufferIdx[c_PCM_ID_CH1]++;
}
//ch2
if(g_FlagPcmEn & c_PCM_DA_En_Ch2)
{
if(g_ReadSpiOffset[c_PCM_ID_CH2] + g_ReadSpiStartAdd[c_PCM_ID_CH2] >= g_ReadSpiEndAdd[c_PCM_ID_CH2])
{
g_ReadSpiOffset[c_PCM_ID_CH2] = c_BitClear;
g_PcmDA_Sts[1] = c_PCM_Stop;
return;
}
if(g_IrqSendBufferIdx[c_PCM_ID_CH2] >= c_SendPCM_BufferSize)
{
g_IrqSendBufferIdx[c_PCM_ID_CH2] = c_BitClear;
g_SendBufferIdx[c_PCM_ID_CH2]++;
if(g_SendBufferIdx[c_PCM_ID_CH2] >= c_BufferNum)
{
g_SendBufferIdx[c_PCM_ID_CH2] = c_BitClear;
}
g_FlagBufferPcmInit |= 2;
}
if(g_SendBufferIdx[c_PCM_ID_CH2] == 1)
{
*P_DAC_CH2_Data = R_DataBuffer2[g_IrqSendBufferIdx[c_PCM_ID_CH2]];
}
else
{
*P_DAC_CH2_Data = R_DataBuffer1[g_IrqSendBufferIdx[c_PCM_ID_CH2]];
}
g_IrqSendBufferIdx[c_PCM_ID_CH2]++;
}
}
一周热门 更多>