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

📄 ps2_drv.c

📁 ps2键盘的时序介绍和开发程序
💻 C
字号:
//====================================================================================
//文 件 名:PS2_Drv.c
//功能描述: PS2底层驱动程序
//维护记录: 2007年3月17日
//====================================================================================
#include "spce061a.h"
#include "PS2_Drv.h"

typedef enum{
	PS2_DISABLE,
	PS2_READENABLE,
	PS2_WRITEENABLE,
	PS2_READING,
	PS2_WRITING,
	PS2_WAITACK,
	PS2_WAITACK2,
	PS2_READDONE,
	PS2_WRITEDONE,
	PS2_READERROR,
	PS2_WRITEERROR,
}STATUS_FLAG;

STATUS_FLAG PS2_StatusFlag;
unsigned short PS2_StatusCode;
unsigned short PS2_DataMask;
unsigned short PS2_Counter;
unsigned short PS2_Data;
unsigned short PS2_ReadBuf[PS2_BUFSIZE];
unsigned short PS2_BufPointerW;
unsigned short PS2_BufPointerR;

//=============================================================
//语法格式:	void PS2_Init(void);
//实现功能:	PS2初始化
//参数:		无
//返回值:		无
//=============================================================
void PS2_Init(void)
{
	unsigned char i;
	
	PS2_Data = 0x0000;
	PS2_Counter = 0x0000;
	PS2_DataMask = 0x0000;
	PS2_StatusFlag = PS2_READENABLE;
	PS2_StatusCode = PS2_STATUS_IDLE;
	for(i=0; i<PS2_BUFSIZE; i++)
	{
		PS2_ReadBuf[i] = 0xffff;        //接受缓冲去清零
	}
	PS2_BufPointerW = 0;                
	PS2_BufPointerR = 0;              

	*P_SystemClock = 0x0098;//选择CPUCLK为49M

	//输入、上拉
	PS2_DAT_Input();
	PS2_CLK_Input();
	
//============================================================
//				选择TimerA/B,修改此处
//============================================================
	__asm("FIQ OFF");
	*P_PS2TMR_CTRL = C_TMB_FOSC_2;
	*P_PS2TMR_DATA = 0xFE14;
	*P_INT_Ctrl_New |= C_FIQ_TMB;

	__asm("FIQ ON");
}

//=============================================================
//语法格式:	void PS2_Write(unsigned char Data);
//实现功能:	向PS2设备写入一字节
//参数:		Data:	待写入的数据
//返回值:		无
//=============================================================
void PS2_Write(unsigned char Data)
{
	unsigned char i;
	unsigned short DataMask, ParityMask;
	
	PS2_StatusFlag = PS2_DISABLE;
	PS2_DataMask = 0x0000;
	PS2_Counter = 0x0000;
	PS2_Data = Data | 0x0200;
	
	DataMask = 0x0001;
	ParityMask = 0x0100;
	for(i=0; i<8; i++)
	{
		if(PS2_Data&DataMask)
			ParityMask ^= 0x0100;                 //奇检验wei
		DataMask <<= 1;
	}
	PS2_Data |= ParityMask;
	PS2_StatusFlag = PS2_WRITEENABLE;
	PS2_StatusCode |= PS2_STATUS_WRITING;
	PS2_StatusCode &= ~PS2_STATUS_WRITEERR;
	PS2_CLK_Clr();       //clk=0
	PS2_CLK_Output();    //*P_PS2_GPIO_ATTRIB |= 0x0001<<(PS2_CLK_BIT);*P_PS2_GPIO_DIR |= 0x0001<<PS2_CLK_BIT
}

