📄 source4.c
字号:
if (PS2DATA)
{ //高电平是停止位
if (key ==0xe0) //本次是扩展键
{PS2Buffers.PS2KeyExtFlage =0xe0;}//置扩展键标志(小键盘只有回车键)
else if (key ==0xf0)//本次是键断码,键释放
{PS2Buffers.PS2KeyExtFlage =0xf0;}//置键释放标志
else
{ //本次必为键值
if ((key ==0xAA) || (key ==0xFA)) PS2Buffers.PS2KeyPushCount = 0;//长压键计数器清零
else
{
PS2CLOCK =0;//阻止PS2键盘立即回送数据
PS2Buffers.PS2KeyPopError =0xAA;//出错码
for (i =0; i <20; i++)
{
if (key ==(PS2TAB[i]))
{ //搜索匹配按键
key =i ;
if (PS2Buffers.PS2KeyExtFlage ==0xF0)
{
key |=0x80;//键释放
PS2Buffers.PS2KeyPushCount =0;//长压键计数器清零
PS2Buffers.PS2KeyMessage =key;//存入当前键值并执行命令
Ir_Data[1] =key;
}
else
{
if (key !=PS2Buffers.PS2KeyVal)
{ //换了一个键
PS2Buffers.PS2KeyPushCount =0;//长压键计数器清零
PS2Buffers.PS2KeyMessage =key;//存入当前键值并执行命令
Ir_Data[2] =key;
}
else
{ //未换键
PS2Buffers.PS2KeyPushCount++; //长压键计数器计数
if (PS2Buffers.PS2KeyPushCount >DEFPS2PUSHCOUNT)
{ //长压时间到
PS2Buffers.PS2KeyMessage =key | 0x40; //存入当前键值并执行命令
PS2Buffers.PS2KeyPushCount =0; //长压键计数器清零
Ir_Data[3] =key | 0x40;
}
}
}
PS2Buffers.PS2KeyVal =key; //存入当前键值值1~20或0x80+(1~20)
key_sign =1;
if(Ir_Data[3] ==0x53)Ir_Data[3] =F3;
PS2Buffers.PS2KeyTemp =0; //键码移位记录器
PS2Buffers.PS2KeyExtFlage =0; //扩展键标志
PS2Buffers.PS2KeyPopError =0; //键释放标志或出错码
break;
}
}//for循环出口
if (PS2Buffers.PS2KeyPopError) PS2Buffers.PS2KeyPushCount =0;
//长压键计数器清零
PS2CLOCK =1; //释放PS2时钟总线
}
}
}//得到停止位,完成键值处理
else PS2Buffers.PS2KeyPopError =0xed;//置停止位错误号0xed
}
else PS2Buffers.PS2KeyCount =0;//PS2键盘出错
}
ZLG7290RES =1;EA =1;// 对于不知道键值的键盘可在此处加key_sign=1,但会影响红外
}
void ZLG7290KEY_ISR (void) interrupt 0 //7290中断处理
{
unsigned char m;
Ir_Data[0] =0x72;
Ir_Data[1] =0x90;
Ir_Data[2] =0;
if(j!=1)
{
Ir_Data[3] =SLA_READ(CHIP_7290,KEY);
if(Ir_Data[3] ==0)
{
Ir_Data[3] =SLA_READ(CHIP_7290,FKEY);
j =1;
}
key_sign =1;
}
else
j =0;
m =SLA_READ(CHIP_7290,KEY);
if(m !=0)
{
Ir_Data[3] =m;
key_sign =1;
}
else
{
j =0;
}
}
/*********************************************************************************/
//函数名称:SLA_WRITE
//函数功能:在指定从器件指定的字节地址中写入一个字节数据
//输入参数:从器件寻址地址chip,写入数据在器件中的字节地址wordadr
// 待写入的数据word;
//输出参数:无
/*********************************************************************************/
void SLA_WRITE(char chip, char wordadr, char word)
{
SMBMODE=chip & 0xfe; //SENDMODE作读/写控制字
while(SM_BUSY); // 若SMBUS忙碌就等待
SM_BUSY = 1; // 置SM_BUSY位(忙碌标志位)为1
WORD = word; // WORD中存放要送到24C02中去的数据(8位)
WORDADR = wordadr; // OP_CODE 中存放被传送数据送入24C02的首地址.
SMB_num=1;
STO = 0;
STA = 1; // 启动数据传输
while(SM_BUSY); // 等待传输完成
}
/*********************************************************************************/
//函数名称:SLA_READ
//函数功能:在指定从器件指定的字节地址中读出一个字节数据
//输入参数:从器件寻址地址chip,读出数据在器件中的字节地址wordadr
//输出参数:读出的一个字节数据WORD
/*********************************************************************************/
char SLA_READ(char chip, char wordadr)
{
SMBMODE=chip | 0x01;
while(SM_BUSY); // 若SMBUS忙碌就等待
SM_BUSY = 1; // 置SM_BUSY位(忙碌标志位)为1
WORDADR = wordadr; // OP_CODE 中存放从24C02读出数据的的首地址.
SMB_num=1;
STO = 0;
STA = 1; // 启动传输
while(SM_BUSY); // 等待传输完成
return WORD; //返回读出来的数据(一个字节)
}
void SMBUS_ISR (void) interrupt 7 //SMB0中断服务程序
{
switch (SMB0STA) // 根据中断状态码跳转
{ //(SMB0STA 是中断状态寄存器)
case 0x08: //0x08, (MT & MR) 发送起始位
SMB0DAT = SMBMODE & 0xfe; // 装入被访问的从芯片的读/写地址
STA = 0; // 人工清除 STA 位
break;
case 0x10: //0x10,(MT & MR) 重复发送起始位
SMB0DAT = SMBMODE | 0x01; // 装入被访问的从芯片的读地址
STA = 0; // 人工清除 STA 位
break;
case 0x18: //0x18 ,(MT) 发送从地址 + W 后收到ACK
SMB0DAT = WORDADR;
break;
case 0x20: //0x20,(MT) 发送从地址 + W 后收到NACK
STO = 1;
STA = 1;
break;
case 0x28: //0x28,(MT) 发送数据后收到ACK
if(SMB_num)
{
if (SMBMODE & 0x01) // 如果为读操作则重新启动总线.
{
STO = 0;
STA = 1;
}
else
{
SMB0DAT = WORD; //如果为写操作则将数据写入SMB0DAT.
SMB_num--;
}
}
else //如果数据写入完毕则发送停止信号.
{
STO = 1;
SM_BUSY = 0;
}
break;
case 0x30: //0x30,(MT) 发送数据后收到NACK
STO = 1;
STA = 1;
break;
case 0x40: //0x40,(MR) 发送从地址 + R 后收到 ACK
AA = 0;
break;
case 0x48: //0x48,(MR) 发送从地址 + R 后收到 NACK
STO = 0;
STA = 1;
break;
case 0x58: //0x58,(MR) 收到数据字节 后已发送NACK
WORD = SMB0DAT;
STO = 1;
SM_BUSY = 0;
AA = 1;
break;
default:
STO = 1;
SM_BUSY = 0;
break;
}
SI = 0;
}
/*********************************************************************************/
// 初始化函数
/*********************************************************************************/
/*延时子程序*/
void delay_ms(unsigned int count)
{
unsigned int ii,jj;
for(ii=0;ii<count;ii++)
{
for(jj=0;jj<250;jj++)
_nop_();
_nop_();
_nop_();
_nop_();
}
}
void Port_IO_Init()
{
EMI0CF = 0x2C; //选择高端口模式,只用外部存储器,EMIF工作在
//地址/数据复用方式,/WR和/RD占用12个SYSCLK周期
EMI0TC = 0x3C; //地址建立/保持时间为0,ALE高/低脉宽占1个SYSCLK周期
P3MDOUT = 0x2D; //P3.5--> LCD_RES,P3.3--> LCD_REQ,P3.2--> 7290_/RES,
//P3.0--> OE574 四位设置为推拉输出方式;
//P3.4--> LCD_BUSY,P3.1-->PS2_DATA两位设置为开漏输出方式。
P74OUT = 0xFF; //将P4,P6,P5,P7口配置为推拉输出方式
P0MDOUT = 0x01; //将TX0,TX1设置为推拉输出方式
P1MDOUT = 0x01;
XBR0 = 0xDF; //按照配置表进行各个外设的配置
XBR1 = 0x1C;
XBR2 = 0x44;
/*额外的配置请在本行文字以下进行配置并请加详细注释*/
/*------------------------------------------------*/
}
void Oscillator_Init() //系统时钟初始化
{
int i = 0;
OSCXCN = 0x67;
for (i = 0; i < 3000; i++); // Wait 1ms for initialization
while ((OSCXCN & 0x80) == 0);
OSCICN = 0x88; //使用外部22.1184M晶振,使能时钟丢失检测
}
void SMBus_Init()
{
SMB0CN = 0x44; //允许SMBUS, 应答返回AA(低电平
SMB0CR = 0x00; //配置传送速度为40K
}
void Interrupts_Init()
{
EIE1 |= 0x02;//使能SMB0中断
IE |= 0x05;//使能中断0
TCON |= 0x04;
IP |= 0x00;
EIP1 |= 0x02;//设置SMBUS中断为高优先级
IE |= 0x80;//使能全局中断
}
void PCA0_Init (void)//PCA0初始化
{
PCA0MD = 0x00;//PCA0采用系统时钟12分频,禁止PCA0溢出中断
EIE1 |= 0x08;//允许PCA0中断
PCA0CPM0 = 0x11;//模块0下降沿中断允许
PCA0CPM1 =0x11;
CR = 0; //关PCA0
}
void Init_Device(void) //初始化主函数
{
Oscillator_Init();
Port_IO_Init();
SMBus_Init();
Interrupts_Init();
PCA0_Init();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -