本帖最后由 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
}
}
}
}
/********************************************************************************/
|