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

📄 main.c

📁 MP3_PLAYER.rar
💻 C
字号:
/*******************************************************************************
* File Name          : main.c
* Author             : Wuhan R&D Center, Embest
* Date First Issued  : 08/08/2008
* Description        : Main program body
********************************************************************************/

/*******************************************************************************
Wave播放器,支持FAT16文件系统,支持长文件名和汉字。
命令说明:
dir:      列出当前目录的所有项包括文件和子目录
cd:      后跟子目录名,或“..”到上一级目录。
read:     后跟文件名。读出并输出文件的ASCII码。可以正确显示文本文件如以txt,c,h,s
		  为后缀的文件
free:     查看SD卡空闲空间
play:     后跟要播放的WAVE文件。用来播放WAVE文件。注意,WAV文件需要转化为单声道,
		  8位,8KHZ的格式
*******************************************************************************/ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_lib.h"
#include "hw_config.h"
#include "config.h"
#include "fat16.h"
#include "msd.h"

/* Private define ------------------------------------------------------------*/
#define TIM2ARRValue    9000 /* 8KHz = 72MHz / 9000 */

/* Global variables-----------------------------------------------------------*/
/*******************************************************************************
以下为两个缓存,为了连续播放声音,需要用两个缓存
并行给播放器和读文件缓存播放器在用其中一个缓存时,
将文件流读入另一个缓存这样在播放器用完缓存便可立即
使用另一个存有正确数据的缓存.(读文件需要一定的时间)
*******************************************************************************/ 
u8  Stream_Buff[2][buffsize];
u8  SBNo;					//标识读文件使用哪个缓存
u8  readNextBytes; 
s16 Out_Data_Offset;

/* Extern declare -------------------------------------------------------------*/
extern void SetupUART1(void);
extern void Speaker_Timer_Config(void);
extern void Get_Medium_Characteristics(void);

extern u32 Mass_Block_Count;
extern u32 Mass_Block_Size;
extern u32 Mass_Memory_Size;

/*******************************************************************************
* Function Name  : USART_Scanf_Name
* Description    : Gets Char values from the hyperterminal.
* Input          : None
* Output         : None
* Return         : Length
*******************************************************************************/
u8 USART_Scanf_Name(u8 * str)
{	
  u8 index = 0;
  while(1) 
  {
    /* Loop until RXNE = 1 */
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
    {
    }
    str[index++] = (USART_ReceiveData(USART1));
	printf("%c",str[index - 1]);
	if(str[index - 1] == 13)
	{  
	    index--;
	    return index;
    }
  }													
}

/*******************************************************************************
* Function Name  : USART_Scanf_Cmd
* Description    : Gets Char values from the hyperterminal.
* Input          : None
* Output         : None
* Return         : Length
*******************************************************************************/
u8 USART_Scanf_Cmd(u8 * str)
{	
  u8 index = 0;
  while(1) 
  {
    /* Loop until RXNE = 1 */
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
    {
    }
    str[index++] = (USART_ReceiveData(USART1));
	printf("%c",str[index - 1]);
	if(str[index - 1] == 13 || str[index - 1] == 32)
	{  
	    index--;
	    return index;
    }
  }
}

/*******************************************************************************
* Function Name  : Equal
* Description    : Compare the string A and B
* Input          : A-- one string,B-- anohter string,SizeB-- the size of string
* Output         : None
* Return         : 1-- Equal 0-- Not Equal
*******************************************************************************/
u8 Equal(void* A, void* B, u8 SizeA, u8 SizeB)
{
	u8 i, *a = A, *b = B;
	if(SizeA != SizeB)
        return 0;
	for(i = 0; i < SizeA; i++)
		if(a[i] != b[i])
			return 0;
	return 1;
}

/*******************************************************************************
* Function Name  : PrintPass
* Description    : Print the pass
* Input          : pass-- the pass string
* Output         : None
* Return         : None
*******************************************************************************/
void PrintPass(u8 * pass)
{
   	printf("\r\nX:");
	while(* pass != '\0')
	   printf("%c",*(pass++));
	printf(">");
}

/*******************************************************************************
* Function Name  : SetupClock.
* Description    : Setup the system's clock
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
void SetupClock(void)
{

  ErrorStatus HSEStartUpStatus;
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
    /* PCLK2 = HCLK/2 */
    RCC_PCLK2Config(RCC_HCLK_Div2); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

	/* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
 
   /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08);
    
  }

/* Enable peripheral clocks --------------------------------------------------*/
  /* GPIOA, GPIOB and SPI1 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOE |
                         RCC_APB2Periph_USART1 |RCC_APB2Periph_SPI1, ENABLE);
  
  /* SysTick event each 10 ms with input clock equal to 9MHz (HCLK/8)         */
  SysTick_SetReload(90000);

  SysTick_ITConfig(ENABLE);             /* Enable SysTick interrupt           */
}

void Sleep(u32 cpt_loop)
{
  cpt_loop = cpt_loop * 10000;
  while (cpt_loop -- != 0);
}   
/*******************************************************************************
* Function Name  : main.
* Description    : Main routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int main(void)
{	
	u8 ret = 1;

	u32 currSec; 	// currSec记录当前目录所在的首扇区 ,fileSec记录打开文件首扇区
    u32 temp ,fileoffset;
	u8 pass[512];					// 记录路径
	u8 foldername[128];				// 文件或目录名
    u8 command[4];					// 记录命令
	u8 len1,len2;
	u32 tmp;
	s16 index;
	SetupClock ();
  	SetupUART1 ();
    ret = MSD_Init();
    printf("\r\nMSD_Init result: %d",ret);
	Get_Medium_Characteristics();
	printf("\r\nMsdBlockCount: %d",Mass_Block_Count);
	printf("\r\nMsdBlockSize: %d Byte",Mass_Block_Size);
	printf("\r\nMsdMemorySize: %d MB\r\n",Mass_Memory_Size/1024/1024);
 	
  	FAT_Init();
	currSec = DirStartSec();							// 找到根目录的开始扇区号
	pass[0] = '\\';
	pass[1] = '\0';
    index = 0;	
	while(1)
	{
	   PrintPass(pass);
       len1 = USART_Scanf_Cmd(command);
	   if(Equal(command, "dir",len1,3))					// 列出目录中所有项	
	   {
	       printf("\r\n\r\n");
           List_AllDir_Long(currSec);
		}
       else if(Equal(command, "cd",len1,2)) 			// 更改路径	
   	   {    
           len2 = USART_Scanf_Name(foldername);
		   temp = SearchFoler(currSec, foldername, len2, 1);
		   if(temp)
		   {
	 		  currSec = temp;	 
			  if(Equal(foldername, "..",len2,2))   		// 上级目录,修改路径
			  {
			      if(index > 0)
				  {
	    		      while(pass[--index] != '\\') ;
        			  pass[index + 1] = '\0';
				  }
			  }
			  else if(Equal(foldername, ".",len2,1)) ;  // 当前目录,路径保持不变
			  else 										// 子目录,修改路径
			  {
	    		  for(tmp = 0; tmp < len2; tmp++) 		// 记录路径
	    		      pass[++index] = foldername[tmp];
				  pass[++index] = '\\';
    			  pass[index + 1] = '\0';
			  }			 
		   }
    	}
       else if(	Equal(command, "read",len1,4))			// 以文本文件的方式打开文件	
	   {
           len2 = USART_Scanf_Name(foldername);
		   temp = SearchFoler(currSec, foldername, len2, 0); // 查找文件,并返回长度
		   if(temp)										// 找到文件
		   {	 
			   printf("\r\n");
			   // 输出文件内容
			   for( fileoffset = 0 ; fileoffset < temp / buffsize ; fileoffset++)
			   {
    			   FAT_FileRead(fileoffset * buffsize, buffsize, Stream_Buff[0]);
    			   for(tmp = 0; tmp < buffsize; tmp++)
				      printf("%c", Stream_Buff[0][tmp]);
			   }

			   FAT_FileRead(fileoffset * buffsize , temp % buffsize, Stream_Buff[0]);
			   for( tmp = 0; tmp < temp % buffsize; tmp ++)
                  printf("%c",Stream_Buff[0][tmp]);

           }
	   }
	   else if(	Equal(command, "free",len1,4))					// 计算剩余空间	
	   {
		   printf("\r\n\r\nfree space: %dMB\r\n",CalcuFreeSpace() / 1024 / 1024);
	   }
	   else if(	Equal(command, "play",len1,4))					// 播放wave文件	
	   {

		   readNextBytes = 1;
		   Out_Data_Offset = 0;
           len2 = USART_Scanf_Name(foldername);
		   temp = SearchFoler(currSec, foldername, len2, 0); 	// 查找文件,并返回长度
		   if(temp)												// 找到文件
		   {
    		   FAT_FileRead(0 , buffsize, Stream_Buff[0]); 		// 读取头一个文件流
			   fileoffset = 1;
			   SBNo = 0;
			   printf("\r\nplaying...");
	 	       Set_System();
               Speaker_Timer_Config();
               NVIC_Config();		      			   
			   while(1)
			   {
			       if(readNextBytes)
				   {
    				   if(fileoffset < temp / buffsize)
            		   	   FAT_FileRead(fileoffset++ * buffsize, buffsize, Stream_Buff[1-SBNo]);
    				   else
					   {
			    		    FAT_FileRead(fileoffset++ * buffsize, temp % buffsize, Stream_Buff[1-SBNo]);
                            // 停止TIM4和TIM2
						    TIM_Cmd(TIM4, DISABLE);
							TIM_Cmd(TIM2, DISABLE);							 
                            break; 								// 返回
				       }
					   readNextBytes = 0;
				   }
				   
			   }
			   
           }

	   }

	}

}

/*******************************************************************************
* Function Name  : Speaker_Timer_Config
* Description    : Configure and enable the timer
* Input          : None.
* Return         : None.
*******************************************************************************/
void Speaker_Timer_Config(void)
{
  /* Peripherals InitStructure define */
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef        TIM_OCInitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;


  /* Configure PB.08 as alternate function (TIM4_OC3) */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* TIM4 configuration */
  TIM_TimeBaseStructure.TIM_Prescaler = 0x00; /* TIM4CLK = 72 MHz */
  TIM_TimeBaseStructure.TIM_Period = 0xFF;   /* PWM frequency : 281.250KHz*/
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  /* TIM4's Channel3 in PWM1 mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_Channel_3;
  TIM_OCInitStructure.TIM_Pulse = 0x7F;  /* Duty cycle: 50%*/
  TIM_OC1Init(TIM4, &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);

  /* TIM2 configuration */
  TIM_TimeBaseStructure.TIM_Period = TIM2ARRValue;
  TIM_TimeBaseStructure.TIM_Prescaler = 0x00;    /* TIM2CLK = 72 MHz */
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;	
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;	
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  /* Output Compare Inactive Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;
  TIM_OCInitStructure.TIM_OutputState = TIM_Channel_1;
  TIM_OCInitStructure.TIM_Pulse = 0x0;
  TIM_OC1Init(TIM2, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);

  /* Start TIM4 */
  TIM_Cmd(TIM4, ENABLE);

  /* Start TIM2 */
  TIM_Cmd(TIM2, ENABLE);

  /* Enable TIM2 update interrupt */
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
} 

#ifdef  DEBUG
/*******************************************************************************
* Function Name  : assert_failed
* Description    : Reports the name of the source file and the source line number
*                  where the assert error has occurred.
* Input          : - file: pointer to the source file name
*                  - line: assert error line source number
* Output         : None
* Return         : None
*******************************************************************************/
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while(1)
  {
  }
}
#endif
/******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/

⌨️ 快捷键说明

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