DSP2812并口读写U盘的问题

大家好 不知道哪位大侠琢磨过用TM320F2812来控制CH376S芯片读写U盘的实验的,小弟最近一直在做这个 琢磨了好久 初始化一直有问题 我是照着官方提供的51程序在CCS里面写代码的,我用的是GPIO口模拟并口 单步调试 一直初始化有问题 不知哪位大侠可以帮忙解解惑 代码如下 完全照着官方的51的例程来移植的 一直有问题 求高手 #include "DSP28_Device.h"

//#define CH376_CMD_PORT (*((volatile Uint16 *)0x22f1)) //假定CH376命令端口的I/O地址 //#define CH376_DATA_PORT (*((volatile Uint16 *)0x22f0)) //假定CH376命令端口的I/O地址 //#define xReadCH376Data() (CH376_DATA_PORT)

#define TRUE 1 #define NULL 0x0000 #define CMD11_CHECK_EXIST 0x0006 #define ERR_USB_UNKNOWN 0x00FA #define CMD11_SET_USB_MODE 0x0015 //设置USB的工作模式 #define CMD_RET_SUCCESS 0x0051 //命令操作成功 #define USB_INT_SUCCESS 0x0014 //USB事务或者传输操作成功 #define CMD01_GET_STATUS 0x0022 #define CMD0H_DISK_CONNECT 0x0030 #define CMD0H_DISK_MOUNT 0x0031 #define CMD01_GET_IC_VER 0x0001 #define CMD10_SET_FILE_NAME 0x002f #define CMD0H_FILE_OPEN 0x0032 //打开文件或者目录,或者枚举文件或目录 #define VAR_DISK_STATUS 0x002b //主机文件模式下的磁盘及文件状态 是系统变量的地址 #define DEF_DISK_READ 0x0010 //已经分析磁盘的文件系统并且能够支持 显示主机模式下的磁盘及文件状态 #define CMD11_READ_VAR8 0x000a //读取指定的8位文件系统变量 #define CMD50_WRITE_VAR32 0x000d //设置指定的32位文件系统变量 #define CMD4H_BYTE_LOCATE 0x0039 //主机文件模式:以字节为单位移动当前文件指针 #define CMD0H_FILE_CREATE 0x0034 //主机文件模式:新建文件,如果文件已经存在 那么删除 #define VAR_FILE_SIZE 0x0068 //当前文件的总长度(总长度32位,低字节在前) #define CMD14_READ_VAR32 0x000c //读取指定的32位文件系统变量 #define ERR_MISS_FILE 0x0042 //指定路径的文件没有找到 可能是文件名称错误 #define CMD2H_BYTE_WRITE 0x003c //主机文件模式:以字节为单位向当前位置写入数据块 #define USB_INT_DISK_WRITE 0x001e //USB存储器请求数据写入 #define CMD01_WR_REQ_DATA 0x002d //向内部指定缓冲区写入请求的数据块 #define CMD0H_BYTE_WR_GO 0x003d //主机文件模式:继续字节写 #define VAR_CURRENT_OFFSET 0x006c //当前位置的指针,当前文件指针,当前读写位置的字节偏移(总长度32位,低字节在前) #define CMD1H_FILE_CLOSE 0x0036 //主机模式:关闭当前已经打开的文件或者目录

char buf[64];

void delay_ms(Uint16 i); void delay_us(Uint16 j); void xWriteCH376Cmd(Uint16 mCmd); void xWriteCH376Data(Uint16 mData); void mStopIfError(Uint16 iError); void CH376SetFileName(char *str); void CH376WriteVar32(Uint16, Uint32 dat);

void CH376_PORT_INIT(void); //CH376通讯接口初始化 void CH376_DATA_DIR_IN(void); //设置并口方向为输入 void CH376_DATA_DIR_OUT(void); //设置并口方向为输出 向CH376S输出数据或者命令

Uint32 CH376GetFileSize(void); Uint16 CH376DiskMount(void); Uint16 Wait376Interrupt( void ); Uint16 mInitCH376Host(void); Uint16 xReadCH376Data(void); Uint16 CH376DiskConnect(void); Uint16 Query376Interrupt(void); Uint16 CH376GetIntStatus(void); Uint16 CH376SendCmdWaitInt( Uint16 mCmd); Uint16 CH376FileOpen(char *name); Uint16 CH376ReadVar8(Uint16 var); Uint16 CH376ByteLocate(Uint32 offset); //以字节为单位移动当前文件指针 Uint16 CH376FileCreate(char *str); //在根目录或者当前目录下新建文件,如果文件已经存在 那么删除 Uint32 CH376ReadVar32(Uint16 var); //读CH376芯片内部的32位变量 Uint32 CH376Read32bitDat(void); //从CH376芯片读取32位的数据并结束命令 Uint16 CH376ByteWrite(char *buf,Uint16 ReqCount,char *RealCount); //以字节为单位向当前位置写入数据块 Uint16 CH376WriteReqBlock(char *buf); //向内部指定缓冲区写入请求的数据块,返回长度 Uint16 CH376FileClose(Uint16 UpdateSz); //关闭当前已经打开的文件或者目录 Uint16 CH376SendCmdDatWaitInt(Uint16 mCmd,Uint16 mDat); //发出命令码和一字节数据后,等待中断

void main() { Uint16 s; Uint16 hour; Uint16 adc; /*初始化系统*/ InitSysCtrl(); /* 关中断 */ DINT; IER = 0x0000; IFR = 0x0000;

/*初始化PIE*/ InitPieCtrl();

/* 初始化PIE中断矢量表 */ InitPieVectTable();

/* 初始化外设 */ InitPeripherals();

InitGpio();

EINT; ERTM; delay_ms(100); s = mInitCH376Host(); mStopIfError(s);

while(1) { while(CH376DiskConnect() != USB_INT_SUCCESS ) //检查U盘是否插入 { delay_ms(100); }

delay_ms(200);

/*如果检测到USB设备*/ for(s=0;s<10;s++) { delay_ms(50); if(CH376DiskMount() == USB_INT_SUCCESS) break; //初始化磁盘并测试磁盘是否就绪 } s = CH376FileOpen("/MY_ADC.TXT"); if(s==USB_INT_SUCCESS ) //文件存在并且已经被打开,移动文件指针到尾部以便添加数据 { s = CH376ByteLocate(0xffffffff) ; //移到文件的尾部 mStopIfError(s); } else if (s==ERR_MISS_FILE) //没有找到文件 必须新建文件 { s=CH376FileCreate( NULL ); //新建文件并打开,如果文件已经存在则先删除后在新建,不必再提供文件名,刚才已经提供给CH376FileOpen mStopIfError(s); } else mStopIfError(s); s=sprintf(buf,"此前文件长度=%ld 字节 \xd\xa",CH376GetFileSize()); s=CH376ByteWrite(buf,s,NULL); //以字节为单位向文件写数据 mStopIfError(s); for(hour = 8;hour<20;hour++) { adc=0; s=sprintf(buf,"%02d,%02d,%02d ADC=%u\xd\xa",adc); s=CH376ByteWrite(buf,s,NULL); //以字节为单位向文件写数据 //有些U盘可能会要求在写数据后等待一会儿才能继续操作,所以,如果在某些U盘中发现数据丢失现象,建议在每次写入数据后稍作延时再继续 mStopIfError(s); printf("Current offset (file point) is %ld\n",CH376ReadVar32(VAR_CURRENT_OFFSET) ); //读取当前文件的指针 } printf("Write end\n"); strcpy(buf,"今天的ADC数据到此结束\xd\xa"); s=CH376ByteWrite(buf,strlen(buf),NULL); //以字节为单位向文件写数据 mStopIfError(s); printf("Close\n"); s= CH376FileClose(TRUE); //关闭文件,自动计算文件长度,以字节为单位写文件,建议让程序库关闭文件以便自动更新文件长度 mStopIfError(s); printf("Take out\n"); while(CH376DiskConnect() == USB_INT_SUCCESS ) //检查U盘是否连接,等待U盘拔出 { delay_ms(100); } delay_ms(200); } }

void delay_ms(Uint16 i) //延时ms { Uint16 n; Uint16 j; Uint16 k; for(n=0;n for(j=0;j<1000;j++) for(k=0;k<256;k++); } void delay_us(Uint16 j) //延时us { Uint16 n; Uint16 k; for(n=0;n for(k=0;k<256;k++); } Uint16 mInitCH376Host(void) { Uint16 res; CH376_PORT_INIT();//接口硬件初始化 xWriteCH376Cmd(CMD11_CHECK_EXIST); xWriteCH376Data(0x0055); res = xReadCH376Data(); if(res!=0x00aa) { return(ERR_USB_UNKNOWN); //如果通讯接口不正常 发送错误信号 } xWriteCH376Cmd(CMD11_SET_USB_MODE); //设置USB的工作模式 xWriteCH376Data(0x0006); //切换到已启用的USB主机方式,自动产生SOF包 delay_ms(20); res = xReadCH376Data(); if(res == CMD_RET_SUCCESS ) { return(USB_INT_SUCCESS); } else { return(ERR_USB_UNKNOWN); } } Uint16 xReadCH376Data(void) { Uint16 val; CH376_DATA_DIR_IN(); //设置并口方向为输入 GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 写数据 GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 片选 GpioDataRegs.GPADAT.bit.GPIOA4=0; //RD=0 输出有效读控制信号,读CH376芯片的数据端口 GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 该操作无意义,仅用作延时,CH376要求读写脉冲宽度大于40ns, 强烈建议此处执行一条空指令延时以确保并口有足够的时间输入数据 val= GpioDataRegs.GPBDAT.all; //从CH376S并口输入数据 GpioDataRegs.GPADAT.bit.GPIOA4=1; //RD=1 输出无效的控制信号 完成操作CH376芯片 GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 CH376_DATA_DIR_IN(); //禁止数据输出 return val; } Uint16 CH376DiskMount(void) { return(CH376SendCmdWaitInt(CMD0H_DISK_MOUNT)); } Uint16 CH376DiskConnect(void) { if(GpioDataRegs.GPADAT.bit.GPIOA0==0) //CH376向CPU申请中断 低电平有效 INT# { CH376GetIntStatus(); } return(CH376SendCmdWaitInt(CMD0H_DISK_CONNECT)); } Uint16 CH376GetIntStatus(void) { Uint16 s; xWriteCH376Cmd(CMD01_GET_STATUS); s = xReadCH376Data(); return( s ); } Uint16 Wait376Interrupt( void ) { while(GpioDataRegs.GPADAT.bit.GPIOA0==0); return(CH376GetIntStatus()); } Uint16 CH376SendCmdWaitInt( Uint16 mCmd) { xWriteCH376Cmd( mCmd ); return( Wait376Interrupt() ); } Uint16 CH376FileOpen(char *name) { CH376SetFileName(name); return(CH376SendCmdWaitInt(CMD0H_FILE_OPEN)); } Uint16 CH376ReadVar8(Uint16 var) //读CH376芯片内部的8位变量 { Uint16 c0; xWriteCH376Cmd(CMD11_READ_VAR8); xWriteCH376Data(var); c0 = xReadCH376Data(); return(c0); } Uint16 CH376ByteLocate(Uint32 offset) //以字节为单位移动当前文件指针 { xWriteCH376Cmd(CMD4H_BYTE_LOCATE); xWriteCH376Data((Uint16)offset); xWriteCH376Data((Uint16)offset>>8); xWriteCH376Data((Uint16)(offset>>16)); xWriteCH376Data((Uint16)(offset>>24)); return(Wait376Interrupt()); } Uint16 CH376FileCreate(char *name) //在根目录或者当前目录下新建文件,如果文件已经存在 那么删除 { if(name) CH376SetFileName(name); return(CH376SendCmdWaitInt(CMD0H_FILE_CREATE)); } Uint16 CH376ByteWrite(char *buf,Uint16 ReqCount,char *RealCount) //以字节为单位向当前位置写入数据块 { Uint16 s; xWriteCH376Cmd(CMD2H_BYTE_WRITE); xWriteCH376Data((Uint16)ReqCount); xWriteCH376Data((Uint16)(ReqCount>>8)); if(RealCount) *RealCount = 0; while(1) { s=Wait376Interrupt(); if( s== USB_INT_DISK_WRITE) { s=CH376WriteReqBlock(buf); //向内部指定缓冲区写入请求的数据块,返回长度 xWriteCH376Cmd(CMD0H_BYTE_WR_GO); //继续写 buf+=s; if(RealCount) *RealCount+=s; } else return(s); } } Uint16 CH376WriteReqBlock(char *buf) //向内部指定缓冲区写入请求的数据块,返回长度 { Uint16 s; Uint16 l; xWriteCH376Cmd(CMD01_WR_REQ_DATA); l=xReadCH376Data(); //返回CH376请求单片机写入的后续数据流的字节数 s=l; if(l) { do { xWriteCH376Data(*buf) ; buf++; } while(--l); } return(s); } Uint16 CH376FileClose(Uint16 UpdateSz) //关闭当前已经打开的文件或者目录 { return(CH376SendCmdDatWaitInt(CMD1H_FILE_CLOSE,UpdateSz)); } Uint16 CH376SendCmdDatWaitInt(Uint16 mCmd,Uint16 mDat) //发出命令码和一字节数据后,等待中断 { xWriteCH376Cmd(mCmd); xWriteCH376Data(mDat); return(Wait376Interrupt()); } Uint32 CH376GetFileSize(void) { return( CH376ReadVar32( VAR_FILE_SIZE)); } Uint32 CH376ReadVar32(Uint16 var) //读CH376芯片内部的32位变量 { xWriteCH376Cmd(CMD14_READ_VAR32); xWriteCH376Data(var); return(CH376Read32bitDat()); //从CH376芯片读取32位的数据并结束命令 } Uint32 CH376Read32bitDat(void) //从CH376芯片读取32位的数据并结束命令 { Uint16 c0; Uint16 c1; Uint16 c2; Uint16 c3; c0 = xReadCH376Data(); c1 = xReadCH376Data(); c2 = xReadCH376Data(); c3 = xReadCH376Data(); return(c0|c1<<8|(Uint32)c2<<16|(Uint32)c3<<24); } void xWriteCH376Cmd(Uint16 mCmd) { CH376_DATA_DIR_OUT(); //设置IO口为输出 GpioDataRegs.GPBDAT.all= mCmd; //需要输入的命令 //CH376_DATA_DIR_OUT(); //设置IO口为输出 GpioDataRegs.GPADAT.bit.GPIOA1=1; //A0=1 写命令 GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 片选 GpioDataRegs.GPADAT.bit.GPIOA3=0; //WR=0 写选通 写CH376的命令端口 GpioDataRegs.GPADAT.bit.GPIOA3=1; //WR=1 输出无效的控制信号 完成操作CH376芯片 GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 CH376_DATA_DIR_IN(); //禁止数据输出 } void xWriteCH376Data(Uint16 mData) { CH376_DATA_DIR_OUT(); //设置并口方向为输出 GpioDataRegs.GPBDAT.all= mData; //向CH376的并口输出数据‘ // CH376_DATA_DIR_OUT(); //设置并口方向为输出 GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 写数据 GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 片选 GpioDataRegs.GPADAT.bit.GPIOA3=0; //WR=0 写选通 GpioDataRegs.GPADAT.bit.GPIOA3=1; //WR=1 输出无效的控制信号 完成操作CH376芯片 GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 CH376_DATA_DIR_IN(); //禁止数据输出 } void mStopIfError(Uint16 iError) { if(iError==USB_INT_SUCCESS) { return; } while(1) { delay_ms(200); delay_ms(200); } } void CH376WriteVar32(Uint16 var, Uint32 dat) { xWriteCH376Cmd(CMD50_WRITE_VAR32); xWriteCH376Data(var); xWriteCH376Data((Uint16)dat); xWriteCH376Data((Uint16)dat>>8); xWriteCH376Data((Uint16)(dat>>16)); xWriteCH376Data((Uint16)(dat>>24)); } void CH376SetFileName(char *str) //设置将要操作的文件的文件名 { Uint16 s; xWriteCH376Cmd(CMD01_GET_IC_VER); if(xReadCH376Data() < 0x43) { if(CH376ReadVar8(VAR_DISK_STATUS) < DEF_DISK_READ) { xWriteCH376Cmd(CMD10_SET_FILE_NAME); xWriteCH376Data(0); s = CH376SendCmdWaitInt(CMD0H_FILE_OPEN); if(s==USB_INT_SUCCESS) { s = CH376ReadVar8(0x00CF); if(s) { CH376WriteVar32(0x004c,CH376ReadVar32(0x004c) + (s<<8)); CH376WriteVar32(0x0050,CH376ReadVar32(0x0050) + (s<<8)); CH376WriteVar32(0x0070,0); } } } } } void CH376_PORT_INIT(void) { GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 GpioDataRegs.GPADAT.bit.GPIOA3=1; //WR=1 GpioDataRegs.GPADAT.bit.GPIOA4=1; //RD=1 GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 CH376_DATA_DIR_IN(); //设置并口输入 } void CH376_DATA_DIR_IN(void) { EALLOW; GpioMuxRegs.GPBDIR.all=0x0000; //输入 EDIS; } void CH376_DATA_DIR_OUT(void) { EALLOW; GpioMuxRegs.GPBDIR.all=0xffff; //输出 输送命令字或者数据给CH376S EDIS; }

你的测试命令能通过吗?如果测试命令没有通过的话注意以下两点: (1)芯片有没有正常工作,晶振起振,第25脚复位输出脚为低电平。 (2)时序是否正确,如果单片机主频比较快的话,注意字节读写之间需要加延时。


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