#include <iom8v.h>
#include <macros.h>
#define PB375_VER 0x30 /* 当前模块版本 */
/* ********************************************************************************************************************* */
/* 返回的操作状态码 */
/* 以下是事件通知状态码,检测到当前U盘已经连接或者已经断开,可以作为最终状态码 */
#define ERR_USB_CONNECT 0x15 /* 检测到USB设备连接事件,磁盘已经连接 */
#define ERR_DISK_DISCON 0x82 /* 检测到USB设备连接事件,磁盘已经断开,或者磁盘尚未连接 */
/* 代码0XH用于USB设备方式的操作状态代码,由PB375返回,是USB设备模式的中断状态 */
#define ERR_USB_DAT_DOWN 0x02 /* USB设备模式: 数据下传成功,上位机下传的数据已经在模块中 */
#define ERR_USB_DAT_UP 0x0A /* USB设备模式: 数据上传成功,模块中的上传数据已经被上位机取走 */
/* 最终状态码 */
#define ERR_SUCCESS 0x00 /* 操作成功 */
#define ERR_PB375_ERROR 0x81 /* PB375硬件错误,可能需要复位PB375 */
#define ERR_STATUS_ERR 0x83 /* 磁盘状态错误,可能正在连接或者断开磁盘 */
#define ERR_MBR_ERROR 0x91 /* 磁盘的主引导记录无效,可能磁盘尚未分区或者尚未格式化 */
#define ERR_TYPE_ERROR 0x92 /* 磁盘分区类型不支持,只支持FAT12/FAT16/BigDOS/FAT32,需要由磁盘管理工具重新分区 */
#define ERR_BPB_ERROR 0xA1 /* 磁盘尚未格式化,或者参数错误,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_TOO_LARGE 0xA2 /* 磁盘非正常格式化并且容量大于4GB,或者容量大于250GB,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_FAT_ERROR 0xA3 /* 磁盘的文件系统不支持,只支持FAT12/FAT16/FAT32,需要由WINDOWS采用默认参数重新格式化 */
#define ERR_DISK_FULL 0xB1 /* 磁盘文件太满,剩余空间太少或者已经没有,需要磁盘整理 */
#define ERR_FDT_OVER 0xB2 /* 目录内文件太多,没有空闲的目录项,FAT12/FAT16根目录下的文件数应该少于500个,需要磁盘整理 */
#define ERR_MISS_DIR 0xB3 /* 指定路径的某个子目录没有找到,可能是目录名称错误 */
#define ERR_FILE_CLOSE 0xB4 /* 文件已经关闭,如果需要使用,应该重新打开文件 */
#define ERR_OPEN_DIR 0x41 /* 指定路径的目录被打开 */
#define ERR_MISS_FILE 0x42 /* 指定路径的文件没有找到,可能是文件名称错误 */
#define ERR_FOUND_NAME 0x43 /* 搜索到与通配符相匹配的文件名,文件名及其完整路径在命令缓冲区中,如果需要使用,应该打开该文件 */
#define ERR_USB_DISK_ERR 0x1F /* USB存储器操作失败,在初始化时可能是USB存储器不支持,在读写操作中可能是磁盘损坏或者已经断开 */
/* 其余错误代码未定义,可以发出命令CMD_QueryStatus查询模块状态并分析 */
/* ********************************************************************************************************************* */
/* 磁盘及文件状态,适用于CMD_PARAM.Status.mDiskStatus */
#define DISK_UNKNOWN 0x00 /* 尚未初始化,未知状态 */
#define DISK_DISCONNECT 0x01 /* 磁盘没有连接或者已经断开 */
#define DISK_CONNECT 0x02 /* 磁盘已经连接,但是尚未初始化或者无法识别该磁盘 */
#define DISK_MOUNTED 0x03 /* 磁盘已经初始化成功,但是尚未分析文件系统或者文件系统不支持 */
#define DISK_READY 0x10 /* 已经分析磁盘的文件系统并且能够支持 */
#define DISK_OPEN_ROOT 0x12 /* 已经打开根目录,扇区模式,只能以扇区为单位读写目录的内容,使用后必须关闭,注意FAT12/FAT16根目录是固定长度 */
#define DISK_OPEN_DIR 0x13 /* 已经打开子目录,扇区模式,只能以扇区为单位读写目录的内容 */
#define DISK_OPEN_FILE 0x14 /* 已经打开文件,扇区模式,可以以扇区为单位进行数据读写 */
#define DISK_OPEN_FILE_B 0x15 /* 已经打开文件,字节模式,可以以字节为单位进行数据读写 */
/* 外部命令码 */
#define CMD_DiskQuery 0x61 /* 查询磁盘信息 */
#define CMD_FileOpen 0x64 /* 打开文件 */
#define CMD_FileCreate 0x65 /* 新建文件并打开,如果文件已经存在则先删除后再新建 */
#define CMD_FileErase 0x66 /* 删除文件并关闭 */
#define CMD_FileClose 0x67 /* 关闭当前文件 */
#define CMD_ByteLocate 0x7A /* 以字节为单位移动当前文件指针 */
#define CMD_ByteRead 0x7B /* 以字节为单位从当前文件读取数据块 */
#define CMD_ByteWrite 0x7C /* 以字节为单位向当前文件写入数据块 */
#define CMD_DiskReady 0x71 /* 查询磁盘是否准备好 */
#define CMD_RESET 0x7D /*复位*/
/*
CS------PC0
SCK-----PC1
SDI-----PC3
SDO-----PC2
*/
#define PB375_CS_SET PORTC |= (1<<PC0)
#define PB375_CS_CLR PORTC &= ~ (1<<PC0)
#define PB375_SCK_SET PORTC |= (1<<PC1)
#define PB375_SCK_CLR PORTC &= ~(1<<PC1)
#define PB375_SDI_SET PORTC |= (1<<PC2)
#define PB375_SDI_CLR PORTC &= ~(1<<PC2)
#define PB375_SDO (PINC &(1<<PC3))
#define MAXBUFLEN 128
//发送缓冲区
unsigned char sendBuff[MAXBUFLEN];
//接收缓冲区
unsigned char recBuff[MAXBUFLEN];
//初始化IO口 设置CS SCK SDI 为输出 SDO为输入
void initPort()
{
PORTC |= 0x07;
DDRC |= 0x07;
DDRC &= 0xF7;
}
/* 以毫秒为单位延时,适用于24MHz时钟 */
void mDelaymS( unsigned char delay )
{
unsigned char i, j, c;
for ( i = delay; i != 0; i -- )
{
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz时钟下延时500uS */
for ( j = 200; j != 0; j -- ) c += 3; /* 在24MHz时钟下延时500uS */
}
}
/* 发送一个字节数据给PB375模块,同时接收一个字节,以SPI模式0方式(SPI_SCK默认为0) */
unsigned char mSpiExchange( unsigned char c )
{
unsigned char i, d;
d = 0;
PB375_SCK_CLR;
for ( i = 8; i != 0; i -- ) { /* 8个位 */
if ( c & 0x80 )
PB375_SDI_SET; /* 向模块的SDI输入引脚输出数据 */
else
PB375_SDI_CLR;
d <<= 1;
if ( PB375_SDO )
d++; /* 如果模块的SDO输出引脚为高电平则输入位1 PB375_SDO */
mDelaymS(1);
PB375_SCK_SET; /* SPI时钟上升沿,模块接收数据并输出数据 */
c <<= 1;
mDelaymS(1);
PB375_SCK_CLR;
}
return( d );
}
/* 执行命令 */
unsigned char ExecCommand( unsigned char cmd, unsigned char len )
{
unsigned char i, j, status;
PB375_CS_CLR; /* 产生SPI片选 */
mSpiExchange( cmd ); /* 写入命令码 */
mSpiExchange( len ); /* 写入后续参数的长度 */
if ( len ) { /* 有参数 */
for ( i = 0; i != len; i ++ ) mSpiExchange( sendBuff[ i ] ); /* 依次写入参数 */
}
PB375_CS_SET; /* 结束SPI片选 */
while ( 1 ) { /* 处理数据传输,直到操作完成才退出 */
PB375_CS_CLR; /* 产生SPI片选 */
status = mSpiExchange( 0xFF ); /* 写入0xFF作为无效命令码(不应该写其它值),返回模块操作状态 */
if ( status == 0xFF ) { /* 模块操作尚未完成,也就是INT#没有中断产生 */
PB375_CS_SET; /* 结束SPI片选 */
mDelaymS( 1 );
continue; /* 继续等待模块完成操作 */
}
if ( status == ERR_SUCCESS ) /* 操作成功 */
{
i = mSpiExchange( 0 ); /* 返回结果数据的长度,写入0没有意义,可以是任何值 */
if ( i ) { /* 有结果数据 */
j = 0;
do { /* 使用do+while结构是因为其效率高于for */
recBuff[ j ] = mSpiExchange( 0 ); /* 接收结果数据并保存到参数结构中,写入0没有意义 */
j ++;
} while ( -- i );
}
PB375_CS_SET; /* 结束SPI片选 */
break; /* 操作成功返回 */
}
else /* 操作失败 */
{
PB375_CS_SET; /* 结束SPI片选 */
if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT ) mDelaymS( 100 ); /* U盘刚刚连接或者断开,应该延时几十毫秒再操作 */
break; /* 操作失败返回 */
}
PB375_CS_SET; /* 结束SPI片选 */
}
return( status );
}
/*
主程序
*/
void main( )
{
unsigned char i;
initPort();
mDelaymS( 500 ); /* 延时500毫秒,PB375模块上电后需要500毫秒左右的复位时间 */
for ( i = 0; i < 5; i ++ )
{
mDelaymS( 100 );
if ( ExecCommand( CMD_DiskReady, 0 ) == ERR_SUCCESS )
break; /* 查询磁盘是否准备好 */
}
//写入数据到文件
/*
sendBuff[0] = 92;
sendBuff[1] = 0x52;
sendBuff[2] = 0x41;
sendBuff[3] = 0x42;
sendBuff[4] = 0x43;
sendBuff[5] = 0x35;
sendBuff[6] = 0x36;
sendBuff[7] = 0x4C;
sendBuff[8] = 0x2e;
sendBuff[9] = 0x54;
sendBuff[10] = 0x58;
sendBuff[11] = 0x54;
sendBuff[12] = 0;
sendBuff[0] = 92;
sendBuff[1] = 0x42;
sendBuff[2] = 0x4F;
sendBuff[3] = 0x44;
sendBuff[4] = 0x59;
sendBuff[5] = 0x44;
//sendBuff[6] = 0x41;
//sendBuff[7] = 0x54;
//sendBuff[8] = 0x41;
sendBuff[6] = 0x2E;
sendBuff[7] = 0x54;
sendBuff[8] = 0x58;
sendBuff[9] = 0x54;