⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 部功能。本手册中没有提供CH375 在USB 设备方式下的说明
💻 C
字号:
/* 2006.10.15
****************************************
**  Copyright  (C)  W.ch  1999-2006   **
**  Web:  http://www.wch.cn  **
****************************************
**  Mp3 Module Test      @CH375  **
**  TC2.0@PC, KC7.0@MCS51             **
****************************************
*/

#include <reg52.h>
#include <string.h>
#include <stdio.h>

#define MAX_PATH_LEN			64		// 最大路径长度,含所有斜杠分隔符和小数点间隔符以及路径结束符00H,CH375模块支持的最大值是62,最小值是1
#include "CH375HM.H"

/*	该程序查找U盘中的/C51/CH375HFT.MP3文件
	1.若找到,则播放,播放完毕,获取U盘中第一个音频文件名,并播放,播放完毕枚举下一曲。
	2.找不到,则获取U盘中第一个音频文件名, 并播放,播放完毕枚举下一曲。
*/
/*  电路连接方式,只需要连接3根线,使用串口同步码启动操作
		PC			单片机		模块
		RXD		=	TXD		=	RXD
		--		=	RXD		=	TXD
		GND	    =	GND		=	GND
*/
//  说明:
// 	1. 在通过PC监视演示过程中,当向PC发送演示信息时,模块也会收到数据,频繁进入串口中断,但会忽略收到的数据。
//  2. 模块必须先上电
//  3. 晶振:24M,波特率:9600bps
//  4. 若启用PC监视,开放宏PC_DEMO

//	#define PC_DEMO	1					// 启用PC监视

#define CMD_RootMp3Inf          0xE0	// 枚举U盘中所有音频文件数量
#define CMD_Decode				0xE1	// 播放当前音频文件
#define CMD_Pause				0xE2    // 暂停播放
#define CMD_Stop				0xE3	// 停止播放
#define CMD_VolumeH	     		0xE4	// 音量增大
#define CMD_VolumeL		    	0xE5	// 音量减小
#define CMD_EnumUpMp3      	    0xE6	// 枚举上一个文件
#define CMD_EnumDownMp3      	0xE7	// 枚举下一个文件
#define CMD_EnumCurrent			0xE8	// 枚举第一首音频文件
#define CMD_AutoDec		    	0xEF	// 自动播放

CMD_PARAM	idata	mCmdParam;			// 默认情况下该结构将占用60字节的RAM,可以修改MAX_PATH_LEN常量,当修改为32时,只占用32字节的RAM
sbit	LED_OUT		=	P1^4;			// P1.4 低电平驱动LED显示,用于监控演示程序的进度

/* 以毫秒为单位延时,适用于24MHz时钟 */
void	mDelaymS( unsigned char delay )
{
	unsigned char	i, j, c;
	for ( i = delay; i != 0; i -- )
	{
		for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
		for ( j = 200; j != 0; j -- ) c += 3;  /* 在24MHz时钟下延时500uS */
	}
}

/* 发送一个字节数据给CH375模块 */
void mSendByte( unsigned char c )
{
	TI = 0;
	SBUF = c;
	while ( TI == 0 );
}

/* 从CH375模块接收一个字节数据 */
unsigned char mRecvByte( )
{
	unsigned char	c;
	
	while ( RI == 0 );
	c = SBUF;
	RI = 0;
	return c;
}

/* 执行命令 */
unsigned char	ExecCommand( unsigned char cmd, unsigned char len )
/* 输入命令码和输入参数长度,返回操作状态码,输入参数和返回参数都在CMD_PARAM结构中 */
{
	unsigned char i, j, status;
	mSendByte( SER_SYNC_CODE1 );  /* 发送串口同步码通知模块,说明命令码开始发送,请求开始执行命令 */
	mSendByte( SER_SYNC_CODE2 );  /* 用两个串口同步码代替STA#的下降沿 */
/* 上面两个串口同步码应该连续发送,如果不连续,那么间隔时间不能超过20mS,否则命令无效 */
	RI = 0;
	mSendByte( cmd );  /* 写入命令码 */
	mSendByte( len );  /* 写入后续参数的长度 */
	if ( len ) {  /* 有参数 */
		for ( i = 0; i != len; i ++ ) mSendByte( mCmdParam.Other.mBuffer[ i ] );  /* 依次写入参数 */
	}
	while ( 1 ) {  /* 处理数据传输,直到操作完成才退出 */
		status = mRecvByte( );  /* 等待模块完成操作并返回操作状态 */
		if ( status == ERR_SUCCESS ) {  /* 操作成功 */
			i = mRecvByte( );  /* 返回结果数据的长度 */
			if ( i ) {  /* 有结果数据 */
				j = 0;
				do {  /* 使用do+while结构是因为其效率高于for */
					mCmdParam.Other.mBuffer[ j ] = mRecvByte( );  /* 接收结果数据并保存到参数结构中 */
					j ++;
				} while ( -- i );
			}
			break;  /* 操作成功返回 */
		}
		else if ( status == USB_INT_DISK_READ || status == USB_INT_DISK_WRITE || status == USB_INT_DISK_RETRY ) {  /* 正在从U盘读数据块,请求数据读出,正在向U盘写数据块,请求数据写入,读写数据块失败重试 */
			break;  /* 本程序只使用以字节为单位的文件读写子程序,所以正常情况下不会收到该状态码,操作失败返回 */
		}
		else {  /* 操作失败 */
			if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT )
				mDelaymS( 100 );  /* U盘刚刚连接或者断开,应该延时几十毫秒再操作 */
			break;  /* 操作失败返回 */
		}
	}
	return( status );
}

/* 检查操作状态,如果错误则显示错误代码并停机 */
void	mStopIfError( unsigned char iError )
{
	unsigned char	led;
	if ( iError == ERR_SUCCESS ) return;  /* 操作成功 */
#ifdef PC_DEMO
	printf( "\nPC_DEMO: Error: %02x\n", (unsigned short)iError );  /* 显示错误 */
#endif
	led = 0;
	while(1)
	{
		LED_OUT = led & 1;  /* LED闪烁 */
		mDelaymS( 100 );
		led ^= 1;
	}
}

void main(void)
{
	unsigned char i;
	unsigned char mCmdCode;								// 命令码
	

	LED_OUT = 0; 										// 开机后LED亮一下以示工作
	mDelaymS(100);
	LED_OUT = 1;
// 设置与Mp3模块通讯的串口
	SCON = 0x50;
	PCON = 0x80;
	TMOD = 0x21;
	TH1 = 0xF3;		// 24MHz晶振, 9600bps
	TR1 = 1;
	TI = 1;

#ifdef PC_DEMO
	printf("\nPC_DEMO: Start Demo\n");	
#endif
	while( 1 )												// 使用查询方式看U盘是否连接
	{	
		i = ExecCommand( CMD_QueryStatus, 0 );				// 查询当前模块的状态
		mStopIfError( i );
		if ( mCmdParam.Status.mDiskStatus >= DISK_CONNECT )
			break;  										// U盘已经连接
		mDelaymS( 100 );									// 可以在打算读写U盘时再查询,没有必要一直连续不停地查询,可以让单片机做其它事,没事可做就延时等待一会再查询
	}
	mDelaymS( 200 );										// 延时,可选操作,有的USB存储器需要几十毫秒的延时
	LED_OUT = 0;

	for( i = 0; i < 5; i ++ )								// 检查U盘是否准备好,大多数U盘不需要这一步,但是某些U盘必须要执行这一步才能工作
	{
		mDelaymS( 100 );
#ifdef PC_DEMO
		printf("\nPC_DEMO: Ready?\n");
#endif
		if ( ExecCommand( CMD_DiskReady, 0 ) == ERR_SUCCESS )
		{
#ifdef PC_DEMO
			printf("\nPC_DEMO: Disk is Ready!\n");
#endif
			break;											// 查询磁盘是否准备好
		}
	}
#ifdef PC_DEMO
	printf("\nPC_DEMO: Search File:/C51/CH375HFT.MP3\n");
#endif
	strcpy(mCmdParam.Open.mPathName, "/C51/CH375HFT.MP3");			// 文件名,该文件在C51子目录下
	i = ExecCommand(CMD_FileOpen,MAX_PATH_LEN);				// 打开文件,输入参数置为最大值,省得再计算参数长度
	if ( i == ERR_MISS_DIR || i == ERR_MISS_FILE )  /* ERR_MISS_DIR说明没有找到C51子目录,ERR_MISS_FILE说明没有找到文件 */
	{
#ifdef PC_DEMO
		printf("\nPC_DEMO: Can't Find File:/C51/CH375HFT.MP3\n" );
#endif
EnumAllFile:
		mCmdCode = CMD_EnumCurrent;
		while(1)
		{
			switch(mCmdCode)
			{
				case CMD_EnumCurrent:
				{
					i = ExecCommand(CMD_EnumCurrent,0);
					mStopIfError(i);
#ifdef PC_DEMO
					printf("\nPC_DEMO: Current File Is:%s\n",mCmdParam.Other.mBuffer);
#endif
					mCmdCode = CMD_Decode;
				}break;
				case CMD_EnumDownMp3:
				{
#ifdef PC_DEMO
					printf("\nPC_DEMO: Enum Next Files:...\n");
#endif
					i = ExecCommand( CMD_EnumDownMp3,0 );
					mStopIfError( i );
#ifdef PC_DEMO
					printf("\nPC_DEMO: Current File Is:%s\n",mCmdParam.Other.mBuffer);
#endif
					mCmdCode = CMD_Decode;
				}break;
				case CMD_Decode:
				{
#ifdef PC_DEMO
					printf("\nPC_DEMO: Paly...\n");
#endif
					i = ExecCommand(CMD_Decode,0);
					mStopIfError(i);
CONTINUE0:			i = mRecvByte();
					if(i == 0xF2) mCmdCode = CMD_EnumDownMp3;
					else goto CONTINUE0;
				}break;
			}
		}
	}
	else
	{
		mStopIfError(i);
		i = ExecCommand(CMD_Decode,0);
		mStopIfError(i);
#ifdef PC_DEMO
		printf("\nPC_DEMO: Play:/C51/CH375HFT.MP3\n");
#endif
CONTINUE1:
		i = mRecvByte();
		if(i == 0xF2) goto EnumAllFile;
		else goto CONTINUE1;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -