历史上的今天
返回首页

历史上的今天

今天是:2025年02月03日(星期一)

2020年02月03日 | MSP430学习笔记9-PS2键盘解码

2020-02-03 来源:elecfans

    PS2键盘解码的基本原理是通过外部中断读取键盘输出的串行信号,在根据扫描码进行查表解码。键盘发送往主机的信号总是在时钟的下降沿因此此中断是在下降沿触发,且时钟信号是由键盘给出,因此使用P1口中断(已经在初始化端口时设置)。发送的数据位11位,第一位是起始位,总为0,紧接是8个数据位,然后是奇校验位,最后是停止位总为1.


    本程序只能对基本按键(即键被按下时产生三个字节的扫描码的按键)做出解码,包括所有的可显示字符键和Table,Back Space和Ente三个特殊功能键。基本按键的扫描码由三个字节组成,第1个字节为接通码,第2、3字节为断开码;其中第1字节和第3字节相同,中间字节为断开标志0xf0。例如:通码和断码是以什么样的序列发送到你的计算机使得字符G 出现在你的字处理软件里呢?因为这是一个大写字母需要发生这样的事件次序按下Shift 键按下G 键释放G 键释放Shift 键,与这些时间相关的扫描码如下:Shift 键的通码12h G键的通码34h G 键的断码F0h 34h Shift 键的断码F0h 12h 因此发送到你的计算机的数据应该是12h 34h F0h 34h F0h 12h如果按键按着不放会连续发送通码命令,可以连续显示字符(没有验证,实验验证是可以的)。


    具体的说明都已经在程序中做了注释,主程序,中断服务函数中读取键盘发送的值:

/*****************************************************

程序功能:接收并解码来自标准键盘的基本按键的扫描码

然后在1602液晶上显示。按Back Space键可以前向删除显

示字符,按Space键可以后向删除显示字符。


-----------------------------------------------------

将拨码开关的SN74LVC2454和LCD位拨至ON

读取键盘的信号需要电平转换,注意设置SN74LVC2454的转换方向

跳线设置:将跳线座J13的B8脚和P1.7脚短接

-----------------------------------------------------

测试说明:敲定标准键盘上的按键,观察液晶显示

*****************************************************/

#include 

#include "cry1602.h"

#include "cry1602.C"

#include "PS2Keyboard.h"

#include "PS2Keyboard.C"


#define SIDval  P5IN & BIT6

#define BufferSize  32      //显示缓存大小

unsigned char bitcount=11;          //位计数变量

unsigned char kb_buffer[BufferSize];    //显示缓存

unsigned char input=0;       //数据压入缓存位置指针

unsigned char output=0;      //数据弹出缓存位置指针   

unsigned char pebit=0xff;    //奇偶校验标志位

unsigned char recdata=0;     //接收到的数据

unsigned char tishi[]={"this is a demo!"};


/****************主函数****************/

void main(void)

{

    uchar disptmp,i;

    uchar x = 0,y = 0;

    uchar first = 1;

    

    WDTCTL = WDTPW + WDTHOLD;       //关闭看门狗

    P6DIR |= BIT2;P6OUT &= ~BIT2;   //打开电平转换

    P2DIR |= BIT3;P2OUT |= BIT3;    //方向5V-->3.3V

    /*------选择系统主时钟为8MHz-------*/

    BCSCTL1 &= ~XT2OFF;                 // 打开XT2高频晶体振荡器

    do

    {

        IFG1 &= ~OFIFG;                 //清除晶振失败标志

        for (i = 0xFF; i > 0; i--);     //等待8MHz晶体起振

    }

    while ((IFG1 & OFIFG));             // 晶振失效标志仍然存在?

    BCSCTL2 |= SELM_2;                  //主时钟选择高频晶振

    

    LcdReset();                 //复位液晶

    DispNchar(0,0,15,tishi);    //液晶显示提示信息

    Init_KB();                  //初始化键盘端口

    _EINT();                    //打开全局中断

  

    while(1)

    {

        LPM3;                   //进入低功耗模式

        

        if(first)

        {

            first = 0;

            LcdWriteCommand(0x01, 1);   //显示清屏

            LcdWriteCommand(0x0f, 1);   //打开游标

        }

        

        disptmp = GetChar();    //读取键值对应的ASCII码

        if(disptmp != 0xff)     //取出了一个有效字符

        {

            if(disptmp == 8) //如果是退格键

            {

                if((x == 0) && (y == 0))//如果游标在第1行第1位

                {

                    x = 15;

                    y = 1;

                    Disp1Char(x,y,0x20); //0x20是空格的ASCII码

                    LocateXY(x,y);

                }

                else if((x == 0) && (y == 1))//如果游标在第2行第1位

                {

                    x = 15;

                    y = 0;

                    Disp1Char(x,y,0x20); 

                    LocateXY(x,y);

                }

                else

                {

                    Disp1Char(--x,y,0x20); 

                    LocateXY(x,y);

                }

            }

            else if((disptmp == 9) || (disptmp == 13)) //如果是Table键或Enter键

            {

                _NOP();   

            }

            else    //其余字符显示

            {

                Disp1Char(x++,y,disptmp);

                if(x == 16)           //如果一行显示完毕

                {

                    x = 0;

                    y ^= 1;

                    LocateXY(x,y);  //重新定位游标位置

                }

            }

        }

    }

}


/*******************************************

函数名称:PORT1_ISR 

功    能:P1端口的中断服务函数,在这里接收来

          自键盘的字符


说明:键盘发送往主机的信号总是在时钟的下降沿

因此此中断是在下降沿触发,且时钟信号是由键盘

给出,因此使用P1口中断(已经在初始化端口时

设置)。发送的数据位11位,第一位是起始位,总

为0,紧接是8个数据位,然后是奇校验位,最后是

停止位总为1.

参    数:无

返回值  :无

********************************************/

#pragma vector=PORT1_VECTOR

__interrupt void  PORT1_ISR(void)

{

    if(P1IFG & BIT7)            //如果是clock的中断

    {

        P1IFG &=~ BIT7;         //清除中断标志 

        

        if(bitcount == 11)        //接收第1位

        {

            if(SIDval)          //起始位总为0如果是1就不是起始位

                return;         //返回

            else  

                bitcount--;     //是起始位就接着接收下一位,进行计数

        } 

        else if(bitcount == 2)    //接收奇偶校验位

        {   

            if(SIDval)          //如果校验位等于1

                pebit = 1;      //这个程序中只是对校验位进行读取,正确与否并为做判断

            else

                pebit = 0;

            bitcount--;

        }

        else if(bitcount == 1)    //接收停止位

        {

            if(SIDval)          //若停止位正确

            {

                bitcount = 11;    //复位位计数变量

                if( Decode(recdata) )    //解码获得此键值的ASCII值并保存

                    LPM3_EXIT;           //退出低功耗模式

                recdata = 0;          //清除接收数据

            }

            else                //如果出错

            {

                bitcount = 11;

                recdata = 0;    

            }

        }

        else                    //接收8个数据位

        {

            recdata >>= 1;

            if(SIDval)  recdata |= 0x80;

            bitcount--;

        }

   }

}


解码程序PS2Keyboard.C:

#include

#include "PS2Keyboardcode.h"


#define BufferSize  32

extern uchar kb_buffer[BufferSize];

extern uchar input;

extern uchar output;

extern uchar flag;

/*******************************************

函数名称:PushBuff

功    能:将一个字符压入显示缓存,如果缓存以

          满则覆盖前面的数据

参    数:c--要显示的字符

返回值  :无

********************************************/

推荐阅读

史海拾趣

问答坊 | AI 解惑

不错的单片机模拟软件

对于学习51单片机系列的模拟有很好的实现方式,有很好的学习效果…

查看全部问答>

射频关键性设计教程

射频关键性设计教程…

查看全部问答>

group box 问题

我用的wm5.0 对话框里放置groupbox, 里面添加了几个控件 但是运行起来的时候,只能看见groupbox,里面的控件看不到? 请问时怎么回事?…

查看全部问答>

wince调用webservice问题

用一块2410板子上的wince系统调用webservice必须要板子和电脑联网吗?利用usb连接是否可以?怎样才能配置板子上的wince的ip使得wince与pc可以相互ping通?求救!!!…

查看全部问答>

让GPRS模块智能化,嵌入应用更轻松

让GPRS模块智能化,嵌入应用更轻松     目前GPRS模块供应商,各自提供自己的标准品, 面对不同行业应用,用户必须自己编写软件来 使用通信功能。这要求用户必须熟悉GSM通信, 可能需要更改原有产品设计,用户需要反复调试, 延长产 ...…

查看全部问答>

CE6 Camera 应用程序

平台:WINCE6.0+S3C6410    camera 驱动已写好,用BSP里面的CameraDshowApp.exe,能正常地进行120x160、320x240、 640x480进行预览, 但是现在用了某家开发板的camera App DEMO,能用120x160进行预览,但是当调到640x480进行预览,就出现 ...…

查看全部问答>

lwIP的TCP client在资料接收问题?

使用8962範例专案enet_lwip中加入tcp client,使mcu能连接到PC端的tcp listener. 已测试可正常连线至pc,接通时发送6个byte至pc端去,如下程式码:static err_tTcpClient_Connected(void *arg, struct tcp_pcb *pcb, err_t err){unsigned char bb[ ...…

查看全部问答>

关于MDK支持unicode码的问题

应用MDK 执行代码char *test="汉字"后,test内的内容为“汉字”的AnsiCode内码:BABAD7D6 我希望test内的内容是“汉字”的UniCode内码:496C575B 请问应该如何设置?…

查看全部问答>

TI DSP部门处理器分类法

德州仪器 (TI) 为各种应用(包括基于 ARM® 的微处理器 (ARM MPU) 和数字信号处理器 (DSP))的开发提供了广泛的嵌入式处理器平台。 请浏览我们的选择指南以选择适合您的应用开发的器件。    * Sitara™ ARM 微处理器  ...…

查看全部问答>

请问大家现在都用什么PCB制图软件?altium designer有msp430库么?

请问大家现在都用什么PCB制图软件?altium designer现在比例怎样?altium designer有msp430的sch和pcb的封装库么?谢谢…

查看全部问答>