📄 udisk.c
字号:
//此版本为测试375自带模块函数设计,
//测试读取文件,新建文件,写入文件,修改属性
#include <iom32v.h>
#include "macros.h"
#include <string.h>
#include <stdio.h>
#include "twi.h"
#include "UART.h"
#include "udisk.h"
#define uchar unsigned char
#define UINT8 unsigned char
#define ulong unsigned long
#define uint unsigned int
//端口的定义,用I/O模拟总线方式
//LED定义
#define LEDPORT PORTD
#define ALLLED 0xF0
#define LEDRD PD7
#define LEDWR PD6
#define LEDBUSY PD5
#define LEDERR PD4
//按键定义
#define KEYPORT PIND
#define S1 PD3
//模拟总线定义
#define DATAOUT PORTA //D0~D7在PA口
#define DATAIN PINA
#define CTRLBUS PORTC
#define CTRLWR PC7 //WR信号线在PC7
#define CTRLRD PC6 //RD信号线在PC6
#define ADDRBUS PORTB
#define A0 PB0 //A0地址线在PB0
#define CSPORT PORTB
#define CS PB1 //片选线在PB1
//一些总线控制宏定义
#define WRCTRL CTRLBUS&= ~BIT(CTRLWR) //写总线置低
#define RDCTRL CTRLBUS&= ~BIT(CTRLRD) //读总线置低
#define CLRCTRL CTRLBUS|= (BIT(CTRLWR)|BIT(CTRLRD)) //读写总线均置高
#define MCMD ADDRBUS|= BIT(A0) //指令的读写模式,A0置高
#define MDATA ADDRBUS&= ~BIT(A0) //数据的读写模式,A0置低
#define CSEN ADDRBUS&= ~BIT(CS) //CS使能置低
#define CSDIS ADDRBUS|= BIT(CS) //CS不使能置高
#define DATADIRI DDRA=0 //数据输入方式把DDRA置0
#define DATADIRO DDRA=0xff //数据输出方式把DDAR置0xff
//点灯的宏定义
#define LIGHT_WR LEDPORT&= ~BIT(LEDWR)
#define OFF_WR LEDPORT|= BIT(LEDWR)
#define LIGHT_RD LEDPORT&= ~BIT(LEDRD)
#define OFF_RD LEDPORT|= BIT(LEDRD)
#define LIGHT_BUSY LEDPORT&= ~BIT(LEDBUSY)
#define OFF_BUSY LEDPORT|= BIT(LEDBUSY)
#define LIGHT_ERR LEDPORT&= ~BIT(LEDERR)
#define OFF_ERR LEDPORT|= BIT(LEDERR)
#define LIGHT_ALL LEDPORT&= ~ALLLED
#define OFF_ALL LEDPORT|= ALLLED
#define I2C_SEND_READY DataPrepared = 0xff
#define CLR_COMFLAGE I2cComStatus = 0
#define FILE_ATTRI_BYTES 9
#define RETURN_SUCCESS nComBuff.AckData.Ack = A_SUCCESS
//决定是否使能应答
#define OPEN_ACK TWCR|= 1<<TWEA
#define CLOSE_ACK TWCR&= ~(1<<TWEA)
/* 以下定义的详细说明请看CH375HF9.H文件 */
#define LIB_CFG_FILE_IO 1 /* 文件读写的数据的复制方式,0为"外部子程序",1为"内部复制" */
#define LIB_CFG_INT_EN 0 /* CH375的INT#引脚连接方式,0为"查询方式",1为"中断方式" */
/* 单片机的RAM有限,其中CH375子程序用512字节,剩余RAM部分可以用于文件读写缓冲 */
#define FILE_DATA_BUF_LEN 512 /* 外部RAM的文件数据缓冲区,缓冲区长度不小于一次读写的数据长度 */
#define CH375_INT_WIRE ( PIND & 0x04 ) /* PIND.2, CH375的中断线INT#引脚,连接CH375的INT#引脚,用于查询中断状态 */
#define NO_DEFAULT_CH375_F_ENUM 1 /* 未调用CH375FileEnumer程序故禁止以节约代码 */
//#define NO_DEFAULT_CH375_F_QUERY 1 /* 未调用CH375FileQuery程序故禁止以节约代码 */
#define LIB_CFG_FILE_IO_DEFAULT
#define NO_DEFAULT_DELAY_100US //用自己定义的延时100us函数实现延时
#define NO_DEFAULT_DELAY_WRITE //用自己定义的延时函数实现写入后的延时
#include "CH375HFB.h"
void init_devices(void );
void mDelaymS( UINT8 ms );
void xDelay100uS( void );
void xDelayAfterWrite( void );
void twi_process(void);
void transmit_process(void);
void receive_process(void);
void twisentbyte(unsigned char SentData);
void delay_us(void);
void xWriteCH375Cmd( UINT8 mCmd );
void xWriteCH375Data( UINT8 mData );
UINT8 xReadCH375Data( void );
void timer0_ovf_isr(void);
void timer0_init(void);
void twi_isr(void);
void variable(void);
void RecieveFrameProcess( void );
void ModuleSetOffset(uchar ModeLocate);
COM_BUFF nComBuff;
uchar ys20ms;
uchar B_status; //模块大状态变量
uchar temp[10];
uchar OperReturn;
uchar DataPrepared; //数据是否准备好变量
uchar rdcount;
extern uint *SlaveSendLength;
extern uchar I2cComStatus; //通信状态变量
/*Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
I2CRecCom I2C_sendCom
I2C_RecCom--Recieve complete
I2C_SendCom--Transmmit complete
**********************************************************/
extern unsigned char *I2cReceiveData; //I2c数据接收缓冲地址
extern unsigned char *I2cSendData; //I2c数据发送缓冲地址
extern unsigned char *UartRx; //存放接收数据的指针
extern unsigned int *RxLength; //数据接收长度地址指针
extern unsigned char UartState; //UART状态变量
void main(void)
{
UINT8 i;
uint j=200;
begin: variable( ); //变量的初始化
i2cSetBitrate(100);
i2cInit();
i2cSetLocalDeviceAddr(0x60,1);
init_USART(0);
init_devices( );
/*测试延时时间是否充足*/
xDelay100uS( );
delay_us( );
put_s("Start\n");
for(i=0;i<3;i++) //闪烁三次
{
LIGHT_ALL;
ys20ms=20;
while(ys20ms);
OFF_ALL;
ys20ms=20;
while(ys20ms);
}
OperReturn = CH375LibInit( ); // 初始化CH375程序库和CH375芯片,操作成功返回0
if(OperReturn)
{
goto begin; //重新启动程序
}
while( CH375DiskStatus != DISK_CONNECT ) xQueryInterrupt( ); // 查询CH375中断并更新中断状态,等待U盘插入
mDelaymS( 200 ); //延时,可选操作,有的USB存储器需要几十毫秒的延时
/* 检查U盘是否准备好,有些U盘不需要这一步,但是某些U盘必须要执行这一步才能工作 */
for ( i = 0; i < 10; i ++ )
{ /* 有的U盘总是返回未准备好,不过可以被忽略 */
mDelaymS( 100 );
if ( CH375DiskReady( ) == ERR_SUCCESS )
{
B_status = S_READY;
break; /* 查询磁盘是否准备好 */
}
else
{
B_status = S_NOTREADY;
}
}
put_s("Prepared\n");
while(1)
{
if(I2cComStatus & BIT(I2C_RECCOM))
{
CLOSE_ACK; //停止应答
LIGHT_BUSY;
puts("Command received\n");
put_bytes(&nComBuff.ReqData.Com,1);
I2cComStatus&= ~BIT(I2C_RECCOM);
if(nComBuff.ReqData.Com == R_RESET)
{
nComBuff.ReqData.Com = 0;
goto begin;
}
RecieveFrameProcess( );
DataPrepared = 0xff;
}
if(DataPrepared)
{
DataPrepared = 0;
put_bytes((char* )&nComBuff,MAX_BYTE_TRANS+5);
OPEN_ACK; //进行应答
OFF_BUSY;
}
}
}
/* 延时指定毫秒时间,根据单片机主频调整,不精确 */
void mDelaymS( UINT8 ms )
{
UINT16 i;
while ( ms -- ) for ( i = 1325; i != 0; i -- );
}
/******************************************************************************
延时1uS
*******************************************************************************/
void delay_us(void)
{
uchar j;
j++;
}
/*****************************************************************************
/函数库要调用的100us延时
*****************************************************************************/
void xDelay100uS( void ) /* 延时100uS */
{
UINT16 count;
for ( count = 150; count != 0; count -- );
}
/****************************************************************************
/函数库要调用的写入后延时
****************************************************************************/
void xDelayAfterWrite( void ) /* 写操作后延时 */
{
UINT16 count;
for ( count = 300; count != 0; count -- ); /* 延时200uS左右 */
}
/**************************************************************************
外部定义的被CH375程序库调用的子程序,向CH375写命令,最小周期为4uS,
否则之前之后各延时2uS
***************************************************************************/
void xWriteCH375Cmd( UINT8 mCmd )
{
delay_us();
delay_us();
MCMD; //A0置高
DATADIRO; //数据方向为输出
DATAOUT=mCmd; //数据输出
CSEN; //使能
WRCTRL; //写信号
WRCTRL; //延时
CLRCTRL; //关写信号
CSDIS; //使能禁止
delay_us();
delay_us();
}
/**************************************************************************
外部定义的被CH375程序库调用的子程序,向CH375写数据,最小周期为1.5uS,
否则之后延时1.5uS
***************************************************************************/
void xWriteCH375Data( UINT8 mData )
{
MDATA; //A0置高
DATADIRO; //数据方向为输出
DATAOUT=mData; //数据输出
CSEN; //使能
WRCTRL; //写信号
WRCTRL; //延时
CLRCTRL; //关写信号
CSDIS; //使能禁止
delay_us();
delay_us();
}
/**************************************************************************
外部定义的被CH375程序库调用的子程序,从CH375读数据,最小周期为1.5uS,
否则之前延时1.5uS
***************************************************************************/
UINT8 xReadCH375Data( void )
{
UINT8 inData;
delay_us();
MDATA;
DATADIRI;
CSEN;
RDCTRL;
RDCTRL;
inData=DATAIN;
CLRCTRL;
CSDIS;
return(inData);
}
/****************************************************************************
/动作执行完,返回结果,OperReturn为0则返回A_SUCCESS,非零则返回OperReturn值
****************************************************************************/
void ReturnProResult( void )
{
if(OperReturn)
{
nComBuff.AckData.Ack = OperReturn;
}
else
{
nComBuff.AckData.Ack = A_SUCCESS;
}
}
/************************************************************************/
/* 发送错误码。自动组帧。
入口参数:ErrorCode */
/************************************************************************/
void ReturnErrorCode(uchar ErrorCode)
{
I2C_SEND_READY;
nComBuff.AckData.Ack = ErrorCode;
nComBuff.AckData.FrameLen = 3;
}
/************************************************************************/
/* 复制数据
入口参数:
uchar destination *:目的地址
uchar source *:源地址
uint number: 字节数 */
/************************************************************************/
void CopyBytes(uchar* destination,uchar* source,uint number)
{
uint i;
for(i=0;i<number;i++)
{
*(destination+i) = *(source+i);
}
}
/************************************************************************/
/* 新建文件(文件夹)函数
入口参数:directory,0=新建文件,!0=新建文件夹 */
/************************************************************************/
void ModuleNewFile(uchar directory)
{
nComBuff.ReqData.VeryData.FileName[MAX_PATH_LEN-1]=0; //确保最后一个是“0”,作为字符串的尾部
strcpy((char *)mCmdParam.Create.mPathName,(char *)nComBuff.ReqData.VeryData.FileName);
OperReturn = CH375FileCreate( ); //新建文件
if(OperReturn)
{
ReturnErrorCode(OperReturn);
B_status = S_READY;
}
else if(directory)
{
mCmdParam.Modify.mFileAttr = ATTR_DIRECTORY;
mCmdParam.Modify.mFileDate = 0xffff;
mCmdParam.Modify.mFileSize = 0xffffffff;
mCmdParam.Modify.mFileTime = 0xffff;
OperReturn = CH375FileModify();
directory = 0; //把此值清零防止再进入此分支
if(OperReturn)
{
ReturnErrorCode(OperReturn);
B_status = S_READY;
}
else
{
mCmdParam.Close.mUpdateLen = 1; //自动更新文件长度
OperReturn = CH375FileClose( );
if(OperReturn)
{
ReturnErrorCode(OperReturn);
B_status = S_READY;
}
else
{
ReturnErrorCode(A_SUCCESS);
B_status = S_READY;
}
}
}
else
{
ReturnErrorCode(A_SUCCESS);
B_status=S_OPEN;
}
}
/************************************************************************/
/* 如果优盘的状态是准备好,但未读写,进入的分支 */
/************************************************************************/
void StatusReady(void)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -