/***********************************************************************************************************/
//hc-sr04 超声波测距模块DEMO程序
//晶振:11。0592
//接线:模块TRIG接 P0.2ECH0 接P0.1
//数码管:共阳数码管P1接数据口,P2.5 P2.4 P2.3接选通数码管
/***********************************************************************************************************/
#include //器件配置文件
#include
#define uchar unsigned char
#define uint unsigned int
unsigned inttime=0;
unsigned inttimer=0;
unsigned char posit=0;
unsigned long S=0,S1,S2;
bit flag =0;
sbitTX123=P3^4; //T
sbitRX123=P3^5; //E
sbitKJA=P3^6; //近距离存储按钮
sbitKJAN=P3^7; //远距离存储按钮
sbitS1J=P3^3; //近距离动作继电器
sbitS2J=P3^2; //远距离动作继电器
unsigned char const discode[] ={ 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0xff/*-*/};
unsigned char const positon[3]={ 0xdf,0xef,0xf7};
unsigned char disbuff[4]={ 0,0,0,0,};
/******************定义命令字节******************/
#define Read_COM 0x01 //字节读数据命令
#define Prog_COM 0x02//字节编程数据命令
#define Erase_COM 0x03 //扇区擦除数据命令
#define En_Wait_TIME 0x81//设置等待时间 ,并使能ISP/IAP
#define Start_ADDRH 0x20//扇区地址高位
#define Start_ADDRL 0x00//扇区地址低位
/****************特殊功能寄存器声明****************/
sfr ISP_DATA = 0xe2;
sfr ISP_ADDRH = 0xe3;
sfr ISP_ADDRL = 0xe4;
sfr ISP_CMD = 0xe5;
sfr ISP_TRIG = 0xe6;
sfr ISP_CONTR = 0xe7;
/*****************关闭ISP&IAP功能*****************/
void ISP_IAP_disable(void)
{
ISP_CONTR = 0x00;
ISP_CMD = 0x00;
ISP_TRIG = 0x00;
}
/*********************字节读**********************/
uchar Byte_read(uint byte_addr)
{
EA = 0; //关中断
ISP_CONTR = En_Wait_TIME; //开启ISP&IAP,并送等待时间
ISP_CMD = Read_COM; //送字节读命令字
ISP_ADDRH = (uchar)(byte_addr >> 8); //送地址高字节
ISP_ADDRL = (uchar)(byte_addr & 0x00ff); //送地址低字节
ISP_TRIG = 0x46;//送触发命令字0x46
ISP_TRIG = 0xB9;//送触发命令字0xB9
_nop_();
ISP_IAP_disable(); //关闭ISP&IAP功能
EA = 1; //开中断
return (ISP_DATA);
}
/*********************字节编程*********************/
void Byte_program(uint byte_addr,uchar isp_iap_data)
{
EA = 0; //关中断
ISP_CONTR = En_Wait_TIME; //开启ISP&IAP,并送等待时间
ISP_CMD = Prog_COM; //送字节编程命令字
ISP_ADDRH = (uchar)(byte_addr >> 8); //送地址高字节
ISP_ADDRL = (uchar)(byte_addr & 0x00ff); //送地址低字节
ISP_DATA = isp_iap_data;//送数据进ISP_DATA
ISP_TRIG = 0x46;//送触发命令字0x46
ISP_TRIG = 0xB9;//送触发命令字0xB9
_nop_();
ISP_IAP_disable(); //关闭ISP&IAP功能
EA = 1; //开中断
}
/*********************扇区擦除*********************/
void Sector_erase(uint sector_addr)
{
EA = 0; //关中断
ISP_CONTR = En_Wait_TIME; //开启ISP&IAP;并送等待时间
ISP_CMD = Erase_COM; //送扇区擦除命令字
ISP_ADDRH = (uchar)(sector_addr >> 8); //送地址高字节
ISP_ADDRL = (uchar)(sector_addr & 0X00FF); //送地址低字节
ISP_TRIG = 0X46;//送触发命令字0x46
ISP_TRIG = 0XB9;//送触发命令字0xB9
_nop_();
ISP_IAP_disable(); //关闭ISP&IAP功能
EA = 1;
}
/********************************************************/
void Display(void) //扫描数码管
{
if(posit==0)
{P1=(discode[disbuff[posit]])&0x7f;}
else
{P2=discode[disbuff[2]];
P0=discode[disbuff[1]];}
if(++posit>=3)
posit=0;
}
/********************************************************/
void Conut(void)
{
time=TH0*256+TL0;
TH0=0;
TL0=0;
S=(time*1.7)/100; //算出来是CM
if((S>=250)||flag==1) //超出测量范围显示“-”
{
flag=0;
S=250;
}
else
{
disbuff[0]=S%1000/100;
disbuff[1]=S%1000%100/10;
disbuff[2]=S%1000%10 %10;
}
}
/********************************************************/
void zd0() interrupt 1//T0中断用来计数器溢出,超过测距范围
{
flag=1; //中断溢出标志
}
/********************************************************/
voidzd3()interrupt 3//T1中断用来扫描数码管和计800MS启动模块
{
TH1=0xfc;
TL1=0x30;
Display();
timer++;
if(timer>=400) //调节测速频率
{
timer=0;
TX123=1; //800MS启动一次模块
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
TX123=0;
}
}
/*****************************************************************************
*延时子程序 *
* *
******************************************************************************/
void delay(unsigned int ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
/*********************************************************/
voidmain(void)
{
S1J=0;
delay(1000);
S1J=1;
TMOD=0x11; //设T0为方式1,GATE=1;
TH0=0;
TL0=0;
TH1=0xf8; //2MS定时
TL1=0x30;
ET0=1;//允许T0中断
ET1=1; //允许T1中断
TR1=1; //开启定时器
EA=1; //开启总中断
S1=Byte_read(0x2000);
S2=Byte_read(0x2200); //读EEPROM
disbuff[0]=S1%1000/100;
disbuff[1]=S1%1000%100/10;
disbuff[2]=S1%1000%10 %10;
Display();
delay(1000);
disbuff[0]=S2%1000/100;
disbuff[1]=S2%1000%100/10;
disbuff[2]=S2%1000%10 %10;
Display();
delay(1000);
while(1)
{
while(!RX123);//当RX为零时等待
TR0=1;//开启计数
while(RX123); //当RX为1计数并等待
TR0=0;//关闭计数
Conut(); //计算
if(!KJA){Sector_erase(0x2000); //扇区擦除
Byte_program(0x2000,S); //写EEPROM
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
S1=Byte_read(0x2000); }
if(!KJAN){Sector_erase(0x2200); //扇区擦除
Byte_program(0x2200,S); //写EEPROM
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
S2=Byte_read(0x2200); }
if(S>=S1)S1J=0;
else S1J=1;
}
}