|
//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz
#include "STC89C52RC.h"
#include "intrins.h"
#define uchar unsigned char//宏定义无符号字符型
#define uint unsigned int //宏定义无符号整型
typedef unsigned char BYTE;
typedef unsigned int WORD;
#define FOSC 11059200L //系统频率
#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 NONE_PARITY //定义校验位
/*Declare SFR associated with the IAP */
sfr IAP_DATA = 0xE2; //Flash data register
sfr IAP_ADDRH = 0xE3; //Flash address HIGH
sfr IAP_ADDRL = 0xE4; //Flash address LOW
sfr IAP_CMD = 0xE5; //Flash command register
sfr IAP_TRIG = 0xE6; //Flash command trigger
sfr IAP_CONTR = 0xE7; //Flash control register
/*Define ISP/IAP/EEPROM command*/
#define CMD_IDLE 0 //Stand-By
#define CMD_READ 1 //Byte-Read
#define CMD_PROGRAM 2 //Byte-Program
#define CMD_ERASE 3 //Sector-Erase
/*Define ISP/IAP/EEPROM operation const for IAP_CONTR*/
//#define ENABLE_IAP 0x80 //if SYSCLK<40MHz
#define ENABLE_IAP 0x81 //if SYSCLK<20MHz
//#define ENABLE_IAP x82 //if SYSCLK<10MHz
//#define ENABLE_IAP 0x83 //if SYSCLK<5MHz
//Start address for STC89C58xx EEPROM
#define IAP_ADDRESS 0x02000
sbit IN1= P2^0;
sbit IN2= P2^1;
sbit IN3= P2^2;
sbit IN4= P2^3;
sbit out1= P1^0;
sbit out2= P1^1;
sbit out3= P1^2;
sbit out4= P1^3;
bit flagTxd=0,flagFrame=0,flag=0;
unsigned char cntRxd = 0; //接收字节计数器
unsigned char xdata bufRxd[10];
unsigned char xdata qjc[22];
bit k1=0,kt=0;
unsigned char addr=0,addr1=0;
void UartWrite(unsigned char *buf, unsigned char len);
unsigned int GetCRC16(unsigned char *ptr, unsigned char len);
unsigned int crc;
unsigned char crch, crcl;
bit bz1=0,bz2=0,bz3=0,bz4=0,ks=0,bk1=0,bzw=0;
uchar input=0;
uchar xx_1=0x00,xx_2=0x00,xx_3=0x00,xx_4=0x00;
uchar y_1=0x00,y_2=0x00,y_3=0x00,y_4=0x00;
uchar dat1=0x00,dat2=0x00,yy_1=0,zt1=0x00;
uchar dat4=0,dat5=0,dat6=0,dat7=0,dat8=0,dat9=0;
uint js=0;
/********************************************************************
E2P函数
*********************************************************************/
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr, BYTE dat);
void IapEraseSector(WORD addr);
/*******************************************************************
* 配置串口
********************************************************************/
void ConfigUART(unsigned int baud)
{
#if (PARITYBIT == NONE_PARITY)
SCON = 0x50; //8位可变波特率
#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
SCON = 0xda; //9位可变波特率,校验位初始为1
#elif (PARITYBIT == SPACE_PARITY)
SCON = 0xd2; //9位可变波特率,校验位初始为0
#endif
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1为模式2
TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值
TL1 = TH1; //初值等于重载值
ET1 = 0; //禁止T1中断
ES = 1; //使能串口中断
TR1 = 1; //启动T1
// SCON = 0x50; //8位可变波特率
// T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
// T2H = (65536 - (FOSC/4/BAUD))>>8;
// AUXR = 0x14; //T2为1T模式, 并启动定时器2
// AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
}
/*******************************************************************
* 配置定时器
********************************************************************/
void Timer0Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
/*******************************************************************
* 串口检测
********************************************************************/
void UartRxMonitor(unsigned char ms){//串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔
static unsigned char cntbkp = 0;
static unsigned char idletmr = 0;
if (cntRxd > 0){ //接收计数器大于零时,监控总线空闲时间
if (cntbkp != cntRxd){ //接收计数器改变,即刚接收到数据时,清零空闲计时
cntbkp = cntRxd;
idletmr = 0;
}else{ //接收计数器未改变,即总线空闲时,累积空闲时间
if (idletmr < 30){ //空闲计时小于30ms时,持续累加
idletmr += ms;
if (idletmr >= 30){ //空闲时间达到30ms时,即判定为一帧接收完毕
flagFrame = 1; //设置帧接收完成标志
}
}
}
}else{
cntbkp = 0;
}
}
/*******************************************************************
* 串口接收函数
********************************************************************/
void UartDriver(){//串口1接收
unsigned char xdata buf[20];
unsigned char len=0,lenx=0,bz=0,i=0;
if(flagFrame==1)
{
flagFrame=0; //定时器0检测接收的数据
len = cntRxd; //读取接收的字节数量
lenx = cntRxd;
cntRxd = 0; //接收计数器清零
if(bufRxd[0]==addr)
{
crc = GetCRC16(bufRxd, len-2); //计算CRC校验值
crch = crc >> 8;
crcl = crc & 0xFF;
if ((bufRxd[len-2] == crch) && (bufRxd[len-1] == crcl)) //判断CRC校验是否正确
{
switch (bufRxd[1]) //按功能码执行操作
{
case 0x01://读取输出状态
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(out1==0){yy_1=0x01;}else{yy_1=0x00;}break;
case 0x01:if(out2==0){yy_1=0x01;}else{yy_1=0x00;}break;
case 0x02:if(out3==0){yy_1=0x01;}else{yy_1=0x00;}break;
case 0x03:if(out4==0){yy_1=0x01;}else{yy_1=0x00;}break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = yy_1;//输出状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(out1==0){y_1=0x01;}else{y_1=0x00;}
if(out2==0){y_2=0x02;}else{y_2=0x00;}
yy_1=(y_1|y_2);
break;
case 0x01:if(out2==0){y_2=0x01;}else{y_2=0x00;}
if(out3==0){y_3=0x02;}else{y_3=0x00;}
yy_1=(y_2|y_3);
break;
case 0x02:if(out3==0){y_3=0x01;}else{y_3=0x00;}
if(out4==0){y_4=0x02;}else{y_4=0x00;}
yy_1=(y_3|y_4);
break;
case 0x03:if(out4==0){y_4=0x01;}else{y_4=0x00;}
yy_1=y_4;
break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = yy_1;//输出状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x03)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(out1==0){y_1=0x01;}else{y_1=0x00;}
if(out2==0){y_2=0x02;}else{y_2=0x00;}
if(out3==0){y_3=0x04;}else{y_3=0x00;}
yy_1=(y_1|y_2|y_3);
break;
case 0x01:if(out2==0){y_2=0x01;}else{y_2=0x00;}
if(out3==0){y_3=0x02;}else{y_3=0x00;}
if(out4==0){y_4=0x04;}else{y_4=0x00;}
yy_1=(y_2|y_3|y_4);
break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = yy_1;//输出状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x04)&&((len-2)==6))
{
if(out1==0){y_1=0x01;}else{y_1=0x00;}
if(out2==0){y_2=0x02;}else{y_2=0x00;}
if(out3==0){y_3=0x04;}else{y_3=0x00;}
if(out4==0){y_4=0x08;}else{y_4=0x00;}
dat1=(y_1|y_2|y_3|y_4);
buf[0] = addr; //地址位
buf[1] = 0x01; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = dat1;//输出状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x02://查询输入状态
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} dat1=xx_1;break;//查询输入状态打开为1,关闭为0
case 0x01:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;} dat1=xx_2;break;
case 0x02:if(IN3 == 0){xx_3 = 0x01;}else{xx_3 = 0x00;} dat1=xx_3;break;
case 0x03:if(IN4 == 0){xx_4 = 0x01;}else{xx_4 = 0x00;} dat1=xx_4;break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = dat1; //输入状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} //查询输入状态打开为1,关闭为0
if(IN2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}
dat1=(xx_1|xx_2);
break;
case 0x01:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;}
if(IN3 == 0){xx_3 = 0x02;}else{xx_3 = 0x00;}
dat1=(xx_2|xx_3);
break;
case 0x02:if(IN3 == 0){xx_3 = 0x01;}else{xx_3 = 0x00;}
if(IN4 == 0){xx_4 = 0x02;}else{xx_4 = 0x00;}
dat1=(xx_3|xx_4);
break;
case 0x03:if(IN4 == 0){xx_4 = 0x01;}else{xx_4 = 0x00;} dat1=xx_4;break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = dat1; //输入状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x03)&&((len-2)==6))
{
switch(bufRxd[3])
{
case 0x00:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} //查询输入状态打开为1,关闭为0
if(IN2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}
if(IN3 == 0){xx_3 = 0x04;}else{xx_3 = 0x00;}
dat1=(xx_1|xx_2|xx_3);
break;
case 0x01:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;}
if(IN3 == 0){xx_3 = 0x02;}else{xx_3 = 0x00;}
if(IN4 == 0){xx_4 = 0x04;}else{xx_4 = 0x00;}
dat1=(xx_2|xx_3|xx_4);
break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = dat1; //输入状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x04)&&((len-2)==6))
{
if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} //查询输入状态打开为1,关闭为0
if(IN2 == 0){xx_2 = 0x02;}else{xx_2 = 0x00;}
if(IN3 == 0){xx_3 = 0x04;}else{xx_3 = 0x00;}
if(IN4 == 0){xx_4 = 0x08;}else{xx_4 = 0x00;}
dat1=(xx_1|xx_2|xx_3|xx_4);
buf[0] = addr; //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = dat1; //输入状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x03://读取寄存器状态
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01)&&((len-2)==6))//读取2个字节
{
dat5=addr;
buf[0] = addr; //地址位
buf[1] = 0x03; //功能位
buf[2] = 0x02; //数据长度位
buf[3] = dat4;//高
buf[4] = dat5;//低
len = 5;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x04://读取寄存器状态
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x01))//读取2个字节
{
switch(bufRxd[3])
{
case 0x00: dat4=qjc[0];dat5=qjc[1];break;
case 0x01: dat4=qjc[2];dat5=qjc[3];break;
case 0x02: dat4=qjc[4];dat5=qjc[5];break;
case 0x03: dat4=qjc[6];dat5=qjc[7];break;
case 0x04: dat4=qjc[8];dat5=qjc[9];break;
case 0x05: dat4=qjc[10];dat5=qjc[11];break;
case 0x06: dat4=qjc[12];dat5=qjc[13];break;
case 0x07: dat4=qjc[14];dat5=qjc[15];break;
case 0x08: dat4=qjc[16];dat5=qjc[17];break;
case 0x09: dat4=qjc[18];dat5=qjc[19];break;
case 0x0A: dat4=qjc[20];dat5=qjc[21];break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x04; //功能位
buf[2] = 0x02; //数据长度位
buf[3] = dat4;//高
buf[4] = dat5;//低
len = 5;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02))//读取4个字节
{
switch(bufRxd[3])
{
case 0x00: dat4=qjc[0];dat5=qjc[1];dat6=qjc[2];dat7=qjc[3];break;
case 0x01: dat4=qjc[2];dat5=qjc[3];dat6=qjc[4];dat7=qjc[5];break;
case 0x02: dat4=qjc[4];dat5=qjc[5];dat6=qjc[6];dat7=qjc[7];break;
case 0x03: dat4=qjc[6];dat5=qjc[7];dat6=qjc[8];dat7=qjc[9];break;
case 0x04: dat4=qjc[8];dat5=qjc[9];dat6=qjc[10];dat7=qjc[11];break;
case 0x05: dat4=qjc[10];dat5=qjc[11];dat6=qjc[12];dat7=qjc[13];break;
case 0x06: dat4=qjc[12];dat5=qjc[13];dat6=qjc[14];dat7=qjc[15];break;
case 0x07: dat4=qjc[14];dat5=qjc[15];dat6=qjc[16];dat7=qjc[17];break;
case 0x08: dat4=qjc[16];dat5=qjc[17];dat6=qjc[18];dat7=qjc[19];break;
case 0x09: dat4=qjc[18];dat5=qjc[19];dat6=qjc[20];dat7=qjc[21];break;
case 0x0A: dat4=qjc[20];dat5=qjc[21];dat6=0x00;dat7=qjc[22];break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x04; //功能位
buf[2] = 0x04; //数据长度位
buf[3] = dat4;//高
buf[4] = dat5;//低
buf[5] = dat6;//高
buf[6] = dat7;//低
len = 7;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x05://设置单个输出状态
if((bufRxd[2]==0x00)&&(bufRxd[5]==0x00))//输出1
{
if((bufRxd[3]==0x00)&&(bufRxd[4]==0xFF)){out1=0;}//打开第一路输出
if((bufRxd[3]==0x00)&&(bufRxd[4]==0x00)){out1=1;}//关闭第一路输出
if((bufRxd[3]==0x01)&&(bufRxd[4]==0xFF)){out2=0;}//打开第二路输出
if((bufRxd[3]==0x01)&&(bufRxd[4]==0x00)){out2=1;}//关闭第二路输出
if((bufRxd[3]==0x02)&&(bufRxd[4]==0xFF)){out3=0;}//打开第二路输出
if((bufRxd[3]==0x02)&&(bufRxd[4]==0x00)){out3=1;}//关闭第二路输出
if((bufRxd[3]==0x03)&&(bufRxd[4]==0xFF)){out4=0;}//打开第二路输出
if((bufRxd[3]==0x03)&&(bufRxd[4]==0x00)){out4=1;}//关闭第二路输出
buf[0] = addr; //地址位
buf[1] = 0x05; //功能位
buf[2] = 0x00; //线圈地址高
buf[3] = bufRxd[3]; //线圈地址低
buf[4] = bufRxd[4]; //打开FF/关闭00
buf[5] = 0x00;
len = 6;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x06://写单个寄存器
if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00))
{
addr=bufRxd[5];//k1=1;
IapEraseSector(0x2000);
IapProgramByte(0x2001,addr); //写入扇区
buf[0] = addr; //地址位
buf[1] = 0x06; //功能位
buf[2] = bufRxd[2]; //线圈地址高
buf[3] = bufRxd[3]; //线圈地址低
buf[4] = bufRxd[4]; //发什么回什么
buf[5] = bufRxd[5];
len = 6;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x10://写多个寄存器
if((bufRxd[2]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x02)&&(bufRxd[6]==0x04))
{
switch(bufRxd[3])
{
case 0x00: qjc[0]=bufRxd[7];qjc[1]=bufRxd[8];qjc[2]=bufRxd[9];qjc[3]=bufRxd[10];break;
case 0x01: qjc[2]=bufRxd[4];qjc[3]=bufRxd[5];qjc[4]=bufRxd[9];qjc[5]=bufRxd[10];break;
case 0x02: qjc[4]=bufRxd[4];qjc[5]=bufRxd[5];qjc[6]=bufRxd[9];qjc[7]=bufRxd[10];break;
case 0x03: qjc[6]=bufRxd[4];qjc[7]=bufRxd[5];qjc[8]=bufRxd[9];qjc[9]=bufRxd[10];break;
case 0x04: qjc[8]=bufRxd[4];qjc[9]=bufRxd[5];qjc[10]=bufRxd[9];qjc[11]=bufRxd[10];break;
case 0x05: qjc[10]=bufRxd[4];qjc[11]=bufRxd[5];qjc[12]=bufRxd[9];qjc[13]=bufRxd[10];break;
case 0x06: qjc[12]=bufRxd[4];qjc[13]=bufRxd[5];qjc[14]=bufRxd[9];qjc[15]=bufRxd[10];break;
case 0x07: qjc[14]=bufRxd[4];qjc[15]=bufRxd[5];qjc[16]=bufRxd[9];qjc[17]=bufRxd[10];break;
case 0x08: qjc[16]=bufRxd[4];qjc[17]=bufRxd[5];qjc[18]=bufRxd[9];qjc[19]=bufRxd[10];break;
case 0x09: qjc[18]=bufRxd[4];qjc[19]=bufRxd[5];qjc[20]=bufRxd[9];qjc[21]=bufRxd[10];break;
case 0x0A: qjc[20]=bufRxd[4];qjc[21]=bufRxd[5];qjc[22]=bufRxd[10];break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x10; //功能位
buf[2] = bufRxd[2]; //线圈地址高
buf[3] = bufRxd[3]; //线圈地址低
buf[4] = bufRxd[4]; //发什么回什么
buf[5] = bufRxd[5];
len = 6;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
case 0x0F://多路控制
if((bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0x00)&&(bufRxd[5]==0x04)&&(bufRxd[6]==0x01))
{
zt1=bufRxd[7]; //
P1=~zt1;
buf[0] = addr; //地址位
buf[1] = 0x0F; //功能位
buf[2] = bufRxd[2]; //数据长度位
buf[3] = bufRxd[3];
buf[4] = bufRxd[4];
buf[5] = bufRxd[5];
len = 6;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
}
break;
default:break;
}
}
}
if((bufRxd[0]==0xAA)&&(bufRxd[1]==0x00)&&(bufRxd[2]==0x00)&&(bufRxd[3]==0x00)&&(bufRxd[4]==0xBB)&&(len==5))
{
addr1=IapReadByte(0x2001);
buf[0]=0xAA;
buf[1]=addr;
buf[2]=addr1;
buf[3]=0x00;
buf[4]=0xBB;
len=5;
UartWrite(buf, len);//发送其他数据用串口1
}
for(bz=0;bz<lenx;bz++){bufRxd[bz] = 0;} //把串口接收的数据缓存清零
}
}
void senddate()//发送输入状态
{
unsigned char xdata buf[10];
unsigned char len=0;
if((k1==1)&&(bk1==0))
{
bk1=1;
switch(input)
{
case 1:if(IN1 == 0){xx_1 = 0x01;}else{xx_1 = 0x00;} dat1=xx_1;break;//查询输入状态打开为1,关闭为0
case 2:if(IN2 == 0){xx_2 = 0x01;}else{xx_2 = 0x00;} dat1=xx_2;break;
case 3:if(IN3 == 0){xx_3 = 0x01;}else{xx_3 = 0x00;} dat1=xx_3;break;
case 4:if(IN4 == 0){xx_4 = 0x01;}else{xx_4 = 0x00;} dat1=xx_4;break;
default:break;
}
buf[0] = addr; //地址位
buf[1] = 0x02; //功能位
buf[2] = 0x01; //数据长度位
buf[3] = dat1; //输入状态2进制表示有输入为1,没输入为0
len = 4;
crc = GetCRC16(buf, len); //计算CRC校验值
buf[len++] = crc >> 8; //CRC高字节
buf[len++] = crc & 0xFF; //CRC低字节
UartWrite(buf, len);//发送其他数据用串口1
k1=0;
ks=1;
}
if(bzw==1){bzw=0;bk1=0;}//消抖延时后清零
}
/*******************************************************************
* 主函数
********************************************************************/
void main()
{
P1=0XFF;
ES = 1; //使能串口1中断
EA = 1;
ConfigUART(9600);
Timer0Init();
if(IapReadByte(0x2001)==0xff){addr=0x01;}//首次读取,如果读到0xFF说明没有存过数据,直接付给00值
else
{
addr=IapReadByte(0x2001);
}
while(1)
{
if((IN1==0)&&(bz1==0)){bz1=1;k1=1;input=1;}
if((IN1==1)&&(bz1==1)){bz1=0;k1=1;input=1;}
if((IN2==0)&&(bz2==0)){bz2=1;k1=1;input=2;}
if((IN2==1)&&(bz2==1)){bz2=0;k1=1;input=2;}
if((IN3==0)&&(bz3==0)){bz3=1;k1=1;input=3;}
if((IN3==1)&&(bz3==1)){bz3=0;k1=1;input=3;}
if((IN4==0)&&(bz4==0)){bz4=1;k1=1;input=4;}
if((IN4==1)&&(bz4==1)){bz4=0;k1=1;input=4;}
senddate();
UartDriver();
// if(k1==1)
// {
// IapEraseSector(0x08000);
// IapProgramByte(0x08001,addr); //写入扇区
// k1=0;
// }
}
}
void InterruptTimer0() interrupt 1{//T0中断服务函数,执行串口接收监控
TL0 = 0xCD; //设置定时初值
TH0 = 0xD4;
if(ks==1){js++;if(js==150){js=0;bzw=1;ks=0;}}
UartRxMonitor(1); //串口接收监
}
/*******************************************************************
* 串口中断
********************************************************************/
void Uart() interrupt 4 using 1
{
if (RI)
{
RI = 0; //清除RI位
ACC=SBUF;
if(P==RB8){flag=1;}else{flag=0;}
if (cntRxd < sizeof(bufRxd)) {//接收缓冲区尚未用完时,保存接收字节,并递增计数器
bufRxd[cntRxd++] = SBUF; // cntRxd++这个很重要,一开始 cntRxd < sizeof(bufRxd)当进入函数的次数增加,cntRxd慢慢变大,当传入的数据不满的时候就 用时间检测,判断是否是传输完成
}
}
if (TI)
{
TI = 0; //清除TI位
flagTxd = 1;
}
}
/*******************************************************************
* 串口发送函数
********************************************************************/
void UartWrite(unsigned char *buf, unsigned char len){//串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度
while (len--){ //循环发送所有字节
flagTxd = 0; //清零发送标志
ACC = *buf;
if (P) //根据P来设置校验位
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 0; //设置校验位为0
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 1; //设置校验位为1
#endif
}
else
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 1; //设置校验位为1
#elif (PARITYBIT == EVEN_PARITY)
TB8 = 0; //设置校验位为0
#endif
}
SBUF = ACC; //发送一个字节数据
buf++;
while (!flagTxd); //等待该字节发送完成
}
}
/*----------------------------
Disable ISP/IAP/EEPROM function
Make MCU in a safe state
----------------------------*/
void IapIdle()
{
IAP_CONTR = 0; //Close IAP function
IAP_CMD = 0; //Clear command to standby
IAP_TRIG = 0; //Clear trigger register
IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area
IAP_ADDRL = 0; //Clear IAP address to prevent misuse
}
/*----------------------------
Read one byte from ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
Output:Flash data
----------------------------*/
BYTE IapReadByte(WORD addr)
{
BYTE dat; //Data buffer
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_READ; //Set ISP/IAP/EEPROM READ command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
dat = IAP_DATA; //Read ISP/IAP/EEPROM data
IapIdle(); //Close ISP/IAP/EEPROM function
return dat; //Return Flash data
}
/*----------------------------
Program one byte to ISP/IAP/EEPROM area
Input: addr (ISP/IAP/EEPROM address)
dat (ISP/IAP/EEPROM data)
Output:-
----------------------------*/
void IapProgramByte(WORD addr, BYTE dat)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_DATA = dat; //Write ISP/IAP/EEPROM data
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}
/*----------------------------
Erase one sector area
Input: addr (ISP/IAP/EEPROM address)
Output:-
----------------------------*/
void IapEraseSector(WORD addr)
{
IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time
IAP_CMD = CMD_ERASE; //Set ISP/IAP/EEPROM ERASE command
IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low
IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high
IAP_TRIG = 0x46; //Send trigger command1 (0x46)
IAP_TRIG = 0xb9; //Send trigger command2 (0xb9)
_nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete
IapIdle();
}
/********************************************************************
结束
*********************************************************************/
|
|