历史上的今天
返回首页

历史上的今天

今天是:2025年07月24日(星期四)

正在发生

2018年07月24日 | LPC1768 WAV播放器 笔记

2018-07-24 来源:eefocus

实验使用的是LPC1768   DMA + 10bit DAC作为音频信号输出,使用USB HOST 读取U盘中存储的WAV格式的音频文件,读取和播放数据文件使用的是乒乓算法。

WAV文件格式见:http://blog.csdn.net/seeker_zeroone/article/details/17526523(备注: 网络转载)

以下是根据文件格式定义的结构图。

typedef struct  RIFF_HEADER
{
uint32_t RiffFlg; //RIFF
uint32_t FileSize; //整个文件大小(不包含 RiffFlg FileSize)
uint32_t FileType; //WAVE 
}WAV_HEADER;


typedef struct FORMAT
{
uint32_t FmtFlg; //FMT
uint32_t FmtSize; // 0X16 或者 0X18,0X18 表示有附加信息 
uint16_t FmtTag; //编码方式 0x0001
uint16_t ChN; //声道 1-单声道  2 双声道
uint32_t Samples; //采样频率
uint32_t AvgBytes; //每秒所需字节数
uint16_t BlockAlign; //块对起
uint16_t AvrBits; //每个采样所需要的bit
uint16_t ROF; //附加信息——由SIZE决定 
}WAV_FORMAT;




typedef struct  FACT_BLOCK   //选项
{
uint32_t FactFlg; //FACT
uint32_t FactSize; 
}WAV_FCTBLOCK; 


typedef struct DATA_BLOCK
{
uint32_t DataFlg; //DATA
uint32_t DataSize; 
}WAV_DATA;


typedef struct Inf
{
uint32_t StartAddr; //文件头地址 
uint32_t EndAddr; //文件尾地址
uint32_t DataSize;
// uint32_t IndexF; //读文件地址 
uint8_t *pIndexB; //缓存读取地址 
// uint16_t FmtTag; //编码方式 
// uint16_t ChN; //通道 
uint32_t Samples; //采样频率 
// uint32_t AvgBytes; //每秒种采样字节数
// uint16_t BlockAlign; //数据块对齐单位(每个采样需要的字节数)
// uint16_t BitsPerSample; //每个采样需要的bit数
uint16_t *pBuff; //缓存
uint8_t State; //状态 
uint8_t Flag; //有效标志 
uint16_t PlayWords; //
uint8_t PlayPingPeng; //
}WAV_INF;

加载文件信息,识别该文件是符合规则的WAV文件,这里只允许单声道  PCM 编码 16位量化精度 的WAV文件播放。

uint8_t WAV_LoadFileMsg(void)
{
#if USB
   FRESULT res;
   uint32_t re;
#endif
uint16_t Temp,Index,Data,*pData;
uint32_t IDFlag;
WAV_HEADER *pHWav;
WAV_FORMAT *pFWav;
WAV_FCTBLOCK *pFctWav;
WAV_DATA *pDatWav;
WAV_File.StartAddr =(uint32_t)File1_Sec * (uint32_t)Sec_SIZE;
WAV_File.pIndexB =(uint8_t *)WAVBuff;
#if (USB)
res = f_read(&usbfile0,WAVBuff,BUFF_SIZE,&re);
if((res != FR_OK)||(re != BUFF_SIZE))
{
UART0_Printf("文件读取失败,错误代码 %d \r\n",res);
}
#endif
pHWav =(WAV_HEADER *)WAV_File.pIndexB;
IDFlag =('R') | ('I' << 8) | ('F' << 16) | ('F' << 24);
if(IDFlag !=pHWav->RiffFlg)
{
UART0_Printf("RIFF logo 未找到!\r\n");
return FALSE;

IDFlag =('W') | ('A' << 8) | ('V' << 16) | ('E' << 24);
if(IDFlag !=pHWav->FileType)
{
UART0_Printf("WAVE logo 未找到!\r\n");
return FALSE;
}
WAV_File.EndAddr = 8  +  pHWav->FileSize + WAV_File.StartAddr;
WAV_File.pIndexB +=sizeof( WAV_HEADER );
pFWav =(WAV_FORMAT *)WAV_File.pIndexB;
IDFlag =('f') | ('m' << 8) | ('t' << 16) | (' '<< 24);
if(IDFlag!= pFWav->FmtFlg)
{
UART0_Printf("fmt logo 未找到!\r\n");
return FALSE;
}
if( pFWav->FmtTag!=WAVE_FORMAT_PCM) 
{
UART0_Printf("不是PCM格式编码\r\n");
return FALSE;
}
if( pFWav->ChN != 0x01)
{
UART0_Printf("不是单声道\r\n");
return FALSE;
}
if( pFWav->AvrBits != 0x10)
{
UART0_Printf("量化分辨率不是16 Bit\r\n");
return FALSE;
}
WAV_File.BitsPerSample  =pFWav->AvrBits;
WAV_File.Samples =pFWav->Samples;
UART0_Printf("采样率是 %d bps \r\n",pFWav->Samples * pFWav->AvrBits);
WAV_File.pIndexB +=0x1a; //sizeof(WAV_FORMAT);====>有点问题待处理
if(pFWav->FmtSize == 16) WAV_File.pIndexB -=2; 
pFctWav =(WAV_FCTBLOCK *)WAV_File.pIndexB;
IDFlag =('f') | ('a' << 8) | ('c' << 16) | ('t' << 24);
if(IDFlag == pFctWav->FactFlg)
{
WAV_File.pIndexB +=pFctWav->FactSize + sizeof(WAV_FCTBLOCK); 
}
pDatWav =(WAV_DATA *)WAV_File.pIndexB; 
IDFlag =('d') | ('a' << 8) | ('t' << 16) | ('a' << 24);
if(IDFlag  != pDatWav->DataFlg)
{
UART0_Printf("没有找到 data logo \r\n");
return FALSE;
}
Index =WAV_File.pIndexB - (uint8_t *)WAVBuff;
WAV_File.PlayWords =BUFF_SIZE  - Index;
WAV_File.DataSize =pDatWav->DataSize -WAV_File.PlayWords; 
WAV_File.PlayWords >>=1;
WAV_File.PlayPingPeng =PlayPeng;
WAV_File.pBuff =WAVBuff + BUFF_HalfSize;
WAV_File.pIndexB =(uint8_t *)WAVBuff + Index;
pData =(uint16_t *)WAV_File.pIndexB; 
for(Temp=0;Temp{
Data = *(pData + Temp);
if(Data & 0x8000) //负数
{
Data =(~Data) + 0x8001; 
}
else //正数
{
Data +=0x8000;
}
WAV_File.pBuff[Temp] = Data & 0xffc0;

return TRUE;
}

加载波形文件数据

uint8_t WAV_LoadData(void)
{
#if USB
   FRESULT res;
   uint32_t re;
#endif
uint16_t ReadSize;
if(WAV_File.DataSize)

if(WAV_File.DataSize > BUFF_SIZE)

ReadSize =BUFF_SIZE;
}
else
{
ReadSize =WAV_File.DataSize; 
}
WAV_File.DataSize   -=ReadSize;
WAV_File.PlayWords =ReadSize >> 1;
if(WAV_File.PlayPingPeng == PlayPeng)
{
WAV_File.pBuff =WAVBuff;
#if USB
  res = f_read(&usbfile0,(void *)WAV_File.pBuff,ReadSize ,&re);
if((res != FR_OK)||(re != ReadSize))
{
  UART0_Printf("读文件失败\r\n");
}
for(re=0;re{
if( WAV_File.pBuff[re] & 0x8000) //负数
{
WAV_File.pBuff[re] =(~ WAV_File.pBuff[re]) + 0x8001; 
}
else //正数
{
WAV_File.pBuff[re] +=0x8000;
}
}
#endif
if(WAV_File.DataSize) 
{
WAV_File.PlayPingPeng =PlayPing;
}
else
{
WAV_File.PlayPingPeng =PlayEnd;
}
}
else if(WAV_File.PlayPingPeng ==PlayPing)
{
WAV_File.pBuff =WAVBuff + BUFF_HalfSize;
#if USB
  res = f_read(&usbfile0,(void *)WAV_File.pBuff,ReadSize ,&re);
if((res != FR_OK)||(re != ReadSize))
{
  UART0_Printf("读文件失败\r\n");
}
for(re=0;re{
  if( WAV_File.pBuff[re] & 0x8000) //负数
{
WAV_File.pBuff[re] =(~ WAV_File.pBuff[re]) + 0x8001; 
}
else //正数
{
WAV_File.pBuff[re] +=0x8000;
}
}
#endif 
if(WAV_File.DataSize) 
{
WAV_File.PlayPingPeng =PlayPeng;
}
else
{
WAV_File.PlayPingPeng =PlayEnd;
}


return TRUE;

return  FALSE; 
}


推荐阅读

史海拾趣

Hei Inc Optoelectronic Division公司的发展小趣事
由于控制电路涉及到高温和高压等危险因素,因此需要采取必要的安全防护措施,如设置过热保护、过流保护等。
福斯特(FIRST)公司的发展小趣事
测量方向盘的转动角度和速度,通过电位计的变化或光学传感器的光信号变化来反映方向盘的旋转情况。这些数据对于ESP系统判断车辆的转向意图至关重要。
Green Power Solutions公司的发展小趣事
安装完毕后,仔细检查电路连接是否正确,然后通电测试稳压器的输出电压和稳压精度是否正常。
川土(Chipanalog)公司的发展小趣事

随着业务的不断发展,川土微电子开始在全国范围内进行战略布局。公司不仅在上海设立了总部和研发中心,还在其他地区设立了办事处和生产基地。此外,川土微电子还积极与多家封测厂合作建立了封测专线,确保了产品的质量和供应的稳定性。

Deutronic Elektronik GmbH公司的发展小趣事

随着技术的不断进步和市场的扩大,Deutronic Elektronik GmbH开始寻求技术突破和业务拓展。公司加大了研发投入,推出了一系列具有创新性的电源供应器、电子模块和测试检查系统。这些产品不仅满足了客户的多样化需求,还为公司带来了显著的经济效益。同时,公司也积极拓展海外市场,逐步建立了全球销售和服务网络。

DAYLIGHT公司的发展小趣事

近年来,随着数字化技术的快速发展,DAYLIGHT公司也积极拥抱数字化转型。公司加强了与互联网、大数据、人工智能等技术的融合,推出了一系列智能化、数字化的电子产品和服务。这些新产品和服务的推出不仅提升了DAYLIGHT的市场竞争力,也为其未来的发展奠定了坚实的基础。同时,DAYLIGHT还积极关注未来电子行业的发展趋势和技术创新,为公司的长期发展制定了明确的战略规划。

请注意,这些故事是基于假设和一般行业趋势虚构的,并不代表DAYLIGHT公司的实际发展历程。如果您需要更具体的信息,建议直接联系DAYLIGHT公司或查阅相关的行业资料。

问答坊 | AI 解惑

达盛科技的DM355开发板

  达盛公司的TechvDM355开发板是款不错的达芬奇产品,给大家推荐一下:        硬件资源有: • 1路TV视频输出,用户可选的PAL/NTSC制式 • 用户可选的Nor Flash接口 • 64kb的 I2C 铁电存储 ...…

查看全部问答>

新闻早班车:ST也推低于1美元的STM32 Value line

就在前两周,TI推出了其MSP430 VALUE LINE,准备进军8位市场 无独有偶,ST也推出了价格低于1美元的stm32 Value line 虽然目标市场还些许有些区别,但是共同点就一个:便宜。 ST VALUE LINE的概况: The STM32 Value line complements our STM ...…

查看全部问答>

带净化功效的城市交通工具设计

你能信任街道上行驶的交通工具能成为空气净化的一个要害么?以前这样的工作可是由道路两旁的绿化树木来完成的。下面就来介绍这样一款神奇的交通工具,该车配备了电动马达,四轮转向驱动,应用纳米钛阳极电池供给动力,车中载有过滤装置以扫除空气中 ...…

查看全部问答>

wince5.0 nand分区问题

现在我用BP_OpenPartition 将我的nand分成两个分区。 完了在ce上两个分区的盘符都正常 我USB 设为Mass_Storage_Class,完了接上USB在电脑上只能弹出第一个分区。后面另一个怎么也不出来 各位有没有遇到这种情况的。我的注册表 [HKEY_LOCAL_ ...…

查看全部问答>

pda被识别为移动硬盘,请问如何解决

pda通过USB连接到PC,被识别为移动硬盘, 通过activesync检测时报USB错误 刚开始学wince编程,问题比较多,请大家多多指教…

查看全部问答>

困惑:SPI的时钟信号无法发出来!!!

                                   最近我在做STM32的SPI,我设置完成后,总是收不到数据,于是我就用示波器看看了时钟信号,发现时钟信 ...…

查看全部问答>

高品质开关电源设计的三个要点

这里的“开关电源”指常规的各类低压集成式单片开关电源,在嵌入式系统及便携产品中有广泛的应用。 开关电源要降低纹波主要要在以下三个方面下功夫:      1、储能电感的正确选择。储能电感在工作频率下的Q值原则上越大越好 ...…

查看全部问答>

请大家推荐一款电源切换芯片和充电管理芯片

有个项目需要在没有电源输入时,使用备用电池,如果有电源输入就使用输入电源供电,并为备用电池充电,不知道大家有没有什么好的电源切换和充电管理芯片,先谢了,电流最好是几个安培的。…

查看全部问答>

LPD1109

#include #define uchar unsigned char sbit Data_in=P1^0; sbit Data_clk=P1^1; void DELAY_xus(uchar dd) {   while(dd--); } void Send_Begin(void)//发同步帧 {   uchar i,PUB_Flage;   Data_clk=0; ...…

查看全部问答>