大家好 不知道哪位大俠琢磨過用TM320F2812來控制CH376S芯片讀寫U盤的實(shí)驗(yàn)的,小弟最近一直在做這個(gè) 琢磨了好久 初始化一直有問題 我是照著官方提供的51程序在CCS里面寫代碼的,我用的是GPIO口模擬并口 單步調(diào)試 一直初始化有問題 不知哪位大俠可以幫忙解解惑 代碼如下 完全照著官方的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 //設(shè)置USB的工作模式 #define CMD_RET_SUCCESS 0x0051 //命令操作成功 #define USB_INT_SUCCESS 0x0014 //USB事務(wù)或者傳輸操作成功 #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 //主機(jī)文件模式下的磁盤及文件狀態(tài) 是系統(tǒng)變量的地址 #define DEF_DISK_READ 0x0010 //已經(jīng)分析磁盤的文件系統(tǒng)并且能夠支持 顯示主機(jī)模式下的磁盤及文件狀態(tài) #define CMD11_READ_VAR8 0x000a //讀取指定的8位文件系統(tǒng)變量 #define CMD50_WRITE_VAR32 0x000d //設(shè)置指定的32位文件系統(tǒng)變量 #define CMD4H_BYTE_LOCATE 0x0039 //主機(jī)文件模式:以字節(jié)為單位移動(dòng)當(dāng)前文件指針 #define CMD0H_FILE_CREATE 0x0034 //主機(jī)文件模式:新建文件,如果文件已經(jīng)存在 那么刪除 #define VAR_FILE_SIZE 0x0068 //當(dāng)前文件的總長(zhǎng)度(總長(zhǎng)度32位,低字節(jié)在前) #define CMD14_READ_VAR32 0x000c //讀取指定的32位文件系統(tǒng)變量 #define ERR_MISS_FILE 0x0042 //指定路徑的文件沒有找到 可能是文件名稱錯(cuò)誤 #define CMD2H_BYTE_WRITE 0x003c //主機(jī)文件模式:以字節(jié)為單位向當(dāng)前位置寫入數(shù)據(jù)塊 #define USB_INT_DISK_WRITE 0x001e //USB存儲(chǔ)器請(qǐng)求數(shù)據(jù)寫入 #define CMD01_WR_REQ_DATA 0x002d //向內(nèi)部指定緩沖區(qū)寫入請(qǐng)求的數(shù)據(jù)塊 #define CMD0H_BYTE_WR_GO 0x003d //主機(jī)文件模式:繼續(xù)字節(jié)寫 #define VAR_CURRENT_OFFSET 0x006c //當(dāng)前位置的指針,當(dāng)前文件指針,當(dāng)前讀寫位置的字節(jié)偏移(總長(zhǎng)度32位,低字節(jié)在前) #define CMD1H_FILE_CLOSE 0x0036 //主機(jī)模式:關(guān)閉當(dāng)前已經(jīng)打開的文件或者目錄
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); //設(shè)置并口方向?yàn)檩斎? void CH376_DATA_DIR_OUT(void); //設(shè)置并口方向?yàn)檩敵?向CH376S輸出數(shù)據(jù)或者命令
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); //以字節(jié)為單位移動(dòng)當(dāng)前文件指針 Uint16 CH376FileCreate(char *str); //在根目錄或者當(dāng)前目錄下新建文件,如果文件已經(jīng)存在 那么刪除 Uint32 CH376ReadVar32(Uint16 var); //讀CH376芯片內(nèi)部的32位變量 Uint32 CH376Read32bitDat(void); //從CH376芯片讀取32位的數(shù)據(jù)并結(jié)束命令 Uint16 CH376ByteWrite(char *buf,Uint16 ReqCount,char *RealCount); //以字節(jié)為單位向當(dāng)前位置寫入數(shù)據(jù)塊 Uint16 CH376WriteReqBlock(char *buf); //向內(nèi)部指定緩沖區(qū)寫入請(qǐng)求的數(shù)據(jù)塊,返回長(zhǎng)度 Uint16 CH376FileClose(Uint16 UpdateSz); //關(guān)閉當(dāng)前已經(jīng)打開的文件或者目錄 Uint16 CH376SendCmdDatWaitInt(Uint16 mCmd,Uint16 mDat); //發(fā)出命令碼和一字節(jié)數(shù)據(jù)后,等待中斷
void main() { Uint16 s; Uint16 hour; Uint16 adc; /*初始化系統(tǒng)*/ InitSysCtrl(); /* 關(guān)中斷 */ DINT; IER = 0x0000; IFR = 0x0000;
/*初始化PIE*/ InitPieCtrl();
/* 初始化PIE中斷矢量表 */ InitPieVectTable();
/* 初始化外設(shè) */ 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);
/*如果檢測(cè)到USB設(shè)備*/ for(s=0;s<10;s++) { delay_ms(50); if(CH376DiskMount() == USB_INT_SUCCESS) break; //初始化磁盤并測(cè)試磁盤是否就緒 } s = CH376FileOpen("/MY_ADC.TXT"); if(s==USB_INT_SUCCESS ) //文件存在并且已經(jīng)被打開,移動(dòng)文件指針到尾部以便添加數(shù)據(jù) { s = CH376ByteLocate(0xffffffff) ; //移到文件的尾部 mStopIfError(s); } else if (s==ERR_MISS_FILE) //沒有找到文件 必須新建文件 { s=CH376FileCreate( NULL ); //新建文件并打開,如果文件已經(jīng)存在則先刪除后在新建,不必再提供文件名,剛才已經(jīng)提供給CH376FileOpen mStopIfError(s); } else mStopIfError(s); s=sprintf(buf,"此前文件長(zhǎng)度=%ld 字節(jié) \xd\xa",CH376GetFileSize()); s=CH376ByteWrite(buf,s,NULL); //以字節(jié)為單位向文件寫數(shù)據(jù) 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); //以字節(jié)為單位向文件寫數(shù)據(jù) //有些U盤可能會(huì)要求在寫數(shù)據(jù)后等待一會(huì)兒才能繼續(xù)操作,所以,如果在某些U盤中發(fā)現(xiàn)數(shù)據(jù)丟失現(xiàn)象,建議在每次寫入數(shù)據(jù)后稍作延時(shí)再繼續(xù) mStopIfError(s); printf("Current offset (file point) is %ld\n",CH376ReadVar32(VAR_CURRENT_OFFSET) ); //讀取當(dāng)前文件的指針 } printf("Write end\n"); strcpy(buf,"今天的ADC數(shù)據(jù)到此結(jié)束\xd\xa"); s=CH376ByteWrite(buf,strlen(buf),NULL); //以字節(jié)為單位向文件寫數(shù)據(jù) mStopIfError(s); printf("Close\n"); s= CH376FileClose(TRUE); //關(guān)閉文件,自動(dòng)計(jì)算文件長(zhǎng)度,以字節(jié)為單位寫文件,建議讓程序庫關(guān)閉文件以便自動(dòng)更新文件長(zhǎng)度 mStopIfError(s); printf("Take out\n"); while(CH376DiskConnect() == USB_INT_SUCCESS ) //檢查U盤是否連接,等待U盤拔出 { delay_ms(100); } delay_ms(200); } }
void delay_ms(Uint16 i) //延時(shí)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) //延時(shí)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); //如果通訊接口不正常 發(fā)送錯(cuò)誤信號(hào) } xWriteCH376Cmd(CMD11_SET_USB_MODE); //設(shè)置USB的工作模式 xWriteCH376Data(0x0006); //切換到已啟用的USB主機(jī)方式,自動(dòng)產(chǎn)生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(); //設(shè)置并口方向?yàn)檩斎? GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 寫數(shù)據(jù) GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 片選 GpioDataRegs.GPADAT.bit.GPIOA4=0; //RD=0 輸出有效讀控制信號(hào),讀CH376芯片的數(shù)據(jù)端口 GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 該操作無意義,僅用作延時(shí),CH376要求讀寫脈沖寬度大于40ns, 強(qiáng)烈建議此處執(zhí)行一條空指令延時(shí)以確保并口有足夠的時(shí)間輸入數(shù)據(jù) val= GpioDataRegs.GPBDAT.all; //從CH376S并口輸入數(shù)據(jù) GpioDataRegs.GPADAT.bit.GPIOA4=1; //RD=1 輸出無效的控制信號(hào) 完成操作CH376芯片 GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 CH376_DATA_DIR_IN(); //禁止數(shù)據(jù)輸出 return val; } Uint16 CH376DiskMount(void) { return(CH376SendCmdWaitInt(CMD0H_DISK_MOUNT)); } Uint16 CH376DiskConnect(void) { if(GpioDataRegs.GPADAT.bit.GPIOA0==0) //CH376向CPU申請(qǐng)中斷 低電平有效 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芯片內(nèi)部的8位變量 { Uint16 c0; xWriteCH376Cmd(CMD11_READ_VAR8); xWriteCH376Data(var); c0 = xReadCH376Data(); return(c0); } Uint16 CH376ByteLocate(Uint32 offset) //以字節(jié)為單位移動(dòng)當(dāng)前文件指針 { 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) //在根目錄或者當(dāng)前目錄下新建文件,如果文件已經(jīng)存在 那么刪除 { if(name) CH376SetFileName(name); return(CH376SendCmdWaitInt(CMD0H_FILE_CREATE)); } Uint16 CH376ByteWrite(char *buf,Uint16 ReqCount,char *RealCount) //以字節(jié)為單位向當(dāng)前位置寫入數(shù)據(jù)塊 { 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); //向內(nèi)部指定緩沖區(qū)寫入請(qǐng)求的數(shù)據(jù)塊,返回長(zhǎng)度 xWriteCH376Cmd(CMD0H_BYTE_WR_GO); //繼續(xù)寫 buf+=s; if(RealCount) *RealCount+=s; } else return(s); } } Uint16 CH376WriteReqBlock(char *buf) //向內(nèi)部指定緩沖區(qū)寫入請(qǐng)求的數(shù)據(jù)塊,返回長(zhǎng)度 { Uint16 s; Uint16 l; xWriteCH376Cmd(CMD01_WR_REQ_DATA); l=xReadCH376Data(); //返回CH376請(qǐng)求單片機(jī)寫入的后續(xù)數(shù)據(jù)流的字節(jié)數(shù) s=l; if(l) { do { xWriteCH376Data(*buf) ; buf++; } while(--l); } return(s); } Uint16 CH376FileClose(Uint16 UpdateSz) //關(guān)閉當(dāng)前已經(jīng)打開的文件或者目錄 { return(CH376SendCmdDatWaitInt(CMD1H_FILE_CLOSE,UpdateSz)); } Uint16 CH376SendCmdDatWaitInt(Uint16 mCmd,Uint16 mDat) //發(fā)出命令碼和一字節(jié)數(shù)據(jù)后,等待中斷 { xWriteCH376Cmd(mCmd); xWriteCH376Data(mDat); return(Wait376Interrupt()); } Uint32 CH376GetFileSize(void) { return( CH376ReadVar32( VAR_FILE_SIZE)); } Uint32 CH376ReadVar32(Uint16 var) //讀CH376芯片內(nèi)部的32位變量 { xWriteCH376Cmd(CMD14_READ_VAR32); xWriteCH376Data(var); return(CH376Read32bitDat()); //從CH376芯片讀取32位的數(shù)據(jù)并結(jié)束命令 } Uint32 CH376Read32bitDat(void) //從CH376芯片讀取32位的數(shù)據(jù)并結(jié)束命令 { 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(); //設(shè)置IO口為輸出 GpioDataRegs.GPBDAT.all= mCmd; //需要輸入的命令 //CH376_DATA_DIR_OUT(); //設(shè)置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 輸出無效的控制信號(hào) 完成操作CH376芯片 GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 CH376_DATA_DIR_IN(); //禁止數(shù)據(jù)輸出 } void xWriteCH376Data(Uint16 mData) { CH376_DATA_DIR_OUT(); //設(shè)置并口方向?yàn)檩敵? GpioDataRegs.GPBDAT.all= mData; //向CH376的并口輸出數(shù)據(jù)‘ // CH376_DATA_DIR_OUT(); //設(shè)置并口方向?yàn)檩敵? GpioDataRegs.GPADAT.bit.GPIOA1=0; //A0=0 寫數(shù)據(jù) GpioDataRegs.GPADAT.bit.GPIOA2=0; //cs=0 片選 GpioDataRegs.GPADAT.bit.GPIOA3=0; //WR=0 寫選通 GpioDataRegs.GPADAT.bit.GPIOA3=1; //WR=1 輸出無效的控制信號(hào) 完成操作CH376芯片 GpioDataRegs.GPADAT.bit.GPIOA2=1; //cs=1 CH376_DATA_DIR_IN(); //禁止數(shù)據(jù)輸出 } 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) //設(shè)置將要操作的文件的文件名 { 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(); //設(shè)置并口輸入 } void CH376_DATA_DIR_IN(void) { EALLOW; GpioMuxRegs.GPBDIR.all=0x0000; //輸入 EDIS; } void CH376_DATA_DIR_OUT(void) { EALLOW; GpioMuxRegs.GPBDIR.all=0xffff; //輸出 輸送命令字或者數(shù)據(jù)給CH376S EDIS; }