/*****************************生产线数据采集器***************************/
/*****按键扫描、串口通信*****/
#include<reg51.h>
#include<stdio.h>
#define GREEN 5 //通信成功指示灯, 灯一直亮;
#define YELLOW 6 //通信失败指示灯, 灯闪烁;
#define START_VAL 0x55 //起始位码 转化为十进制公式 (0xaa/16)*16+0xaa%16
#define MAC_ID 0x01 //机器编码
#define END_VAL 0xAA //结束位码
bit flag_ok = 0;
//unsigned char pro_id[7] = {0x00,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
unsigned char pro_id[7] = {'0','A','B','C','D','E','f'};
unsigned char r[8] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //判断按键是否按下的值
unsigned char pro_no=0,key_val=0,key=0,key1=0,ver_val=0;
signed char send_data[29]={0};
/****************串口初始化,11.0592M,波特率9600b/s,方式3**********/
void inituart(void)
{
SCON = 0x50; //串行口工作方式3,SM2=0,REN = 1;
PCON = 0x00;
TMOD = 0x20; //定时器T1 ,工作方式2
TH1 = 0xFD; //装入初值(波特率9600)
TL1 = 0xFD;
ET1=0; //禁止定时器T1中断,因为T1用作波特率发生器
TR1 = 1; //启动T1
ES = 1; //串口开中断
EA = 1; //全局开中断
}
//void delay1s(void)//12M晶振,延时999999.00us
//{
// unsigned char i,j,k;
// for(i=46;i>0;i--)
// for(j=152;j>0;j--)
// for(k=70;k>0;k--);
//}
void delay50us(unsigned int i)
{
unsigned char j;
for(;i>0;i--)
for(j=19;j>0;j--) ;
}
/********指示灯键扫描**********/
void led_up(unsigned char up_val)
{
// P1 = r[(up_val-1)%4+4]; //行
// P2 = r[(up_val-1)/4]; //列
P0 = r[up_val];
}
void led_twink(unsigned char twink_val)
{
P0 = r[twink_val];
delay50us(1600);
P0 = 0xff;
}
/************** 扫描按键****************/
unsigned char key_scan()
{
unsigned char a=0,b=0,i,j,k=0;
bit get_back = 0;
while(get_back==0)
{
for(i=0;i<=7;i++)
{
if(P1==r)
{
delay50us(1000); //20ms去抖*6
if(P1==r)
{
a=i;
P2 = 0xff;
P1 = 0x0;
break ;
}
}
}
for(j=0;j<=3;j++)
{
if(P2==r[j])
{
delay50us(1000); //20ms去抖*6
if(P2==r[j])
{
b=j;
P1 = 0xff;
P2 = 0x0;
get_back = 1;
break ;
}
}
}
}
k = 4*a + b + 1;
a = 0;
b = 0;
return k;
}
void key_get(signed char send_tmp[29]) //用数组来封装通信协议,行为产品信息。列为采集数据;
{
bit rekey;
unsigned char pro_type,v;
if(key_val > 0)
{
if((0<key_val) && (key_val<25))
{
if((pro_no>0)&&(pro_no<7)&&(send_tmp[2] == pro_type))
{
if((0<key1) && (key1<25))
{
send_tmp[key1+2] = send_tmp[key1+2] + 0x01; //输入不良类型信息
key1 =0;
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //校验码
ver_val = 0;
}
key = key_val;
P0 = 0xfd;
delay50us(500);
P0 = 0xdf;
key_val = 0;
while(1) //判断下一按键值
{
key_val = key_scan();
if((0<key_val) && (key_val<25))
{
send_tmp[key+2] = send_tmp[key+2] + 0x01; //输入不良类型信息
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //更新校验码
ver_val = 0;
key = 0;
key1 = key_val;
key_val = 0;
P0 = 0xfd;
delay50us(500);
P0 = 0xdf;
break;
}
else
{
key1 = key;
key = 0;
break;
}
}
}
}
if((24<key_val) && (key_val<31)) //产品信息
{
pro_no = key_val-25 + 1;
pro_type = pro_id[pro_no];
if((send_tmp[2] == pro_type)||(send_tmp[2] == 0))
{
send_tmp[2] = pro_type; //输入产品类型信息
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //更新校验码
ver_val = 0;
key_val=0;
}
else //换另一种产品时 ,等待上衣产品发送成功,才录入;
{
if((0<key1) && (key1<25)) //取得上一种产品的最后一件不良品数
{
send_tmp[key1+2] = send_tmp[key1+2] + 0x01; //输入不良类型信息
key1 =0;
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //校验码
ver_val = 0;
P0 = 0xfd;
delay50us(500);
P0 = 0xdf;
}
while(1)
{
led_twink(YELLOW);
if(send_tmp[2] == send_tmp[27]) //当更换产品时,产品类型值可以改变
{
send_tmp[2] = pro_type; //输入产品类型信息
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //校验码
ver_val = 0;
led_up(GREEN);
break;
}
}
}
P0 = 0xbf;
delay50us(500);
P0 = 0xdf;
}
if((key_val == 31) && (key1 > 0)) //回滚上一次数据(如果要回滚前几次数据,需要多次记录按键值)
{
key1 =0;
key_val=0;
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //更新校验码
P0 = 0x7f;
delay50us(500);
P0 = 0xdf;
}
if(key_val == 32) // 暂停,锁定键盘
{
if((0<key1) && (key1<25))
{
send_tmp[key1+2] = send_tmp[key1+2] + 0x01; //输入不良类型信息
key1 =0;
for(v=2;v<27;v++)
{
ver_val = ver_val + send_tmp[v];
}
send_tmp[27] = ver_val; //校验码
ver_val = 0;
}
rekey = 1;
key_val = 0;
while(1)
{
key_val = key_scan();
if((key_val == 32) && (rekey == 1)) //再按此键,解锁按键
{
rekey = 0;
key_val=0;
break ;
}
}
}
}
else
{
key_val = 0;
led_up(GREEN);
key_val = key_scan();
}
}
//调试用keyval为24(P0.5&P1.3)和28(P0.6&P1.3),及31(P0.7&P1.2)和32(P0.7&P1.3)。
/******等待发送*****/
void send_wait()
{
while(TI == 0);
TI = 0;
}
/******等待接收*****/
void receive_wait()
{
while(RI == 0);
RI = 0;
}
void main(void)
{
P0 = 0xff;
P1 = 0xff;
P2 = 0x00;; //系统初始化,开机自检、自诊断程序,机器不能带病工作(可用跑马灯的实验来测试);
inituart();
led_up(GREEN); //串口初始化
while(1)
{
key_get(send_data);
}
}
/**********串行口中断之接收数据*************/
/***********串行口中断之发送数据*****************/
void serial_int(void) interrupt 4 using 1 //表明使用串行口中断,第一组寄存器
{
unsigned char b,resend_cmd,flag_no; //resend_cmd为是否重发的命令
// unsigned char *send_data = send_tmp;
flag_no = 0; //Flag_no为重发的次数
/*****与上位机进行通信*****/
if(RI)
{
RI = 0;
if(SBUF!=0x55) //判断第一字节是否为起始码(55)
return ;
receive_wait();
if(SBUF != MAC_ID) //判断第二字节是否本机地址(1)
{
// SM2 = 1;
return ;
}
SM2 = 0;
receive_wait();
resend_cmd = SBUF; //判断第三字节是发送还是重传(00/01)
receive_wait();
if(SBUF!=0xAA) //判断第四字节是否为结束码(AA),加状态机结束接收标识
return ;
switch(resend_cmd)
{
case 0x00: //发送
for(b=0;b<29;b++)
{
send_data[0] = START_VAL;
send_data[1] = MAC_ID;
send_data[28] = END_VAL;
// ACC = send_data;
// TB8 = P;
// delay50us(100); //20ms去抖*6
SBUF = send_data;
send_wait();
}
// led_up(YELLOW);
break;
case 0x01: //重传,重传三次后还不成功,发出警报;
flag_no++;
for(b=0;b<29;b++)
{
send_data[0] = START_VAL;
send_data[1] = MAC_ID;
send_data[28] = END_VAL;
// ACC = send_data;
// TB8 = P;
// delay50us(100); //20ms去抖*6
SBUF = send_data;
send_wait();
}
if(flag_no >= 4)
{
led_twink(YELLOW);
return;
//break 是跳出循环
//return 是跳到循环开始处继续执行
}
else
{
led_up(GREEN);
flag_no = 0;
break;
}
case 0x02: //表示发送成功;
for(b=3;b<27;b++)
{
send_data = 0;
}
for(b=2;b<27;b++)
{
ver_val = ver_val + send_data;
}
send_data[27] = ver_val; //校验码
ver_val = 0;
led_up(GREEN);
// SM2 = 1;
break;
default: //若是非法命令,则返回
return ;
break;
}
}
else //发送中断
{
}
}
/*******把本机地址和当前状态回发给主机。设置如果需要,还可以设
置在工作空闲时或定时自检程序(送帧:数组str[]={aa,01,01,55})********/
|