打印

用16F677与四线电阻触摸屏构成的PS2键盘

[复制链接]
1868|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 LBQ691477940 于 2013-4-27 00:03 编辑

公司的AOI检测机台原来是用电脑键盘来进行查看图片的但是由于PC键盘没有限时功能即可以猛按键盘使图片翻的很快;
担心工人没认真看不良品的图片,所以将下翻按键加上延时使工人有足够的时间来查看对比良品与不良品的图片。
PC键盘经常按也不耐用,考虑用电子开关代替机械开关,之前搭了一个人体触摸的电路来代替按键但是由于工人
带了静电手套使起来不理想,就拿公司产品中次品LCD上的电阻触屏代替,老玩51单片机不新鲜,最近喜欢上PIC单片机拿它折腾下,刚开始玩PIC单片机程序写得......但是可以实现想要的功能。
/********************************************************************************
                                        使用16F677与四线电阻触摸屏构成的PS2键盘

使用IC内部4MHZ振荡
IC Pin17        接指示灯
IC Pin11        接驱动有源蜂鸣器
IC Pin16         接X+(触屏Pin1)加一个300K电阻到VCC
IC Pin15        接Y+(触屏Pin3)加一个300K电阻到VCC
IC Pin14        接X-(触屏Pin2)
IC Pin13         接Y-(触屏Pin4)
IC Pin3         接USB TO PS2的CLOCK加一个10K电阻到VCC
IC Pin2         接USB TO PS2的DATA加一个10K电阻到VCC

本程序共处理4个触摸按键用软件分为上下左右各二个共四个按键
其中一个按键未用于发送PS2键码
另三个分别为PC的空格键、上一页键、下一页键
下一页键有延时触摸才发送键码的功能
下图为产品上的废板,就是想用其上面的CPU懒得焊所以直接在上面引线



仿真文件 PIC16F677_XY.rar (33.02 KB)

程序编辑:红尘有你                QQ:691477940                2013-04-20
/********************************************************************************/
#include <pic.h>              //包含PIC头文件
__CONFIG(0x30E4);         //芯片配置字        //内部振荡 RA4/RA5作 I/O口用

#define uchar unsigned char
#define uint unsigned int
/********************************************************************************/
#define PS2CLK        RA4                //Pin3
#define PS2DAT        RA5                //Pin2
uchar num,k0 = 1;
/********************************************************************************/
void delayUS(uchar i)//延时子函数
{
     while(--i);
}
/********************************************************************************/
void delayMS(uchar a)
{
        do
        {
                delayUS(199);
        }
        while(--a);
}
/********************************************************************************/
void BEEP(uchar di)
{
        for(;di > 0;di--)
        {
                RB6 = 1;
                delayMS(150);
                RB6 = 0;
                delayMS(50);
        }
}
/********************************************************************************/
uint get_ad(uchar ch)        //AD采样函数ch为通道AN0/AN1
{
        uint adval;
        if(!ch)
        {
                TRISC0 = 1;                //设为入
                TRISC2 = 1;                //设为入
                TRISC1 = 0;                //设为输出供触屏
                TRISB4 = 0;                //设为输出供触屏
                RC1 = 1;                //输出-正电源
                RB4 = 0;                //输出-相当于接地
                ADCON0 = 0x91;        //右对齐 /参考电压VDD / 通道RA0
                //ADCON0 = 0x01;        //左对齐 /参考电压VDD / 通道RA0
        }
        else if(ch)
        {
                TRISC1 = 1;                //设为入
                TRISB4 = 1;                //设为入
                TRISC0 = 0;                //设为输出供触屏
                TRISC2 = 0;                //设为输出供触屏
                RC0 = 1;                //输出-正电源
                RC2 = 0;                //输出-相当于接地
                ADCON0 = 0x95;        //右对齐 /参考电压VDD / 通道RA1
                //ADCON0 = 0x15;        //左对齐 /参考电压VDD / 通道RA1
        }
        //ADCON1 = 0x10;                //采样速率为Fosc/8
        ADCS0 = 1;                                //采样速率为Fosc/8
        delayMS(1);
        GO_DONE = 1;
        while(GO_DONE);
        adval = ADRESH;
        //adval =(adval << 2) + (ADRESL >> 6);//左对齐时使用
        adval = adval << 8 | ADRESL;        //右对齐时使用
        return (adval);        
}
/*******************************************************************************/
#define N 10
uint ADC_filter(uchar ch) //算术平均滤波法
{
        uint sum = 0;        //如果N定义值小于13时sum可要定义为int型
        //unsigned long sum = 0;        //如果N定义值大于13时sum要定义为long型
        float advalf;
        uchar count;
        for(count = 0;count < N;count++)
        {
                sum += get_ad(ch);
        }
        advalf = sum / 1023.0 * 5.0;        //5.0为参考基准电压值
        sum = advalf * 1000;
        return (uint)(sum / N);
}
/********************************************************************************/        
uchar CheckSum(uchar dat)        //求奇偶,偶数个1时返回0x01
{
        uchar temp,i;
        for (temp = 0,i = 0; i < 8;i++)
        {
            temp += (dat & 0x01);
                dat >>= 1;
        }
        temp += 1;                //如果上面前8次循环结果为1再加1则变为2以0x01相于则为0
                                        //如果上面前8次循环结果为0再加1则变为1以0x01相于则为1
        temp &= 0x01;        //求奇偶校验和,偶数个1为1
        return temp;
}
/********************************************************************************/        
void send_char(uchar send_data)//PS2键盘码发送函数
{                                
        uchar i;
        uchar checksum;                //奇偶校验位
        checksum = CheckSum(send_data);  //奇偶校验位
        TRISA |= 0x30;                //将二个端口设为输入
        PORTA |= 0x30;                //将二个端口置高
        while(!PS2CLK)                //CLK为低说明PC正忙,故在此等待
                delayUS(10);        //延时5~20uS 不能小于5uS或大于25uS //等待主机释放抑制
        if(!PS2DAT)
                return;                        //主机要发送数据(可跳到从主机读取字节的程序中)
        delayUS(20);                //延时20~40uS
/********************************************************************************/
        TRISA &= 0xCF;        //将二个端口设为输出
        PS2DAT = 0;                //发送起始位总是为0
        delayUS(10);        //延时5~20uS 不能小于5uS或大于25uS
        PS2CLK = 0;                //发送起始位
        delayUS(20);        //延时20~40uS
        PS2CLK = 1;                //发送起始位
        delayUS(10);        //延时5~20uS 不能小于5uS或大于25uS
        PS2DAT = 1;                //释放PS2DAT口
/********************************************************************************/               
        for(i = 0;i < 8;i++)                //发送8位数据
        {
                if(send_data & 0x01)        //先发送低位,判断最低位是否为1
                        PS2DAT = 1;
                else
                        PS2DAT = 0;
                delayUS(10);                        //延时5~20uS 不能小于5uS或大于25uS
                send_data >>= 1;
                delayUS(10);                        //延时5~20uS 不能小于5uS或大于25uS
                PS2CLK = 0;
                delayUS(20);                        //延时20~40uS
                PS2CLK = 1;
                delayUS(10);                        //延时5~20uS 不能小于5uS或大于25uS                        
        }
/********************************************************************************/                                
        PS2DAT = checksum;                         //发送奇偶校验位
        delayUS(10);                                //延时5~20uS 不能小于5uS或大于25uS
        PS2CLK = 0;                                        //发送校验位
        delayUS(20);                                //延时20~40uS        //发送校验位
        PS2CLK = 1;                                        //发送校验位
        delayUS(10);                                //延时5~20uS 不能小于5uS或大于25uS
        PS2DAT = 1;                                        //释放PS2DAT口
/********************************************************************************/               
        PS2DAT = 1;                                        //发送停止位总是为1
        delayUS(10);                                //延时5~20uS 不能小于5uS或大于25uS
        PS2CLK = 0;                                        //发送停止位
        delayUS(20);                                //延时20~40uS        //发送停止位
        PS2CLK = 1;                                        //释放PS2CLK口
}
/********************************************************************************/
void interrupt time1()        //定时器中断服务函数
{
        TMR1IF = 0;                        //清除定时器溢出标志
        TMR1H = (65536 - 50000) / 256;//重装50ms定时器1初值
        TMR1L = (65536 - 50000) % 256;//重装50ms定时器1初值         //4Mhz
        num++;
        if(num == 5)        //50mS x 10=0.5S
        {
                k0 = 1;
                num = 0;
                RA2 = !RA2;
        }               
}
/********************************************************************************/
#define XY_MAX        4400

#define K13Y_MAX 4300
#define K13Y_MIN 2500

#define K12X_MAX 2100
#define K12X_MIN 450
/********************/
#define K24Y_MAX 2000
#define K24Y_MIN 450
/********************/
#define K34X_MAX 4380
#define K34X_MIN 2400
/********************************************************************************/
void main()//主函数
{   
        uint X,Y;
        TRISA = TRISB = TRISC = ANSEL = ANSELH = 0x00;
        RB6 = 0;
        k0 = 1;
        OSCCON = 0xEE;//选择内部4Mhz振荡 0xEE
/********************************************************************************/
        INTCON = 0xC0;
        PIE1 = 0x01;
        TMR1L = (65536 - 50000) % 256;//50ms定时器1初值
        TMR1H = (65536 - 50000) / 256;//50ms定时器1初值
        T1CON = 0x04;        //关闭定时器1
        
/********************************************************************************/
        while(1)
        {
/********************************************************************************/               
                X = ADC_filter(0); //算术平均滤波法
                Y = ADC_filter(1); //算术平均滤波法
/********************************   k1        *****************************************/
                if(((Y <= K13Y_MAX) && (Y >= K13Y_MIN)) && ((X <= K12X_MAX) && (X >= K12X_MIN)))
                {
                        delayMS(5);
                        X = ADC_filter(0); //算术平均滤波法
                        Y = ADC_filter(1); //算术平均滤波法
                        if(((Y <= K13Y_MAX) && (Y >= K13Y_MIN)) && ((X <= K12X_MAX) && (X >= K12X_MIN)))
                        {
                                BEEP(1);
                                RA2 = 0;
                                TMR1ON = 0;
                                do
                                {
                                        X = ADC_filter(0); //算术平均滤波法
                                        Y = ADC_filter(1); //算术平均滤波法
                                }
                                while((X < XY_MAX) && (Y < XY_MAX));//等待触屏松手
                        }
                }
/********************************   k2        *****************************************/
                else if(((Y <= K24Y_MAX) && (Y >= K24Y_MIN)) && ((X <= K12X_MAX) && (X >= K12X_MIN)))
                {
                        delayMS(5);
                        X = ADC_filter(0); //算术平均滤波法
                        Y = ADC_filter(1); //算术平均滤波法
                        if(((Y <= K24Y_MAX) && (Y >= K24Y_MIN)) && ((X <= K12X_MAX) && (X >= K12X_MIN)))
                        {
                                //BEEP(2);                                
                                /*************************************************/
                                send_char(0x29);                //发送SPACE键通码
                                send_char(0xf0);                //发送SPACE键断码
                                send_char(0x29);                //发送SPACE键断码
                                /*************************************************/
                                do
                                {
                                        X = ADC_filter(0); //算术平均滤波法
                                        Y = ADC_filter(1); //算术平均滤波法
                                }
                                while((X < XY_MAX) && (Y < XY_MAX));//等待触屏松手
                        }
                }
/********************************   k3        *****************************************/
                else if(((Y <= K13Y_MAX) && (Y >= K13Y_MIN)) && ((X <= K34X_MAX) && (X >= K34X_MIN)))
                {
                        delayMS(5);
                        X = ADC_filter(0); //算术平均滤波法
                        Y = ADC_filter(1); //算术平均滤波法
                        if(((Y <= K13Y_MAX) && (Y >= K13Y_MIN)) && ((X <= K34X_MAX) && (X >= K34X_MIN)))
                        {
                                //BEEP(3);
                                /*************************************************/
                                send_char(0xe0);                        //发送PgUp键断码
                                send_char(0x7d);                        //发送PgUp键断码
                                send_char(0xe0);                        //发送PgUp键断码
                                send_char(0xf0);                        //发送PgUp键断码        
                                send_char(0x7d);                        //发送PgUp键断码
                                /*************************************************/
                                do
                                {
                                        X = ADC_filter(0); //算术平均滤波法
                                        Y = ADC_filter(1); //算术平均滤波法
                                }
                                while((X < XY_MAX) && (Y < XY_MAX));//等待触屏松手
                        }
                }
/********************************   k4        *****************************************/
                else if(((Y <= K24Y_MAX) && (Y >= K24Y_MIN)) && ((X <= K34X_MAX) && (X >= K34X_MIN))&& k0)
                {
                        delayMS(5);
                        X = ADC_filter(0); //算术平均滤波法
                        Y = ADC_filter(1); //算术平均滤波法
                        if(((Y <= K24Y_MAX) && (Y >= K24Y_MIN)) && ((X <= K34X_MAX) && (X >= K34X_MIN))&& k0)
                        {
                                //BEEP(4);
                                /*************************************************/
                                k0 = num = 0;
                                TMR1L = (65536 - 50000) % 256;//50ms定时器1初值
                                TMR1H = (65536 - 50000) / 256;//50ms定时器1初值
                                send_char(0xe0);                        //发送pgdn键通码
                                send_char(0x7a);                        //发送pgdn键通码
                                send_char(0xe0);                        //发送pgdn键断码
                                send_char(0xf0);                        //发送pgdn键断码        
                                send_char(0x7a);                        //发送pgdn键断码
                                /*************************************************/
                                do
                                {
                                        X = ADC_filter(0); //算术平均滤波法
                                        Y = ADC_filter(1); //算术平均滤波法
                                }
                                while((X < XY_MAX) && (Y < XY_MAX));//等待触屏松手
                                TMR1ON = 1;                //开启定时器1
                        }
                }
        }
}        
/********************************************************************************/

评分
参与人数 1威望 +3 收起 理由
ZG11211 + 3 赞一个!
沙发
弓长月月鸟| | 2013-4-27 09:10 | 只看该作者
不错,支持一下。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

13

帖子

1

粉丝