我用mega128+375主機(jī)方式操作USB鍵盤(pán), void main() { unsigned char i; CH375_PORT_INIT( ); delayms(250); set_usb_mode( 6 ); /* 設(shè)置USB主機(jī)模式, 如果設(shè)備端是CH37X, 那么5和6均可 */// while(1) { while ( wait_interrupt()!=USB_INT_CONNECT ); 程序一直停在wait_interrupt()函數(shù)中的查詢(xún)狀態(tài)while( CH375_INT_WIRE ); 我接上了鍵盤(pán),按理說(shuō)應(yīng)該產(chǎn)生中斷,返回操作狀態(tài),但程序一直處于while( CH375_INT_WIRE ); 我想不是硬件問(wèn)題,因?yàn)椋矣貌僮鱑盤(pán)的例子卻可以進(jìn)中斷
首先你要做測(cè)試命令看下你的硬件上面有沒(méi)有問(wèn)題,如果測(cè)試命令沒(méi)有問(wèn)題的話,那么你設(shè)置模式6之后,不論你插上什么USB設(shè)備,CH375的中斷引腳(第一腳)都會(huì)拉低.如果測(cè)試命令沒(méi)有 通過(guò)的話,那么設(shè)置模式之后是檢測(cè)不到中斷的
測(cè)試沒(méi)有問(wèn)題, unsigned char wait_interrupt() { /* 主機(jī)端等待操作完成, 返回操作狀態(tài) */ while( CH375_INT_WIRE ); /* 查詢(xún)等待CH375操作完成中斷(INT#低電平) */ xWriteCH375Cmd( CMD_GET_STATUS ); /* 產(chǎn)生操作完成中斷, 獲取中斷狀態(tài) */ return( xReadCH375Data() ); } void main() { unsigned char i; CH375_PORT_INIT( ); delayms(250); set_usb_mode( 6 ); /* 設(shè)置USB主機(jī)模式, 如果設(shè)備端是CH37X, 那么5和6均可 */// while(1) { while ( wait_interrupt()!=USB_INT_CONNECT ); 真的想不出是什么原因
我用你們提供的讀寫(xiě)庫(kù)的函數(shù)CH375DiskConnect( )中應(yīng)該有查詢(xún)中斷的操作吧(我的猜測(cè)),就能正常建立文件,測(cè)試也通過(guò)了,應(yīng)該是軟件的原因,軟件又是從你們51的例子移植到AVR上的,只是截取了一小部分,如樓上,幫忙看看
如果你的鍵盤(pán)是低速設(shè)備,需要把ch375切換到低速設(shè)備模式,另外用示波器看一下,在設(shè)備插上的時(shí)候有沒(méi)有中斷產(chǎn)生. void set_freq(void) { xWriteCH375Cmd(0x0b); /* 切換使375B進(jìn)入低速模式 */ xWriteCH375Dat(0x17); xWriteCH375Dat(0xd8); }
那你接上鍵盤(pán)之后,你用萬(wàn)用表去測(cè)下UD+和UD-的電壓是多少?以及你中斷引腳會(huì)不會(huì)拉低
不好意思,我沒(méi)有萬(wàn)用表,也沒(méi)有示波器,只能靠PD口輸出不同值來(lái)確定程序卡在了什么位置 我把程序貼出來(lái)吧 #include #include #include #include "sunchao.h" //unsigned char volatile xdata CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */ //unsigned char volatile xdata CH375_DAT_PORT _at_ 0xBCF0; /* CH375數(shù)據(jù)端口的I/O地址 */ //sbit CH375_INT_WIRE = 0xB0^2; /* P3.2, INT0, 連接CH375的INT#引腳,用于查詢(xún)中斷狀態(tài) */ //sbit P1_0=P1^0; //sbit P1_2=P1^2; #define TRUE 1 #define FALSE 0 #define CH375_INT_WIRE ( PINB & 0x10 ) /* PINB.4, CH375的中斷線INT#引腳,連接CH375的INT#引腳,用于查詢(xún)中斷狀態(tài) */ unsigned char endp_int; //中斷端點(diǎn)號(hào) unsigned char num_interfaces; //接口數(shù) unsigned char config_value; //配置值 unsigned char report_descr_len=0;//REPORT描述符長(zhǎng)度 unsigned char flag_config_2=0; //第二次獲取描述符標(biāo)志位 //bit flag_interface_2=0; //多個(gè)接口標(biāo)志位 unsigned char endp6_mode=0x80, endp7_mode=0x80;//同步標(biāo)志位初值 unsigned char status=0xff; //全局狀態(tài) unsigned char data_buf[96];//描述符緩沖區(qū)可以適當(dāng)減小 //******************************************************************************* union _REQUEST //請(qǐng)求包結(jié)構(gòu) { struct { unsigned char bmRequestType; unsigned char bRequest; unsigned int wValue; unsigned int wIndex; unsigned int wLength; }Req; unsigned char Req_buf[8]; }Request; unsigned char report_cou=0; //REPORT描述符長(zhǎng)度計(jì)數(shù) //bit flag_output=0; //串口輸出標(biāo)志位 unsigned char data_in[1000];//串口輸出緩沖區(qū) //****************************************************************************** /* 延時(shí)指定毫秒時(shí)間,根據(jù)單片機(jī)主頻調(diào)整,不精確 */ void delayms( UINT8 ms ) { UINT16 i; while ( ms -- ) for ( i = 2600; i != 0; i -- ); } void delay2us(void){ unsigned char i; for(i=20;i!=0;i--); } void mDelay1uS(void) { unsigned char i; for(i=10;i!=0;i--); } //****************************************************************************** void CH375_PORT_INIT( ) /* 由于使用通用I/O模塊并口讀寫(xiě)時(shí)序,所以進(jìn)行初始化 */ { DDRA = 0x00; /* 設(shè)置8位并口為輸入 */ PORTB = 0x07; /* 設(shè)置CS,WR,RD默認(rèn)為高電平 */ DDRB = 0x0F; /* 設(shè)置CS,WR,RD,A0為輸出,設(shè)置INT#為輸入 */ DDRD=0XFF; } //********************************************************************************* void xWriteCH375Cmd( UINT8 mCmd ) /* 外部定義的被CH375程序庫(kù)調(diào)用的子程序,向CH375寫(xiě)命令 */ { mDelay1uS( ); mDelay1uS( ); /* 至少延時(shí)1uS */ /* *(volatile unsigned char *)CH375_CMD_PORT_ADDR = mCmd; 通過(guò)并口直接讀寫(xiě)CH375而非普通I/O模擬 */ PORTB |= 0x08; /* 輸出A0=1 */ PORTA = mCmd; /* 向CH375的并口輸出數(shù)據(jù) */ DDRA = 0xFF; /* 并口D0-D7輸出 */ PORTB &= 0xF9; /* 輸出有效寫(xiě)控制信號(hào), 寫(xiě)CH375芯片的命令端口, A0=1; CS=0; WR=0; RD=1; */ DDRA = 0xFF; /* 該操作無(wú)意義,僅作延時(shí),CH375要求讀寫(xiě)脈沖寬度大于100nS */ PORTB |= 0x07; /* 輸出無(wú)效的控制信號(hào), 完成操作CH375芯片, A0=1; CS=1; WR=1; RD=1; */ DDRA = 0x00; /* 禁止數(shù)據(jù)輸出 */ PORTB &= 0xF7; /* 輸出A0=0; 可選操作 */ mDelay1uS( ); mDelay1uS( ); /* 至少延時(shí)2uS */ }
void xWriteCH375Data( UINT8 mData ) /* 外部定義的被CH375程序庫(kù)調(diào)用的子程序,向CH375寫(xiě)數(shù)據(jù) */ { /* *(volatile unsigned char *)CH375_DAT_PORT_ADDR = mData; 通過(guò)并口直接讀寫(xiě)CH375而非普通I/O模擬 */ PORTA = mData; /* 向CH375的并口輸出數(shù)據(jù) */ DDRA = 0xFF; /* 并口D0-D7輸出 */ PORTB &= 0xF1; /* 輸出有效寫(xiě)控制信號(hào), 寫(xiě)CH375芯片的數(shù)據(jù)端口, A0=0; CS=0; WR=0; RD=1; */ DDRA = 0xFF; /* 該操作無(wú)意義,僅作延時(shí),CH375要求讀寫(xiě)脈沖寬度大于100nS */ PORTB |= 0x07; /* 輸出無(wú)效的控制信號(hào), 完成操作CH375芯片, A0=0; CS=1; WR=1; RD=1; */ DDRA = 0x00; /* 禁止數(shù)據(jù)輸出 */ mDelay1uS( ); /* 至少延時(shí)1.2uS */ }
UINT8 xReadCH375Data( void ) /* 外部定義的被CH375程序庫(kù)調(diào)用的子程序,從CH375讀數(shù)據(jù) */ { UINT8 mData; /* mData = *(volatile unsigned char *)CH375_DAT_PORT_ADDR; 通過(guò)并口直接讀寫(xiě)CH375而非普通I/O模擬 */ mDelay1uS( ); /* 至少延時(shí)1.2uS */ DDRA = 0x00; /* 數(shù)據(jù)輸入 */ PORTB &= 0xF2; /* 輸出有效讀控制信號(hào), 讀CH375芯片的數(shù)據(jù)端口, A0=0; CS=0; WR=1; RD=0; */ DDRA = 0x00; /* 該操作無(wú)意義,僅作延時(shí),CH375要求讀寫(xiě)脈沖寬度大于100nS */ mData = PINA; /* 從CH375的并口PA輸入數(shù)據(jù) */ PORTB |= 0x07; /* 輸出無(wú)效的控制信號(hào), 完成操作CH375芯片, A0=0; CS=1; WR=1; RD=1; */ return( mData ); } //**************************************************************************************************** unsigned char set_usb_mode( unsigned char mode ) { /* 設(shè)置CH37X的工作模式 */ unsigned char i; xWriteCH375Cmd( CMD_SET_USB_MODE ); xWriteCH375Data( mode ); endp6_mode=endp7_mode=0x80; /* 主機(jī)端復(fù)位USB數(shù)據(jù)同步標(biāo)志 */ for( i=0; i!=100; i++ ) { /* 等待設(shè)置模式操作完成,不超過(guò)30uS */ if ( xReadCH375Data()==CMD_RET_SUCCESS ) return( TRUE ); /* 成功 */ } return( FALSE ); /* CH375出錯(cuò),例如芯片型號(hào)錯(cuò)或者處于串口方式或者不支持 */ }
void set_freq(void) { xWriteCH375Cmd(0x0b); /* 切換使375B進(jìn)入低速模式 */ xWriteCH375Data(0x17); xWriteCH375Data(0xd8); } //**************************************************************************************************** /* 數(shù)據(jù)同步 */ /* USB的數(shù)據(jù)同步通過(guò)切換DATA0和DATA1實(shí)現(xiàn): 在設(shè)備端, CH372/CH375可以自動(dòng)切換; 在主機(jī)端, 必須由SET_ENDP6和SET_ENDP7命令控制CH375切換DATA0與DATA1. 主機(jī)端的程序處理方法是為SET_ENDP6和SET_ENDP7分別提供一個(gè)全局變量, 初始值均為80H, 每執(zhí)行一次成功事務(wù)后將位6取反, 每執(zhí)行一次失敗事務(wù)后將其復(fù)位為80H. */
void toggle_recv() { /* 主機(jī)接收成功后,切換DATA0和DATA1實(shí)現(xiàn)數(shù)據(jù)同步 */ xWriteCH375Cmd( CMD_SET_ENDP6 ); xWriteCH375Data( endp6_mode ); endp6_mode^=0x40; delay2us(); }
void toggle_send() { /* 主機(jī)發(fā)送成功后,切換DATA0和DATA1實(shí)現(xiàn)數(shù)據(jù)同步 */ xWriteCH375Cmd( CMD_SET_ENDP7 ); xWriteCH375Data( endp7_mode ); endp7_mode^=0x40; delay2us(); }
//void clr_stall6() { /* 主機(jī)接收失敗后,復(fù)位設(shè)備端的數(shù)據(jù)同步到DATA0 */ // CH375_WR_CMD_PORT( CMD_CLR_STALL ); // CH375_WR_DAT_PORT( 2 | 0x80 ); /* 如果設(shè)備端不是CH37X芯片,那么需要修改端點(diǎn)號(hào) */ // endp6_mode=0x80; // status=0xff; //}
//void clr_stall7() { /* 主機(jī)發(fā)送失敗后,復(fù)位設(shè)備端的數(shù)據(jù)同步到DATA0 */ // CH375_WR_CMD_PORT( CMD_CLR_STALL ); // CH375_WR_DAT_PORT( 2 ); /* 如果設(shè)備端不是CH37X芯片,那么需要修改端點(diǎn)號(hào) */ // endp7_mode=0x80; // status=0xff; //} //**************************************************************************************** unsigned char rd_usb_data( unsigned char *buf ) { /* 從CH37X讀出數(shù)據(jù)塊 */ unsigned char i, len; xWriteCH375Cmd( CMD_RD_USB_DATA ); /* 從CH375的端點(diǎn)緩沖區(qū)讀取接收到的數(shù)據(jù) */ //我們芯片內(nèi)部就是第一次讀取到的是數(shù)據(jù)長(zhǎng)度. len=xReadCH375Data(); /* 后續(xù)數(shù)據(jù)長(zhǎng)度 */ for ( i=0; i!=len; i++ ) *buf++=xReadCH375Data(); return( len ); }
void wr_usb_data( unsigned char len, unsigned char *buf ) { /* 向CH37X寫(xiě)入數(shù)據(jù)塊 */ xWriteCH375Cmd( CMD_WR_USB_DATA7 ); /* 向CH375的端點(diǎn)緩沖區(qū)寫(xiě)入準(zhǔn)備發(fā)送的數(shù)據(jù) */ xWriteCH375Data( len ); /* 后續(xù)數(shù)據(jù)長(zhǎng)度, len不能大于64 */ while( len-- ) xWriteCH375Data( *buf++ ); } //**************************************************************************************** void issue_token( unsigned char endp_and_pid ) { /* 執(zhí)行USB事務(wù) */ xWriteCH375Cmd( CMD_ISSUE_TOKEN ); xWriteCH375Data( endp_and_pid ); /* 高4位目的端點(diǎn)號(hào), 低4位令牌PID */ status=0xff; } //************************************************************************************ void interrupt() { unsigned char len_temp,i; xWriteCH375Cmd( CMD_GET_STATUS ); /* 產(chǎn)生操作完成中斷, 獲取中斷狀態(tài) */ status=xReadCH375Data(); if(status!=USB_INT_SUCCESS)//&&((status&0xf0)==0x20)) { xWriteCH375Cmd( CMD_CLR_STALL ); xWriteCH375Data(1); /* 如果設(shè)備端不是CH37X芯片,那么需要修改端點(diǎn)號(hào) */ endp6_mode=0x80; endp7_mode=0x80; toggle_recv(); issue_token(( endp_int << 4 ) | DEF_USB_PID_IN);//發(fā)送從中斷端點(diǎn)讀數(shù)據(jù)的令牌 } else { len_temp=rd_usb_data(data_buf); //鍵盤(pán)中斷端點(diǎn)數(shù)據(jù)長(zhǎng)度一般為8字節(jié),鼠標(biāo)為4字節(jié) for(i=0;i!=len_temp;i++)data_in[i]=data_buf[i]; //flag_output=1; toggle_recv(); issue_token(( endp_int << 4 ) | DEF_USB_PID_IN);//發(fā)送從中斷端
在wait_interrupt()中查詢(xún)中斷while( CH375_INT_WIRE )PORTD=0X02;如果INT一直為高,PD輸出2, 如果INT變低,返回的狀態(tài)不是USB_INT_CONNECT,PD輸出3 程序運(yùn)行結(jié)過(guò)是2
你插如USB鍵盤(pán)之后一定要測(cè)試一下UD-,UD+電壓是多少.還有你用的是CH375A,還是CH375B?這兩個(gè)用法有區(qū)別
我用的是375B,外接12M晶振,為什么一定要測(cè)UD-,UD+電壓,目的是什么
目的有二:一是確認(rèn)設(shè)備是否存在,二是設(shè)備的速度類(lèi)型 D+為高則表示全速設(shè)備;D-為高則表示低速設(shè)備,此時(shí)需要切換主機(jī)的速度為低速狀態(tài)
那我接上鍵盤(pán),ACT#輸出低電平,是不是說(shuō)明設(shè)備已經(jīng)連接上了呢,INT不拉低,難道是我用I/0模擬375時(shí)序的問(wèn)題
INT不拉低的原因很多,你把引腳翹起來(lái),插入設(shè)備后看是不是變低了,如果變低了,那就說(shuō)明可能是MCU的IO設(shè)置有問(wèn)題,或者硬件上強(qiáng)制的將其拉高了.