/*****************************生產(chǎn)線數(shù)據(jù)采集器***************************/
/*****按鍵掃描、串口通信*****/
#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用作波特率發(fā)生器
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]) //用數(shù)組來封裝通信協(xié)議,行為產(chǎn)品信息。列為采集數(shù)據(jù);
{
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)) //產(chǎn)品信息
{
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; //輸入產(chǎn)品類型信息
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 //換另一種產(chǎn)品時 ,等待上衣產(chǎn)品發(fā)送成功,才錄入;
{
if((0<key1) && (key1<25)) //取得上一種產(chǎn)品的最后一件不良品數(shù)
{
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]) //當更換產(chǎn)品時,產(chǎn)品類型值可以改變
{
send_tmp[2] = pro_type; //輸入產(chǎn)品類型信息
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)) //回滾上一次數(shù)據(jù)(如果要回滾前幾次數(shù)據(jù),需要多次記錄按鍵值)
{
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();
}
}
//調(diào)試用keyval為24(P0.5&P1.3)和28(P0.6&P1.3),及31(P0.7&P1.2)和32(P0.7&P1.3)。
/******等待發(fā)送*****/
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;; //系統(tǒng)初始化,開機自檢、自診斷程序,機器不能帶病工作(可用跑馬燈的實驗來測試);
inituart();
led_up(GREEN); //串口初始化
while(1)
{
key_get(send_data);
}
}
/**********串行口中斷之接收數(shù)據(jù)*************/
/***********串行口中斷之發(fā)送數(shù)據(jù)*****************/
void serial_int(void) interrupt 4 using 1 //表明使用串行口中斷,第一組寄存器
{
unsigned char b,resend_cmd,flag_no; //resend_cmd為是否重發(fā)的命令
// unsigned char *send_data = send_tmp;
flag_no = 0; //Flag_no為重發(fā)的次數(shù)
/*****與上位機進行通信*****/
if(RI)
{
RI = 0;
if(SBUF!=0x55) //判斷第一字節(jié)是否為起始碼(55)
return ;
receive_wait();
if(SBUF != MAC_ID) //判斷第二字節(jié)是否本機地址(1)
{
// SM2 = 1;
return ;
}
SM2 = 0;
receive_wait();
resend_cmd = SBUF; //判斷第三字節(jié)是發(fā)送還是重傳(00/01)
receive_wait();
if(SBUF!=0xAA) //判斷第四字節(jié)是否為結束碼(AA),加狀態(tài)機結束接收標識
return ;
switch(resend_cmd)
{
case 0x00: //發(fā)送
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: //重傳,重傳三次后還不成功,發(fā)出警報;
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 是跳出循環(huán)
//return 是跳到循環(huán)開始處繼續(xù)執(zhí)行
}
else
{
led_up(GREEN);
flag_no = 0;
break;
}
case 0x02: //表示發(fā)送成功;
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 //發(fā)送中斷
{
}
}
/*******把本機地址和當前狀態(tài)回發(fā)給主機。設置如果需要,還可以設
置在工作空閑時或定時自檢程序(送幀:數(shù)組str[]={aa,01,01,55})********/
|