⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 demo.c

📁 Ch372开发软硬件详细资料,硬件为CH372+8051 软件为VB或VC皆有
💻 C
📖 第 1 页 / 共 3 页
字号:
// 2003.09.08, 2003.12.28, 2004.12.10, 2004.12.28
//****************************************
//**  Copyright  (C)  W.ch  1999-2004   **
//**  Web:  http://www.winchiphead.com  **
//****************************************
//**  EXE for USB interface chip CH375  **
//**  C, VC5.0                          **
//****************************************
//
// USB总线接口芯片CH375的应用层演示程序 V1.2
// 南京沁恒电子有限公司  作者: W.ch 2004.12
// CH375-EXE  V1.2 , Support: Ctrl/Bulk/Int
// 运行环境: Windows 98/ME, Windows 2000/XP
// support USB chip: CH372/CH375
//


#define		mTHIS_VERSION		0x12		// 当前版本
#define		mTHIS_VER_STR		"1.2"		// 当前版本字符串

#include	<windows.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	"CH375DLL.H"		// CH372/CH375的动态链接库
#pragma comment(lib,"CH375DLL")

#include	"DEMO.H"

#define		IDC_INT_PRESS		2222	// 按键按下事件信号
#define		IDC_INT_RELEASE		2223	// 按键释放事件信号
#define		IDC_INT_DEVARRIVAL	2224	// 设备插上事件信号
#define     IDC_INT_DEVREMOVAL  2225    // 设备拔出事件信号

typedef	struct	_COMMAND_PACKET	{	// 自定义的命令包结构
	UCHAR	mCommandCode;		// 命令请求码,见下面的定义
	UCHAR	mCommandCodeNot;	// 命令码的反码,用于校验命令包
	union	{
		UCHAR	mParameter[5];	// 参数
		struct {
			UCHAR	mBufferID;  // 缓冲区识别码,本程序针对MCS51单片机定义: 1-专用功能寄存器SFR, 2-内部RAM, 3-外部RAM, 不过本程序实际只演示内部RAM
			USHORT	mBufferAddr;	// 读写操作的起始地址,寻址范围是0000H-0FFFFH,低字节在前
			USHORT	mLength;	// 数据块总长度,低字节在前
		};
	};
}	mCOMMAND_PACKET,	*mpCOMMAND_PACKET;

#define		CONST_CMD_LEN		0x07	// 命令块的长度
// 由于命令与数据都是通过数据下传管道(USB端点2的OUT)下传, 为了防止两者混淆,
// 我们可以在计算机应用程序与单片机程序之间约定, 命令块的长度总是7, 而数据块的长度肯定不是7, 例如64,32等
// 另外, 可以约定, 命令块的首字节是命令码, 等等
// 本程序约定命令码: 80H-0FFH是通用命令,适用于各种应用
//                   00H-7FH是专用命令,针对各种应用特别定义
// 通用命令
#define		DEF_CMD_GET_INFORM		0x90	// 获取下位机的说明信息,长度不超过64个字符,字符串以00H结束
#define		DEF_CMD_TEST_DATA		0x91	// 测试命令,下位机将PC机发来的命令包的所有数据取反后返回
#define		DEF_CMD_CLEAR_UP		0xA0	// 在上传数据块之前进行同步,实际是让下位机清除上传缓冲区的已有内容
#define		DEF_CMD_UP_DATA			0xA1	// 从下位机的指定地址的缓冲区中读取数据块(上传数据块)
#define		DEF_CMD_DOWN_DATA		0xA2	// 向下位机的指定地址的缓冲区中写入数据块(下传数据块)
// 专用命令
#define		DEMO_CH451_CMD			0x56	// PC发送命令给CH451,用于演示CH451的功能
// 对于MCS51单片机在使用通用命令时,还需要指定缓冲区识别码
#define		ACCESS_MCS51_SFR		1		// 读写51单片机的SFR
#define		ACCESS_MCS51_IRAM		2		// 读写51单片机的内部RAM
#define		ACCESS_MCS51_XRAM		3		// 读写51单片机的外部RAM

HINSTANCE   mSaveInstance;		// 实例
HWND        mSaveDialogMain;	// 主对话框
HWND        mEnterDialog;	// 输入数据对话框

UCHAR	mEnterBuffer[8];		// 数据输入缓冲区
UINT	mBufferLength = 0;		// 缓冲区内的有效数据长度
UINT	mShowLED = 0;			// 不为0则LED亮
UINT	mKeyCode = 0xff;		// 按键编号
UINT	mIndex = 0;				// 如果有多个CH372/CH375则指示序号
CHAR	mCaptionInform[] = " 信息提示 ";
BOOL    openflag=FALSE;
BOOL    Arrivalflag=FALSE; //是设备插上

LRESULT CALLBACK mDialogMain(HWND,UINT,WPARAM,LPARAM);  //主对话框调用程序
LRESULT CALLBACK mDialogEnter(HWND,UINT,WPARAM,LPARAM); //输入数字对话框调用程序
VOID SendCH452Command();  //发送CH452命令.//mEnterBuffer存储的是三位十六进制的命令字符
UCHAR	mCharToBcd(UCHAR);								// 将ASCII字符转换为一位BCD码
VOID	mSyncKeyboard(HWND,UINT);						// 同步按键显示
VOID	CALLBACK mInterruptEvent(PUCHAR);						// 中断服务程序
UINT	mDownloadData( UCHAR *iBuffer, UINT iLength );	// 下传数据块,返回实际传输长度
UINT	mUploadData( UCHAR *iBuffer, UINT iLength );	// 上传数据块,返回实际传输长度
VOID CALLBACK NotifyRoutine (ULONG	iEventStatus );  // 设备事件通知回调程序
VOID Testcommunication();   //测试PC机与单片机之间的USB通讯
VOID devremoval();        //设备移除处理函数
VOID devarrival();        //设备插入处理函数


//程序入口
int	APIENTRY	WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd )
{
	CHAR	*CmdLine;
	CmdLine = lpCmdLine;
	mSaveInstance = hInstance;
	if ( CmdLine != NULL && *CmdLine >= '0' && *CmdLine <= '9' ) {  // 在命令行中指定CH375设备序号
// 如果运行DEMO时在命令行指定参数0至9,则对应CH375设备序号0-9,如果没有命令行参数则默认为CH375设备序号0
// 例如,执行"DEMO 1"对应1#CH375设备,执行"DEMO 8"对应8号CH375设备
// 命令行带参数可以通过Windows操作系统的"开始"中的"运行"窗口执行,或者在DOS窗口中执行
		mIndex = *CmdLine - '0';
	}
	return( DialogBox( hInstance, "IDD_MAIN", NULL, mDialogMain ) );    //调用主对话框
}

//主对话框事件  
LRESULT CALLBACK mDialogMain( HWND hDialog, UINT uMessage, WPARAM wParam, LPARAM lParam )
{
	mCOMMAND_PACKET	mDemoReq;
	UINT		mLength;
	switch( uMessage )
	{
		case WM_INITDIALOG:        //初始化
			mSaveDialogMain = hDialog;
// 需要使用DLL则需要先加载
			CheckDlgButton(mSaveDialogMain,IDC_WordShift,BST_CHECKED);
			CheckDlgButton(mSaveDialogMain,IDC_SegUnLight,BST_CHECKED);

			if ( LoadLibrary( "CH375DLL.DLL" ) == NULL )  // 加载DLL失败,可能未安装到系统中
			{
				MessageBox( hDialog, "无法加载CH372/CH375的DLL", mCaptionInform, MB_ICONSTOP | MB_OK );
				EndDialog( hDialog, 0x81 );  // 关闭对话框
				return( TRUE );
			}

/* 为了从多个CH372/CH375设备中找出自己的设备,应用程序可以查询USB设备的ID号(厂商ID和产品ID),直到ID比较正确,可以在打开设备之前或者之后查询
#define		MY_VENDOR_ID	0x4348
#define		MY_PRODUCT_ID	0x5537
			for ( mIndex = 0; mIndex < mCH375_MAX_NUMBER; mIndex ++ )
			{
				if ( CH375GetUsbID( mIndex ) == ( ( MY_PRODUCT_ID << 16 ) | MY_VENDOR_ID ) ) break;  // 获取USB设备ID,返回数据中,低16位为厂商ID,高16位为产品ID,错误时返回全0(无效ID)
			}
			if ( mIndex >= mCH375_MAX_NUMBER )
			{
				MessageBox( hDialog, "找不到指定的CH372/CH375设备", mCaptionInform, MB_ICONSTOP | MB_OK );
				EndDialog( hDialog, 0x81 );  // 关闭对话框
				return( TRUE );
			}*/

            if(!CH375SetDeviceNotify(mIndex,NULL,NotifyRoutine)) //设置设备插拔监视
				MessageBox( hDialog, "设置监视CH372/CH375设备插拔失败", mCaptionInform, MB_ICONSTOP | MB_OK );

			if ( CH375OpenDevice( mIndex ) == INVALID_HANDLE_VALUE )  // 打开设备 
			{
				openflag=FALSE;
                NotifyRoutine(CH375_DEVICE_REMOVE);   //设备没打开,按钮禁用
				return ( TRUE );
				break;
			}
			else  //打开成功
				openflag=TRUE;			    

			NotifyRoutine(CH375_DEVICE_ARRIVAL);  //设备打开,按钮可用
			CH375SetTimeout( mIndex, 3000, 3000 );  // 设置USB数据读写的超时,超过3000mS未完成读写将强制返回,避免一直等待下去
            Testcommunication(); // 测试PC机与单片机之间的USB通讯,仅作演示,本身没有意义
/* 下面是下传/上传数据块的例子
			{
				UCHAR mBuffer[4096];
				mBuffer[0]=data;	// 准备下传的数据
				mLength = mDownloadData( mBuffer, 4096 ) ;	// 将数据块从计算机下传给单片机,返回实际传输长度
				mLength = mUploadData( mBuffer, 4096 ) ;	// 从单片机上传数据块到计算机,返回实际传输长度
			}*/
			CH375SetExclusive( mIndex, FALSE );  // 临时设置共享使用当前CH375设备,因为下面设置中断服务程序时需要使用当前这个CH375设备
// 下面加载中断服务程序,中断服务程序是在应用层执行的,其线程优先级是THREAD_PRIORITY_TIME_CRITICAL
// 当单片机有事需要通知计算机时,可以用CMD_WR_USB_DATA5命令写入中断特征数据,计算机的mInterruptEvent线程将会收到该中断特征数据
// 然后mInterruptEvent线程向主程序发出消息进行处理,mInterruptEvent线程相当于中断服务程序,代替主程序定时查询单片机
			CH375SetIntRoutine( mIndex, mInterruptEvent );  //设置中断
			Sleep( 50 );  // 主程序休息50mS,以等待上一个操作CH375SetIntRoutine创建线程并由该线程再次打开CH375,否则下一个操作CH375SetExclusive将导致创建的线程无法打开CH375
			CH375SetExclusive( mIndex, TRUE );  // 设置独占使用当前CH375设备,在此之后其它应用程序不能同时使用当前这个CH375设备,实际是无法再打开CH375设备
			return ( TRUE );
			break;
		case WM_COMMAND:
			switch ( LOWORD( wParam ) )
			{				
				char i=0,j=0,k=0;
				char ledval[4]="",oldledval[4]="";

				case IDC_N1:  // 发送数据到演示板上的第1个数码管,左边第1个
				case IDC_N2:
				case IDC_N3:
				case IDC_N4:
				case IDC_N5:
				case IDC_N6:
				case IDC_N7:
				case IDC_N8:  // 发送数据到演示板上的第8个数码管,右边第1个
                    if(Arrivalflag== 0){  //将软件上的显示信息发送到评估板,不要输入,保证上下显示信息相同,					
						if(DialogBox( mSaveInstance, "IDD_ENTER", NULL, mDialogEnter )==IDC_CANCEL)
							break;
					}
					Arrivalflag=FALSE;  					
					if ( mBufferLength )  // 已经输入数据
					{
						UCHAR	mBcdCode;
						UCHAR	mNumber;
						if ( mEnterBuffer[0] == ' ' ) mBcdCode = 0x10;  // 空格
						else if ( mEnterBuffer[0] == '=' ) mBcdCode = 0x13;
						else if ( mEnterBuffer[0] == '.' ) mBcdCode = 0x1a;
						else mBcdCode = mCharToBcd( mEnterBuffer[0] );
						// 如果输入一个字符和一个小数点,则在字符右下角追加小数点
						if ( mBufferLength >= 2 && mEnterBuffer[1] == '.' ) mBcdCode |= 0x80;
						if ( mBcdCode != 0xff )  // 输入的字符有效
						{   
							ZeroMemory(&mDemoReq,sizeof(mDemoReq));
							mNumber = LOWORD( wParam ) - IDC_N1;  // 如果IDC_N1至IDC_N8有序,则结果为0-7,分别对应于各个数码管按钮
							mNumber = 7 - mNumber;  // 以最高位为左,最低位为右,所以N1对应位7,N8对应0
							mDemoReq.mCommandCode = DEMO_CH451_CMD;
							mDemoReq.mCommandCodeNot = ~ DEMO_CH451_CMD;
							mDemoReq.mParameter[2] = 0x08 | mNumber;  // CH451命令:加载字数据到指定数码管
							mDemoReq.mParameter[1] = mBcdCode;  // 字数据,对应于BCD译码方式
							mLength = CONST_CMD_LEN;	// 命令包的长度
							if ( CH375WriteData( mIndex, &mDemoReq, &mLength ) )  // 通过CH375发送数据,成功
						// 如果输入时mLength大于64,则成功返回时,为了更加可靠,可以检查实际发送的长度是否符合
							{
								if(lstrlen(mEnterBuffer)==1)
									mEnterBuffer[1] = 0;  // 字符串结束符,只要一个字符
								else
									mEnterBuffer[2] = 0;
								SetDlgItemText( hDialog, LOWORD( wParam ), CharUpper(mEnterBuffer) );   //设置按钮上的字符
							}
							else
								MessageBox( hDialog, "CH375WriteData 失败", mCaptionInform, MB_OK | MB_ICONERROR );
						}
						else 
							MessageBox( hDialog, "请输入字符:\n0-9,A-F或者空格,小数点", mCaptionInform, MB_OK | MB_ICONERROR );
					}
					else 
						MessageBox( hDialog, "请至少输入一个字符:\n0-9,A-F或者空格,小数点", mCaptionInform, MB_OK | MB_ICONERROR );					
					break;				
				case IDC_INT_PRESS:  // 键被按下,以下先释放原按键再读取新按键值
					mSyncKeyboard( hDialog, 0xff );  // 释放上次的按键
					mSyncKeyboard( hDialog, mKeyCode );  // 根据键值作同步显示					
					break;
				case IDC_INT_RELEASE:  // 按键释放
					mSyncKeyboard( hDialog, 0xff );  // 释放按键					
					break;				

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -