搜索
bottom↓
回复: 13

请问有没有人做过51单片机控制PS/2口条形码扫描器的?

[复制链接]

出0入0汤圆

发表于 2012-8-11 16:51:08 | 显示全部楼层 |阅读模式
新手一个,请教如何通过PS/2口来接受条形码扫描的信息?

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2012-8-11 18:48:26 | 显示全部楼层
各位大神给点反应啊!!

出0入0汤圆

发表于 2012-8-11 22:58:57 | 显示全部楼层
可以实现,和键盘一样的。

刚上电时会发个检测码。

PS2解码的程序很多,搜下吧!

出0入0汤圆

 楼主| 发表于 2012-8-12 09:46:19 | 显示全部楼层
liujinhan 发表于 2012-8-11 22:58
可以实现,和键盘一样的。

刚上电时会发个检测码。

键盘解码一次只是一个字符,但怎么获得扫描器扫描的一串字符呢?

你有没有跟条形扫描器解码相关的c51代码呢?网上基本是键盘跟鼠标的。。。。。

出0入0汤圆

发表于 2012-8-12 14:14:40 | 显示全部楼层
连续解码,不就是一串字符了吗?

扫描枪扫描的速度很快,定义200ms内连续解码。200ms到了,就说明一次扫码完成。

//以下是STM32的程序,改改 51也能用。

void EXTI2_IT_Handle(void)
{
       
        if(EXTI_GetITStatus(EXTI_Line2) != RESET)                                  //判断中断发生来源
          {
                   //EXTI_ClearITPendingBit(EXTI_Line2);    //清除中断标志

                //GPIO_ResetBits(GPIOE,GPIO_Pin_15);        //for debug
               
                #if 1
                PS2CntBusy=PS2_TimeOUT;         // 定时器会将此变量每1ms减1,等于0后通知主程序处理数据
               
                if((IntNum > 0) && (IntNum < 9))
                   {
                        KeyV = KeyV >> 1;                //因键盘数据是低>>高,结合上一句所以右移一位
                        if (Key_Data==1)
                            KeyV = KeyV | 0x80;          //当键盘数据线为1时到最高位
                }
                IntNum++;
               
                //while (!Key_CLK);                //等待PS/2CLK拉高
                while (Key_CLK==0);                //等待PS/2CLK拉高NG if add delayus
                //{
                //        Delay_us(cnt++);
                //        if(cnt>=1000)        break;
                //}
               
                if (IntNum > 10)
                {
                        IntNum = 0;                  //当中断11次后表示一帧数据收完,清变量准备下一次接收

                        PS2_buf[PS2_cnt]=KeyV;                 // 存放到PS2的接收缓冲区去
                           PS2_cnt++;                                     // 指针调整
                           if(PS2_cnt>=100)
                        PS2_cnt=100;       
                        //EA = 0;                      //关中断等显示完后再开中断
                }
                #endif
               
                /* Clear the Key Button EXTI line pending bit */
                    EXTI_ClearITPendingBit(EXTI_Line2);
        }

       
}

出0入0汤圆

 楼主| 发表于 2012-8-12 15:39:51 | 显示全部楼层
好的,谢谢啦

出0入0汤圆

发表于 2012-8-12 23:19:55 来自手机 | 显示全部楼层
前几天看到一个帖子 你找找看吧

出0入0汤圆

 楼主| 发表于 2012-8-14 13:57:18 | 显示全部楼层
gaoyichuan000 发表于 2012-8-12 23:19
前几天看到一个帖子 你找找看吧

找了,好像跟条形码关联的不多,也不是我要的。。。。。

出0入0汤圆

 楼主| 发表于 2012-8-14 14:19:18 | 显示全部楼层
liujinhan 发表于 2012-8-12 14:14
连续解码,不就是一串字符了吗?

扫描枪扫描的速度很快,定义200ms内连续解码。200ms到了,就说明一次扫码 ...

条形码扫描器扫描的时候是扫描到一个数字就像键盘那样有那个数字的通码跟断码输出吗?例如:扫描到第一位数字是6的话,就输出6的通码跟断码(共3个16进制码),假如扫描完一整条共10数的条形码,就得到30个16进制码。

这样理解对吗?

出0入0汤圆

发表于 2012-8-14 21:05:26 | 显示全部楼层
键盘的长度不一样,不都是30个。

第二套扫描码
101 102 和104 键的键盘:

KEY        通码        断码                KEY        通码        断码                KEY        通码        断码
A        1C        F0 1C                9        46        F0 46                [        54        F0 54
B        32        F0 32                `        0E        F0 0E                INSERT        E0 70        E0 F0 70
C        21        F0 21                -        4E        F0 4E                HOME        E0 6C        E0 F0 6C


E0 F0  区别开来就可以了。






转个代码,慢慢看吧。

#include "PS2.h"   
#include "scancode.h"   
//5ms延时   
static unsigned char IntNum = 0; //中断次数计数   
static unsigned char KeyV; //键值   
static unsigned char Key_UP=0, Shift = 0;//Key_UP是键松开标识,Shift是Shift键按下标识   
static unsigned char BF = 0; //标识是否有字符被收到   
static unsigned char PS2_ready = 0; //键盘初始化完毕标志   
static unsigned char LEDS=0; //键盘上灯的状态   
   
void wait_us(unsigned int delay)   
{   
delay=delay*OSC_US;   
while (delay--);   
}   
   
   
void Keyboard_out(void) interrupt 2   
{   
if ((IntNum > 0) && (IntNum  9))   
{   
KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位   
if (Key_Data) KeyV = KeyV | 0x80; //当键盘数据线为1时为1到最高位   
}   
IntNum++;   
while (!Key_CLK); //等待PS/2CLK拉高   
if (IntNum > 10)   
{   
IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收   
BF = 1; //标识有字符输入完了   
EX1 = 0; //关中断等显示完后再开中断 (注:如这里不用BF和关中断直接调Decode()则所Decode中所调用的所有函数要声明为再入函数)   
//PutChar(2,0,KeyV);   
}   
}   
   
void SendKeyCmd(unsigned char cmd){   
bit D0,D1,D2,D3,D4,D5,D6,D7,parity,text1;   
text1=EX1;   
EX1=0;   
      
if (Key_CLK)   
{   
    wait_us(2000);   
    Key_CLK=0;     
    D0=cmd&0x01;D1=cmd&0x02;D2=cmd&0x04;D3=cmd&0x08;   
    D4=cmd&0x10;D5=cmd&0x20;D6=cmd&0x40;D7=cmd&0x80;   
    parity=D0^D1^D2^D3^D4^D5^D6^D7;   
    wait_us(20);   
    Key_Data=0;   
    wait_us(2);   
    Key_CLK=1;   
    while(Key_CLK);   
    Key_Data=D0;    //写D0   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D1;    //写D1   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D2;    //写D2   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D3;    //写D3   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D4;    //写D4   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D5;    //写D5   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D6;    //写D6   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=D7;    //写D7   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=!parity;   //写奇偶校验位   
    while(!Key_CLK);   
    while(Key_CLK);   
    Key_Data=1; //写停止位   
    wait_us(20);   
}   
EX1=text1;   
}   
   
unsigned char Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码   
{   
unsigned char TempCyc,asc=0;   
   
    if (ScanCode==0xAA) PS2_ready=1;   
   
if (!Key_UP) //当键盘松开时   
{   
switch (ScanCode)   
{   
case 0xF0 : // 当收到0xF0,Key_UP置1表示断码开始   
    Key_UP = 1;   
    break;   
   
case 0xFC :   
    asc=0xFC;  //自检失败   
    break;   
   
case 0xEE:   
    asc=0xEE;  //键盘回复   
    break;   
   
case 0x58: //若按下CapsLock   
    LEDS^=KEY_LED_CAPS;   
    SetKeyLED(LEDS);   
    wait_us(2000);   
    break;   
case 0x77: //若按下NumLock   
    LEDS^=KEY_LED_NUM;   
    SetKeyLED(LEDS);   
    wait_us(2000);   
    break;   
case 0x7E: //若按下ScrollLock   
    LEDS^=KEY_LED_SCROLL;   
    SetKeyLED(LEDS);   
    wait_us(2000);   
    break;   
case 0x12 : // 左 SHIFT   
    Shift = 1;   
    asc=0x10;   
    break;   
   
case 0x59 : // 右 SHIFT   
    Shift = 1;   
    asc=0x10;   
    break;   
   
default:   
           for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<26); TempCyc++);   
            if (UnShifted[TempCyc][0] == ScanCode)   
                {   
                if ((((LEDS&KEY_LED_CAPS)>0)&&(!Shift))||(((LEDS&KEY_LED_CAPS)==0)&&(Shift)))    //判断大写     
                        asc=Shifted[TempCyc][1];   
                        else   
                        asc=UnShifted[TempCyc][1];   
                }   
        if (asc==0)   
        {   
            for (TempCyc = 26;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<47); TempCyc++);   //判断shift   
            if (UnShifted[TempCyc][0] == ScanCode)   
                {   
                    if (Shift)   
                        asc=Shifted[TempCyc][1];   
                        else      
                        asc=UnShifted[TempCyc][1];   
                }   
        }   
        if (asc==0)   
        {   
            for (TempCyc = 47;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++);   
            if (UnShifted[TempCyc][0] == ScanCode)   
                {                                                                          //小键盘开关   
                    if ((LEDS&KEY_LED_NUM)>0)   
                        asc=Shifted[TempCyc][1];   
                        else   
                        asc=UnShifted[TempCyc][1];   
                }   
        }   
        if (asc==0)   
        {   
         for(TempCyc = 0; (FuncKey[TempCyc][0]!=ScanCode)&&(TempCyc<34); TempCyc++);   
         if (FuncKey[TempCyc][0] == ScanCode) asc=FuncKey[TempCyc][1];   
        }   
break;   
}   
}   
else   
{   
    Key_UP = 0;   
    switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理   
    {   
        case 0x12 : // 左 SHIFT   
        Shift = 0;   
        break;   
   
        case 0x59 : // 右 SHIFT   
        Shift = 0;   
        break;   
    }   
}   
return asc;   
}   
   
unsigned char KeyInit()   
{   
EX1=1;   
if (BF&&KeyV==0xAA)   
{   
    SetKeyRate(0x1f);   
    //SetKeySet(2);   
    //SetAllKeyType(KEY_TYPE_M);   
    LEDS^=KEY_LED_NUM;   
    SetKeyLED(LEDS);   
    //SendEcho();   
    BF=0;   
    return 1;   
}   
return 0;   
}   
   
bit KeyState()   
{   
    return BF;   
}   
void SetState(bit b)   
{   
    BF=b;   
}   
unsigned char GetCode()   
{   
unsigned char ktmp=KeyV;   
    BF = 0; //标识字符处理完了   
    EX1 = 1;//开键盘中断接收下一数据   
    return ktmp;   
}   
unsigned char LEDState()   
{   
    return LEDS;   
}   
   
void KeyReset()   
{   
    BF=0;   
    ResetKey();   
    EX1=1;   
    LEDS=0;   
}   
unsigned char GetOneKey()   
{   
    unsigned char key;   
    while(1)   
    {   
        if(KeyState())   
        {   
            key=Decode(GetCode());   
            if(key!=0)return key;   
        }   
    }   
}  

出0入0汤圆

发表于 2012-8-15 09:51:43 | 显示全部楼层
http://www.amobbs.com/forum.php? ... 1%E7%A0%81%E6%9E%AA

这个帖子,Pioneermcu  网友,可惜没提供型号,,,,又没时间去深圳买个一样的,

出0入21汤圆

发表于 2012-8-15 10:14:59 | 显示全部楼层
这个要MARK

出0入0汤圆

 楼主| 发表于 2012-8-17 14:58:05 | 显示全部楼层
谢谢各位的帮助,我已经弄出来了

出0入0汤圆

发表于 2012-11-26 10:52:55 | 显示全部楼层
zzzhangxiang 发表于 2012-8-17 14:58
谢谢各位的帮助,我已经弄出来了

我现在也在做单片机连接ps/2口的条码枪,想通过串口输出扫描的数据,用串口小助手检测数据,出来过几次数据 就再也不出现数据了  能帮帮忙吗
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 20:27

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表