单片机源程序下载(7)——51单片机操作U盘文件和目录(C51)
单片机操作U盘文件和目录(C51)
//例K5-1.c
//该程序的功能是通过控制芯片CH376对U盘文件和目录进行操作
//在单片机系统中使用U盘,主要目的是长期保存大批量的文件数据,并方便与PC机进行数据交换
//在一般情况下,这些数据会转移到PC机,并由它做进一步的后续处理
//所以该实验安排了以下的硬件环境:51实验主板+keil仿真器+CH376读写U盘扩展板
//在该扩展板上还安排有转接PC机USB口的电缆接口和切换开关
//系统所用CH376为SSOP20封装的CH376T,与单片机的通信采用软件模拟SPI,系统时钟为11.0592MHz,
//该程序首先对CH376按主机工作方式进行初始化,然后等待U盘的插入和就绪
//此后,用户可通过按键以字节操作方式(另一种为扇区操作方式)实现以下功能
//K1键--打开或创建1级子目录/20yy,修改它的生成日期和时间,然后关闭
//K2键--在前一操作的基础上,打开或创建2级子目录/20yy/mm-dd,修改它的生成日期和时间,然后关闭
//K3键--在2级子目录下打开或创建文本文件DEMO1.TXT,追加模拟数据块,修改目录项后关文件
//K4键--第1步:在1级子目录下创建二进制文件DEMO2.DAT,写入18B20测温数据2B和读1302得到的时间数据6B
//修改目录项后关文件;第2步:再次打开该文件,读取文件中的8B数据,先显示十六进制原始数据
//经处理后再显示实际的温度,年月日和时分秒
//若程序运行出错(如中途拔出U盘),它就会进入一个出错处理的死循环,此时实验主板上的8个红色LED会不断闪烁
//注意程序中的C函数分别来自本书作者(函数名全部小写)和沁恒公司(函数名大小写并用)
//由沁恒公司提供的源代码以文件包含的形式被利用,其中
//1,文件SPI_SW.C和HAL_BASE.C中的一些源码要根据系统的具体硬件连接和时钟频率进行修改
//2,文件DEBUG.C中的源码用于系统出错指示和调试时能通过串口来输出调试信息,一般也要适当修改
//3,文件FILE_SYS.C中的源码不会全部用到,对那些没有用到C函数最后应进行清理(一般是将它们注释掉)
//该程序在运行中会输出较多的调试信息,注意它们将显示在串口窗口#1,这些信息与输出到文件中的数据不是一回事
//还要注意程序对文件DEMO1.TXT和DEMO2.DAT的操作有以下不同
//1,文件打开方式不同:前者是打开文件,若原先没有则创建;后者是创建文件,若原先有将抹去重建
//2,数据表示形式不同:前者是写入文本,并以逗号来间隔数据,以回车换行来结束记录;后者是直接写入原始数据
//3,数据写入方式不同:前者是追加数据到文件尾;后者是从头写入数据,所以原有数据将被覆盖
//Program Size: data=121.2 xdata=0 code=7411
//以下头文件由uVision提供,存于系统子目录
#include <reg52.h>
#include <stdio.h>
#include <string.h>
#include <intrins.h>
#include <absacc.h>
//以下文件由沁恒公司提供,存于当前项目,有些经过修改
#include "CH376INC.H" //说明操作CH376需要用到的数据和数据结构
#include "HAL.H" //说明软件延时函数
#include "HAL_BASE.C" //经修改,内含2个软件延时函数
#include "SPI_SW.C" //经修改,内含软件模拟SPI需要用到的一批函数
#include "DEBUG.H" //说明系统出错处理和UART串口初始化函数
#include "DEBUG.C" //经修改,内含出错处理和UART串口初始化函数
#define EN_DIR_CREATE 1 //允许新建多级子目录
#include "FILE_SYS.H" //说明一批文件目录操作类的函数和数据
#include "FILE_SYS.C" //内含一批文件目录操作类的函数
#define uchar unsigned char
#define uint unsigned int
#define ON 0
#define OFF 1
#define FILE_MODIFY 0
#define FILE_CREATE 1
#define RST_1302 A15=0;A14=A13=1; //1302复位有效
#define NRST_1302 A15=A14=A13=0; //1302复位无效
#define skiprom_cmd1820(); wr_byte1820(0xcc); //跳过ROM操作(不识别芯片)
#define convert_cmd1820(); wr_byte1820(0x44); //启动测温转换
#define wrscrat_cmd1820(); wr_byte1820(0x4e); //拟写高速暂存
#define rdscrat_cmd1820(); wr_byte1820(0xbe); //拟读高速暂存
#define copyscrat_cmd1820(); wr_byte1820(0x48); //将高速暂存复制到EERAM保存
sbit BEEP=P1^3; //蜂鸣器控制端
sbit DQ_1820=P1^0; //18B20的DQ端
sbit DIO_1302=P1^1; //1302的DIO端
sbit CLK_1302=P1^2; //1302的CLK端
sbit DAT_164=P3^4; //74HC164串入端DAT
sbit CLK_164=P3^5; //74HC164时钟端CLK
uchar time[7]={0,0,8,1,4,4,0x10}; //初始时间设为2010年4月1日8:00:00星期4
uchar disbuf[6]; //数码管显示缓冲区
uchar keyvalue; //存按键键值
bit KEY_FLG; //键按下标志
union //利用该结构来分离测温数据中的高/低8位
{ int i;
uchar c[2];
}temp; //拟存温度数据volatile
uchar idata buf[52],buf1[6]; //文件操作时作数据缓冲区使用
uint fdate,fclk; //修改目录项中时间数据时使用
uint len; //保存读文件数据块时实际读到的数据长度
uchar s; //保存CH376的操作状态或出错代码
uchar i; //循环控制用
uchar code seg[]={ //七段码表
0x3f,0x06,0x5b,0x4f,0x66, //0~4
0x6d,0x7d,0x07,0x7f,0x6f, //5~9
0x77,0x7c,0x39,0x5e,0x79, //A~E
0x71,0x40,0x46,0x00,0x76, //F,-,-1,全灭
0xbf,0x86,0xdb,0xcf,0xe6, //0.~4.
0xed,0xfd,0x87,0xff,0xef //5.~9.
};
void delay_10us(uchar n) //10微秒级延时
{ do
{ _nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--n);
}
void delay_ms(uint n) //毫秒级延时
{ do delay_10us(131);
while(--n);
}
void sendchar(uchar ch) //向数码管送1位显示数码
{ uchar i;
for(i=0;i<8;i++)
{ DAT_164=ch&0x01;
CLK_164=0;
CLK_164=1;
ch>>=1;
}
}
void display() //将显示缓冲区数据送数码管显示
{ uchar i;
for(i=0;i<6;i++) sendchar(seg[disbuf[i]]);
}
void wr_byte1302(uchar dat) //底层函数,写1B到1302
{ uchar i;
for(i=8;i>0;i--)
{ DIO_1302=dat&0x01;
CLK_1302=1;
CLK_1302=0;
dat>>=1;
}
}
uchar rd_byte1302() //底层函数,从1302读1B
{ uchar i,dat=0;
for(i=8;i>0;i--)
{ dat>>=1;
if(DIO_1302) dat|=0x80;
CLK_1302=1;
CLK_1302=0;
}
return(dat);
}
void wr_addr_byte1302(uchar addr, uchar dat) //向指定地址写单字节数据
{ RST_1302 //复位1302
CLK_1302=0;
NRST_1302
wr_byte1302(addr); //写地址/命令
wr_byte1302(dat); //写数据
CLK_1302=1;
RST_1302 //复位1302
}
void wr_time_burst1302(uchar *ptr) //突发方式写1302时钟,ptr为写数据指针
{ uchar i;
wr_addr_byte1302(0x8e,0x00); //去写保护
RST_1302 //复位1302
CLK_1302=0;
NRST_1302
wr_byte1302(0xbe); //0xbe为突发写时钟命令
for(i=7;i>0;i--) //7B时钟
{ wr_byte1302(*ptr); //写1B数据
ptr++;
}
wr_byte1302(0x80); //加写保护
CLK_1302=1;
RST_1302 //复位1302
}
void rd_time_burst1302(uchar *ptr) //突发方式读1302时钟,ptr读数据指针
{ uchar i;
RST_1302 //复位1302
CLK_1302=0;
NRST_1302
wr_byte1302(0xbf); //0xbf为突发读时钟命令
for(i=7;i>0;i--)
{ *ptr=rd_byte1302(); //读1B数据
ptr++;
}
RST_1302 //复位1302
}
void reset_1820() //复位18B20
{ DQ_1820=0;
delay_10us(60); //延时约500us(要求>480us)
DQ_1820=1; //主机上拉DQ_1820
delay_10us(7); //延时约60uS
while(!DQ_1820); //等18B20送出0
}
void wr_byte1820(uchar dat) //写18B20
{ uchar i;
for(i=0;i<8;i++) //依次发送8位数据
{ DQ_1820=0;
delay_10us(2); //延时约20us
DQ_1820=dat&0x01;
dat>>=1;
delay_10us(7); //延时约60us
DQ_1820=1; //主机上拉DQ_1820
}
}
uchar rd_byte1820() //读18B20
{ uchar i,dat=0;
for(i=0;i<8;i++) //依次接收8位数据
{ dat>>=1;
DQ_1820=0; //主机下拉DQ_1820
DQ_1820=1; //主机上拉DQ_1820
if(DQ_1820) dat|=0x80;
delay_10us(7); //满足延时要求58us
}
return dat;
}
void res1820_to_disbuf() //处理转换结果并送显示缓冲区
{ uchar i;
uchar tint; //用它处理温度数据的整数部分
uint tdec; //用它处理温度数据的小数部分
disbuf[0]=18; //正数时显示空格
if(temp.i<0)
{ disbuf[0]=16; //显示"-"
temp.i=-temp.i; //负数取绝对值
}
tint=temp.i>>4; //右移4位后得8位整数(折合3位十进制)
disbuf[1]=tint/100; //取百位上数据
disbuf[2]=tint/10%10; //取十位上数据
disbuf[3]=tint%10+20; //取个位上数据并加小数点
i=1; //消隐数码显示前导0
while(disbuf[i]==0) disbuf[i++]=18;
tdec=temp.c[1]&0x0f; //得4位小数,最低位权重=0.0625
tdec=tdec*625+50; //小数作整数处理避免浮点运算(保留2位小数)
disbuf[4]=tdec/1000; //取十分之一位数据
disbuf[5]=tdec/100%10; //取百分之一位数据
}
void key_prc() //按键处理
{ uchar key;
key=XBYTE[0x2000]; //读键盘口
if(key!=0xff) //有按键
{ BEEP=ON; //延时去抖,蜂鸣器鸣响
delay_ms(10);
BEEP=OFF;
KEY_FLG=1; //设置标志
if((key=XBYTE[0x2000])!=0xff) //再读键盘口
{ keyvalue=0; //获取键值
while(key&0x01!=0)
{ key>>=1;
keyvalue++;
}
if(!INT1) keyvalue+=8; //扩展键
if(keyvalue>=16) KEY_FLG=0; //无效键
while(XBYTE[0x2000]!=0xff); //等释放
delay_ms(15); //延时去抖
}
}
}
void get_ftime() //从1302读时间换算成目录项中的日期时间形式
{ uchar t1,t2,t3;
rd_time_burst1302(time); //突发读1302时间数据
t1=2000+time[6]/16*10+time[6]%16; //年数据从压缩BCD码换算为十进制(20yy)
t2=time[4]/16*10+time[4]%16; //月数据从压缩BCD码换算为十进制
t3=time[3]/16*10+time[3]%16; //日数据从压缩BCD码换算为十进制
fdate=MAKE_FILE_DATE(t1,t2,t3); //得到目录项中需要的日期数据形式
t1=time[2]/16*10+time[2]%16; //时数据从压缩BCD码换算为十进制
t2=time[1]/16*10+time[1]%16; //分数据从压缩BCD码换算为十进制
t3=time[0]/16*10+time[0]%16; //秒数据从压缩BCD码换算为十进制
fclk=MAKE_FILE_TIME(t1,t2,t3); //得到目录项中需要的时间数据形式
}
void modify_ftime(uchar mod) //文件/目录打开后修改目录项中的创建/修改时间
{ s=CH376DirInfoRead(); //读目录项信息,相关数据调芯片内存
if(s==USB_INT_SUCCESS)
{ buf[0]=(uchar)fdate; //形成日期低8位
buf[1]=(uchar)(fdate>>8); //形成日期高8位
buf[2]=(uchar)fclk; //形成时间低8位
buf[3]=(uchar)(fclk>>8); //形成时间高8位
if(mod) //写文件/目录创建的日期时间
{ CH376WriteOfsBlock(buf,STRUCT_OFFSET(FAT_DIR_INFO,DIR_CrtDate),2); //写2B创建日期
CH376WriteOfsBlock(buf+2,STRUCT_OFFSET(FAT_DIR_INFO,DIR_CrtTime),2); //写2B创建时间
}
else //写文件/目录最近一次修改的日期时间
{ CH376WriteOfsBlock(buf,STRUCT_OFFSET(FAT_DIR_INFO,DIR_WrtDate),2); //写2B修改日期
CH376WriteOfsBlock(buf+2,STRUCT_OFFSET(FAT_DIR_INFO,DIR_WrtTime),2); //写2B修改时间
}
s=CH376DirInfoSave(); //保存目录项
mStopIfError(s); //出错处理
}
}
void work0() //打开或新建1级子目录并修改目录项中的时间数据
{ printf("Open or create Dir.:\n"); //PC显示将打开或生成1级子目录
sprintf(buf,"/20%b02X",time[6]); //将1级目录名格式化到字符数组buf
printf(buf);printf("\n"); //PC显示1级目录为\20yy
s=CH376DirCreate(buf); //打开或新建目录
mStopIfError(s); //出错处理
get_ftime(); //得到用于文件/目录的时间数据
modify_ftime(FILE_CREATE); //修改目录创建时间
modify_ftime(FILE_MODIFY); //修改目录修改时间
printf("Close the Dir.\n\n"); //PC显示将关闭该目录
s=CH376FileClose(FALSE); //关闭该目录
mStopIfError(s); //出错处理
}
void work1() //打开或新建2级子目录并修改目录项中的时间数据
{ printf("Open or create Dir.:\n"); //PC显示将打开或生成2级子目录
sprintf(buf,"/20%b02X/%b02X-%b02X",time[6],time[4],time[3]); //将路径格式化到字符数组buf
printf(buf);printf("\n"); //PC显示2级目录为\20yy\mm-dd
s=CH376DirCreatePath(buf); //打开或新建目录
mStopIfError(s); //出错处理
get_ftime(); //得到用于文件/目录的时间数据
modify_ftime(FILE_CREATE); //修改目录创建时间
modify_ftime(FILE_MODIFY); //修改目录修改时间
printf("Close the Dir.\n\n"); //PC显示将关闭该目录
s=CH376FileClose(FALSE); //关闭该目录
mStopIfError(s); //出错处理
}
void work2() //在2级目录下建文件DEMO1.TXT并添加模拟数据
{ printf("Open or create file:\n"); //PC显示打开或新建文件DEMO1.TXT
sprintf(buf,"/20%b02X/%b02X-%b02X",time[6],time[4],time[3]); //将路径格式化到字符数组buf
strcat(buf,"/DEMO1.TXT"); //路径名连接文件名
printf(buf);printf("\n"); //PC显示文件的完整路径
s=CH376FileOpenPath(buf); //打开文件,若已存在则先删再建
if(s==USB_INT_SUCCESS) //文件存在时打开,移动指针到文件尾
{ printf("Open and locate tail\n"); //PC显示文件打开指针移到文件尾
s=CH376ByteLocate(0xFFFFFFFF); //指针移到文件尾
mStopIfError(s); //出错处理
}
else if(s==ERR_MISS_FILE) //未找到文件需要新建
{ printf("Create\n"); //PC显示新建文件
s=CH376FileCreatePath(NULL); //新建文件,文件名刚才已提供
mStopIfError(s); //出错处理
get_ftime(); //得到用于文件/目录的时间数据
modify_ftime(FILE_CREATE); //修改文件创建时间
}
else
mStopIfError(s); //打开文件时出错
printf("File size=%ldB\n",CH376GetFileSize()); //PC显示文件原先的长度
printf("Write begin\n"); //PC显示写数据开始
buf[0]='\0'; //将多个数据依次格式化并连接到字符数组buf
for(i=0;i<15;i++) //前15个数据
{ sprintf(buf1,"%b2d,",i); //格式化到字符数组buf1
strcat(buf,buf1); //连接到字符数组buf
printf(buf1); //PC显示要写入的数据
}
sprintf(buf1,"%b2d\r\n",i); //最后1个数据格式化到字符数组buf1
strcat(buf,buf1); //连接到字符数组buf
printf(buf1); //PC显示要写入的最后一个数据
s=CH376ByteWrite(buf,strlen(buf),NULL); //以字节写形式将数据块写入文件
mStopIfError(s); //出错处理
printf("Write end\n"); //PC显示写数据结束
printf("File size=%ldB\n",CH376GetFileSize()); //提示文件现在的长度
get_ftime(); //得到用于文件/目录的时间数据
modify_ftime(FILE_MODIFY); //修改文件修改时间
printf("Close DEMO1.TXT\n\n"); //PC显示将关闭文件DEMO1.TXT
s=CH376FileClose(TRUE); //关闭文件并更新文件的字节长度
mStopIfError(s);
}
void work3() //在1级子目录下创建文件DEMO2.DAT
{ printf("Create file:\n"); //PC显示新建文件
sprintf(buf,"/20%b02X/DEMO2.DAT",time[6]); //将文件名格式化到字符数组buf
printf(buf);printf("\n"); //PC显示文件的完整路径
s=CH376FileCreatePath(buf); //新建文件,若文件原来存在将删除重建
mStopIfError(s); //出错处理
printf("File size=%ldB\n",CH376GetFileSize()); //PC显示文件原先的长度
reset_1820(); //复位18B20
skiprom_cmd1820(); //跳过ROM操作(不进行芯片识别)
convert_cmd1820(); //启动测温
delay_ms(750); //延时等转换结束,12位精度约需750ms
reset_1820(); //复位18B20
skiprom_cmd1820(); //跳过ROM操作
rdscrat_cmd1820(); //拟读高速暂存
temp.c[1]=buf[0]=rd_byte1820(); //读18B20测温2B数据中的低字节
temp.c[0]=buf[1]=rd_byte1820(); //读18B20测温2B数据中的高字节
reset_1820(); //复位18B20,强迫读过程中止
printf("Temp.=%6.2f\n",temp.i*0.0625); //PC显示测得的当前温度
res1820_to_disbuf(); //数据送显示缓冲区
display(); //数码管显示数据,格式:(-)xxx.xx
printf("Write Temp.\n"); //PC显示写测温数据(2B二进制补码)
s=CH376ByteWrite(buf,2,NULL); //将2B原始测温数据写入文件
mStopIfError(s); //出错处理
rd_time_burst1302(time); //突发读1302时间数据共7B
printf("Date=20%b02X.%b02X.%b02X\n",time[6],time[4],time[3]); //提示当前日期
printf("Clk.=%b02X:%b02X:%b02X\n",time[2],time[1],time[0]); //提示当前时间
buf[0]=time[6]; //年数据(压缩BCD)存写入缓冲区
buf[1]=time[4]; //月数据(压缩BCD)存写入缓冲区
buf[2]=time[3]; //日数据(压缩BCD)存写入缓冲区
buf[3]=time[2]; //时数据(压缩BCD)存写入缓冲区
buf[4]=time[1]; //分数据(压缩BCD)存写入缓冲区
buf[5]=time[0]; //秒数据(压缩BCD)存写入缓冲区
printf("Write Time\n"); //PC显示写时间数据(6B压缩BCD码)
s=CH376ByteWrite(buf,6,NULL); //将6B时间数据(压缩BCD)写入文件
mStopIfError(s); //出错处理
printf("Write end\n"); //PC显示写数据结束
printf("File size=%ldB\n",CH376GetFileSize()); //PC显示文件现在的长度
get_ftime(); //得到用于文件/目录的时间数据
modify_ftime(FILE_CREATE); //修改文件创建时间
modify_ftime(FILE_MODIFY); //修改文件修改时间
printf("Close DEMO2.DAT\n\n"); //PC显示将关闭文件DEMO2.DAT
s=CH376FileClose(TRUE); //关闭文件并更新文件的字节长度
mStopIfError(s);
}
void work4() //在打开文件DEMO2.DAT读出其中数据并显示
{ printf("Open file:\n"); //PC显示打开文件
sprintf(buf,"/20%b02X/DEMO2.DAT",time[6]); //将文件名格式化到字符数组buf
printf(buf);printf("\n"); //PC显示文件的完整路径
s=CH376FileOpenPath(buf); //打开文件,若文件原来存在将删除重建
mStopIfError(s); //出错处理
printf("Read 8 Byte\n"); //PC显示读8B文件数据
s=CH376ByteRead(buf,8,&len); //读8B数据块,实际读取长度将返回到flen中
mStopIfError(s); //出错处理
for(i=0;i<8;i++) //PC显示从文件中读取的8B原始数据
printf("%b02X ",buf[i]);
printf("\nTemp.=%6.2f\n",(buf[1]*256+buf[0])*0.0625); //显示文件中的温度数据
printf("Date=20%b02X.%b02X.%b02X\n",buf[2],buf[3],buf[4]); //显示文件中的日期数据
printf("Clk.=%b02X:%b02X:%b02X\n",buf[5],buf[6],buf[7]); //显示文件中的时间数据
printf("Close DEMO2.DAT\n\n"); //PC显示将关闭文件DEMO2.DAT
s=CH376FileClose(FALSE); //关闭文件
mStopIfError(s);
}
void main()
{ for(i=0;i<6;i++) disbuf[i]=18; //令数码管熄灭显示
display();
XBYTE[0x2000]=XBYTE[0x4000]=0; //令所有LED熄灭
wr_time_burst1302(time); //突发读1302获得7B时间数据
mInitSTDIO(); //为在串口输出调试信息初始化串口
s=mInitCH376Host(); //初始化CH376,主机工作模式
mStopIfError(s);
printf("Wait Udisk"); //PC显示等待U盘插入
while(CH376DiskConnect()!=USB_INT_SUCCESS) //检查U盘是否连接,等待U盘插入
{ mDelaymS(100); //延时100ms
printf("."); //PC显示仍在等U盘插入
}
printf("\nFound Udisk!\n"); //PC显示发现U盘
mDelaymS(200); //可选延时操作,有的USB存储器需几十毫秒延时
for(i=0;i<10;i++) //多次测U盘是否就绪最长可等10*50ms
{ mDelaymS(50);
printf("Ready?\n"); //PC显示U盘尚未就绪
if(CH376DiskMount()==USB_INT_SUCCESS) break; //U盘就绪时退出
}
printf("Wait key\n"); //PC显示等待用户按键
while(1)
{ key_prc(); //查有无按键
if(KEY_FLG) //有按键
{ KEY_FLG=0; //清有按键标志
switch(keyvalue)
{ case 0: //若按下K0键
work0(); //打开或新建1级子目录/20yy
break;
case 1: //若按下K1键
work1(); //打开或新建2级子目录/20yy/mm-dd
break;
case 2: //若按下K2键,在2级目录下打开或创建文本文件
work2(); //DEMO1.TXT,并追加16个以逗号分隔的模拟数据
break;
case 3: //若按下K3键,在1级目录下创建二进制文件
work3(); //DEMO2.DAT,并写入8B温度时间数据
work4(); //再次打开该文件读取其中数据计算并显示
}
}
}
}
以下是对几个包含在程序中由沁恒公司提供的C源文件所做的具体改动。
//对文件HAL_BASE.C所做改动
void mDelayuS(UINT8 us) //微秒级延时,不精确
{ while(us--);
}
void mDelaymS(UINT8 ms) //毫秒级延时,不精确
{ while(ms--)
{ mDelayuS(250);
mDelayuS(250);
mDelayuS(250);
}
}
//对文件SPI_SW.C所做改动
sbit A13=P2^5; //3-8译码器的3个输入端
sbit A14=P2^6;
sbit A15=P2^7;
#define E_CH376_SPI_SCS A15=A14=1;A13=0; //令#CS6有效选中CH376
#define N_CH376_SPI_SCS A15=A14=1;A13=1; //令#CS6无效不选中CH376
sbit P15=P1^5; //用这3个引脚模拟SPI总线
sbit P16=P1^6;
sbit P17=P1^7;
#define CH376_SPI_SDI P15 //模拟SPI总线的SDI
#define CH376_SPI_SDO P16 //模拟SPI总线的SDO
#define CH376_SPI_SCK P17 //模拟SPI总线的SCK
//对文件DEBUG.C所做改动
void mStopIfError(UINT8 iError)
{ if(iError==USB_INT_SUCCESS) return; //操作成功时返回
printf("Error: %02X\n",(UINT16)iError); //否则输出错误编号
while(1) //并进入以下死循环
{ XBYTE[0x2000]=0xff; //主板上的红色LED灯闪烁
mDelaymS(200);
XBYTE[0x2000]=0x00;
mDelaymS(200);
}
}
void mInitSTDIO(void) //为输出调试信息初始化串口
{ SCON=0x52; //串口工作在方式1,允许接收,TI=1
TMOD=0x20; //定时器1用作波特率发生器
TH1=TL1=0xfd; //晶振11.0592MHz时波特率9600
TR1=1; //启动定时器1
}