/*************************************
STC15W201S 仅有T0 T2两个定时器,仅有一个串口
*************************************/
//#include <reg52.h>
#include "STC15Fxxxx.H"
/******************************************/
sbit P_LED = P1^3; //LED闪烁输出
// STC15F101W 1K flash,128 SRAM
/*************IO 配置************
M1 M0
0 0 准双向口
0 1 推挽输出
1 0 高阻输入
1 1 开漏
****************************/
/**********30MHZ****1T***********/
/*******************************************
38K 时,在30MHZ 1T模式下,计时次数26.3us--对应789.47,分解成低电平263次,高电平526次
IO 输出低电平红外发射
//#define T1MS (65536-FOSC/1000) //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式
********************************************/
/****************************************
1Hz下,1/4时间量,3/4时间不亮,以节约电能
T0计时,12T模式 每10毫秒中断一次
******************************************/
#define LEDT_TH 0x9E
#define LEDT_TL 0x58
#define LEDLMAX 10//25 //250毫秒亮
#define LEDHMAX 250//75 //750毫秒不亮
/*******************串口相关*****************************/
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define FOSC 30000000L //系统频率 30M
#define BAUD 9600 //串口波特率
#define NONE_PARITY 0 //无校验
#define ODD_PARITY 1 //奇校验
#define EVEN_PARITY 2 //偶校验
#define MARK_PARITY 3 //标记校验
#define SPACE_PARITY 4 //空白校验
//#define PARITYBIT EVEN_PARITY //定义校验位
#define PARITYBIT NONE_PARITY //定义校验位
#define S1_S0 0x40 //P_SW1.6
#define S1_S1 0x80 //P_SW1.7
bit busy;
void SendData(BYTE dat);
void SendString(char *s);
/*volatile unsigned char bdata COM1flag;
sbit Fs1Rbufempty = COM1flag^0;
sbit Fs1Rbufffull = COM1flag^1;
sbit Fs1Rstart = COM1flag^2;
sbit Fs1Rdofinish = COM1flag^3;*/
/*************led灯处理*****************/
volatile unsigned char ledTimeNum;
void do_led(void);
/****************io中断处理控制************************/
sbit P_first = P3^2; //INT0 进
sbit P_last = P3^3; //INT1 出
volatile unsigned char bdata iovalue;
volatile unsigned char iovaluereadbk,iovaluebefore,iovaluereadnum; //为防止干扰,定为读4次,机40毫秒的数据保持,否则认定为干扰
bit ioupdateflag; //数据有变化,则更新标志
/*************数据处理*****************/
#define IOOUTMAX 16
//volatile unsigned char iobuf[IOOUTMAX]={2,3,1,0,1,3,2,0,3,2,0};
volatile unsigned char iobuf[IOOUTMAX];
volatile unsigned char iohead,iotail;//=11;
//unsigned char iobufdo[IOOUTMAX]; //将数据处理用
bit iofullflag; //0 数据已经满了 ;1 则为空
#define DIRECTION_MANIN 0x01//0x02 //人进去的区分
#define DIRECTION_MANOUT 0x02//0x01 //人出来的区分
unsigned char judgenum,judgeStart,judgemiddle,judgerear,judgeresult; //数据判断用
bit judgesomeone,judgesomeonefinishi; //门口中间有人标志
/************************************
2 3 1 0 进的正常流程 1 3 2 0,出的正常流程 现在判断规,出现非零50毫秒,就认为有人,再判断人是出来还是进去,0后第一个数字,作为
方向参考,主要是判断3后的数据,如果为3后的数据,与第一个相等,则是退出,不增减人数,在0之前的数据是2,则是出,是1,则是进,如果3后为0,则以3之前的为参考,
**********************************/
/**************串口处理**********************/
unsigned char comsendbuf[5];
unsigned char comseq;
volatile unsigned short comsendtime;
bit comsendflag;
#define COMMAN_IN 0xaa //人进去了
#define COMMAN_OUT 0xbb //人出来了
#define COMMAN_MIDDLE 0xcc //人在中间
#define COMMAN_NONE 0xdd //人不在中间了
//包头 序号 状态 累加和 结束符
//unsigned char const code man_insbuf[5] = {0x5a,0xB0,0xB0,0xB0,0xa5};
#define COMQUERY_IO 0x01 //上位机下发的查询命令,查询当前IO状态
unsigned char comrecievenum; //接收判断,如果连续收到5个0xB0,则取消有人状态
#define CHAR_HEADID 0x5a //开始状态
#define CHAR_TAILID 0xa5 //结束状态
volatile unsigned char comrecivetime;
bit comRflag; //串口收到了回复数据
unsigned char comrecivebuf[5];
/*************数据缓冲区发送**********************/
void Sendbuf(unsigned char *pbuf,unsigned char dataNum);
/*************** 主函数**************************/
#define Inc_Addr(Addr,BufSize) { Addr++; if(Addr >= BufSize) { Addr = 0; } }
#define Add_Addr(Addr,Num,BufSize) { Addr +=Num; if(Addr >= BufSize) { Addr -= BufSize; } }
/************获取已经得到的数据量 ************/
unsigned char getIObuf(void){
unsigned char templen;
if(iofullflag){
templen=IOOUTMAX;
}
else{
if(iotail>=iohead) {
templen= iotail- iohead;
}
else{
templen= IOOUTMAX- iohead;
templen = templen + iotail;
}
}
return templen;
}
/**************清空判断用数据缓冲**************************/
void clearjudgeman(void){
judgenum=0;
judgeStart=0;
judgemiddle=0;
judgerear=0;
judgeresult=0;
judgesomeone=0;
//judgesomeonefinishi=0;
}
/***************组串口包******************************/
void makesendpacket(unsigned char devtype){
comseq++;
comsendbuf[0]=0x5a;
comsendbuf[1]=comseq;
comsendbuf[2]=devtype;
comsendbuf[3]=comsendbuf[0]+comsendbuf[1]+comsendbuf[2];
comsendbuf[4]=0xa5;
Sendbuf(comsendbuf,5);
comsendflag=1;
comsendtime=0;
}
/**************************/
/*void doceshi(void){
unsigned char tempdolen,tempiovalue;
tempdolen= getIObuf();
if(0!=tempdolen){
SendData(tempdolen);
tempiovalue=iobuf[iohead];
SendData(tempiovalue);
Inc_Addr(iohead,IOOUTMAX);
}
} */
/*********串口发送处理***********************/
void docomprocess(void){
unsigned char tempdolen,tempiovalue;
tempdolen= getIObuf();
if(0==tempdolen){
if(judgesomeone){ //80毫秒
judgesomeone=0; //发送有人的数据
if(0==judgesomeonefinishi){
makesendpacket(COMMAN_MIDDLE);
judgesomeonefinishi=1;
}
}
else{
;
}
return;
}
tempiovalue=iobuf[iohead];
Inc_Addr(iohead,IOOUTMAX);
iofullflag=0; //清除
/* tempi=tempiovalue&0xfb;
if(tempi){ //数据异常,丢弃
return;
} */
switch(judgenum){
case 0: //判断开始
if(tempiovalue){
judgesomeone=1;
if(3==tempiovalue){
judgeStart=0xff; //未知值
judgenum=2; //
}
else{
judgenum=1;
judgeStart=tempiovalue; //初始值
}
}
break;
case 1:
if(0==tempiovalue) {
makesendpacket(COMMAN_NONE);
judgesomeonefinishi=0;
clearjudgeman();
}
else if(3==tempiovalue){
judgesomeone=1;
judgemiddle=3;
judgenum=2;
}
else{ //异常数据,不处理
judgesomeone=1;
judgenum=1; //继续等待
}
break;
case 2: //经过了中间的两级红外
if(3==tempiovalue){
judgesomeone=1;
judgenum=2; //等待红外有所变化
}
else if(0==tempiovalue){ // 3后直接为0,则
makesendpacket(COMMAN_NONE);//串口发送,中间无人
judgesomeonefinishi=0;
clearjudgeman(); //开始下一轮判断
}
else{
judgerear= tempiovalue;
judgesomeone=1; //有人
judgenum=3;
}
break;
case 3:
if(0==tempiovalue){ //
if(DIRECTION_MANIN==judgerear){ //
if(judgeStart==judgerear){
makesendpacket(COMMAN_NONE); //进去了又退出来了
}
else{
makesendpacket(COMMAN_IN); //串口发送 人出来了
}
}
else if(DIRECTION_MANOUT==judgerear){
if(judgeStart==judgerear){
makesendpacket(COMMAN_NONE); //串口发送 人出来了
}
else{
makesendpacket(COMMAN_OUT);//串口发送 人进去了
}
}
else if(0==judgerear){
makesendpacket(COMMAN_NONE);//串口发送,中间无人
}
judgesomeonefinishi=0;
clearjudgeman(); //开始下一轮判断
}
else if(3==tempiovalue){
judgesomeone=1;
judgerear= tempiovalue;
judgenum=2; //有人
}
else{ //继续等待,直到0退出
judgesomeo