?? ch375451.c
字號:
}
}
else if ( length == 0 ) return; /* 長度為0,沒有數據則直接退出,在某些應用中也可以將長度0定義為一種特殊命令 */
else { /* 不是命令包 */
/* 接收下傳的數據塊,每組數據的長度不超過64字節,例如總長度150個字節,則第1組和第2組各是64字節,第3組是剩余長度22字節
; 為了將數據塊與命令包區分開來,剩余長度不能等于CONST_CMD_LEN,可以用填充數據的辦法避免相同 */
if ( CMD_PKT.mCommandCode == DEF_CMD_DOWN_DATA ) { /* 向下位機的指定地址的緩沖區中寫入數據塊(下傳數據塊) */
/* 接收下傳的數據塊,每組數據的長度不超過64字節,由于演示板中沒有外部RAM,并且外部RAM的效率很低,所以用內部RAM示范 */
CurrentRamLen -= length;
while ( length-- ) {
*CurrentRamAddr = CH375_DAT_PORT;
CurrentRamAddr ++;
}
}
else { /* 未定義的命令 */
while ( length -- ) c1 = CH375_DAT_PORT; /* 丟棄數據 */
}
}
}
else if ( InterruptStatus == USB_INT_EP2_IN ) { /* 批量數據發送成功 */
if ( CMD_PKT.mCommandCode == DEF_CMD_UP_DATA ) { /* 從下位機的指定地址的緩沖區中讀取數據塊(上傳數據塊) */
len2 = CurrentRamLen >= CH375_MAX_DATA_LEN ? CH375_MAX_DATA_LEN : CurrentRamLen; /* 數據上傳,準備數據 */
LoadUpData( CurrentRamAddr, len2 ); /* 加載上傳數據 */
CurrentRamLen -= len2;
CurrentRamAddr += len2;
}
/* 收到上傳成功中斷后,在退出之前必須解鎖USB緩沖區,以便繼續收發數據 */
CH375_CMD_PORT = CMD_UNLOCK_USB; /* 釋放當前USB緩沖區 */
}
else if ( InterruptStatus == USB_INT_EP1_IN ) { /* 中斷數據發送成功 */
CH375_CMD_PORT = CMD_UNLOCK_USB; /* 釋放當前USB緩沖區 */
FLAG_INT_WAIT = 0; /* 清發送中斷等待標志,通知應用程序可以繼續發送中斷數據 */
}
else { /* 內置固件的USB方式下不應該出現其它中斷狀態 */
}
}
/* 上傳中斷數據子程序(通過中斷端點上傳),可選子程序 */
void LoadIntData( unsigned char c1, unsigned char c2 )
{
unsigned int i;
for ( i=1000; i!=0; i-- ) { /* 等待發送中斷數據完成,因為PC機每隔1毫秒就讀取中斷數據,所以最多等待1毫秒 */
if ( FLAG_INT_WAIT == 0 ) break; /* 前次中斷數據已經被PC機取走 */
}
/* 如果未與計算機相連,或者計算機中的應用程序未運行,則會出現超時,否則不超過1毫秒中斷數據就應該被PC機取走 */
EX0 = 0; /* 為了防止中途被中斷而亂了順序,必須先禁止中斷 */
CH375_CMD_PORT = CMD_WR_USB_DATA5; /* 向USB端點1的發送緩沖區寫入數據塊 */
Delay2us( );
CH375_DAT_PORT = 2; /* 后續數據長度 */
/* 雖然每次可以上傳8個字節, 但是本程序中用于鍵盤中斷, 所以每次只需要傳輸兩個字節 */
FLAG_INT_WAIT = 1; /* 置中斷等待標志 */
CH375_DAT_PORT = c1; /* 發送中斷數據1 */
CH375_DAT_PORT = c2; /* 發送中斷數據2 */
EX0 = 1; /* 允許中斷 */
}
/* CH451初始化子程序 */
void CH451_Init( )
{
CH451_din=0; /* 先低后高,選擇4線輸入 */
CH451_din=1;
IT1 =0; /* 置外部信號為低電平觸發 */
IE1 =0; /* 清中斷標志 */
EX1 =1; /* 允許鍵盤中斷 */
}
/* CH451輸出命令子程序 */
/* 定義一無符號整型變量存儲12字節的命令字 */
void CH451_Write( unsigned int command )
{
unsigned char i;
EX1 = 0; /* 禁止鍵盤中斷 */
CH451_load=0; /* 命令開始 */
for( i=0; i<12; i++ ) { /* 送入12位數據,低位在前 */
CH451_din = command & 1;
CH451_dclk = 0;
command >>= 1;
CH451_dclk = 1; /* 上升沿有效,產生時鐘上升沿鎖通知CH451輸入位數據 */
}
CH451_load = 1; /* 加載數據,產生加載上升沿通知CH451處理命令數據 */
EX1 = 1; /* 允許鍵盤中斷 */
}
/* 讀取CH451鍵值子程序 */
unsigned char CH451_Read( )
{
unsigned char i;
unsigned char command, keycode;
EX1 = 0; /* 禁止鍵盤中斷 */
command=0x07; /* 輸入讀451命令字,只需要高4位,低8位可省去 */
CH451_load=0; /* 命令開始 */
for( i=0; i<4; i++ ){ /* 送入4位數據,低位在前 */
CH451_din = command & 1;
CH451_dclk = 0;
command >>= 1;
CH451_dclk = 1; /* 上升沿有效,產生時鐘上升沿鎖通知CH451輸入位數據 */
}
CH451_load = 1; /* 加載數據,產生加載上升沿通知CH451處理命令數據 */
keycode=0;
for( i=0; i<7; i++ ){ /* 輸入鍵值,7位 */
keycode<<=1; /* 數據移入keycode,高位在前,低位在后 */
keycode|=CH451_dout; /* 從高到低讀入451的數據 */
CH451_dclk=0; /* 產生時鐘下升沿通知CH451輸出下一位 */
CH451_dclk=1;
}
IE1=0; /* 清中斷標志,是讀取時DOUT輸出低電平產生的 */
EX1=1;
return( keycode ); /* 反回鍵值 */
}
/* CH451鍵盤中斷服務程序INT1,使用寄存器組1 */
void mCH451Interrupt( ) interrupt 2 using 1
{
unsigned char i, command;
command=0x07; /* 輸入讀451命令字,只需要高4位,低8位可省去 */
CH451_load=0; /* 命令開始 */
for( i=0; i<4; i++ ){ /* 送入4位數據,低位在前 */
CH451_din = command & 1;
CH451_dclk = 0;
command >>= 1;
CH451_dclk = 1; /* 上升沿有效,產生時鐘上升沿鎖通知CH451輸入位數據 */
}
CH451_load = 1; /* 加載數據,產生加載上升沿通知CH451處理命令數據 */
CH451_KEY=0;
for( i=0; i<7; i++ ){ /* 輸入鍵值,7位 */
CH451_KEY<<=1; /* 數據移入,高位在前,低位在后 */
CH451_KEY|=CH451_dout; /* 從高到低讀入451的數據 */
CH451_dclk=0; /* 產生時鐘下升沿通知CH451輸出下一位 */
CH451_dclk=1;
}
IE1=0; /* 清中斷標志 */
}
/* 由單片機控制演示,等待按鍵,然后先左移原顯示,再加上按鍵值 */
void DEMO_CH451_ONLY( )
{
unsigned char key;
CH451_Write( 0x0f00 | 0x17 ); /* 向第1個數碼管加載數據'H' */
CH451_Write( 0x0e00 | 0x0e ); /* 向第1個數碼管加載數據'E' */
CH451_Write( 0x0d00 | 0x18 ); /* 向第1個數碼管加載數據'L' */
CH451_Write( 0x0c00 | 0x19 ); /* 向第1個數碼管加載數據'P' */
CH451_Write( 0x0b00 | 0x10 ); /* 向第1個數碼管加載數據' ' */
CH451_Write( 0x0a00 | 0x14 ); /* 向第1個數碼管加載數據'[' */
CH451_Write( 0x0900 | 0x88 ); /* 向第1個數碼管加載數據'8.' */
CH451_Write( 0x0800 | 0x15 ); /* 向第1個數碼管加載數據']' */
CH451_Write( 0x0600 | 0x30 ); /* 第3個和第4個數碼管閃爍 */
while ( 1 ) { /* 以下演示為顯示按鍵代碼,并且左移 */
if ( CH451_KEY != 0xff ) { /* 檢測到新的按鍵,先左移顯示再顯示鍵值 */
key = CH451_KEY;
CH451_KEY = 0xff; /* 取按鍵值并清除原值 */
CH451_Write( 0x0300 ); /* 左移一位 */
CH451_Write( 0x0300 ); /* 左移一位 */
key &= 0x3f; /* 鍵值0-63 */
CH451_Write( 0x0900 | ( key / 10 ) ); /* 第7個數碼管顯示鍵值的十位數 */
CH451_Write( 0x0800 | ( key % 10 ) ); /* 第8個數碼管顯示鍵值的個位數 */
}
}
}
/* 由PC機通過USB演示CH451的功能,驗證USB通訊 */
void DEMO_USB( )
{
unsigned int ch451cmd;
TR0 = 1; /* 由定時器0自由計數值產生偽隨機數 */
CH451_CMD_H = 0xff; /* 清除CH451的命令碼 */
while ( 1 ) { /* 以下指令開始工作循環,等待PC機命令進行操作 */
if ( CH451_CMD_H == 0xff ) { /* 沒有CH451的命令, 以下檢測按鍵狀態 */
/* LAST_KEY和CH451_KEY兩個變量,都是0FFH則沒有鍵按下 */
/* 僅CH451_KEY為有效鍵值則是鍵剛按下, 兩者都是有效鍵值并且相同則已經通知過計算機 */
if ( LAST_KEY == 0xff ) { /* 按鍵未按下或者已按下但是尚未通知過PC機 */
if ( CH451_KEY != 0xff && CH451_KEY >= 0x40 ) { /* 檢測到新的鍵鍵,則置入有效的中斷特征數據,以通知PC機應用層 */
LAST_KEY = CH451_KEY;
/* 設定中斷特征數據01H,通知PC機的應用層,按鍵已按下, 中斷數據的次字節就是鍵碼,所以PC機應用層直接獲取鍵值,不必再讀取 */
LoadIntData( 1, LAST_KEY ); /* 上傳中斷數據,本程序用于鍵盤中斷,所以每次只需要傳輸兩字節 */
}
}
else { /* 按鍵已經按下并且已經通知過PC機,所以檢測按鍵釋放 */
CH451_KEY = CH451_Read( ); /* 重新讀取最近一次有效按鍵的鍵值 */
if ( CH451_KEY != LAST_KEY ) { /* 鍵值不同,按鍵已經釋放或者新鍵按下,如果鍵碼相同,說明按鍵仍然沒有釋放 */
/* 設定中斷特征數據02H,通知PC機的應用層,按鍵已釋放, 中斷數據的次字節就是鍵碼,所以PC機應用層直接獲取鍵值 */
LoadIntData( 2, LAST_KEY ); /* 上傳中斷數據 */
LAST_KEY = 0xff; /* 已經發送釋放信號給PC */
}
}
}
else { /* 在CH375中斷服務程序中接收到PC機發給CH451的命令 */
/* PC發送命令給CH451,由于主程序中的CH451_READ可能會被CH375的高優先級中斷,所以不宜在CH375中斷服務程序中執行 */
ch451cmd = ( (unsigned int)CH451_CMD_H << 8 ) + CH451_CMD_L; /* 高4位命令及低8位命令 */
CH451_CMD_H = 0xff; /* 清除原命令碼,防止重發 */
CH451_Write( ch451cmd ); /* 向CH451發送命令 */
}
}
}
main( ) {
Delay50ms( ); /* 延時等待CH375初始化完成,如果單片機由CH375提供復位信號則不必延時 */
CH375_Init( ); /* 初始化CH375 */
CH451_Init( ); /* 初始化CH451 */
/* 啟動CH451的顯示驅動和鍵盤掃描 */
CH451_Write( 0x0403 ); /* 設置系統參數命令,使能顯示驅動,使能鍵盤功能 */
CH451_Write( 0x058C ); /* 設置顯示參數,BCD譯碼方式,12級亮度 */
/* 由于在CH451啟動鍵盤功能前的串行輸出數據有可能產生鍵盤中斷,所以需要再次取消中斷 */
IE1 = 0;
CH451_KEY = 0xff; /* 清除按鍵代碼,在使能鍵盤前,CH451的DOUT輸出串行數據 */
LAST_KEY = 0xff; /* 有可能被當作鍵盤中斷請求INT1,所以要先清除 */
EA = 1; /* 允許中斷 */
/* 如果P2的第5腳和第6腳之間插上短路子則由單片機控制演示,否則由PC機通過USB控制進行演示 */
if ( T1 ) DEMO_USB( ); /* T1,P3.5為默認的高電平,由PC機通過USB演示 */
else DEMO_CH451_ONLY( ); /* 由單片機控制演示,等待按鍵,然后先左移原顯示,再加上按鍵值 */
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -