使用此方式,上位機能進入偽中斷程序,但進行讀取數(shù)據(jù)時出錯,讀不到數(shù)據(jù),這是什么原因? 下位機部分程序: CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); /* 向USB端點2的發(fā)送緩沖區(qū)寫入數(shù)據(jù)塊 */ CH375_WR_DAT_PORT( length ); /* 首先寫入后續(xù)數(shù)據(jù)長度,回傳剛接收到的數(shù)據(jù)長度 */ for ( i = 0; i < length; i ++ ) CH375_WR_DAT_PORT( ~ buffer[ i ] ); /* 數(shù)據(jù)取反后返回,由計算機應用程序測試數(shù)據(jù)是否正確 */ CH375_WR_CMD_PORT( CMD_WR_USB_DATA5 ); CH375_WR_DAT_PORT( 1 ); CH375_WR_DAT_PORT( 1 );
沒人知道??技術人員在不?請幫忙解決一下
是不是在處理時序上要注意什么東西啊?有沒有技術人員在?????? 下位機也能收到中斷數(shù)據(jù)上傳成功的中斷,但讀取沒反應,有沒高手在啊??????
有沒人用過這種方式啊?是不是不能用啊?不能用我就換種方式了,真是郁悶,你們技術人員只會回答些"請看看USB線是不是屏蔽線什么的"....
以偽中斷方式發(fā)起的數(shù)據(jù)上傳,正常的話,單片機將會收到CH372芯片通知的兩次中斷,一次是中斷端點上傳成功,一次是批量端點數(shù)據(jù)上傳成功。按你說的應該只獲取到了中斷端點上傳成功,數(shù)據(jù)應該沒有上傳上去。 可以將你完整的程序貼出來看一下。
下位機程序在TEST.C上改的 /* ; CH375/CH372 Bulk Data Test ; U2(AT89C51) Program ; 本程序測試數(shù)據(jù)傳輸?shù)恼_性,可以用于長時間連續(xù)測試,對應的計算機端的測試程序為TEST.EXE ; 方法: 下傳隨機長度的隨機數(shù)據(jù)包,被單片機接收并將數(shù)據(jù)按位取反后返回,最終由計算機程序接收后比較數(shù)據(jù)是否正確 ; ; Website: http://winchiphead.com ; Email: 個人信息保護,已隱藏 ; Author: W.ch 2003.09 */
/* MCS-51單片機C語言的示例程序,用于其它單片機時一般只要修改前面幾個接口子程序及硬件定義 */
#pragma NOAREGS #include #include #include "stc89le516ad.h" #include "CH375INC.H" /* 頭文件,在網上下載的CH372或者CH375評估板資料中有 */
//unsigned char volatile xdata CH375_CMD_PORT _at_ 0xA0; /* CH375命令端口的I/O地址 */ //unsigned char volatile xdata CH375_DAT_PORT _at_ 0xA0; /* CH375數(shù)據(jù)端口的I/O地址 */ unsigned char data buffer[ 64 ]; unsigned char flag,length; unsigned char counter_50ms; unsigned char is_4s_over;
/* 延時2微秒,不精確 */ void delay2us( ) { unsigned char i; for ( i = 2; i != 0; i -- ); /* 根據(jù)單片機的時鐘選擇初值 */ }
/* 延時1微秒,不精確,因為MCS51單片機較慢所以實際上無需延時 */ //void delay1us( ) //{ // unsigned char i; // for ( i = 1; i != 0; i -- ); //}
/* 基本操作 */
void SendCharToUsart( unsigned char byte ) { ES = 0; TI = 0; SBUF = byte;
while ( TI != 1 ) ;
TI = 0; ES = 1; }
void CH375_WR_CMD_PORT( unsigned char cmd ) reentrant{ /* 向CH375的命令端口寫入命令,周期不小于4uS,如果單片機較快則延時 */ // delay2us(); // CH375_CMD_PORT=cmd; // ******************** 注釋中是用普通I/O引腳模擬8位并口的時序,CH375_CS引腳是可選的,可以一直接GND強制片選 P2 = cmd; CH375_A0 = 1; //選擇CH375的命令口 CH375_RD = 1; //如果I/O默認電平是高電平,那么這是可選操作 // P0 = 1; CH375_WR = 0; _nop_(); //對于高速單片機,該指令用于延時,以便向CH375_WR產生寬度至少為80nS的低電平脈沖 CH375_WR = 1; //P0 = 0; CH375_A0 = 0; P2 = 0xFF; //對于準雙向I/O,請在此設置輸出全高電平 //******************** */ // delay2us(); }
void CH375_WR_DAT_PORT( unsigned char dat ) reentrant { /* 向CH375的數(shù)據(jù)端口寫入數(shù)據(jù),周期不小于1.5uS,如果單片機較快則延時 */ //CH375_DAT_PORT=dat; //* ******************** 注釋中是用普通I/O引腳模擬8位并口的時序 P2 = dat; // CH375_D0_D7_DIR = output; 對于標準雙向I/O,請在此設置為輸出方向 //P0 = 1; CH375_WR = 0; // while(1){} _nop_(); //對于高速單片機,該指令用于延時,以便向CH375_WR產生寬度至少為80nS的低電平脈沖 CH375_WR = 1; //P0 = 0; // while(1){} // CH375_D0_D7_DIR = input; 對于標準雙向I/O,請在此設置為輸入方向 P2 = 0xFF; //對于準雙向I/O,請在此設置輸出全高電平 //******************** */ // delay1us(); /* 因為MCS51單片機較慢所以實際上無需延時 */ }
unsigned char CH375_RD_DAT_PORT( void ) reentrant{ /* 從CH375的數(shù)據(jù)端口讀出數(shù)據(jù),周期不小于1.5uS,如果單片機較快則延時 */ unsigned char dat; // delay1us(); /* 因為MCS51單片機較慢所以實際上無需延時 */ /* ******************** 注釋中是用普通I/O引腳模擬8位并口的時序*/ // CH375_D0_D7_DIR = input; 對于標準雙向I/O,請在此設置為輸入方向 P2 = 0xFF; //對于準雙向I/O,請在此設置輸出全高電平,便于輸入 //P0 = 1; CH375_RD = 0; // delay2us(); // CH375_CS = 0; 對于高速單片機,該指令用于延時,以便向CH375_RD產生寬度至少為80nS的低電平脈沖 _nop_(); dat = P2; CH375_RD = 1; //P0 = 0; P2 = 0xFF; //對于準雙向I/O,請在此設置輸出全高電平 return( dat ); /********************* */ // return( CH375_DAT_PORT ); }
/* 延時50毫秒,不精確 */ void Delay50ms( ) { unsigned char i, j; for ( i=200; i!=0; i-- ) for ( j=250; j!=0; j-- ); }
/* CH375初始化子程序 */ void CH375_Init( ) { unsigned char i; /* 測試CH375是否正常工作,可選操作,通常不需要 */ // CH375_WR_CMD_PORT( CMD_CHECK_EXIST ); /* 測試CH375是否正常工作 */ // CH375_WR_DAT_PORT( 0x55 ); /* 寫入測試數(shù)據(jù) */ // i = ~ 0x55; /* 返回數(shù)據(jù)應該是測試數(shù)據(jù)取反 */ // if ( CH375_RD_DAT_PORT( ) != i ) { /* CH375不正常 */ // SendCharToUsart('E'); // } // SendCharToUsart('F'); // for ( i=80; i!=0; i-- ) { // CH375_WR_CMD_PORT( CMD_RESET_ALL ); /* 多次重復發(fā)命令,執(zhí)行硬件復位 */ // CH375_RD_DAT_PORT( ); // } // CH375_WR_CMD_PORT( 0 ); // Delay50ms( ); /* 延時50ms */ // } /* 設置USB工作模式, 必要操作 */ CH375_WR_CMD_PORT( CMD_SET_USB_MODE ); CH375_WR_DAT_PORT( 2 ); /* 設置為使用內置固件的USB設備方式 */ for ( i=100; i!=0; i-- ) { /* 等待操作成功,通常需要等待10uS-20uS */ if ( CH375_RD_DAT_PORT( ) == CMD_RET_SUCCESS ) break; } // if ( i==0 ) { SendCharToUsart('E'); }; // SendCharToUsart('F'); /* 下述啟用中斷,假定CH375連接在INT0 */ IT0 = 0; //下降沿/* 置外部信號為低電平觸發(fā) */ IE0 = 0; /* 清中斷標志 */ EX0 = 1; /* 允許CH375中斷 */ }
/* CH375中斷服務程序,使用寄存器組1 */ void mCh375Interrupt( ) interrupt 0 using 1 { unsigned char InterruptStatus; unsigned char i; // EA = 0; // SendCharToUsart('D'); CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 獲取中斷狀態(tài)并取消中斷請求 */ InterruptStatus = CH375_RD_DAT_PORT( ); /* 獲取中斷狀態(tài) */ // SendCharToUsart(InterruptStatus); switch ( InterruptStatus ) { /* 分析中斷狀態(tài)處理 */ case USB_INT_EP2_OUT: { /* 批量端點下傳成功 */ // CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 從當前USB中斷的端點緩沖區(qū)讀取數(shù)據(jù)塊,并釋放緩沖區(qū) */ length = CH375_RD_DAT_PORT( ); /* 首先讀取后續(xù)數(shù)據(jù)長度 */ // SendCharToUsart(length); for ( i = 0; i < length; i ++ ) { buffer[ i ] = CH375_RD_DAT_PORT( ); /* 接收數(shù)據(jù)包 */ } // CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); // flag = 1; /* 測試數(shù)據(jù)正確性,將接收到的命令包數(shù)據(jù)取反后返回給PC機 */ // for ( i = 0; i < length; i ++ ) SendCharToUsart(buffer[i]); CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); /* 向USB端點2的發(fā)送緩沖區(qū)寫入數(shù)據(jù)塊 */ CH375_WR_DAT_PORT( length ); /* 首先寫入后續(xù)數(shù)據(jù)長度,回傳剛接收到的數(shù)據(jù)長度 */ for ( i = 0; i < length; i ++ ) CH375_WR_DAT_PORT( ~ buffer[ i ] ); /* 數(shù)據(jù)取反后返回,由計算機應用程序測試數(shù)據(jù)是否正確 */ // delay2us(); CH375_WR_CMD_PORT( CMD_WR_USB_DATA5 ); CH375_WR_DAT_PORT( 1 ); CH375_WR_DAT_PORT( 1 ); // SendCharToUsart(length); break; } case USB_INT_EP2_IN: { /* 批量數(shù)據(jù)發(fā)送成功 */ CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區(qū) */ SendCharToUsart('K'); break; } case 9: { SendCharToUsart( 'B' ); break; } default: { /* 其它中斷,未用到,解鎖后退出即可 */ CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區(qū) */ // CH375_WR_CMD_PORT( CMD_RESET_ALL ); //flag = 1; // (*(void(*)())0)(); SendCharToUsart('C'); break; } } // EA = 1; }
void SetTimer( void ) { counter_50ms++;
if ( counter_50ms > 79 ) { counter_50ms = 0; is_4s_over = 1; /* counter_2s++;
if ( counter_2s > 89 ) { counter_2s = 0; is_3min_over = TRUE; counter_3min++;
if ( counter_3min > 59 ) { counter_3min = 0; is_3hour_over = TRUE; }
} */ } }
void Timer0Interrupt( void ) interrupt 1 using 3 { TF0 = 0; TL0 = 0; TH0 = 0x4c; SetTimer(); }
main( ) { unsigned char i; Delay50ms( ); /* 延時等待CH375初始化完成,如果單片機由CH375提供復位信號則不必延時 */ P0 = 1; // P2 = 0xF0; // CH375_A0 = 1; // CH375_RD = 0; // CH375_WR = 1;
SCON = 0x50; //0101 0000 sm0,sm1,sm2,ren
TMOD &= 0x0F; //use timer1 TMOD |= 0x20; //8bit auto reload initial value of timer TH1 = 253; TL1 = 253; //AUXR &= 0x3F; //12T TR1 = 1; ES = 1; TR0 = 1; TMOD &= 0xF0; TMOD |= 0x01; //16 bit timer TL0 = 0; TH0 = 0x4c; //65536-15536=50000uS, 15536=0x3CB0 ET0 = 1; SendCharToUsart('S'); CH375_Init( ); /* 初始化CH375 *
不使用偽中斷上傳,上位機寫入數(shù)據(jù)后立刻讀取數(shù)據(jù),這樣可以得到正確的值. 上位機程序 If CH375WriteData(mIndex,@mDemoReq,@mLength) Then // 通過CH375發(fā)送命令數(shù)據(jù),成功 begin mLength := mCH375_PACKET_LENGTH; If (CH375ReadData(mIndex,@mDemoReq, @mLength)) Then // 通過CH375接收應答數(shù)據(jù),成功 begin If (mLength = CONST_CMD_LEN) Then begin 這樣是正確的.
你可以這樣處理,在批量數(shù)據(jù)下傳成功之后,將偽中斷數(shù)據(jù)放入中斷端點(端點1),在中斷端點上傳成功的分支中將第一次要上傳的批量數(shù)據(jù)放入批量緩沖區(qū),上位機取走之后,會進批量數(shù)據(jù)上傳成功(USB_INT_EP2_IN)中斷,在這分支中可以接著上傳其他的批量數(shù)據(jù)。 大體如下:
/* CH375中斷服務程序,使用寄存器組1 */ void mCh375Interrupt( ) interrupt 0 using 1 { unsigned char InterruptStatus; unsigned char i; // EA = 0; // SendCharToUsart('D'); CH375_WR_CMD_PORT( CMD_GET_STATUS ); /* 獲取中斷狀態(tài)并取消中斷請求 */ InterruptStatus = CH375_RD_DAT_PORT( ); /* 獲取中斷狀態(tài) */ // SendCharToUsart(InterruptStatus); switch ( InterruptStatus ) { /* 分析中斷狀態(tài)處理 */ case USB_INT_EP2_OUT: { /* 批量端點下傳成功 */ // CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); CH375_WR_CMD_PORT( CMD_RD_USB_DATA ); /* 從當前USB中斷的端點緩沖區(qū)讀取數(shù)據(jù)塊,并釋放緩沖區(qū) */ length = CH375_RD_DAT_PORT( ); /* 首先讀取后續(xù)數(shù)據(jù)長度 */ // SendCharToUsart(length); for ( i = 0; i < length; i ++ ) { buffer[ i ] = CH375_RD_DAT_PORT( ); /* 接收數(shù)據(jù)包 */ } // CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); // flag = 1; CH375_WR_CMD_PORT( CMD_WR_USB_DATA5 ); CH375_WR_DAT_PORT( 1 ); CH375_WR_DAT_PORT( 1 ); // SendCharToUsart(length); break; } case USB_INT_EP2_IN: { /* 批量數(shù)據(jù)發(fā)送成功 */ CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區(qū) */ CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); //第一次之后需要上傳的批量數(shù)據(jù) CH375_WR_DAT_PORT( length ); for ( i = 0; i < length; i ++ ) CH375_WR_DAT_PORT( buffer[ i ] ); break; } case USB_INT_EP1_IN: { /* 中斷端點發(fā)送成功 */ CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區(qū) */ CH375_WR_CMD_PORT( CMD_WR_USB_DATA7 ); //第一次需要上傳的批量數(shù)據(jù)(以后上傳可以在USB_INT_EP2_IN中) CH375_WR_DAT_PORT( length ); for ( i = 0; i < length; i ++ ) CH375_WR_DAT_PORT( buffer[ i ] ); break; }
case 9: { SendCharToUsart( 'B' ); break; } default: { /* 其它中斷,未用到,解鎖后退出即可 */ CH375_WR_CMD_PORT( CMD_UNLOCK_USB ); /* 釋放當前USB緩沖區(qū) */ // CH375_WR_CMD_PORT( CMD_RESET_ALL ); //flag = 1; // (*(void(*)())0)(); SendCharToUsart('C'); break; } } // EA = 1; }
好,我去試試. 主要是看了372的資料上說,要先把批量數(shù)據(jù)寫入端口2,再寫入中斷數(shù)據(jù),所以那么寫.我先試試,謝謝你的解答
謝謝,用這種方式可以讀取到正確數(shù)據(jù). 能分析一下嗎? 先寫入數(shù)據(jù)再寫入中斷為什么不行呢?
實際在解決問題的時候,你只是拿了片面的程序,當然找不到問題所在,我們只能根據(jù)你描述的現(xiàn)象來分析你最大可能出現(xiàn)問題的地方在什么地方,當然有很多時候問題不是出現(xiàn)在我們所說的地方。還有就是你上面的問題很好解釋,由于USB協(xié)議是一種串行的數(shù)據(jù)傳輸,在實際傳輸?shù)臅r候,就不能實現(xiàn)2個端點的同時上傳或者下傳,同時我們的CH372芯片內部也不支持這種情況,只有在你某一次傳輸完成之后,才能進行下一次的數(shù)據(jù)傳輸,你可以先仔細的看下說明書或者我們的例子程序。
論壇回復只是我們幫客戶解決問題的一種形式之一,我們不可能實時都在查看,只能是不定時隔段時間查看一次。也就說不可能你一提出問題就能得到回復,最快捷的方式還是電話。
上傳數(shù)據(jù)流以偽中斷方式發(fā)起的系統(tǒng)中,計算機應用層初始化時設置一個偽中斷服務程序,然后 應用層就不需要再涉及到上傳數(shù)據(jù)流。當單片機需要上傳數(shù)據(jù)時,首先將數(shù)據(jù)寫入批量端點的上傳緩 沖區(qū)中,然后將中斷特征數(shù)據(jù)寫入中斷端點的上傳緩沖區(qū)中。在1 毫秒之內(理論值),與中斷特征 數(shù)據(jù)對應的偽中斷服務程序被激活,偽中斷服務程序通知主程序調用數(shù)據(jù)上傳API獲得上傳數(shù)據(jù)塊。 在此期間,單片機將會收到CH372 芯片通知的兩次中斷,首先是中斷端點上傳成功中斷,然后是批量 端點上傳成功中斷。
這是我在CH372的PDF資料上看到的,按照上面的說法我剛開始的寫法就是這樣的
引用回復:論壇回復只是我們幫客戶解決問題的一種形式之一,我們不可能實時都在查看,只能是不定時隔段時間查看一次。也就說不可能你一提出問題就能得到回復,最快捷的方式還是電話。 我一開始的確有點沖了,公司催的急..對不起哈.. 畢竟調試程序老調不通是很惱火的事..
我建議你們的芯片資料上把這些都寫進去,比如采用偽中斷上傳單片機的處理機制,最好是先上傳中斷數(shù)據(jù),然后等到中斷數(shù)據(jù)被取走再寫入批量數(shù)據(jù). 這些在芯片資料上都沒寫好的.