標(biāo)題:
VS1053裸機(jī)程序 stm32 MP3音樂播放器源代碼
[打印本頁]
作者:
sjx15751948710
時(shí)間:
2017-4-4 09:45
標(biāo)題:
VS1053裸機(jī)程序 stm32 MP3音樂播放器源代碼
基于vs1053 的音樂播放器?梢圆シ臡P3格式的音頻文件.
0.png
(52.06 KB, 下載次數(shù): 143)
下載附件
2017-4-4 14:53 上傳
0.png
(48.44 KB, 下載次數(shù): 124)
下載附件
2017-4-4 14:53 上傳
完整源碼下載:
1.MINI-V3_VS1053裸機(jī)例程.rar
(7.12 MB, 下載次數(shù): 224)
2017-4-4 09:44 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
下面是VS1053 MP3播放程序的主要部分預(yù)覽(stm32單片機(jī)主控):
#include "bsp_SysTick.h"
#include "VS1053.h"
#include "flac.h"
#include "bsp_usart1.h"
#include "string.h"
//VS1053默認(rèn)設(shè)置參數(shù)
_vs1053_obj vsset=
{
220, //音量:220
6, //低音上線 60Hz
15, //低音提升 15dB
10, //高音下限 10Khz
15, //高音提升 10.5dB
0, //空間效果
};
/*******************************************************************************
* Function Name : SPI_FLASH_SendByte
* Description : Sends a byte through the SPI interface and return the byte
* received from the SPI bus.
* Input : byte : byte to send.
* Output : None
* Return : The value of the received byte.
*******************************************************************************/
unsigned char SPI2_ReadWriteByte(unsigned char writedat)
{
/* Loop while DR register in not emplty */
while(SPI_I2S_GetFlagStatus(VS_SPI,SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(VS_SPI, writedat);
/* Wait to receive a byte */
while(SPI_I2S_GetFlagStatus(VS_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(VS_SPI);
}
////////////////////////////////////////////////////////////////////////////////
//移植時(shí)候的接口
//data:要寫入的數(shù)據(jù)
//返回值:讀到的數(shù)據(jù)
u8 VS_SPI_ReadWriteByte(u8 data)
{
return SPI2_ReadWriteByte(data);
}
static void SPI_SetSpeed(u8 SpeedSet)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
SPI2->CR1&=0XFFC7;
SPI2->CR1|=SpeedSet;
SPI_Cmd(SPI2,ENABLE);
}
void VS_SPI_SpeedLow(void)
{
SPI_SetSpeed(SPI_BaudRatePrescaler_32);//設(shè)置到低速模式
}
void VS_SPI_SpeedHigh(void)
{
SPI_SetSpeed(SPI_BaudRatePrescaler_8);//設(shè)置到高速模式
}
//初始化VS1053的IO口
void VS_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(VS_SPIGPIO_CLK|VS_GPIO_DREQ_CLK|VS_GPIO_RST_CLK|VS_GPIO_XDCS_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = VS_DREQ; //DREQ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //輸入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(VS_GPIO_DREQ_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = VS_RST; //PB9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_Init(VS_GPIO_RST_PORT, &GPIO_InitStructure);
/*初始化STM32 SPI2接口*/
RCC_APB1PeriphClockCmd(VS_SPI_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = VS_SCLK | VS_MISO | VS_MOSI;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 復(fù)用輸出
GPIO_Init(VS_SPIGPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = VS_XCS;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推免輸出
GPIO_Init(VS_SPIGPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = VS_XDCS;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推免輸出
GPIO_Init(VS_GPIO_XDCS_PORT, &GPIO_InitStructure);
/* SPI2 配置 */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(VS_SPI, &SPI_InitStructure);
/* 使能 SPI2 */
SPI_Cmd(VS_SPI, ENABLE);
SPI2_ReadWriteByte(0xff);//啟動(dòng)傳輸
}
////////////////////////////////////////////////////////////////////////////////
//軟復(fù)位VS10XX
void VS_Soft_Reset(void)
{
u8 retry=0;
while(VS_DREQ_IN==0); //等待軟件復(fù)位結(jié)束
VS_SPI_ReadWriteByte(0Xff); //啟動(dòng)傳輸
retry=0;
while(VS_RD_Reg(SPI_MODE)!=0x0800) // 軟件復(fù)位,新模式
{
VS_WR_Cmd(SPI_MODE,0x0804); // 軟件復(fù)位,新模式
Delay_ms(2);//等待至少1.35ms
if(retry++>100)break;
}
while(VS_DREQ_IN==0);//等待軟件復(fù)位結(jié)束
retry=0;
while(VS_RD_Reg(SPI_CLOCKF)!=0X9800)//設(shè)置VS1053的時(shí)鐘,3倍頻 ,1.5xADD
{
VS_WR_Cmd(SPI_CLOCKF,0X9800); //設(shè)置VS1053的時(shí)鐘,3倍頻 ,1.5xADD
if(retry++>100)break;
}
Delay_ms(20);
}
//硬復(fù)位MP3
//返回1:復(fù)位失敗;0:復(fù)位成功
u8 VS_HD_Reset(void)
{
u8 retry=0;
VS_RST_CLR;
Delay_ms(20);
VS_XDCS_SET;//取消數(shù)據(jù)傳輸
VS_XCS_SET;//取消數(shù)據(jù)傳輸
VS_RST_SET;
while(VS_DREQ_IN==0&&retry<200)//等待DREQ為高
{
retry++;
Delay_us(50);
};
Delay_ms(20);
if(retry>=200)return 1;
else return 0;
}
//正弦測試
void VS_Sine_Test(void)
{
VS_HD_Reset();
VS_WR_Cmd(0x0b,0X2020); //設(shè)置音量
VS_WR_Cmd(SPI_MODE,0x0820);//進(jìn)入VS10XX的測試模式
while(VS_DREQ_IN==0); //等待DREQ為高
//printf("mode sin:%x\n",VS_RD_Reg(SPI_MODE));
//向VS1053發(fā)送正弦測試命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00
//其中n = 0x24, 設(shè)定VS1053所產(chǎn)生的正弦波的頻率值,具體計(jì)算方法見VS1053的datasheet
VS_SPI_SpeedLow();//低速
VS_XDCS_CLR;//選中數(shù)據(jù)傳輸
VS_SPI_ReadWriteByte(0x53);
VS_SPI_ReadWriteByte(0xef);
VS_SPI_ReadWriteByte(0x6e);
VS_SPI_ReadWriteByte(0x24);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
Delay_ms(100);
VS_XDCS_SET;
//退出正弦測試
VS_XDCS_CLR;//選中數(shù)據(jù)傳輸
VS_SPI_ReadWriteByte(0x45);
VS_SPI_ReadWriteByte(0x78);
VS_SPI_ReadWriteByte(0x69);
VS_SPI_ReadWriteByte(0x74);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
Delay_ms(100);
VS_XDCS_SET;
// //再次進(jìn)入正弦測試并設(shè)置n值為0x44,即將正弦波的頻率設(shè)置為另外的值
// VS_XDCS_CLR;//選中數(shù)據(jù)傳輸
// VS_SPI_ReadWriteByte(0x53);
// VS_SPI_ReadWriteByte(0xef);
// VS_SPI_ReadWriteByte(0x6e);
// VS_SPI_ReadWriteByte(0x44);
// VS_SPI_ReadWriteByte(0x00);
// VS_SPI_ReadWriteByte(0x00);
// VS_SPI_ReadWriteByte(0x00);
// VS_SPI_ReadWriteByte(0x00);
// Delay_ms(100);
// VS_XDCS_SET;
// //退出正弦測試
// VS_XDCS_CLR;//選中數(shù)據(jù)傳輸
// VS_SPI_ReadWriteByte(0x45);
// VS_SPI_ReadWriteByte(0x78);
// VS_SPI_ReadWriteByte(0x69);
// VS_SPI_ReadWriteByte(0x74);
// VS_SPI_ReadWriteByte(0x00);
// VS_SPI_ReadWriteByte(0x00);
// VS_SPI_ReadWriteByte(0x00);
// VS_SPI_ReadWriteByte(0x00);
// Delay_ms(100);
// VS_XDCS_SET;
}
//ram 測試
//返回值:RAM測試結(jié)果
// VS1053如果得到的值為0x83FF,則表明完好;
u16 VS_Ram_Test(void)
{
VS_HD_Reset();
VS_WR_Cmd(SPI_MODE,0x0820);// 進(jìn)入VS10XX的測試模式
while (VS_DREQ_IN==0); // 等待DREQ為高
VS_SPI_SpeedLow();//低速
VS_XDCS_CLR; // xDCS = 1,選擇VS10XX的數(shù)據(jù)接口
VS_SPI_ReadWriteByte(0x4d);
VS_SPI_ReadWriteByte(0xea);
VS_SPI_ReadWriteByte(0x6d);
VS_SPI_ReadWriteByte(0x54);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
VS_SPI_ReadWriteByte(0x00);
Delay_ms(150);
VS_XDCS_SET;
return VS_RD_Reg(SPI_HDAT0);// VS1053如果得到的值為0x83FF,則表明完好;
}
//向VS1053寫命令
//address:命令地址
//data:命令數(shù)據(jù)
void VS_WR_Cmd(u8 address,u16 data)
{
while(VS_DREQ_IN==0);//等待空閑
VS_SPI_SpeedLow();//低速
VS_XDCS_SET;
VS_XCS_CLR;
VS_SPI_ReadWriteByte(VS_WRITE_COMMAND);//發(fā)送VS10XX的寫命令
VS_SPI_ReadWriteByte(address); //地址
VS_SPI_ReadWriteByte(data>>8); //發(fā)送高八位
VS_SPI_ReadWriteByte(data); //第八位
VS_XCS_SET;
VS_SPI_SpeedHigh(); //高速
}
//向VS10XX寫數(shù)據(jù)
//data:要寫入的數(shù)據(jù)
void VS_WR_Data(u8 data)
{
VS_SPI_SpeedHigh();//高速,對VS1003B,最大值不能超過36.864/4Mhz,這里設(shè)置為9M
VS_XDCS_CLR;
VS_SPI_ReadWriteByte(data);
VS_XDCS_SET;
}
//讀VS10XX的寄存器
//address:寄存器地址
//返回值:讀到的值
//注意不要用倍速讀取,會(huì)出錯(cuò)
u16 VS_RD_Reg(u8 address)
{
u16 temp=0;
while(VS_DREQ_IN==0);//非等待空閑狀態(tài)
VS_SPI_SpeedLow();//低速
VS_XDCS_SET;
VS_XCS_CLR;
VS_SPI_ReadWriteByte(VS_READ_COMMAND); //發(fā)送VS10XX的讀命令
VS_SPI_ReadWriteByte(address); //地址
temp=VS_SPI_ReadWriteByte(0xff); //讀取高字節(jié)
temp=temp<<8;
temp+=VS_SPI_ReadWriteByte(0xff); //讀取低字節(jié)
VS_XCS_SET;
VS_SPI_SpeedHigh();//高速
return temp;
}
//讀取VS10xx的RAM
//addr:RAM地址
//返回值:讀到的值
u16 VS_WRAM_Read(u16 addr)
{
u16 res;
VS_WR_Cmd(SPI_WRAMADDR, addr);
res=VS_RD_Reg(SPI_WRAM);
return res;
}
//寫VS10xx的RAM
//addr:RAM地址
//val:要寫入的值
void VS_WRAM_Write(u16 addr,u16 val)
{
VS_WR_Cmd(SPI_WRAMADDR,addr); //寫RAM地址
while(VS_DREQ_IN==0); //等待空閑
VS_WR_Cmd(SPI_WRAM,val); //寫RAM值
}
//設(shè)置播放速度(僅VS1053有效)
//t:0,1,正常速度;2,2倍速度;3,3倍速度;4,4倍速;以此類推
void VS_Set_Speed(u8 t)
{
VS_WRAM_Write(0X1E04,t); //寫入播放速度
}
//FOR WAV HEAD0 :0X7761 HEAD1:0X7665
//FOR MIDI HEAD0 :other info HEAD1:0X4D54
//FOR WMA HEAD0 :data speed HEAD1:0X574D
//FOR MP3 HEAD0 :data speed HEAD1:ID
//比特率預(yù)定值,階層III
const u16 bitrate[2][16]=
{
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}
};
//返回Kbps的大小
//返回值:得到的碼率
u16 VS_Get_HeadInfo(void)
{
unsigned int HEAD0;
unsigned int HEAD1;
HEAD0=VS_RD_Reg(SPI_HDAT0);
HEAD1=VS_RD_Reg(SPI_HDAT1);
//printf("(H0,H1):%x,%x\n",HEAD0,HEAD1);
switch(HEAD1)
{
case 0x7665://WAV格式
case 0X4D54://MIDI格式
case 0X4154://AAC_ADTS
case 0X4144://AAC_ADIF
case 0X4D34://AAC_MP4/M4A
case 0X4F67://OGG
case 0X574D://WMA格式
case 0X664C://FLAC格式
{
//printf("HEAD0:%d\n",HEAD0);
HEAD1=HEAD0*2/25;//相當(dāng)于*8/100
if((HEAD1%10)>5)return HEAD1/10+1;//對小數(shù)點(diǎn)第一位四舍五入
else return HEAD1/10;
}
default://MP3格式,僅做了階層III的表
{
HEAD1>>=3;
HEAD1=HEAD1&0x03;
if(HEAD1==3)HEAD1=1;
else HEAD1=0;
return bitrate[HEAD1][HEAD0>>12];
}
}
}
//得到平均字節(jié)數(shù)
//返回值:平均字節(jié)數(shù)速度
u32 VS_Get_ByteRate(void)
{
return VS_WRAM_Read(0X1E05);//平均位速
}
//得到需要填充的數(shù)字
//返回值:需要填充的數(shù)字
u16 VS_Get_EndFillByte(void)
{
return VS_WRAM_Read(0X1E06);//填充字節(jié)
}
//發(fā)送一次音頻數(shù)據(jù)
//固定為32字節(jié)
//返回值:0,發(fā)送成功
// 1,VS10xx不缺數(shù)據(jù),本次數(shù)據(jù)未成功發(fā)送
u8 VS_Send_MusicData(u8* buf)
{
u8 n;
if(VS_DREQ_IN!=0) //送數(shù)據(jù)給VS10XX
{
VS_XDCS_CLR;
for(n=0;n<32;n++)
{
VS_SPI_ReadWriteByte(buf[n]);
}
VS_XDCS_SET;
}else return 1;
return 0;//成功發(fā)送了
}
//切歌
//通過此函數(shù)切歌,不會(huì)出現(xiàn)切換“噪聲”
void VS_Restart_Play(void)
{
u16 temp;
u16 i;
u8 n;
u8 vsbuf[32];
for(n=0;n<32;n++)vsbuf[n]=0;//清零
temp=VS_RD_Reg(SPI_MODE); //讀取SPI_MODE的內(nèi)容
temp|=1<<3; //設(shè)置SM_CANCEL位
temp|=1<<2; //設(shè)置SM_LAYER12位,允許播放MP1,MP2
VS_WR_Cmd(SPI_MODE,temp); //設(shè)置取消當(dāng)前解碼指令
for(i=0;i<2048;) //發(fā)送2048個(gè)0,期間讀取SM_CANCEL位.如果為0,則表示已經(jīng)取消了當(dāng)前解碼
{
if(VS_Send_MusicData(vsbuf)==0)//每發(fā)送32個(gè)字節(jié)后檢測一次
{
i+=32; //發(fā)送了32個(gè)字節(jié)
temp=VS_RD_Reg(SPI_MODE); //讀取SPI_MODE的內(nèi)容
if((temp&(1<<3))==0)break; //成功取消了
}
}
if(i<2048)//SM_CANCEL正常
{
temp=VS_Get_EndFillByte()&0xff;//讀取填充字節(jié)
for(n=0;n<32;n++)vsbuf[n]=temp;//填充字節(jié)放入數(shù)組
for(i=0;i<2052;)
{
if(VS_Send_MusicData(vsbuf)==0)i+=32;//填充
}
}else VS_Soft_Reset(); //SM_CANCEL不成功,壞情況,需要軟復(fù)位
temp=VS_RD_Reg(SPI_HDAT0);
temp+=VS_RD_Reg(SPI_HDAT1);
if(temp) //軟復(fù)位,還是沒有成功取消,放殺手锏,硬復(fù)位
{
VS_HD_Reset(); //硬復(fù)位
VS_Soft_Reset(); //軟復(fù)位
}
}
//重設(shè)解碼時(shí)間
void VS_Reset_DecodeTime(void)
{
VS_WR_Cmd(SPI_DECODE_TIME,0x0000);
VS_WR_Cmd(SPI_DECODE_TIME,0x0000);//操作兩次
}
//得到mp3的播放時(shí)間n sec
//返回值:解碼時(shí)長
u16 VS_Get_DecodeTime(void)
{
u16 dt=0;
dt=VS_RD_Reg(SPI_DECODE_TIME);
return dt;
}
//vs10xx裝載patch.
//patch:patch首地址
//len:patch長度
void VS_Load_Patch(u16 *patch,u16 len)
{
u16 i;
u16 addr, n, val;
for(i=0;i<len;)
{
addr = patch[i++];
n = patch[i++];
if(n & 0x8000U) //RLE run, replicate n samples
{
n &= 0x7FFF;
val = patch[i++];
while(n--)VS_WR_Cmd(addr, val);
}else //copy run, copy n sample
{
while(n--)
{
val = patch[i++];
VS_WR_Cmd(addr, val);
}
}
}
}
//設(shè)定VS10XX播放的音量和高低音
//volx:音量大小(0~254)
void VS_Set_Vol(u8 volx)
{
u16 volt=0; //暫存音量值
volt=254-volx; //取反一下,得到最大值,表示最大的表示
volt<<=8;
volt+=254-volx; //得到音量設(shè)置后大小
VS_WR_Cmd(SPI_VOL,volt);//設(shè)音量
}
//設(shè)定高低音控制
//bfreq:低頻上限頻率 2~15(單位:10Hz)
//bass:低頻增益 0~15(單位:1dB)
//tfreq:高頻下限頻率 1~15(單位:Khz)
//treble:高頻增益 0~15(單位:1.5dB,小于9的時(shí)候?yàn)樨?fù)數(shù))
void VS_Set_Bass(u8 bfreq,u8 bass,u8 tfreq,u8 treble)
{
u16 bass_set=0; //暫存音調(diào)寄存器值
signed char temp=0;
if(treble==0)temp=0; //變換
else if(treble>8)temp=treble-8;
else temp=treble-9;
bass_set=temp&0X0F; //高音設(shè)定
bass_set<<=4;
bass_set+=tfreq&0xf; //高音下限頻率
bass_set<<=4;
bass_set+=bass&0xf; //低音設(shè)定
bass_set<<=4;
bass_set+=bfreq&0xf; //低音上限
VS_WR_Cmd(SPI_BASS,bass_set); //BASS
}
//設(shè)定音效
//eft:0,關(guān)閉;1,最小;2,中等;3,最大.
void VS_Set_Effect(u8 eft)
{
u16 temp;
temp=VS_RD_Reg(SPI_MODE); //讀取SPI_MODE的內(nèi)容
if(eft&0X01)temp|=1<<4; //設(shè)定LO
else temp&=~(1<<5); //取消LO
if(eft&0X02)temp|=1<<7; //設(shè)定HO
else temp&=~(1<<7); //取消HO
VS_WR_Cmd(SPI_MODE,temp); //設(shè)定模式
}
///////////////////////////////////////////////////////////////////////////////
//設(shè)置音量,音效等.
void VS_Set_All(void)
{
VS_Set_Vol(vsset.mvol); //設(shè)置音量
VS_Set_Bass(vsset.bflimit,vsset.bass,vsset.tflimit,vsset.treble);
VS_Set_Effect(vsset.effect); //設(shè)置空間效果
}
/*-------------- 以上是VS1053驅(qū)動(dòng)部分 -------------------------*/
/*-------------- 下面開始是音樂播放部分 -------------------------*/
#include "ff.h"
#include "bsp_led.h"
/*
************************************************************************
* FatFs
************************************************************************
*/
FRESULT result;
FIL file;
UINT bw;
static uint8_t buffer[BUFSIZE];
//播放歌曲
void vs1053_player_song(uint8_t *filepath)
{
uint16_t i=0;
VS_Restart_Play();
VS_Set_All();
VS_Reset_DecodeTime();
if(strstr((const char*)filepath,".flac")||strstr((const char*)filepath,".FLAC"))//檢索字符
VS_Load_Patch((u16*)vs1053b_patch,VS1053B_PATCHLEN);
result=f_open(&file,(const TCHAR*)filepath,FA_READ);
if(result==0)
{
VS_SPI_SpeedHigh();
while(1)
{
i=0;
result=f_read(&file,buffer,BUFSIZE,(UINT*)&bw);
do
{
if(VS_Send_MusicData(buffer+i)==0)
{
i+=32;
}
}while(i<bw);
if(bw!=BUFSIZE||result!=0)
{
break;
}
LED2_TOGGLE;
}
f_close(&file);
}
}
/*-------------- END OF FILE -----------------------*/
復(fù)制代碼
作者:
對對對啊
時(shí)間:
2017-12-5 19:16
看看,正需要呢。。。。。。。。。。。。。。。。。
作者:
Luke_dc
時(shí)間:
2018-4-18 15:00
good
作者:
popkart123
時(shí)間:
2018-5-19 12:42
謝謝分享,先下載 有時(shí)間慢慢研究
作者:
qpzm
時(shí)間:
2018-5-19 13:12
這個(gè)是MP3 解碼吧
作者:
WITHER
時(shí)間:
2018-5-19 16:49
多謝樓主分享啊,使用的很好
作者:
學(xué)單片機(jī)的小銘
時(shí)間:
2020-8-28 19:37
請問如何實(shí)現(xiàn)暫停與播放的功能呢
作者:
xingguang11
時(shí)間:
2025-3-27 16:41
看看咋樣
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1