?? ch375blk.c
字號:
/*
; CH375/CH372 Bulk Data Test
; U2(AT89C51) Program
; 本程序測試數據傳輸的正確性, 并通過收發大數據塊來測試傳輸速度,
; 本程序適用于時鐘頻率不高于24MHz的標準MCS-51單片機, 如果高于24MHz則應該適當增加延時, 如果低于24MHz則可以適當減少延時
; 只要單片機允許, 盡量使用較高的時鐘, 例如將原12MHz晶振換為24MHz,
; 因為MCS51單片機自身速度較慢,讀寫外部RAM需要2個周期以及附加的循環指令,即使24MHz時鐘也無法超過500KB/S
; 為了減少單片機自身對速度測試的影響,本程序中速度測試部分在單片機中斷服務程序中完成
;
; Website: http://winchiphead.com
; Email: tech@winchiphead.com
; Author: W.ch 2003.09
*/
/* MCS-51單片機C語言的示例程序 */
#include <reg52.h>
#include <string.h>
#include "..\..\MCU_IF1\MCS51C\CH375INC.H"
/* #define USE_MY_USB_ID YES */
#define MY_USB_VENDOR_ID 0x1234 /* 廠商ID */
#define MY_USB_DEVICE_ID 0x5678 /* 設備ID */
unsigned char volatile xdata CH375_CMD_PORT _at_ 0xBDF1; /* CH375命令端口的I/O地址 */
unsigned char volatile xdata CH375_DAT_PORT _at_ 0xBCF0; /* CH375數據端口的I/O地址 */
unsigned char THIS_CMD_CODE; /* 保存當前命令碼 */
unsigned char RECV_LEN; /* 剛接收到的數據的長度 */
unsigned char RECV_BUFFER[ CH375_MAX_DATA_LEN ]; /* 數據緩沖區,用于保存接收到的下傳數據,長度為0到64字節 */
/* 由于MCS-51單片機存取外部RAM的讀寫速度低于內部RAM, 并且需要用到DPTR, 所以讀寫速度較慢, 其程序可以參考本程序修改 */
/* 定義位標志 */
bit bdata FLAG_RECV_OK; /* 接收成功標志,1指示成功接收到數據塊 */
bit bdata FLAG_SEND_WAIT; /* 發送等待標志,1指示有數據塊正在CH375中等待發送 */
/* 應用層定義 */
/* TEST_OTHER EQU 00H ;其它自定義的命令碼 */
#define TEST_START 0x20 /* 測試過程開始 */
#define TEST_DATA 0x21 /* 測試數據正確性 */
#define TEST_UPLOAD 0x22 /* 測試上傳數據塊 */
#define TEST_DOWNLOAD 0x23 /* 測試下傳數據塊 */
/* 有關CH451的定義,演示板的連接方式,該程序沒有用到鍵盤 */
sbit CH451_dclk=P1^7; /* 串行數據時鐘上升延激活 */
sbit CH451_din=P1^6; /* 串行數據輸出,接CH451的數據輸入 */
sbit CH451_load=P1^5; /* 串行命令加載,上升延激活 */
/* 延時2微秒,不精確 */
void Delay2us( )
{
unsigned char i;
#define DELAY_START_VALUE 1 /* 根據單片機的時鐘選擇初值,20MHz以下為0,30MHz以上為2 */
for ( i=DELAY_START_VALUE; i!=0; i-- );
}
/* 延時50毫秒,不精確 */
void Delay50ms( )
{
unsigned char i, j;
for ( i=200; i!=0; i-- ) for ( j=250; j!=0; j-- );
}
/* CH451初始化子程序 */
void CH451_Init( )
{
CH451_din=0; /* 先低后高,選擇4線輸入 */
CH451_din=1;
}
/* CH451輸出命令子程序 */
/* 定義一無符號整型變量存儲12字節的命令字 */
void CH451_Write( unsigned int command )
{
unsigned char i;
CH451_load=0; /* 命令開始 */
for( i=0; i<12; i++ ) { /* 送入12位數據,低位在前 */
CH451_din = command & 1;
CH451_dclk = 0;
command >>= 1;
CH451_dclk = 1; /* 上升沿有效 */
}
CH451_load = 1; /* 加載數據 */
}
/* CH375初始化子程序 */
void CH375_Init( )
{
unsigned char i;
FLAG_RECV_OK=0; /* 清接收成功標志,1指示成功接收到數據塊 */
FLAG_SEND_WAIT=0; /* 清發送等待標志,1指示有數據塊正在CH375中等待發送 */
/* 測試CH375是否正常工作,可選操作,通常不需要 */
#ifdef TEST_CH375_FIRST
CH375_CMD_PORT = CMD_CHECK_EXIST; /* 測試CH375是否正常工作 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
CH375_DAT_PORT = 0x55; /* 寫入測試數據 */
Delay2us( );
i = ~ 0x55; /* 返回數據應該是測試數據取反 */
if ( CH375_DAT_PORT != i ) { /* CH375不正常 */
for ( i=80; i!=0; i-- ) {
CH375_CMD_PORT = CMD_RESET_ALL; /* 多次重復發命令,執行硬件復位 */
Delay2us( );
}
CH375_CMD_PORT = 0;
Delay50ms( ); /* 延時50ms */
}
#endif
#ifdef USE_MY_USB_ID
/* 設置外部自定義的USB設備VID和PID,可選操作,不執行該命令則使用默認的VID和PID */
CH375_CMD_PORT = CMD_SET_USB_ID; /* 設置外部自定義的USB設備VID和PID,可選操作 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
CH375_DAT_PORT = (unsigned char)MY_USB_VENDOR_ID; /* 寫入廠商ID的低字節 */
CH375_DAT_PORT = (unsigned char)(MY_USB_VENDOR_ID>>8); /* 寫入廠商ID的高字節 */
CH375_DAT_PORT = (unsigned char)MY_USB_DEVICE_ID; /* 寫入設備ID的低字節 */
CH375_DAT_PORT = (unsigned char)(MY_USB_DEVICE_ID>>8); /* 寫入設備ID的高字節 */
Delay2us( );
#endif
/* 設置USB工作模式, 必要操作 */
CH375_CMD_PORT = CMD_SET_USB_MODE;
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
CH375_DAT_PORT = 2; /* 設置為使用內置固件的USB設備方式 */
for ( i=100; i!=0; i-- ) { /* 等待操作成功,通常需要等待10uS-20uS */
if ( CH375_DAT_PORT==CMD_RET_SUCCESS ) break;
}
/* if ( i==0 ) { CH372/CH375存在硬件錯誤 }; */
/* 下述啟用中斷,假定CH375連接在INT0 */
IT0 = 0; /* 置外部信號為低電平觸發 */
IE0 = 0; /* 清中斷標志 */
EX0 = 1; /* 允許CH375中斷 */
}
/* CH375中斷服務程序,使用寄存器組1 */
void mCh375Interrupt( ) interrupt 0 using 1
{
unsigned char InterruptStatus;
unsigned char length, c1;
unsigned char data *cmd_buf;
unsigned char data *ret_buf;
CH375_CMD_PORT = CMD_GET_STATUS; /* 獲取中斷狀態并取消中斷請求 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
InterruptStatus = CH375_DAT_PORT; /* 獲取中斷狀態 */
IE0 = 0; /* 清中斷標志,對應于INT0中斷 */
if ( InterruptStatus == USB_INT_EP2_OUT ) { /* 批量端點下傳成功 */
CH375_CMD_PORT = CMD_RD_USB_DATA; /* 從當前USB中斷的端點緩沖區讀取數據塊,并釋放緩沖區 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
length = CH375_DAT_PORT; /* 首先讀取后續數據長度 */
if ( length != 0 ) { /* 如果長度為0則不處理 */
THIS_CMD_CODE = CH375_DAT_PORT; /* 保存當前命令碼,因為我們測試程序與PC機應用程序約定首字節為命令碼 */
if ( THIS_CMD_CODE == TEST_DOWNLOAD ) { /* 測試下傳速度 */
while ( --length != 0 ) /* 先減1以去掉首字節后 */
c1 = CH375_DAT_PORT; /* 接收數據,為了測試速度,數據舍棄,24MHz的MCS51每讀取一個字節需要2uS */
}
else { /* 不是測試下傳速度的命令,先接收完命令包再分析 */
RECV_LEN = length; /* 命令包的數據長度 */
cmd_buf = RECV_BUFFER; /* 接收緩沖區 */
*cmd_buf = THIS_CMD_CODE;
while ( --length != 0 ) { /* 先減1以去掉首字節后 */
cmd_buf++;
*cmd_buf = CH375_DAT_PORT;
}
/* 以上程序C語言要每讀一個字節可能要十多個機器周期,如果用匯編語言只要4個機器周期
mov a,length
jz skip_get
mov r7,a
mov dptr,#CH375_DAT_PORT
get_next_byte: movx a,@dptr 數據直接放棄
djnz r7,get_next_byte
skip_get: nop
*/
if ( THIS_CMD_CODE == TEST_UPLOAD ) { /* 測試上傳速度 */
CH375_CMD_PORT = CMD_WR_USB_DATA7; /* 向USB端點2的發送緩沖區寫入數據塊 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
length = CH375_MAX_DATA_LEN;
CH375_DAT_PORT = length; /* 首先寫入后續數據長度 */
do {
CH375_DAT_PORT = TL0; /* 發送偽隨機數數據,為了測試速度,數據無效,24MHz的MCS51每寫出一個字節需要2uS */
} while ( --length != 0 );
}
else if ( THIS_CMD_CODE == TEST_START ) { /* 測試過程開始 */
/* 由于上一次測試數據上傳速度時可能在上傳緩沖區中遺留有數據, 所以在第二次測試前需要清除上傳緩沖區 */
CH375_CMD_PORT = CMD_SET_ENDP7; /* 設置USB端點2的IN */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
CH375_DAT_PORT = 0x0e; /* 同步觸發位不變,設置USB端點2的IN正忙,返回NAK */
FLAG_SEND_WAIT = 0; /* 清除發送等待標志,通知應用程序可以繼續發送數據 */
}
else if ( THIS_CMD_CODE == TEST_DATA ) { /* 測試數據正確性,將接收到的命令包數據取反后返回給PC機 */
CH375_CMD_PORT = CMD_WR_USB_DATA7; /* 向USB端點2的發送緩沖區寫入數據塊 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
ret_buf = RECV_BUFFER; /* 接收緩沖區 */
length = RECV_LEN; /* 剛接收到的數據長度 */
CH375_DAT_PORT = length; /* 首先寫入后續數據長度 */
if ( length ) {
do {
CH375_DAT_PORT = ~ *ret_buf; /* 數據取反后返回,由計算機應用程序測試數據是否正確 */
ret_buf++;
} while ( --length != 0 );
}
}
else { /* 其它命令,尚未定義 */
FLAG_RECV_OK = 1; /* 其它命令,設置接收成功標志,通知應用程序取走數據再分析 */
}
}
}
}
else if ( InterruptStatus == USB_INT_EP2_IN ) { /* 批量數據發送成功 */
if ( THIS_CMD_CODE == TEST_UPLOAD ) { /* 測試上傳速度,繼續準備上傳數據 */
CH375_CMD_PORT = CMD_WR_USB_DATA7; /* 向USB端點2的發送緩沖區寫入數據塊 */
Delay2us( ); /* 如果時鐘頻率低于16MHz則無需該指令延時 */
length = CH375_MAX_DATA_LEN;
CH375_DAT_PORT = length; /* 首先寫入后續數據長度 */
do {
CH375_DAT_PORT = TL0; /* 發送偽隨機數數據,為了測試速度,數據無效,24MHz的MCS51每寫出一個字節需要2uS */
} while ( --length != 0 );
}
CH375_CMD_PORT = CMD_UNLOCK_USB; /* 釋放當前USB緩沖區 */
FLAG_SEND_WAIT = 1; /* 清除發送等待標志,通知應用程序可以繼續發送數據 */
}
else if ( InterruptStatus == USB_INT_EP1_IN ) { /* 中斷數據發送成功 */
CH375_CMD_PORT = CMD_UNLOCK_USB; /* 釋放當前USB緩沖區 */
}
else { /* 內置固件的USB方式下不應該出現其它中斷狀態 */
}
}
main( ) {
unsigned char i;
Delay50ms( ); /* 延時等待CH375初始化完成,如果單片機由CH375提供復位信號則不必延時 */
CH375_Init( ); /* 初始化CH375 */
CH451_Init( ); /* 初始化CH451 */
/* 啟動CH451的顯示驅動 */
CH451_Write( 0x0401 ); /* 設置系統參數命令,使能顯示驅動 */
CH451_Write( 0x0588 ); /* 設置顯示參數,BCD譯碼方式,8級亮度 */
for ( i=0; i<8; ++i ) CH451_Write( (unsigned int)i << 8 | 0x0800 | i ); /* 依次顯示12345678 */
EA = 1; /* 允許中斷 */
TR0 = 1; /* 由定時器0自由計數值產生偽隨機數 */
while ( 1 ) { /* 以下指令開始工作循環,等待PC機命令進行操作 */
if ( FLAG_RECV_OK ) { /* 收到未定義的命令 */
CH451_Write( 0x0300 ); /* 發出命令使CH451顯示左移一位,提示收到未定義命令 */
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -