📄 ps2_drv.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 + -