[求助] 读写金士顿U盘的问题?

我用ch375B操作2G金士顿U盘. 用的lib6, 根据exam8.

可是执行到 CH375DiskReady() == ERR_SUCCESS 就不往下执行了, 这是为什么?

现象是: 发送了一次"Wait for USB Ready"后面就什么也不发送了,所以我判断执行到此就进入死循环了还是怎么回事? 大虾指点!

部分代码如下:

//----------------------------------------------------- i = CH375LibInit(); mStopIfError(i);

// while(1) // { while(CH375DiskStatus < DISK_CONNECT) { if(CH375DiskConnect() == ERR_SUCCESS) break; Delay(2000); } // } LED_OUT_ACT(); SendString("USB Connected \n"); Delay(2000); for(i = 0; i < 5; i++) { Delay(1000); SendString("Wait for USB Ready \n"); if(CH375DiskReady() == ERR_SUCCESS) { break; SendString("USB OK \n"); } } SendString("USB Ready \n"); i = CH375DiskSize(); mStopIfError(i);

//-----------------------------------------------------

CH375DiskReady()之前测试磁盘缓冲区,写入与读出的数据是否相同


磁盘缓冲区? 是指我的外部ram么?


我把CH375DiskReady()那段判断注释掉后,发现运行到CH375FileOpen()有运行不下去.

是不是我的库或者硬件连接的问题? 关键是看不到子函数.

另外,我执行完CH375DiskSize()后发现mDiskSizeSec为-67372037,奇怪??

代码如下:

//------------------------------------------- SendString("USB Ready \n"); i = CH375DiskSize(); mStopIfError(i); // printf("TotalSize = %u MB \n", (unsigned int)( mCmdParam.DiskSize.mDiskSizeSec * (CH375vSectorSize / 512) / 2048)); LED_RUN_ACT();

mCopyCodeStringToIRAM(mCmdParam.Open.mPathName, "/MY_ADC.TXT"); SendString("File name copied\n"); i = CH375FileOpen(); SendString("File Opened! \n");

//-------------------------------------------


你需要仔细检查一下DISK_BASE_BUF是不是有问题!一般是缓冲益出,不足等原因造成这个现象. CH375DiskReady()对90%的U盘来说一定要通过,否则操作不起来.


我用的32k的62256, 我的存储区定义如下,大虾帮我看看?

//------------------------------ // 外部RAM的磁盘数据缓冲区的起始地址,从该单元开始的缓冲区长度为SECTOR_SIZE #define DISK_BASE_BUF_ADDR 0x0400 // 默认的磁盘数据缓冲区大小为512字节,建议选择为2048甚至4096以支持某些大扇区的U盘, // 为0则禁止在.H文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 #define DISK_BASE_BUF_LEN 4096 // 外部RAM的文件数据缓冲区的起始地址,缓冲区长度不小于一次读写的数据长度 #define FILE_DATA_BUF_ADDR 0x1400 // 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度,本例要求不小于0x400即可 #define FILE_DATA_BUF_LEN 0x6000 //------------------------------


RAM定义没问题,按帖2作下测试 另,把完整的程序贴出来


我做了两个字节RAM的测试,好象没问题呢. 所有代码如下:

//=============================================

/********************************************************* U ceshi *********************************************************/ #include #include #include #include

#define ulong unsigned long #define uint unsigned int #define uchar unsigned char

// ----- LED Port -----

sbit LED1 = P3^5; sbit LED2 = P3^4;

// ----- CH375 Port ----

sbit CH375_INT = P3^2;

// 磁盘读写的数据的复制方式,1为"单DPTR复制",2为"双DPTR复制",3为"单DPTR和P2+R0复制" #define LIB_CFG_DISK_IO 3 // 文件读写的数据的复制方式,0为"外部子程序",1为"单DPTR复制",2为"双DPTR复制",3为"单DPTR和P2+R0复制" #define LIB_CFG_FILE_IO 3 // CH375的INT#引脚连接方式,0为"查询方式",1为"中断方式" #define LIB_CFG_INT_EN 0 // CH375命令端口的I/O地址 #define CH375_CMD_PORT_ADDR 0xB001 // CH375数据端口的I/O地址 #define CH375_DAT_PORT_ADDR 0xB000 // 外部RAM的磁盘数据缓冲区的起始地址,从该单元开始的缓冲区长度为SECTOR_SIZE #define DISK_BASE_BUF_ADDR 0x0400 // 默认的磁盘数据缓冲区大小为512字节,建议选择为2048甚至4096以支持某些大扇区的U盘, // 为0则禁止在.H文件中定义缓冲区并由应用程序在pDISK_BASE_BUF中指定 #define DISK_BASE_BUF_LEN 8192 // 外部RAM的文件数据缓冲区的起始地址,缓冲区长度不小于一次读写的数据长度 #define FILE_DATA_BUF_ADDR 0x2400 // 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度,本例要求不小于0x400即可 #define FILE_DATA_BUF_LEN 0x5000 // P3.2, CH375_INT, CH375的中断线INT#引脚,连接CH375的INT#引脚,用于查询中断状态 #define CH375_INT_WIRE CH375_INT // 未调用CH375FileEnumer程序故禁止以节约代码 #define NO_DEFAULT_CH375_F_ENUM 1 // 未调用CH375FileQuery程序故禁止以节约代码 #define NO_DEFAULT_CH375_F_QUERY 1

#include "CH375HF6.H" uint total;

#define LED_OUT_INIT() {LED1 = 1;} #define LED_OUT_ACT() {LED1 = 0;} #define LED_OUT_INACT() {LED1 = 1;}

#define LED_RUN_ACT() {LED2 = 0;} #define LED_RUN_INACT() {LED2 = 1;}

#define LED_WR_ACT() {LED1 = 0;} #define LED_WR_INACT() {LED1 = 1;}

//-------子函数实现区------- void SystemInit(void) { ET0 = 1; //T0中断允许 ES = 1; //串口中断允许 TMOD = 0x20; //定时器1自动重载方式,定时器0工作在方式1(16位计数) TL1 = 0xF7; //设置波特率9600 TH1 = 0xF7; SCON = 0x50; //串口工作在方式2(10位异步收发) PCON = 0x00; //电源控制器寄存器设置 TR1 = 1; //启动T1计数(启动波特率计数) // AUXR = 0x00; //访问内部扩展RAM允许

}

void SendOneByte(unsigned char temp) { SBUF = temp; while(TI == 0); TI = 0; }

void Delay(unsigned int t) // Delay about 3.5 uS { do { _nop_(); }while(t--); }

uchar mCopyCodeStringToIRAM(uchar idata *iDestination, uchar code *iSource) { uchar i = 0; while(*iDestination = *iSource) { iDestination++; iSource++; i++; } return i; }

void SendString(uchar code *iString) { while(*iString) { SendOneByte(*iString); iString++; } }

void SendRAMString(uchar xdata *pString) { while(*pString) { SendOneByte(*pString); pString++; } }

void mStopIfError(uchar iError) { if(iError == ERR_SUCCESS) return; // 操作成功 while(1) { LED_OUT_ACT(); // LED闪烁 Delay(10000); LED_OUT_INACT(); Delay(10000); } }

void mFlushBufferToDisk(uchar force) { uchar i; ulong NewSize; if(force) // 强制刷新 { // 将缓冲区中的字节数转换为扇区数(除以CH375vSectorSize),长度加上CH375vSectorSize-1用于确保写入最后的零头数据 mCmdParam.Write.mSectorCount = (total + CH375vSectorSize - 1) / CH375vSectorSize; // 以扇区为单位向文件写入数据,写入缓冲区中的所有数据,含最后的零头数据 i = CH375FileWrite(); mStopIfError(i); // 有些U盘可能会要求在写数据后等待一会才能继续操作,所以如果在某些U盘中发生数据丢失现象,建议在每次写入数据后稍作延时在继续操作 Delay(1000); // 将刚才已写入U盘的零头数据复制到缓冲区的头部 memcpy(FILE_DATA_BUF + 0, FILE_DATA_BUF + (total & ~(CH375vSectorSize - 1)), total & (CH375vSectorSize - 1)); // 缓冲区中只剩下刚才已写入U盘的零头数据,继续保留在缓冲区中是为了方便以后在其后面追加数据 total &= CH375vSectorSize - 1; // if(total) // 以扇区为单位,有零头数据,计算出真正的文件长度(有效数据的长度) NewSize = CH375vFileSize - CH375vSectorSize + total; else // 以扇区为单位,没有零头数据,文件长度是CH375vSectorSize的倍数 NewSize = CH375vFileSize; // 输入参数: 新的文件长度,扇区模式下涉及到零头数据不便自动更新长度 mCmdParam.Modify.mFileSize = NewSize; // 输入参数: 新的文件属性,为0FFH则不修改 mCmdParam.Modify.mFileAttr = 0xFF; // 输入参数: 新的文件时间,为0FFH则不修改 mCmdParam.Modify.mFileTime = 0xFFFF; // 输入参数: 新的文件日期,为0FFH则不修改 mCmdParam.Modify.mFileDate = 0xFFFF; // 修改当前文件的信息,修改文件长度 i = CH375FileModify(); mStopIfError(i); // 移到文件的尾部,以扇区为单位,所以会忽略文件尾部的零头数据 mCmdParam.Locate.mSectorOffset = 0xFFFFFFFF; // 重新回到原文件的尾部,下面如果再写入数据将覆盖尾部零头数据,不过该零头数据有一份副本保留在缓冲区中 i = CH375FileLocate(); mStopIfError(i); } // 缓冲区中的数据快要满了,所以应该先将缓冲区中的原有数据写入U盘 else if(total >= FILE_DATA_BUF_LEN - CH375vSectorSize) { // 将缓冲区中的字节数转换为扇区数(除以CH375vSectorSize),最后的零头数据先不管 mCmdParam.Write.mSectorCount = total / CH375vSectorSize; // 以扇区为单位向文件写入数据,写入缓冲区中的所有数据,不含最后的零头 i = CH375FileWrite(); mStopIfError(i); // 将刚才未写入U盘的零头数据复制到缓冲区的头部 memcpy(FILE_DATA_BUF + 0, FILE_DATA_BUF + (total & ~(CH375vSectorSize - 1)), total & (CH375vSectorSize - 1)); // 缓冲区中只剩下刚才未写入U盘的零头数据 total &= CH375vSectorSize -1; } }

void main(void) { ulong idata lDataTemp = 0; uchar idata i = 0; uchar idata dataTemp1 = 0; uchar idata dataTemp2 = 0; uchar idata dataTemp3 = 0;

SystemInit();

LED_OUT_INIT(); LED_OUT_ACT(); Delay(10000); LED_OUT_INACT();

SendString("MCU Start \n");

i = CH375LibInit(); mStopIfError(i);

// FILE_DATA_BUF[0] = 'a'; // FILE_DATA_BUF[1] = 't';

// SendOneByte(FILE_DATA_BUF[1]); // SendOneByte(FILE_DATA_BUF[0]); // SendOneByte(i + 0x30);

while(CH375DiskStatus < DISK_CONNECT) { if(CH375DiskConnect() == ERR_SUCCESS) break; Delay(2000); }

LED_OUT_ACT(); SendString("USB Connected \n"); Delay(2000); for(i = 0; i < 5; i++) { Delay(1000); SendString("Wait for USB Ready \n"); if(CH375DiskReady() == ERR_SUCCESS) { break; SendString("USB OK \n"); } } SendString("USB Ready \n"); i = CH375DiskSize(); mStopIfError(i);

sprintf(FILE_DATA_BUF, "%ld,\n", mCmdParam.DiskSize.mDiskSizeSec); SendRAMString(FILE_DATA_BUF); // printf("TotalSize = %u MB \n", (unsigned int)( mCmdParam.DiskSize.mDiskSizeSec * (CH375vSectorSize / 512) / 2048)); LED_RUN_ACT();

mCopyCodeStringToIRAM(mCmdParam.Open.mPathName, "/MY_ADC.TXT"); SendString("File name copied\n"); i = CH375FileOpen(); SendString("File Opened! \n"); if(i == ERR_SUCCESS) { mCmdParam.Locate.mSectorOffset = 0xFFFFFFFF; i = CH375FileLocate(); mStopIfError(i); total = CH375vFileSize & (CH375vSectorSize - 1); CH375vFileSize += CH375vSectorSize - 1; mCmdParam.Read.mSectorCount = 1; i = CH375FileRead(); mStopIfError(i); CH375vFileSize -= CH375vSectorSize - 1; mCmdParam.Locate.mSectorOffset = 0xFFFFFFFF; i = CH375FileLocate(); mStopIfError(i); } else if(i == ERR_MISS_FILE) { LED_WR_ACT(); i = CH375FileCreate(); mStopIfError(i); SendString("File Created \n"); total = 0; } else { mStopIfError(i); } LED_WR_ACT(); total += sprintf(FILE_DATA_BUF + total, "在本次添加数据之前,该文件已有数据的长度是 %ld 字节\xd\xa", CH375vFileSize ); mFlushBufferToDisk(0);

total += sprintf( FILE_DATA_BUF + total, " ********************************* " ); /*


我用下面代码测试了所有的ram区,貌似没问题.

//========

for(j = 0; j < 31744; j++) { if(j < 4096) DISK_BASE_BUF[j] = 'A'; else if(j < 30000) DISK_BASE_BUF[j] = 'B'; else DISK_BASE_BUF[j] = 'C'; }

for(j = 0; j < 31744; j++) { SendOneByte(DISK_BASE_BUF[j]); }

//========


问题貌似解决了, 我用的 "单DPTR + P2 + R0"复制不行,改成 "单DPTR"复制即可. 我用的STC89LE58单片机.


这个问题是因为自带1K外部RAM的单片机不支持P2+R0的复制方式,你可以采用双DPTR的方式来操作U盘,或者直接换一个AT89C55WD这个单片机就可以了


该单片机自带1KB的外部RAM,选用 "单DPTR + P2 + R0"这个方式时,必须把自带RAM禁用,即配置AUXR寄存器


恩,是的. 用这款的原因也就是灌程序方便.


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