有誰用xmega單片機(jī)做過U盤讀寫模塊啊。。。。我怎么弄都不行,命令發(fā)出去,沒一點(diǎn)動靜
,是不是和單片機(jī)用3.3V電壓有關(guān)系? 我用的是串口三線模式
有誰用xmega單片機(jī)做過U盤讀寫模塊啊。。。。我怎么弄都不行,命令發(fā)出去,沒一點(diǎn)動靜
,是不是和單片機(jī)用3.3V電壓有關(guān)系? 我用的是串口三線模式
原理圖沒有什么問題。需要注意CH375默認(rèn)的波特率是9600,同時使用串口通信的時候,發(fā)送命令的時候位9為1,發(fā)送數(shù)據(jù)的時候位9為0.還有確認(rèn)下CH375芯片晶振是否起振?
看例程里,串口的數(shù)據(jù)是8位模式的啊, 我把論壇里M64轉(zhuǎn)換后的程序也貼出來..我用的單片機(jī)是ATxmega256A3BU
/* U盤文件讀寫模塊, 連接方式: 3線制串口+查詢 */
/* 電路連接方式,只需要連接3根線,使用串口同步碼啟動操作 單片機(jī) 模塊 TXD = SIN RXD = SOUT GND = GND */ #include #include #define MAX_PATH_LEN 32 /* 最大路徑長度,含所有斜杠分隔符和小數(shù)點(diǎn)間隔符以及路徑結(jié)束符00H,CH375模塊支持的最大值是62,最小值是13 */ #include "CH375HM.H"
CMD_PARAM mCmdParam; /* 默認(rèn)情況下該結(jié)構(gòu)將占用60字節(jié)的RAM,可以修改MAX_PATH_LEN常量,當(dāng)修改為32時,只占用32字節(jié)的RAM */ unsigned char TempLength; /* 臨時緩沖區(qū)中的數(shù)據(jù)長度,從原文件中第二次讀出的字節(jié)數(shù) */ unsigned char TempBuffer[20]; /* 臨時緩沖區(qū),存放從原文件中讀出的內(nèi)容 */
//====================================================================================
/*延時1mS*/ void mDelaymS( uint8_t delay ) { uint8_t i, c; uint16_t j; for ( i = delay; i != 0; i -- ) { for(j=2740; j!=0;j--) { c+=3; asm("nop"); asm("nop"); } } } //============================================================================================ void CCPWrite( volatile uint8_t * address, uint8_t value ) { volatile uint8_t * tmpAddr = address; #ifdef RAMPZ RAMPZ = 0; #endif asm volatile( "movw r30, %0" "\n\t" "ldi r16, %2" "\n\t" "out %3, r16" "\n\t" "st Z, %1" : : "r" (tmpAddr), "r" (value), "M" (CCP_IOREG_gc), "m" (CCP) : "r16", "r30", "r31" ); } //=========================================================== void sysclk_init(void) //設(shè)置系統(tǒng)時鐘,內(nèi)部RC32MHz { uint8_t PSconfig; uint8_t clkCtrl; PSconfig = (uint8_t) CLK_PSADIV_1_gc | CLK_PSBCDIV_1_2_gc; //OSC.XOSCCTRL=0xc7; OSC.CTRL |= OSC_RC32MEN_bm; CCPWrite( &CLK.PSCTRL, PSconfig ); while ( ( OSC.STATUS & OSC_RC32MRDY_bm ) == 0 ); clkCtrl = ( CLK.CTRL & ~CLK_SCLKSEL_gm ) | CLK_SCLKSEL_RC32M_gc; CCPWrite( &CLK.CTRL, clkCtrl ); }
//============================================================================================ /*串口初始化*/ void USART1_Init() { PORTC_DIR|=0X08; PORTR_DIR=0x03; PORTR_OUT=0x03; USARTC0.BAUDCTRLA=105; //9600 波特率 USARTC0.BAUDCTRLB=0X00; USARTC0.CTRLA=0; USARTC0.CTRLB=USART_RXEN_bm|USART_TXEN_bm; //發(fā)送接收使能 USARTC0.CTRLC=USART_CMODE_ASYNCHRONOUS_gc|USART_CHSIZE_8BIT_gc; //異步 8位 1位停止位 } //============================================================================================= void mSendByte( uint8_t data )/* 發(fā)送一個字節(jié)數(shù)據(jù)給CH375模塊 */ { while (!(USARTC0_STATUS&0x20)) {asm("nop");}// 等待發(fā)送緩沖器為空 USARTC0_DATA = data; // 將數(shù)據(jù)放入緩沖器,發(fā)送數(shù)據(jù) } //----------------------------------------------------------------- uint8_t mRecvByte( void )/* 從CH375模塊接收一個字節(jié)數(shù)據(jù) */ { while (!(USARTC0_STATUS&0x80)) {asm("nop");} // 等待接收數(shù)據(jù) return USARTC0_DATA;// 從緩沖器中獲取并返回數(shù)據(jù) } //=============================================================================================== /* 執(zhí)行命令 */ /* 輸入命令碼和輸入?yún)?shù)長度,返回操作狀態(tài)碼,輸入?yún)?shù)和返回參數(shù)都在CMD_PARAM結(jié)構(gòu)中 */ uint8_t ExecCommand( uint8_t cmd, uint8_t len ) { uint8_t i, j, status; mSendByte( SER_SYNC_CODE1 ); /* 發(fā)送串口同步碼通知模塊,說明命令碼開始發(fā)送,請求開始執(zhí)行命令 */ mSendByte( SER_SYNC_CODE2 ); /* 用兩個串口同步碼代替STA#的下降沿 */ /* 上面兩個串口同步碼應(yīng)該連續(xù)發(fā)送,如果不連續(xù),那么間隔時間不能超過20mS,否則命令無效 */ mSendByte( cmd ); /* 寫入命令碼 */ mSendByte( len ); /* 寫入后續(xù)參數(shù)的長度 */ if ( len ) { /* 有參數(shù) */ for ( i = 0; i != len; i ++ ) mSendByte( mCmdParam.Other.mBuffer[ i ] ); /* 依次寫入?yún)?shù) */ } while ( 1 ) { /* 處理數(shù)據(jù)傳輸,直到操作完成才退出 */ status = mRecvByte(); /* 等待模塊完成操作并返回操作狀態(tài) */ if ( status == ERR_SUCCESS ) { /* 操作成功 */ i = mRecvByte( ); /* 返回結(jié)果數(shù)據(jù)的長度 */ if ( i ) { /* 有結(jié)果數(shù)據(jù) */ j = 0; do { /* 使用do+while結(jié)構(gòu)是因?yàn)槠湫矢哂趂or */ mCmdParam.Other.mBuffer[ j ] = mRecvByte( ); /* 接收結(jié)果數(shù)據(jù)并保存到參數(shù)結(jié)構(gòu)中 */ j ++; } while ( -- i ); } break; /* 操作成功返回 */ } else if ( status == USB_INT_DISK_READ || status == USB_INT_DISK_WRITE || status == USB_INT_DISK_RETRY ) { /* 正在從U盤讀數(shù)據(jù)塊,請求數(shù)據(jù)讀出,正在向U盤寫數(shù)據(jù)塊,請求數(shù)據(jù)寫入,讀寫數(shù)據(jù)塊失敗重試 */ break; /* 本程序只使用以字節(jié)為單位的文件讀寫子程序,所以正常情況下不會收到該狀態(tài)碼,操作失敗返回 */ } else { /* 操作失敗 */ if ( status == ERR_DISK_DISCON || status == ERR_USB_CONNECT ) mDelaymS( 100 ); /* U盤剛剛連接或者斷開,應(yīng)該延時幾十毫秒再操作 */ break; /* 操作失敗返回 */ } } return( status ); } //=============================================================================================================================================== /* 檢查操作狀態(tài),如果錯誤則顯示錯誤代碼并停機(jī) */ void mStopIfError( uint8_t iError ) { uint8_t led; if ( iError == ERR_SUCCESS ) return; /* 操作成功 */ while ( 1 ) { /* LED閃爍 */ PORTR_OUT^=0X01; mDelaymS( 100 ); } } //================================================================================= void main( void ) { uint8_t i; uint16_t count; uint8_t *pStr; sysclk_init(); /* 設(shè)置與CH375模塊通訊的串口,9600Bps */ mDelaymS( 200 ); /* 延時600毫秒,CH375模塊上電后需要600毫秒左右的復(fù)位時間 */ mDelaymS( 200 ); mDelaymS( 200 ); USART1_Init(); while ( 1 ) { /* 使用查詢方式看U盤是否連接 */ while ( 1 ) { //PORTR_OUT^=0X02; i = ExecCommand( CMD_QueryStatus, 0 ); /* 查詢當(dāng)前模塊的狀態(tài) */ //mStopIfError( i ); if ( mCmdParam.Status.mDiskStatus >= DISK_CONNECT ) { PORTR_OUT=0Xfe; break; } /* U盤已經(jīng)連接 */ mDelaymS( 100 ); } mDelaymS( 100 ); /* 延時,可選操作,有的USB存儲器需要幾十毫秒的延時 */ // 檢查U盤是否準(zhǔn)備好,大多數(shù)U盤不需要這一步,但是某些U盤必須要執(zhí)行這一步才能工作,建議該步驟必須加上 for ( i = 0; i < 5; i ++ ) { mDelaymS( 100 ); if ( ExecCommand( CMD_DiskReady, 0 ) == ERR_SUCCESS ) break; // 查詢磁盤是否準(zhǔn)備好 } strcpy( mCmdParam.Create.mPathName, "\\南京沁恒.TXT" ); // 新文件名,在根目錄下 i = ExecCommand( CMD_FileCreate, MAX_PATH_LEN ); //新建文件并打開,如果文件已經(jīng)存在則先刪除后再新建 mStopIfError( i ); pStr = "Note: \xd\xaU盤讀寫模塊串口版本_AVR單片機(jī) MEGA 64 C語言示例程序\xd\xa"; count = strlen( pStr ); // 準(zhǔn)備寫入的數(shù)據(jù)的總長度 while ( count ) //如果較大,分多次寫入 { if ( count < sizeof( mCmdParam.ByteWrite.mByteBuffer ) ) i = count; //只剩最后一些數(shù)據(jù)要寫入 else i = sizeof( mCmdParam.ByteWrite.mByteBuffer ); // 數(shù)據(jù)較多,分多次寫入 count -= i; // 計數(shù) memcpy( mCmdParam.ByteWrite.mByteBuffer, pStr, i ); //復(fù)制準(zhǔn)備寫入的數(shù)據(jù)到參數(shù)結(jié)構(gòu)中,源數(shù)據(jù)可以來自ADC等,本例是來自程序空間的說明信息 pStr += i; mCmdParam.ByteWrite.mByteCount = i; //指定本次寫入的字節(jié)數(shù) i = ExecCommand( CMD_ByteWrite, 1+i ); // 以字節(jié)為單位向文件寫入數(shù)據(jù) mStopIfError( i ); } mCmdParam.Close.mUpdateLen = 1; // 自動計算文件長度,當(dāng)以字節(jié)為單位向文件寫入數(shù)據(jù)后,如果沒有用0長度的CMD_ByteWrite更新文件長度, // 那么可以在關(guān)閉文件時讓模塊自動更新文件長度 i = ExecCommand( CMD_FileClose, 1 ); //關(guān)閉文件,當(dāng)以字節(jié)為單位向文件寫入(追加)數(shù)據(jù)后,必須在用完文件后關(guān)閉文件 mStopIfError( i );
//等待U盤斷開
while ( 1 ) { /* 使用查詢方式看U盤是否斷開 */ i = ExecCommand( CMD_QueryStatus, 0 ); /* 查詢當(dāng)前模塊的狀態(tài) */ mStopIfError( i ); if ( mCmdParam.Status.mDiskStatus <= DISK_DISCONNECT ) { PORTR_OUT=0Xfd; break; }/* U盤已經(jīng)斷開 */ mDelaymS( 100 ); /* 沒有必要一直連續(xù)不停地查詢,可以讓單片機(jī)做其它事,沒事可做就延時等待一會再查詢 */ } } }
你看下AVR單片機(jī)的說明上面是有設(shè)置9位數(shù)據(jù)方式的。 仔細(xì)看下說明書。
我知道有9位,我說論壇里給的例程只設(shè)置了8位
http://wch.cn/bbs/View.asp?S=107&I=29782 這里下載的例程
波特率我用示波器看過了 9615 這應(yīng)該在誤差允許的范圍內(nèi)的
你看的這個程序是操作U盤文件讀寫模塊的。不是操作CH375芯片的。
U盤操作模塊是你們上面加了一個單片機(jī)的那種模塊是吧? 操作CH375就是我上面的發(fā)那個圖? 那操作CH375的有沒例程,最好AVR的, 現(xiàn)在有點(diǎn)焦頭爛額了, 用U盤保存一個濃度測試儀的數(shù)據(jù),老板急著要東西了...幫忙多費(fèi)心看一下吧,萬分感謝!
是的,模式就是有一個單片機(jī)的那種,硬件你肯定要自己調(diào)試。暫時沒有AVR操作CH375的例子程序。需要你自己先把硬件調(diào)試通過之后才可以。
51操作 ch375的也行,我自己來做移植
弄老半天,搞錯對像了,,,,,,啊啊啊
你可以去下載CH375LIB.ZIP,在MCS51文件夾下面的LIB5。這個例子是可以修改成串口的。