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

📄 smbuskeyboard______完成.c

📁 PCF8574的键盘程序
💻 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 + -