📄 smbuskeyboard______完成.c
字号:
/////////////////////////////////////
// smbuskey_dispaly.c File ////////////
/////////////////////////////////////
////2007.7.30//fengkun
/////////////////////////////////////
#include <C8051F020.h>
#include <intrins.h>
#define PCF8574 0x71 // 芯片A的器件地址CHIP_A = 1110001最后一位没有用
#define dat P7
unsigned char num=0,a=0,ke=0;
unsigned char hh,j,k,m; //显示位定义
xdata unsigned char aa[3]; //用于存放接收数据
code unsigned char LedCode[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
// 0 1 2 3 4 5 6 7 8 9
sbit dpy1=P3^0;
sbit dpy2=P3^1;
sbit dpy3=P3^2;
sbit dpy4=P3^3;
bit flag;
////////////////////////////////////////////////////////////////////////////
/////////初始化
////////////////////////////////////////////////////////////////////////////
void Reset_Sources_Init()
{
WDTCN = 0xDE;
WDTCN = 0xAD;
}
void Port_IO_Init()
{
//P0MDOUT = 0xFF;
P3MDOUT = 0xFF;
P74OUT = 0xC0;
XBR0 = 0x01;
XBR1 = 0x04;
XBR2 = 0x40;
}
void Oscillator_Init()
{
int i = 0;
OSCXCN = 0x67;
for (i = 0; i < 3000; i++); // Wait 1ms for initialization
while ((OSCXCN & 0x80) == 0);
OSCICN = 0x08;
}
void Init_Device(void)
{
Reset_Sources_Init();
Port_IO_Init();
Oscillator_Init();
}
void Smbus_Init()
{
BUSY=0; // 释放总线
SMB0CR =200; // SMBus时钟频率 = 50kHz.
EIE1 |= 2; // SMBus中断允许
SMB0CN = 0x44; // 允许SMBus在应答周期发送ACK
SMB0ADR=PCF8574;
}
void Display_Init() //显示模块初始化
{
hh=4;j=5;k=6;m=7; //初始化显示值
P3=0xf0; //初始化端口-------------
dat=0x00; //-----------------------
TMOD=0x11; //初始化定时器-----------
TR0=1;
ET0=1;
}
////////////////////初始化外部中断0/////////////////////////////////////
void Int0_Init()
{
EX0=1;
PX0=1;
IT0=0;
}
/////////////////////////////////////////////////////////////////////////////
//键盘判断数据处理-----------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
void keySMBUS()
{
while(BUSY); //wait busybit
BUSY =1; // 为第一次传输释放SMBus。
SMB0CN = 0x44; // 允许SMBus在应答周期发送ACK
STA=1; //开始
while (BUSY); // 等待传输结束
switch(aa[2]&0x0f)
{
case 0x0e:
hh++;
if(hh>9)
hh=0;
break;
case 0x0d :
j++ ;
if(j>9)
j=0;
break;
case 0x0b :
k++ ;
if(k>9)
k=0;
break;
case 0x07 :
m++ ;
if(m>9)
m=0;
break;
}
}
////////////////////////////////////////////////////////////////////////////
//smbus中断,此中断只考虑关键状态处理,以便调试
////////////////////////////////////////////////////////////////////////////
void smbusInt(void) interrupt 7
{
if(SMB0STA==0x08) //起始位发送成功,将地址+读控制装入发送缓冲区
{
SMB0DAT=PCF8574;
ke=0;
STA=0; //将STA清零,否则将处于重发状态
}
if(SMB0STA==0x40) //地址+读控制发送成功,此时SMB0DAT里的数据无意义,不作为接收数据,
{
ke=0;
AA=0; //要确保AA为1,因为接下去是主机发送ACK确认信号如果只接受一位,AA至0
}
/*if(SMB0STA==0x50)//数据成功接收,ACK成功发送
{
if(ke>=3)//共接收4个数据,所以在接收到第3个时将AA清零,注意第一个数据是从ke=1时接收
AA=0;
a[ke]=SMB0DAT;
} *///多组数据用这条
if(SMB0STA==0x10) //重发状态的处理
{
SMB0DAT=0x71;
STA=0;
}
if(SMB0STA==0x58) //最后一个数据接收成功,将STO置1,释放总线本程序只接受一个位数据
{
STO=1;
aa[2]=SMB0DAT;
}
/* ke++;
if(ke>=5)
ke=0;//在此设断点观察全速运行结果 */
SI=0;
}
/////////////////外部中断///////////////////////////////////////////////////
void intInterrupt(void) interrupt 0 using 2
{
EX0=0; //关外部中断
flag=1; //中断标志位
}
////////////////////////////////////////////////////////////////////////////
/////////////定时器0中断----数码管扫描////////////////////////////
////////////////////////////////////////////////////////////////////////////
void time0(void) interrupt 1 using 1
{
EA=0;
TH0=0xff;
TL0=0x00;
TR0=1;
TF0=0;
num++;
if(num>3)
num=0;
////////////////////////////////////////////////////////////////////////////
//以后数码管多了可以在上面加case,但是调节TL的大小,调到使数码管不闪就行!!
switch (num)
{
case 0: dpy4=0;
dat=LedCode[hh];
dpy1=1;
break;
case 1: dpy1=0;
dat=LedCode[j];
dpy2=1;
break;
case 2: dpy2=0;
dat=LedCode[k];
dpy3=1;
break;
case 3: dpy3=0;
dat=LedCode[m];
dpy4=1;
break;
}
EA=1;
}
////////////////////////////////////////////////////////////////////////////
/////主函数///////////////////////////////////////////----------------------
////////////////////////////////////////////////////////////////////////////
main()
{ Init_Device();
Display_Init();
Int0_Init();
Smbus_Init();
EA = 1; // 全局中断允许
while(1)
{
if(flag)
{ long int rr=50000;
keySMBUS();
while(--rr);
EX0=1; //打开外部中断
flag=0; //清标志位
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -