📄 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 + -