//=============================================================
//语法格式:	unsigned char PS2_Read(void);
//实现功能:	从PS2设备读取一字节
//参数:		无
//返回值:		读取到的数据
//=============================================================
unsigned char PS2_Read(void)
{
	unsigned short Ret;
	
	if(PS2_StatusCode&PS2_STATUS_DATARDY)        // #define PS2_STATUS_DATARDY	0x0800
	{
		if(PS2_StatusFlag==PS2_READING)         //正在读
			PS2_StatusFlag = PS2_DISABLE;
		Ret = PS2_ReadBuf[PS2_BufPointerR];
		PS2_BufPointerR += 1;
		PS2_StatusCode -= 1;
		if(PS2_BufPointerR==PS2_BUFSIZE)
			PS2_BufPointerR = 0;
		if(PS2_BufPointerR==PS2_BufPointerW)
			PS2_StatusCode &= ~PS2_STATUS_DATARDY;
		if(PS2_StatusFlag==PS2_DISABLE)
			PS2_StatusFlag = PS2_READING;
	}
	else
	{
		Ret = 0x00;
	}
	PS2_StatusCode &= ~PS2_STATUS_READERR;
	return Ret;
}

//=============================================================
//语法格式:	void PS2_ISR_Routine(void);
//实现功能:	Timer(定时5us)中断服务子程序
//参数:		无
//返回值:		无
//=============================================================
void PS2_ISR_Routine(void)
{
	*P_Watchdog_Clear = 0x0001;
	switch(PS2_StatusFlag)
	{
		case PS2_WRITEENABLE:								// 准备输出
			PS2_Counter += 1;
			if(PS2_Counter>=150)                           //750us
			{
				PS2_DAT_Clr();								// 拉低DAT
				PS2_DAT_Output();                           //设置输出
				PS2_CLK_Input();							// 释放CLK
				PS2_DataMask = 0x0001;
				PS2_StatusFlag = PS2_WRITING;				// 状态更新为正在输出
				PS2_Counter = 0x8000;
			}
			break;
		case PS2_WRITING:									// 正在输出
			if((PS2_Counter&0x8000) && (PS2_CLK_Get()==0))	// 发生下降沿
			{
				PS2_Counter	= 0x0000;
				if(PS2_Data & PS2_DataMask)
					PS2_DAT_Set();
				else
					PS2_DAT_Clr();
				PS2_DataMask <<= 1;
			}
			else if(((PS2_Counter&0x8000)==0) && (PS2_CLK_Get()==1))
			{												// 发生上升沿
				PS2_Counter = 0x8000;
				if(PS2_DataMask==0x0400)					// 发送完毕
				{
					PS2_DAT_Input();						// 释放DAT
					PS2_StatusFlag = PS2_WAITACK;
				}
			}
			else
			{
				PS2_Counter += 1;
				if((PS2_Counter&~0x8000)>20000)				// 超时
				{
					PS2_StatusFlag = PS2_WRITEERROR;
					PS2_StatusCode &= ~PS2_STATUS_WRITING;
					PS2_StatusCode |= PS2_STATUS_WRITEERR;
				}
			}
			break;
		case PS2_WAITACK:									// 等待设备响应
			if((PS2_Counter&0x8000) && (PS2_CLK_Get()==0))	// 发生下降沿
			{
				if(PS2_DAT_Get())							// DAT未被拉低则写出错
				{
					PS2_StatusFlag = PS2_WRITEERROR;
					PS2_StatusCode &= ~PS2_STATUS_WRITING;
					PS2_StatusCode |= PS2_STATUS_WRITEERR;
				}
				else
					PS2_Counter = 0x0000;
			}
			else if(((PS2_Counter&0x8000)==0) && (PS2_CLK_Get()==1))
			{												// 发生上升沿
				PS2_Counter = 0x8000;
				PS2_StatusFlag = PS2_WAITACK2;
			}
			else
			{
				PS2_Counter += 1;
				if((PS2_Counter&~0x8000)>4000)				// 响应超时
				{
					PS2_StatusFlag = PS2_WRITEERROR;
					PS2_StatusCode &= ~PS2_STATUS_WRITING;
					PS2_StatusCode |= PS2_STATUS_WRITEERR;
				}
			}
			break;
		case PS2_WAITACK2:
			PS2_Counter += 1;
			if((PS2_Counter&~0x8000)>4000)					// 响应超时
			{
				PS2_StatusFlag = PS2_WRITEERROR;
				PS2_StatusCode &= ~PS2_STATUS_WRITING;
				PS2_StatusCode |= PS2_STATUS_WRITEERR;
			}
			if(PS2_DAT_Get())
			{
				PS2_StatusFlag = PS2_WRITEDONE;
				PS2_StatusCode &= ~PS2_STATUS_WRITING;
			}
			break;
		case PS2_READENABLE:								// 准备输入
		case PS2_WRITEDONE:
		case PS2_WRITEERROR:
		case PS2_READERROR:
		case PS2_READDONE:
			if(!(PS2_StatusCode&PS2_STATUS_BUFFULL))		// 如果Buffer未满
			if(PS2_CLK_Get()==0)							// 发生下降沿
			{
				if(PS2_DAT_Get()==0)						// 得到起始位
				{
					PS2_StatusFlag = PS2_READING;
					PS2_StatusCode |= PS2_STATUS_READING;
					PS2_Counter = 0x0000;
					PS2_DataMask = 0x0001;
					PS2_Data = 0x0000;
				}
				else
				{
					PS2_StatusFlag = PS2_READERROR;
					PS2_StatusCode |= PS2_STATUS_READERR;
				}
			}
			break;
		case PS2_READING:
			if((PS2_Counter&0x8000) && (PS2_CLK_Get()==0))	// 发生下降沿
			{
				PS2_Counter	= 0x0000;
				if(PS2_DAT_Get())
					PS2_Data |= PS2_DataMask;
				PS2_DataMask <<= 1;
			}
			else if(((PS2_Counter&0x8000)==0) && (PS2_CLK_Get()==1))
			{												// 发生上升沿
				PS2_Counter = 0x8000;
				if(PS2_DataMask==0x0400)					// 读完成
				{
					PS2_ReadBuf[PS2_BufPointerW] = PS2_Data&0xff;
					PS2_BufPointerW += 1;
					if(PS2_BufPointerW==PS2_BUFSIZE)
						PS2_BufPointerW = 0;
					if(PS2_BufPointerW==PS2_BufPointerR)
						PS2_StatusCode |= PS2_STATUS_BUFFULL;
					PS2_StatusFlag = PS2_READDONE;
					PS2_StatusCode |= PS2_STATUS_DATARDY;
					PS2_StatusCode += 1;
				}
			}
			else
			{
				PS2_Counter += 1;
				if((PS2_Counter&~0x8000)>4000)				// 超时
				{
					PS2_StatusFlag = PS2_READERROR;
					PS2_StatusCode &= ~PS2_STATUS_READING;
					PS2_StatusCode |= PS2_STATUS_READERR;
				}
			}
			break;
		default:
			break;
	}
}

//=============================================================
//语法格式:	unsigned short PS2_Status(void);
//实现功能:	获取PS2当前状态
//参数:		无
//返回值:		PS2状态代码
//					低8位:				当前接收缓冲区中的字节数
//					PS2_STATUS_IDLE: 	PS2处于空闲状态
//					PS2_STATUS_WRITING:	正在向设备写数据
//					PS2_STATUS_WRITEERR:写数据出错
//					PS2_STATUS_READING:	正在读取数据
//					PS2_STATUS_READERR:	读数据出错
//					PS2_STATUS_DATARDY:	接收缓冲区中有数据
//					PS2_STATUS_BUFFULL:	接收缓冲区已满
//=============================================================
unsigned short PS2_Status(void)
{
	return PS2_StatusCode;
}

//=============================================================
//语法格式:	void PS2_ClearBuf(void);
//实现功能:	清除PS2接收缓冲区
//参数:		无
//返回值:		无
//=============================================================
void PS2_ClearBuf(void)
{
	if(PS2_StatusFlag==PS2_READING)
		PS2_StatusFlag = PS2_DISABLE;
	PS2_BufPointerW = 0;
	PS2_BufPointerR = 0;
	PS2_StatusCode &= ~(PS2_STATUS_BUFFULL|PS2_STATUS_DATARDY|PS2_STATUS_READERR|0xFF);
	if(PS2_StatusFlag==PS2_DISABLE)
		PS2_StatusFlag = PS2_READENABLE;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -