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

📄 ch375451.c

📁 Ch372开发软硬件详细资料,硬件为CH372+8051 软件为VB或VC皆有
💻 C
📖 第 1 页 / 共 2 页
字号:
			}
		}
		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 + -