📄 main.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 + -