📄 8574keyboard.c
字号:
//#include <reg52.h>
#include <ADI/ADuC834.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//1602移植过来的
sbit rs=P2^3; //1602的数据/指令选择控制线
sbit rw=P2^4; //1602的读写控制线
sbit en=P2^5; //1602的使能控制线
/*P2口接1602的D0~D7,注意不要接错了顺序,我以前可在这上面吃过亏~*/
uchar code table[]="LCD1602 check ok"; //要显示的内容1放入数组tablel
uchar code table1[]="study up"; //要显示的内容2放入数组table1
uchar code esc[]="ESC";
uchar code light[]="LIGHT";
uchar code avc[]="AVC";
uchar code memo[]="MEMO";
uchar code hold[]="HOLD";
uchar code setup[]="SETUP";
uchar code pgdn[]="PgDn";
uchar n,m=0;
uchar slvadr=0x40 ; //被控器地址
uchar ack;
uchar key;
uchar curkey;
uchar key_right_flag=1;
uchar KeyPort;
uchar RBT[8];
//1602移植过来的
void delay(uint n) //延时函数
{
uint x,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
void lcd_wcom(uchar com) //1602写命令函数
{
rs=0; //选择指令寄存器
rw=0; //选择写
P0=com; //把命令字送入P2
delay(5); //延时一小会儿,让1602准备接收数据
en=1; //使能线电平变化,命令送入1602的8位数据口
en=0;
}
void lcd_wdat(uchar dat) //1602写数据函数
{
rs=1; //选择数据寄存器
rw=0; //选择写
P0=dat; //把要显示的数据送入P2
delay(5); //延时一小会儿,让1602准备接收数据
en=1; //使能线电平变化,数据送入1602的8位数据口
en=0;
}
void lcd_init() //1602初始化函数
{
lcd_wcom(0x38); //8位数据,双列,5*7字形
lcd_wcom(0x0F); //开启显示屏,关光标,光标不闪烁
lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
lcd_wcom(0x01); //清屏
}
void PCF8574init(void)
{
I2CM=1;
}
void delay1ms(uchar x)
{
unsigned char i,j;
while(x--)
{
for(i=5;i>0;i--)
for(j=132;j>0;j--);
}
}
void Delay_Cycles(char delay)
{
while(delay--);
}
/*---------------------------------------------------------------------------------------------------
开始:START
描述:启动I2C 总线子程序--发送I2C 起始条件
---------------------------------------------------------------------------------------------------*/
void start(void)
{
MDE=1;
MCO=1;
MDO=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MDO=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MCO=0;
}
void Ack_I2c(uchar a) //a=0发送应答信号,=1发送非应答信号
{
MDE=1;
if(a==0)MDO=0; /*在此发出应答或非应答信号 */
else MDO=1;
_nop_();
_nop_();
_nop_();
MCO=1;
_nop_();
_nop_(); /*时钟低电平周期大于4μs*/
_nop_();
_nop_();
_nop_();
MCO=0; /*清时钟线,钳住I2C总线以便继续接收*/
_nop_();
_nop_();
}
void wrbyt(uchar shu)
{
uchar i;
ack=0;
MDE=1; // SETB MDE ; to enable SDATA pin as an output
MCO=0;
for(i=0;i<8;i++)
{
if(shu&0x80)
{
MDO=1;
_nop_();
MCO=1;
_nop_();
_nop_();
_nop_();
MCO=0;
//MDO=0;
}
else
{
MDO=0;
_nop_();
MCO=1;
_nop_();
_nop_();
_nop_();
MCO=0;
}
shu=shu<<1;
}
MDO=1;
MDE=0; // CLR MDE ; release data line for acknowledge
MCO=1; // SETB MCO ; send clock for acknowledge
Delay_Cycles(3);
MCO=0;
}
//void SendByte_Upon_I2C(unsigned char byte)
//{
// unsigned char send_bitdata;
// unsigned char send_bytedata=byte;
// uchar BITCNT=8; // MOV BITCNT,#8 ; 8 bits in a byte
// MDE=1; // SETB MDE ; to enable SDATA pin as an output
// MCO=0; // CLR MCO ; make sure that the clock line is low
// Delay_Cycles(5);
// while(BITCNT--)
// {
// if(send_bytedata&0x80)send_bitdata=1;
// else send_bitdata=0;
// MDO=send_bitdata; // MOV MDO,C ; put data bit on SDATA line
// MCO=1; // SETB MCO ; clock to send bit
// Delay_Cycles(1);
// Delay_Cycles(5);
// MCO=0; // CLR MCO ; clear clock
// send_bytedata<<=1;
// } // DJNZ BITCNT,SENDBIT ; jump back and send all eight bits
// MDE=0; // CLR MDE ; release data line for acknowledge
// MCO=1; // SETB MCO ; send clock for acknowledge
// Delay_Cycles(3);
// MCO=0; //NEXT: CLR MCO ; clear clock
// return; // RET
//}
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc=0;
MDE=0; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_nop_();
MCO=0; /*置时钟线为低,准备接收数据位*/
_nop_();
_nop_(); /*时钟低电平周期大于4.7μs*/
_nop_();
_nop_();
_nop_();
MCO=1; /*置时钟线为高使数据线上数据有效*/
_nop_();
_nop_();
retc=retc<<1;
if(MDI==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */
_nop_();
_nop_();
}
MCO=0;
_nop_();
_nop_();
return(retc);
}
/*---------------------------------------------------------------------------------------------------
名称:STOP
描述:停止I2C 总线子程序--发送I2C 总线停止条件
---------------------------------------------------------------------------------------------------*/
void stop(void)
{
MDE=1;
MDO=0;
_nop_();
MCO=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
MDO=1;
_nop_();
_nop_();
_nop_();
}
void checkack(void)
{
// MDO=1; /*8位发送完后释放数据线,准备接收应答位*/
// MDE=0;
// _nop_();
// _nop_();
// MCO=1;
// _nop_();
// _nop_();
// _nop_();
if(MDI==0)
ack=1;
else
ack=0; /*判断是否接收到应答信号*/
MCO=0;
MDE=1;
_nop_();
_nop_();
}
/*************************************************************************************
主程序
**************************************************************************************/
void ext0_int() interrupt 0//SPIandI2C_InterruptRoutine(void) interrupt 7//
{
// if(key_right_flag<2)
// {
EX0=0;
start();
wrbyt(0x41);
RBT[1]=RcvByte();
Ack_I2c(1);
stop();
if(RBT[1]>=0x70)//如果接收的数正确
key_right_flag++;
KeyPort = (RBT[1] & 0xF0);
//KeyPort=(0x70&0xF0);
start();
wrbyt(0x40);
wrbyt(0x0F);
checkack();
stop();
start();
wrbyt(0x41);
RBT[2]=RcvByte();
Ack_I2c(1);
stop();
if(RBT[2]<=0x0F)//判断是否正确
key_right_flag++;
key = (RBT[2] & 0x0F);
key|=KeyPort;
if(key!=0xFF)
curkey=key;
// }
// if(key_right_flag>=2)
// {
key_right_flag=0;
start();//恢复8574初始状态
wrbyt(0x40);
wrbyt(0xF0);
checkack();
stop();
EX0=1;
// }
}
/*************************************************************************************
主程序
**************************************************************************************/
void main()
{
EX0=1;
PCF8574init();//主机模式
start();
wrbyt(slvadr);//发一个数据或地址
wrbyt(0xF0);//端口初始化
checkack();
stop();
delay1ms(1);
delay1ms(1);
delay1ms(1);
start();
wrbyt(0x41);
RBT[0]=RcvByte();
Ack_I2c(1);
stop();
EA=1;
//1602移植过来的
lcd_init(); //液晶初始化
lcd_wcom(0x80); //显示地址设为80H(即00H,)上排第一位
for(m=0;m<16;m++) //将table[]中的数据依次写入1602显示
{
lcd_wdat(table[m]);
delay(1);
}
lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位
for(n=0;n<8;n++) //将table1[]中的数据依次写入1602显示
{
lcd_wdat(table1[n]);
delay(1);
}
while(1)
{
uchar i;
switch (curkey)
{/*将按键码输出到显示*/
case 0x7E:
lcd_wcom(0x80);
//lcd_wdat('L');
for(i=0;i<5;i++)
{
lcd_wdat(light[i]);
}
curkey=0;
break;
case 0xBE:
lcd_wcom(0x80);
//lcd_wdat('A');
for(i=0;i<3;i++)
{
lcd_wdat(avc[i]);
}
curkey=0;
break;
case 0xDE:
lcd_wcom(0x80);
//lcd_wdat('M');
for(i=0;i<4;i++)
{
lcd_wdat(memo[i]);
}
curkey=0;
break;
case 0xEE:
lcd_wcom(0x80);
//lcd_wdat('H');
for(i=0;i<4;i++)
{
lcd_wdat(hold[i]);
}
curkey=0;
break;
case 0xED:
lcd_wcom(0x80);
//lcd_wdat('S');
for(i=0;i<5;i++)
{
lcd_wdat(setup[i]);
}
curkey=0;
break;
case 0xDD:
lcd_wcom(0x80);
lcd_wdat('9');
curkey=0;
break;
case 0xBD:
lcd_wcom(0x80);
lcd_wdat('8');
curkey=0;
break;
case 0x7D:
lcd_wcom(0x80);
lcd_wdat('7');
curkey=0;
break;
case 0xEB:
lcd_wcom(0x80);
//lcd_wdat('P');
for(i=0;i<4;i++)
{
lcd_wdat(pgdn[i]);
}
curkey=0;
break;
case 0xDB:
lcd_wcom(0x80);
lcd_wdat('6');
curkey=0;
break;
case 0xBB:
lcd_wcom(0x80);
lcd_wdat('5');
curkey=0;
break;
case 0x7B:
lcd_wcom(0x80);
lcd_wdat('4');
curkey=0;
break;
case 0xE7:
lcd_wcom(0x80);
for(i=0;i<3;i++)
{
lcd_wdat(esc[i]);
}
//lcd_wdat('E');
curkey=0;
break;
case 0xD7:
lcd_wcom(0x80);
lcd_wdat('3');
curkey=0;
break;
case 0xB7:
lcd_wcom(0x80);
lcd_wdat('2');
curkey=0;
break;
case 0x77:
lcd_wcom(0x80);
lcd_wdat('1');
curkey=0;
break;
case 0x7F:
lcd_wcom(0x80);
lcd_wdat('0');
curkey=0;
break;
case 0xBF:
lcd_wcom(0x80);
lcd_wdat('.');
curkey=0;
break;
case 0xDF:
lcd_wcom(0x80);
lcd_wdat('+');
curkey=0;
break;
case 0xEF:
//lcd_wcom(0x80);
lcd_wdat('*');
lcd_wcom(0x80+0x44);
curkey=0;
break;
default :
break;
}
delay1ms(1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -