CH375模块简单实现MCS51单片机U盘读写的问题
劳烦达人们来帮帮我这个没入门的菜菜. :0)
我现在需要用一块ADUC814的评估板结合CH375标准模块(并行)来做一个单片机读写U盘的简单功能. 由于ADUC814只有P1和P3这2个并口, 而且不少的P1位口还被AD占用了,真让人头疼.并口不够我只好不扩展外部RAM了, 打算用字节读写来实现U盘读写功能. 可我找的资料上的例程刚好没有CH375并行模块字节读写的, :(. 只好自己摸索着来,还是有很多不懂的地方.
首先并行+查询的那个例子里有这样一个定义:
#define CH375HM_INDEX XBYTE[0xBDF0], 其中XBYTE[]的意思是否是指定义到外部RAM地址的意思呢? 由于我无法扩展ROM, 所以只好定义#define CH375HM_INDEX BYTE[0x30],
希望能用内部RAM定义索引口地址.可编译的时候说未定义错误,怎么回事呢?
另外我电路连接如下,大家看可以吗?
/* 电路连接方式
单片机 模块
P3 = D0-D7
P17 = CS#
P11 = STA#
P10 = A0
INT0 = INT#
*/
[Emot]1[/Emot]
我自己改写的并行+查询 字节读写的命令运行子程序, 有2种方案, 不懂也只好都先写上
unsigned char ExecCommand( unsigned char cmd, unsigned char len )
/* 输入命令码和输入参数长度,返回操作状态码,输入参数和返回参数都在CMD_PARAM结构中 */
{
unsigned char i, k, status;
//unsigned char data *buf;
CH375HM_INDEX = 0;
CH375HM_DATA = cmd;
CH375HM_DATA = len;
/*if( len ){
i = len;
*buf = (unsigned char *)&mCmdParam; //指向输入参数的起始地址
do{
CH375HM_DATA = *buf;
buf++;
} while (--i);
}*/ //方案1
if( len ){
for(i=0;i!=len;i++)
{
CH375HM_DATA = mCmdParam.Other.mBuffer[ i ];
}// 方案2
}
CH375HM_STA = 0;
CH375HM_STA = 0;
CH375HM_STA = 0;
CH375HM_STA = 1;
while ( 1 )
{
while ( CH375HM_INT_WIRE );
CH375HM_INDEX = 63;
status = CH375HM_DATA;
if ( status == ERR_SUCCESS )
{
CH375HM_INDEX = 1; /*从索引地址1取结果数据的长度*/
i= CH375HM_DATA;
/* if ( i ) {
do {
*buf = CH375HM_DATA;
buf++;
} while(--i); */ // 方案1

if ( i ) {
k = 0;
do {
mCmdParam.Other.mBuffer[ k ] = CH375HM_DATA;
k++;
} while ( --i );
}// 方案2
break;
}

else if ( status == USB_INT_DISK_READ || status == USB_INT_DISK_WRITE || status == USB_INT_DISK_RETRY )
{
break;
}
else { /* 操作失败 */

if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT )
mDelaymS( 200 ); /* U盘刚刚连接或者断开,应该延时几十毫秒再操作 */
break; /* 操作失败返回 */
}

while( CH375HM_INT_WIRE == 0 );

return( status );
}

这是主程序
main( ) {
unsigned char i, k;

LED_OUT = 0; /* 开机后LED亮一下以示工作 */
mDelaymS( 400 ); /* 延时100毫秒,CH375模块上电后需要100毫秒左右的复位时间 */
LED_OUT = 1;
mInitSTDIO( );
printf( "Start\n" );
/* 电路初始化 */
while ( 1 ) { /* 主循环 */
printf( "Wait Udisk\n" );
while ( 1 ) { /* 使用查询方式看U盘是否连接 */
i = ExecCommand( CMD_QueryStatus, 0 ); /* 查询当前模块的状态 */
mStopIfError( i );
if ( mCmdParam.Status.mDiskStatus >= DISK_CONNECT ) break; /* U盘已经连接 */
mDelaymS( 400 ); /* 可以在要读写U盘时再查询,空闲时就延时等待一会再查询 */
}
mDelaymS( 400 );
LED_OUT = 0; /* LED亮 */
/* check disk ready */
for ( i = 0; i < 5; i ++ ) {
mDelaymS( 200 );
printf( "Ready ?\n" );
if ( ExecCommand( CMD_DiskReady, 0 ) == ERR_SUCCESS ) break; /* 查询磁盘是否准备好 */
}
/* 读取原文件 */
printf( "Open\n" );
strcpy( mCmdParam.Open.mPathName, "\\read\\hi", MAX_PATH_LEN ); /* 文件名,该文件在C51子目录下 */
i = ExecCommand( CMD_FileOpen, MAX_PATH_LEN ); /* 输入参数置为最大值,省得再计算参数长度 */
if ( i == ERR_MISS_DIR || i == ERR_MISS_FILE ) { /* 没有找到C51子目录也没有找到文件 */

printf("没找到文件\n"); }
/* 列出根目录下的文件 */
/* printf( "List file \\*\n" );
for ( c = 0; c < 255; c ++ ) { // 最多搜索前255个文件
memcpy( mCmdParam.Enumer.mPathName, "\\*", MAX_PATH_LEN ); //搜索文件名,*为通配符,适用于所有文件或者子目录
for ( i = 0; i < MAX_PATH_LEN - 1; i ++ ) if ( mCmdParam.Enumer.mPathName[ i ] == 0 ) break; // 指向搜索文件名的结束符
mCmdParam.Enumer.mPathName[ i ] = c; //将结束符替换为搜索的序号,从0到255
i = ExecCommand( CMD_FileEnumer, i+1 ); // 枚举文件,如果文件名中含有通配符*,则为搜索文件而不打开,输入参数的长度很好计算
if ( i == ERR_MISS_FILE ) break; // 搜索不到匹配的文件
if ( i == ERR_SUCCESS ) {
printf( " match file %03d#: %s\n", (unsigned int)c, mCmdParam.Enumer.mPathName );
continue;
}
else {
mStopIfError( i );
break;
}
}*/
//未完
}
else { /* 找到文件\read\hi或者出错 */
mStopIfError( i );
printf("read\n");
mCmdParam.ByteRead.mByteCount = 5;
i = ExecCommand( CMD_ByteRead, 1 );
mStopIfError( i );
for(i=0; i!=mCmdParam.ByteRead.mByteCount;i++) printf("%C", mCmdParam.ByteRead.mByteBuffer[i]);
printf("\n");
mCmdParam.ByteRead.mByteCount = 20;
i = ExecCommand( CMD_ByteRead, 1 );
mStopIfError( i );
for(i=0; i!=mCmdParam.ByteRead.mByteCount;i++) printf("%C", mCmdParam.ByteRead.mByteBuffer[i]);
if(mCmdParam.ByteRead.mByteCount<20) printf("end\n");
printf("close\n");
mCmdParam.Close.mUpdateLen = 0;
i = ExecCommand( CMD_FileClose, 1 ); /* 关闭文件 */
mStopIfError( i );
}


/* 等待U盘断开 */
printf( "Take_out\n" );
while ( 1 ) { /* 使用查询方式看U盘是否断开 */
i = ExecCommand( CMD_QueryStatus, 0 ); /* 查询当前模块的状态 */
mStopIfError( i );
if ( mCmdParam.Status.mDiskStatus <= DISK_DISCONNECT ) break; /* U盘已经断开 */
mDelaymS( 200 ); /* 没有必要一直连续不停地查询,可以让单片机做其它事,没事可做就延时等待一会再查询 */
}
LED_OUT = 1; /* LED灭 */
}
}

最后还要问一个菜到你晕的问题: 12M时钟的8052MPU用C写一个延时500us的程序该怎么写啊
我这样写的好象很不精确
VOID DELAY ( )

{
UNSIGNED CHAR I;
I = 500;
WHILE(I--)

}

一、。。。。。”所以只好定义#define CH375HM_INDEX BYTE[0x30],
希望能用内部RAM定义索引口地址.“
是。。。。。彻底错误的!
二、按照你的硬件连接,你只能用模拟并口。所以说所有往CH375HM_INDEX和CH375HM_DATA内送数据都是没用的,
三、你的8052核的单片机,外部64K的地址难道都被外设和RAM占用了吗,并口模块挂到总线上,只需CH375HM_INDEX和CH375HM_DATA两个地址。建议你将模块挂到总线上。然后程序不用改,修改一下CH375HM_INDEX和CH375HM_DATA的地址就行了。
四、延时程序,你自己产生汇编代码,然后去看执行了多少指令。
祝你好运!

楼上的热心人, 谢谢你啊
不过我还是不大明白,单片机、电路硬件方面我都是一个新手,刚开始自学。
你说的“外部64K的地址难道都被外设和RAM占用了吗,并口模块挂到总线上,只需CH375HM_INDEX和CH375HM_DATA两个地址。建议你将模块挂到总线上。” 我还是没领悟。
我用的aduc814芯片,芯片引脚上面只有P1和P3总共16位并口,而且P1.2~P1.7在芯片内还接了AD转换器,只能IN,不能OUT。我只知道P2口可以做外部RAM的64位地址,只有P1和P3口我不知道怎么做, 而且P3口我全部用来做
数据IO口了,剩下为数不多的P1口也没法扩展地址啊。
恳切想和你聊聊, QQ:4003593

哦。。
不好意思,我对ADUC814不大了解,那它是51的核吧,看样子不能扩张外部RAM的,那你就用模拟总线的也行,
不过要8位数据口+CS+RD+WR+A0+INT#,要IO啊,不要‘只能IN,不能OUT’的。或者,用串口模块得了,
不过速度慢。
哎呀。。
这个单片机难搞。

请问RD和WR必须要接入吗? 是不是单片机读写CH375模块必须用的到这两个脚啊?

我来帮帮你吧,P3口跟CH375的D0~~D7连。
P1口剩下来的I/O口分别连接CS,A0,WD,RD,INT#。
操作的时候,先把CS,A0,WD,RD,INT,分别负值(0 OR 1)。
具体负0或者1你自己看看资料,然后就可以往D0~~D7写数据了。对CH375就可以进行操作了。

楼上的谢谢你啊, 我想加你为QQ好友, 你看可以吗?
我的QQ:4003593

你至少要8位双向口做数据口,然后还要至少4个双向IO,用做A0,STA,RD,WR,和一个输入用做INT#,如果没有这么多IO那么,用并口是不行了,只能用串口了。

楼上的谢谢你, 不过我不明白A0为什么一定要用IO呢, 只能能输入不就可以选址了吗?而且好像STA只要能OUT就行,不需要模块应答给单片机的

PUSH~

端口可这样设置:
D0-D7 双向口
STA 输出
INT 输入
A0 输出
WR RD 输出
CS 当不和其他产生冲突的情况下可以直接接地

其实我还是没有明白示例程序里#define CH375HM_INDEX XBYTE[0xBDF0]的意思

这是定义一个外部XRAM地址.

只有登录才能回复,可以选择微信账号登录