?? main.c
字號:
/****************************************************************************
* Copyright (C), 2010 安富萊電子 www.armfly.com
*
* 【本例程在安富萊STM32F103ZE-EK開發板上調試通過 】
* 【QQ: 1295744630, 旺旺:armfly, Email: armfly@qq.com 】
*
* 文件名: main.c
* 內容簡述: 本例程演示如何通過CH376讀寫U盤。
*
*
* 文件歷史:
* 版本號 日期 作者 說明
* v0.1 2010-10-30 armfly 創建該文件
*
*/
#include "stm32f10x.h"
#include <stdio.h>
#include "usart_printf.h"
#include "systick.h"
#include "button.h"
#include "FILE_SYS.H"
#include "string.h"
#define EXAMPLE_NAME "CH376 USB DISK Demo"
#define EXAMPLE_DATE "2010-10-30"
static void InitBoard(void);
static void DispLogo(void);
void TestCH376(void);
/*******************************************************************************
* 函數名:main
* 輸 入:
* 輸 出:
* 功能說明:用戶程序入口
*/
int main(void)
{
InitBoard(); /* 為了是main函數看起來更簡潔些,我們將初始化的代碼封裝到這個函數 */
DispLogo(); /* 顯示例程Logo */
mDelaymS(200);
TestCH376();
}
/*******************************************************************************
* 函數名:mStopIfError
* 輸 入: iError, 錯誤代碼
* 輸 出:
* 功能說明:檢查操作狀態,如果錯誤則顯示錯誤代碼并停機,
* 應該替換為實際的處理措施,例如顯示錯誤信息,等待用戶確認后重試等
*/
void mStopIfError(uint8_t iError)
{
if (iError == USB_INT_SUCCESS)
{
return; /* 操作成功 */
}
printf("Error: %02X\n", iError ); /* 顯示錯誤 */
while(1)
{
/* LED閃爍 */
GPIO_ResetBits(GPIOF, GPIO_Pin_6);
mDelaymS( 200 );
GPIO_SetBits(GPIOF, GPIO_Pin_6);
mDelaymS( 200 );
}
}
void TestCH376(void)
{
uint8_t i, s;
P_FAT_DIR_INFO pDir;
char SrcName[64];
char TarName[64];
char buf[64];
printf( "Start\n\r" );
s = mInitCH376Host( ); /* 初始化CH376 */
mStopIfError( s );
while(1)
{
printf( "Wait Udisk\n\r" );
while (CH376DiskConnect() != USB_INT_SUCCESS)
{ /* 檢查U盤是否連接,等待U盤插入,對于SD卡,可以由單片機直接查詢SD卡座的插拔狀態引腳 */
mDelaymS(100 );
}
mDelaymS(250); /* 延時,可選操作,有的USB存儲器需要幾十毫秒的延時 */
mDelaymS(250);
/* 對于檢測到USB設備的,最多等待100*50mS,主要針對有些MP3太慢,對于檢測到USB設備并且連接DISK_MOUNTED的,最多等待5*50mS,主要針對DiskReady不過的 */
for (i = 0; i < 100; i ++ )
{ /* 最長等待時間,100*50mS */
mDelaymS(50);
printf( "Ready ?\n\r" );
s = CH376DiskMount(); /* 初始化磁盤并測試磁盤是否就緒 */
if (s == USB_INT_SUCCESS)
{
break; /* 準備好 */
}
else if (s == ERR_DISK_DISCON)
{
break; /* 檢測到斷開,重新檢測并計時 */
}
if (CH376GetDiskStatus() >= DEF_DISK_MOUNTED && i >= 5)
{
break; /* 有的U盤總是返回未準備好,不過可以忽略,只要其建立連接MOUNTED且嘗試5*50mS */
}
}
if (s == ERR_DISK_DISCON)
{ /* 檢測到斷開,重新檢測并計時 */
printf("Device gone\n\r");
continue;
}
if (CH376GetDiskStatus( ) < DEF_DISK_MOUNTED)
{ /* 未知USB設備,例如USB鍵盤、打印機等 */
printf("Unknown device\n\r");
goto UnknownUsbDevice;
}
i = CH376ReadBlock((uint8_t *)buf ); /* 如果需要,可以讀取數據塊CH376_CMD_DATA.DiskMountInq,返回長度 */
if (i == sizeof( INQUIRY_DATA))
{ /* U盤的廠商和產品信息 */
buf[i] = 0;
printf("UdiskInfo: %s\n\r", ((P_INQUIRY_DATA)buf) -> VendorIdStr);
}
/* 讀取原文件 */
strcpy(SrcName, "\\C51\\CH376HFT.C"); /* 源文件名,多級目錄下的文件名和路徑名必須復制到RAM中再處理,而根目錄或者當前目錄下的文件名可以在RAM或者ROM中 */
strcpy(TarName, "\\NEWFILE.TXT" ); /* 目標文件名 */
printf("Open\n\r");
mDelaymS(80);
s = CH376FileOpenPath((uint8_t *)SrcName ); /* 打開文件,該文件在C51子目錄下 */
if ((s != ERR_MISS_DIR) && (s != ERR_MISS_FILE))
{
printf("Open Error! Retry\n\r");
//mStopIfError(s);
s = CH376FileOpenPath((uint8_t *)SrcName );
}
if (s == ERR_MISS_DIR || s == ERR_MISS_FILE)
{ /* 沒有找到目錄或者沒有找到文件 */
/* 列出文件,完整枚舉可以參考EXAM13全盤枚舉 */
if ( s == ERR_MISS_DIR )
{
strcpy( buf, "\\*" ); /* C51子目錄不存在則列出根目錄下的文件 */
}
else
{
strcpy( buf, "\\C51\\CH376*" ); /* CH376HFT.C文件不存在則列出\C51子目錄下的以CH376開頭的文件 */
}
printf("List file %s\n\r", buf);
s = CH376FileOpenPath((uint8_t *)buf); /* 枚舉多級目錄下的文件或者目錄,輸入緩沖區必須在RAM中 */
while (s == USB_INT_DISK_READ)
{ /* 枚舉到匹配的文件 */
CH376ReadBlock((uint8_t *)buf); /* 讀取枚舉到的文件的FAT_DIR_INFO結構,返回長度總是sizeof( FAT_DIR_INFO ) */
pDir = (P_FAT_DIR_INFO)buf; /* 當前文件目錄信息 */
if (pDir -> DIR_Name[0] != '.')
{ /* 不是本級或者上級目錄名則繼續,否則必須丟棄不處理 */
if ( pDir -> DIR_Name[0] == 0x05 )
{
pDir -> DIR_Name[0] = 0xE5; /* 特殊字符替換 */
}
pDir -> DIR_Attr = 0; /* 強制文件名字符串結束以便打印輸出 */
printf( "*** EnumName: %s\n\r", pDir -> DIR_Name ); /* 打印名稱,原始8+3格式,未整理成含小數點分隔符 */
}
xWriteCH376Cmd( CMD0H_FILE_ENUM_GO ); /* 繼續枚舉文件和目錄 */
xEndCH376Cmd( );
s = Wait376Interrupt( );
}
if (s != ERR_MISS_FILE )
{
mStopIfError( s ); /* 操作出錯 */
}
mDelaymS(80);
printf( "Create\n\r" );
s = CH376FileCreatePath((uint8_t *)TarName ); /* 新建多級目錄下的文件,支持多級目錄路徑,輸入緩沖區必須在RAM中 */
mStopIfError( s );
printf( "Write\n\r" );
strcpy( buf, "找不到/C51/CH376HFT.C文件\xd\n\r" );
s = CH376ByteWrite((uint8_t *)buf, strlen(buf), NULL ); /* 以字節為單位向當前位置寫入數據塊 */
mStopIfError( s );
printf( "Close\n\r" );
s = CH376FileClose( TRUE ); /* 關閉文件,對于字節讀寫建議自動更新文件長度 */
mStopIfError( s );
}
/* 刪除某文件 */
/* printf( "Erase\n" );
s = CH376FileErase( "/OLD" ); 刪除文件
if ( s != USB_INT_SUCCESS ) printf( "Error: %02X\n", (UINT16)s ); 顯示錯誤
*/
/* 檢查U盤或者SD卡的剩余空間 */
/* printf( "DiskQuery: " );
s = CH376DiskQuery( (PUINT32)buf ); 查詢磁盤剩余空間信息,扇區數
mStopIfError( s );
// printf( "free cap = %ld MB\n", *(PUINT32)buf * DEF_SECTOR_SIZE / 1000000 ); 未用扇區數乘以扇區大小后,除以1M換算為兆字節單位
printf( "free cap = %ld MB\n", *(PUINT32)buf / ( 1000000 / DEF_SECTOR_SIZE ) ); 上面一行的計算可能會溢出,換個順序計算 */
UnknownUsbDevice:
printf( "Take out\n\r" );
while ( CH376DiskConnect( ) == USB_INT_SUCCESS ) { /* 檢查U盤是否連接,等待U盤拔出 */
mDelaymS( 100 );
}
mDelaymS(200 );
}
}
/*******************************************************************************
函數名:GPIO_Configuration
輸 入:
輸 出:
功能說明:配置4個LED為輸出口線
LED口線分配:
LED1 : PF6 (輸出0點亮)
LED2 : PF7 (輸出0點亮)
LED3 : PF8 (輸出0點亮)
LED4 : PF9 (輸出0點亮)
*/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 第1步:打開GPIOA GPIOC GPIOD GPIOF GPIOG的時鐘
注意:這個地方可以一次性全打開
*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG,
ENABLE);
/* 第2步:配置所有的按鍵GPIO為浮動輸入模式(實際上CPUf復位后就是輸入狀態) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); /* PA0 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_Init(GPIOC, &GPIO_InitStructure); /* PC13 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOD, &GPIO_InitStructure); /* PD3 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_13
| GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOG, &GPIO_InitStructure); /* PG7,8,13,14,15 */
/* 第3步:配置所有的LED指示燈GPIO為推挽輸出模式 */
/* 由于將GPIO設置為輸出時,GPIO輸出寄存器的值缺省是0,因此會驅動LED點亮
這是我不希望的,因此在改變GPIO為輸出前,先修改輸出寄存器的值為1 */
GPIO_SetBits(GPIOF, GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOF, &GPIO_InitStructure);
}
/*******************************************************************************
函數名:InitBoard
輸 入:
輸 出:
功能說明:初始化硬件設備
*/
static void InitBoard(void)
{
/*
這個函數是ST庫中的函數,函數實體在
Libraries\CMSIS\Core\CM3\system_stm32f10x.c
配置內部Flash接口,初始化PLL,配置系統頻率
系統時鐘缺省配置為72MHz,你如果需要更改,則需要去修改相關的頭文件中的宏定義
*/
SystemInit();
/* 配置按鍵GPIO和LED GPIO */
GPIO_Configuration();
/* 配置串口 */
USART_Configuration();
/* 在 SysTick_Config()前,必須先調用 */
InitButtonVar();
/* 配置systic作為1ms中斷,這個函數在
\Libraries\CMSIS\Core\CM3\core_cm3.c */
SysTick_Config(SystemFrequency / 1000);
}
/*******************************************************************************
函數名: DispLogo
輸 入:
輸 出:
功能說明:顯示例程Logo (通過串口打印到PC機的超級終端顯示)
*/
static void DispLogo(void)
{
/* 通過串口輸出例程名和更新日期 */
PrintfLogo(EXAMPLE_NAME, EXAMPLE_DATE);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t 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 2009 STMicroelectronics *****END OF FILE****/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -