单片机读tf卡c语言程序,单片机读写U盘闪盘超精简C源程序

#i nclude "CH375INC.H"

#i nclude

/* 以下定义适用于MCS-51单片机,其它单片机参照修改 */

#define  UINT8     unsigned char

#define  UINT16    unsigned short

#define  UINT32    unsigned long

#define  UINT8X    unsigned char xdata

#define  UINT8VX   unsigned char

volatile xdata

UINT8VX    CH375_CMD_PORT _at_ 0xBDF1;  /* CH375命令端口的I/O地址 */

UINT8VX    CH375_DAT_PORT _at_ 0xBCF0;  /* CH375数据端口的I/O地址 */

#define    CH375_INT_WIRE    INT0       /* P3.2, 连接CH375的INT#引脚,用于查询中断状态 */

UINT8X     DISK_BUFFER[512*32] _at_ 0x0000;  /* 外部RAM数据缓冲区的起始地址 */

UINT32  DiskStart;    /* 逻辑盘的起始绝对扇区号LBA */

UINT8   SecPerClus;   /*

逻辑盘的每簇扇区数 */

UINT8   RsvdSecCnt;   /* 逻辑盘的保留扇区数 */

UINT16  FATSz16;      /* FAT16逻辑盘的FAT表占用的扇区数 */

/* **********

硬件USB接口层,无论如何这层省不掉,单片机总要与CH375接口吧 */

void  mDelaymS( UINT8 delay ) {

UINT8  i, j, c;

for ( i = delay; i != 0; i -- ) {

for ( j =

200; j != 0; j -- ) c += 3;

for ( j = 200; j != 0; j -- ) c += 3;

}

}

void CH375_WR_CMD_PORT( UINT8 cmd ) {  /* 向CH375的命令端口写入命令

*/

CH375_CMD_PORT=cmd;

for ( cmd = 2; cmd != 0; cmd -- );  /*

发出命令码前后应该各延时2uS */

}

void CH375_WR_DAT_PORT( UINT8 dat ) {  /*

向CH375的数据端口写入数据 */

CH375_DAT_PORT=dat;          /* 因为MCS51单片机较慢所以实际上无需延时

*/

}

UINT8 CH375_RD_DAT_PORT( void ) {    /* 从CH375的数据端口读出数据 */

return( CH375_DAT_PORT );      /* 因为MCS51单片机较慢所以实际上无需延时 */

}

UINT8

mWaitInterrupt( void ) {  /* 等待CH375中断并获取状态,返回操作状态 */

while(

CH375_INT_WIRE );  /* 查询等待CH375操作完成中断(INT#低电平) */

CH375_WR_CMD_PORT(

CMD_GET_STATUS );  /* 产生操作完成中断,获取中断状态 */

return( CH375_RD_DAT_PORT( ) );

}

/* ********** BulkOnly传输协议层,被CH375内置了,无需编写单片机程序 */

/*

********** RBC/SCSI命令层,虽然被CH375内置了,但是要写程序发出命令及收发数据  */

UINT8  mInitDisk(

void ) {  /* 初始化磁盘 */

UINT8 Status;

CH375_WR_CMD_PORT(

CMD_GET_STATUS );  /* 产生操作完成中断, 获取中断状态 */

Status = CH375_RD_DAT_PORT( );

if ( Status == USB_INT_DISCONNECT ) return( Status );  /* USB设备断开 */

CH375_WR_CMD_PORT( CMD_DISK_INIT );  /* 初始化USB存储器 */

Status =

mWaitInterrupt( );  /* 等待中断并获取状态 */

if ( Status != USB_INT_SUCCESS )

return( Status );  /* 出现错误 */

CH375_WR_CMD_PORT( CMD_DISK_SIZE );  /*

获取USB存储器的容量 */

Status = mWaitInterrupt( );  /* 等待中断并获取状态 */

if (

Status != USB_INT_SUCCESS ) {  /* 出错重试 */

/*

对于CH375A芯片,建议在此执行一次CMD_DISK_R_SENSE命令 */

mDelaymS( 250 );

CH375_WR_CMD_PORT( CMD_DISK_SIZE );  /* 获取USB存储器的容量 */

Status =

mWaitInterrupt( );  /* 等待中断并获取状态 */

}

if ( Status != USB_INT_SUCCESS

) return( Status );  /* 出现错误 */

return( 0 );  /* U盘已经成功初始化 */

}

UINT8  mReadSector( UINT32 iLbaStart, UINT8 iSectorCount, UINT8X

*oDataBuffer ) {

UINT16  mBlockCount;

UINT8  c;

CH375_WR_CMD_PORT( CMD_DISK_READ );  /* 从USB存储器读数据块 */

CH375_WR_DAT_PORT( (UINT8)iLbaStart );  /* LBA的最低8位 */

CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 8 ) );

CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 16 ) );

CH375_WR_DAT_PORT( (UINT8)( iLbaStart >> 24 ) );  /* LBA的最高8位 */

CH375_WR_DAT_PORT( iSectorCount );  /* 扇区数 */

for ( mBlockCount =

iSectorCount * 8; mBlockCount != 0; mBlockCount -- ) {

c =

mWaitInterrupt( );  /* 等待中断并获取状态 */

if ( c == USB_INT_DISK_READ ) {  /*

等待中断并获取状态,请求数据读出 */

CH375_WR_CMD_PORT( CMD_RD_USB_DATA );  /*

从CH375缓冲区读取数据块 */

c = CH375_RD_DAT_PORT( );  /* 后续数据的长度 */

while ( c -- ) *oDataBuffer++ = CH375_RD_DAT_PORT( );

CH375_WR_CMD_PORT( CMD_DISK_RD_GO );  /* 继续执行USB存储器的读操作 */

}

else break;  /* 返回错误状态 */

}

if ( mBlockCount == 0 ) {

c = mWaitInterrupt( );  /* 等待中断并获取状态 */

if ( c== USB_INT_SUCCESS

) return( 0 );  /* 操作成功 */

}

return( c );  /* 操作失败 */

}

/* ********** FAT文件系统层,这层程序量实际较大,不过,该程序仅演示极简单的功能,所以精简 */

UINT16  mGetPointWord( UINT8X *iAddr ) {  /* 获取字数据,因为MCS51是大端格式 */

return( iAddr[0] | (UINT16)iAddr[1] << 8 );

}

UINT8  mIdenDisk( void ) {    /* 识别分析当前逻辑盘 */

UINT8  Status;

DiskStart = 0;  /* 以下是非常简单的FAT文件系统的分析,正式应用绝对不应该如此简单 */

Status =

mReadSector( 0, 1, DISK_BUFFER );  /* 读取逻辑盘引导信息 */

if ( Status != 0 )

return( Status );

if ( DISK_BUFFER[0] != 0xEB && DISK_BUFFER[0] !=

0xE9 ) {  /* 不是逻辑引导扇区 */

DiskStart = DISK_BUFFER[0x1C6] |

(UINT16)DISK_BUFFER[0x1C7] << 8

| (UINT32)DISK_BUFFER[0x1C8]

<< 16 | (UINT32)DISK_BUFFER[0x1C9] << 24;

Status =

mReadSector( DiskStart, 1, DISK_BUFFER );

if ( Status != 0 ) return(

Status );

}

SecPerClus = DISK_BUFFER[0x0D];  /* 每簇扇区数 */

RsvdSecCnt = DISK_BUFFER[0x0E];  /* 逻辑盘的保留扇区数 */

FATSz16 =

mGetPointWord( &DISK_BUFFER[0x16] );  /* FAT表占用扇区数 */

return( 0 );  /*

成功 */

}

UINT16  mLinkCluster( UINT16 iCluster ) {  /* 获得指定簇号的链接簇 */

/* 输入: iCluster 当前簇号, 返回: 原链接簇号, 如果为0则说明错误 */

UINT8  Status;

Status = mReadSector( DiskStart + RsvdSecCnt + iCluster / 256, 1,

DISK_BUFFER );

if ( Status != 0 ) return( 0 );  /* 错误 */

return(

mGetPointWord( &DISK_BUFFER[ ( iCluster + iCluster ) & 0x01FF ] ) );

}

UINT32  mClusterToLba( UINT16 iCluster ) {  /* 将簇号转换为绝对LBA扇区地址 */

return( DiskStart + RsvdSecCnt + FATSz16 * 2 + 32 + ( iCluster - 2 ) *

SecPerClus );

}

void  mInitSTDIO( void ) {  /*

仅用于调试用途及显示内容到PC机,与该程序功能完全无关 */

SCON = 0x50; PCON = 0x80; TMOD = 0x20; TH1

= 0xf3; TR1=1; TI=1;  /* 24MHz, 9600bps */

}

void  mStopIfError( UINT8

iErrCode ) {  /* 如果错误则停止运行并显示错误状态 */

if ( iErrCode == 0 ) return;

printf( "Error status, %02X\n", (UINT16)iErrCode );

}

main( )

{

UINT8  Status;

UINT8X  *CurrentDir;

UINT16  Cluster;

mDelaymS( 200 );  /* 延时200毫秒 */

mInitSTDIO( );

CH375_WR_CMD_PORT( CMD_SET_USB_MODE );  /* 初始化CH375,设置USB工作模式 */

CH375_WR_DAT_PORT( 6 );  /* 模式代码,自动检测USB设备连接 */

while ( 1 ) {

printf( "Insert USB disk\n" );

while ( mWaitInterrupt( ) !=

USB_INT_CONNECT );  /* 等待U盘连接 */

mDelaymS( 250 );  /* 延时等待U盘进入正常工作状态 */

Status = mInitDisk( );  /* 初始化U盘,实际是识别U盘的类型,必须进行此步骤 */

mStopIfError( Status );

Status = mIdenDisk( );  /*

识别分析U盘文件系统,必要操作 */

mStopIfError( Status );

Status = mReadSector(

DiskStart + RsvdSecCnt + FATSz16 * 2, 32, DISK_BUFFER );

mStopIfError(

Status );  /* 读取FAT16逻辑盘的根目录,通常根目录占用32个扇区 */

for ( CurrentDir =

DISK_BUFFER; CurrentDir[0] != 0; CurrentDir += 32 ) {

if ( (

CurrentDir[0x0B] & 0x08 ) == 0 && CurrentDir[0] != 0xE5 ) {

CurrentDir[0x0B] = 0;  /* 为了便于显示,设置文件名或者目录名的结束标志 */

printf( "Name: %s\n", CurrentDir );  /* 通过串口输出显示 */

}

}  /* 以上显示根目录下的所有文件名,以下打开第一个文件,如果是C文件的话 */

if (

(DISK_BUFFER[0x0B]&0x08)==0 && DISK_BUFFER[0]!=0xE5 &&

DISK_BUFFER[8]==""C"" ) {

Cluster = mGetPointWord(

&DISK_BUFFER[0x1A] );  /* 文件的首簇 */

while ( Cluster < 0xFFF8 )

{  /* 文件簇未结束 */

if ( Cluster == 0 ) mStopIfError( 0x8F );  /*

对于首簇,可能是0长度文件 */

Status = mReadSector( mClusterToLba( Cluster ),

SecPerClus, DISK_BUFFER );

mStopIfError( Status );  /* 读取首簇到缓冲区 */

DISK_BUFFER[30] = 0; printf( "Data: %s\n", DISK_BUFFER );  /* 显示首行

*/

Cluster = mLinkCluster( Cluster );  /* 获取链接簇,返回0说明错误 */

}

}

while ( mWaitInterrupt( ) != USB_INT_DISCONNECT

);  /* 等待U盘拔出 */

mDelaymS( 250 );

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用四位led数码管作显示器的篮球比赛24秒计时器求c语言代码,单片机编程控制LED七段数码管作显示的篮球赛计时计分系统...

本次设计用由AT89C51编程控制LED七段数码管作显示的球赛计时计分系统。系统应具有赛程定时设置&#xff0c;赛程时间暂停&#xff0c;及时刷新甲、乙双方的成绩以及赛后成绩暂存等功能。内容包括&#xff1a;显示、键盘、时钟等内容设计说明2.1需求分析2.1.1 计分系统分为“A队…

loading linux img2a,嵌入式Linux中initrd的应用--浅析ramdisk、ramfs、initrd和initramfs

看到这样的一句话很让我费解&#xff0c;因为似乎我理解为这样做能够提高一点嵌入式linux启动速度&#xff0c;我对此是非常地感兴趣自此&#xff0c;就开始了我的解惑之旅首先需要知道的是ramdisk和ramfshttp://www.linuxfordevices.com/c/a/Linux-For-Devices-Articles/Intro…

android短信动态权限设置,Android动态权限申请

从HBuilderX1.9.4及以上版本开始&#xff0c;Android平台默认targetSdkVersion从21(Android5.0)调整为23(Android6.0)。Android动态权限申请机制Android6.0(API23)及以后&#xff0c;系统对权限的管理更加严格&#xff0c;放弃了以往manifest中注册所需权限&#xff0c;用户只要…

android 获取对话框对象,Android 基本Dialog和自定义Dialog

Android 基本Dialog和自定义DialogDialog类是对话框的基类&#xff0c;但你应该避免直接实例化Dialog ,可以使用子类1.AlertDialog 此对话框可以显示标题&#xff0c;最多三个按钮&#xff0c;可选择列表或自定义布局View.2.DatePickerDialog或TimePickerDialog 此对话框带有允…

android inset 标签,android – 有几个WindowInsets?

WindowInsets描述了一组窗口内容的插图.换句话说,WindowInsets有一个可用的应用程序区域(并有其他信息,如isRound).可用区域不包括StatusBar和NavigationBar的Rect.如果您只想知道StatusBar和NavigationBar的高度,请查看this.你可以得到如下的WindowInsets.以下示例使用WindowI…

android root截图软件下载,截屏软件(无需ROOT)

ScreenshotIt是一款功能简单而专一的小软体&#xff0c;利用它你能够非常方便的对你的Android手机进行捉图操作&#xff0c;并将截取的萤幕快照储存为图片。软体功能&#xff1a;-裁剪你的萤幕截图&#xff1b;-萤幕截图状态栏按键&#xff1b;-可以利用重力感应来截图(摇晃手机…

android toolbar源码解析,深入理解Android 5.0中的Toolbar

环境说明&#xff1a;Android Studio 2.0V7包版本&#xff1a;com.android.support:appcompat-v7:23.4.0compileSdkVersion 23buildToolsVersion "24.0.0"Toolbar 引入使用XML布局中加入&#xff1a;android:id"id/toolbar"android:layout_width"matc…

android 9图片报错,Android2.1加载9Patch图片运行后报错

今天遇到一个很无语的问题&#xff0c;竟然是9Patch图片上多加了光晕效果。因为需要自定义Button&#xff0c;所以请用了9Patch图片&#xff0c;而且图片上面还有一点光晕效果&#xff0c;同样也被拉伸了&#xff0c;在2.2的系统上面正常能跑&#xff0c;2.1上面就出问题&#…

鸿蒙系统发布IT直播,华为开源平台上线:鸿蒙系统、方舟编译器在列

华为近日官方宣布&#xff0c;方舟编译器将于8月31日正式开源。这一颠覆式的技术堪称安卓系统性能革命&#xff0c;将带来巨大的性能提升&#xff0c;官方称操作流畅度提升可高达60&#xff05;。8月31日凌晨&#xff0c;华为开源平台网站(HUAWEI OpenSource)就迫不及待地悄然上…

html网页之间怎么切换效果,HTML教程:网页页面切换的各种效果-♚付涛纪实阁♚...

其中,n表示的就是下面的数&#xff0c;n取不同的值&#xff0c;对应有不同的效果&#xff1a;0、box in 1、box out 2、circle in 3、circle out 4、wipe up 5、wipe down 6、wipe right 7、wipe left 8、vertical blinds 9、horizontal blinds 10、checkerboard across 11、ch…

火车头采集html文档没内容,火车头采集器:编辑任务中常见问题

1.标题前面大量空白&#xff0c;应该如何采集&#xff1f;答&#xff1a;程序里有html过滤选项&#xff0c;你可以选中过滤这些空白字符,如果有些空白字符不在html过虑里,你可以在过滤选项里添加那些字符。2.同一个页面&#xff0c;很多相同内容&#xff0c;怎么分做为多条记录…

金字塔图表 html,Highcharts 柱形图(柱状图及条形图)之 金字塔图 演示

JS 代码&#xff1a;var categories [0-4, 5-9, 10-14, 15-19,20-24, 25-29, 30-34, 35-39, 40-44,45-49, 50-54, 55-59, 60-64, 65-69,70-74, 75-79, 80-84, 85-89, 90-94,95-99, 100 ];var chart Highcharts.chart(container, {chart: {type: bar},title: {text: 2015 年德…

angular html页面嵌套,使用AngularJS来实现HTML页面嵌套的方法

html不支持嵌入在html页面中的html页面。实现这一功能通过使用以下方式&#xff1a;使用ajax - 让一台服务器来调用获取相应的html页面&#xff0c;并将其设置在html控件的innerhtml。使用服务器端包含 - jsp&#xff0c;php等web端服务器技术可以在包括动态页面中的html页面。…

jquery属于html框架吗,jquery是前端框架吗?

jquery是前端框架吗&#xff1f;jquery不是前端框架&#xff0c;它是一个JavaScript库。框架与库之间最本质区别在于控制权&#xff1a;you call libs, frameworks call you(控制反转)库&#xff1a;库是一个封装好的特定的集合&#xff0c;提供给开发者使用&#xff0c;而且是…

html ajax 菊花,Ajax加载菊花loding效果

Ajax 异步请求的时候&#xff0c;一般都会利用一个动态的 gif小图片来制作一个Ajax Loading &#xff0c;以便增加用户体验。这里我们使用Spin.js &#xff0c;该 js 脚本压缩后5k&#xff0c;可以不用任何图片&#xff0c;任何外部的CSS样式&#xff0c;就可以创建一个Ajax Lo…

ios html gif 显示,显示gif时出现巨大的内存使用Swift iOS

我正在制作一个应用程序&#xff0c;它在UIImageView中显示gif&#xff0c;并从parse中加载gif。我偶然发现的问题是每当我加载一个Gif时&#xff0c;它会使用大约20 MB的内存&#xff0c;并且当我执行一个segue时&#xff0c;这个内存不会被分配。我从UIImageView中删除图像本…

非一体式台式计算机,一体台式机推荐及介绍【详解】

随着科技的不断发展电脑已经走进了家家户户&#xff0c;几乎每一个家庭都有一台甚至是两台电脑&#xff0c;人们对于电脑的需求越来越高&#xff0c;对于电脑的要求也就越来越大。不仅仅是在性能方面外观设计也很重要。随着人们对于更轻更薄的追求&#xff0c;电脑渐渐的开始走…

窄带物联网应用于工业计算机,工业物联网嵌入式边缘计算机的制作方法

本实用新型涉及工业物联网领域&#xff0c;具体地说是一种工业物联网嵌入式边缘计算机。技术背景加速发展物联网已成国际社会的战略共识&#xff0c;多国纷纷都在加快研发物联网技术&#xff0c;物联网已经升级到了国家级战略目标。传统制造业企业由于工厂中设备型号不一致、新…

计算机网络模拟器 mac,网易mumu模拟器mac版使用常见问题解决办法_3DM手游

不少Mac设备的用户&#xff0c;在使用网易MuMu模拟器时&#xff0c;都会遇到些许问题。关于大家在使用网易MuMu模拟器Mac版时经常会出现的问题&#xff0c;下面小编也为大家带来了一个FAQ。网易MuMu常见问题解答&#xff1a;1、Mac版安装环境操作系统&#xff1a;mac os 10.11.…

如何让cloudflare缓存html,CloudFlareCDN页面规则缓存设置教程

wordpress博客使用CloudFlare的CDN来加速网站(页面规则缓存设置教程)此篇文章只讲wordpress站点使用CloudFlare CDN的页面规则教程。CloudFlare的CDN有一个很好的特点就是可以整站缓存下来&#xff0c;但是整站缓存时我们是无法登陆后台的&#xff0c;新写的文章也无法预览。所…