#include "STC89.h"
#include "intrins.h"
#include "process.h"
#define CycleTime_Ultrasonic 10
#define TR_Ultrasonic TR0
#define TH_Ultrasonic TH0
#define TL_Ultrasonic TL0
#define ET_Ultrasonic ET0
#define TMOD_Ultrasonic TMOD
sbit FrontTrig=P2^2;
sbit FrontEcho=P3^2;//accord to the selected timer, timer 0-->P32 timer 1--->P33
void InitDistance(void);
float GetDistance(void);
void StartCheckDistance(void);
#define AddWr 0x90 //写数据地址 PCF8591 bit321为地址A0 A1 A2
#define AddRd 0x91 //读数据地址 PCF8591
sbit SDA_PCF8591=P2^6;
sbit SCL_PCF8591=P2^7;
unsigned char ReadADC(unsigned char Chl);
unsigned char SysTime;
unsigned char SoundAdc;
unsigned int LedShowData;
unsigned char NumToShow=6;
unsigned int DistanceData;
sbit Key0=P0^4;
unsigned char OldKey0,DisMode=0;
void InitTimer2(void)
{
T2MOD = 0;
T2CON = 0;
RCAP2H = 0xFC;
RCAP2L = 0x17;
EA=1; //总中断打开
ET2=1; //定时器T2允许中断
TR2=1; //定时器T2开始工作
}
void et2(void) interrupt 5 using 0
{
TF2=0;
SysTime++;
}
bit ack; //应答标志位
/*------------------------------------------------
启动总线
------------------------------------------------*/
void Start_I2c()
{
SDA_PCF8591=1; //发送起始条件的数据信号
_nop_();
SCL_PCF8591=1;
_nop_(); //起始条件建立时间大于4.7us,延时
_nop_();
_nop_();
_nop_();
_nop_();
SDA_PCF8591=0; //发送起始信号
_nop_(); //起始条件锁定时间大于4μ
_nop_();
_nop_();
_nop_();
_nop_();
SCL_PCF8591=0; //钳住I2C总线,准备发送或接收数据
_nop_();
_nop_();
}
/*------------------------------------------------
结束总线
------------------------------------------------*/
void Stop_I2c()
{
SDA_PCF8591=0; //发送结束条件的数据信号
_nop_(); //发送结束条件的时钟信号
SCL_PCF8591=1; //结束条件建立时间大于4μ
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SDA_PCF8591=1; //发送I2C总线结束信号
_nop_();
_nop_();
_nop_();
_nop_();
}
/*----------------------------------------------------------------
字节数据传送函数
函数原型: void SendByte(unsigned char c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0 假)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
------------------------------------------------------------------*/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((c<<BitCnt)&0x80)SDA_PCF8591=1; //判断发送位
else SDA_PCF8591=0;
_nop_();
SCL_PCF8591=1; //置时钟线为高,通知被控器开始接收数据位
_nop_();
_nop_(); //保证时钟高电平周期大于4μ
_nop_();
_nop_();
_nop_();
SCL_PCF8591=0;
}
_nop_();
_nop_();
SDA_PCF8591=1; //8位发送完后释放数据线,准备接收应答位
_nop_();
_nop_();
SCL_PCF8591=1;
_nop_();
_nop_();
_nop_();
if(SDA_PCF8591==1)ack=0;
else ack=1; //判断是否接收到应答信号
SCL_PCF8591=0;
_nop_();
_nop_();
}
/*----------------------------------------------------------------
字节数据传送函数
函数原型: unsigned char RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
------------------------------------------------------------------*/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA_PCF8591=1; //置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_nop_();
SCL_PCF8591=0; //置时钟线为低,准备接收数据位
_nop_();
_nop_(); //时钟低电平周期大于4.7us
_nop_();
_nop_();
_nop_();
SCL_PCF8591=1; //置时钟线为高使数据线上数据有效
_nop_();
_nop_();
retc=retc<<1;
if(SDA_PCF8591==1)retc=retc+1; //读数据位,接收的数据位放入retc中
_nop_();
_nop_();
}
SCL_PCF8591=0;
_nop_();
_nop_();
return(retc);
}
/*----------------------------------------------------------------
非应答子函数
原型: void NoAck_I2c(void);
----------------------------------------------------------------*/
void NoAck_I2c(void)
{
SDA_PCF8591=1;
_nop_();
_nop_();
_nop_();
SCL_PCF8591=1;
_nop_();
_nop_(); //时钟低电平周期大于4μ
_nop_();
_nop_();
_nop_();
SCL_PCF8591=0; //清时钟线,钳住I2C总线以便继续接收
_nop_();
_nop_();
}
/*------------------------------------------------
读AD转值程序
输入参数 Chl 表示需要转换的通道,范围从0-3
返回值范围0-255
------------------------------------------------*/
unsigned char ReadADC(unsigned char Chl)
{
unsigned char Val;
Start_I2c(); //启动总线
SendByte(AddWr); //发送器件地址
if(ack==0)return(0);
SendByte(0x00|Chl); //发送器件子地址
if(ack==0)return(0);
Start_I2c();
SendByte(AddRd);
if(ack==0)return(0);
Val=RcvByte();
NoAck_I2c(); //发送非应位
Stop_I2c(); //结束总线
Start_I2c();
SendByte(AddRd);
if(ack==0)return(0);
Val=RcvByte();
NoAck_I2c(); //发送非应位
Stop_I2c(); //结束总线
return(Val);
}
void InitDistance(void) //使用EX0口
{
TMOD_Ultrasonic |= 0x09;//打开GATE0 内部时钟计数模式
ET_Ultrasonic=0;
FrontTrig = 0;
}
void Delay(void)
{
unsigned i=10;
while(i--)
_nop_( );
}
void StartCheckDistance(void)
{
FrontTrig = 1;
TH_Ultrasonic = 0;
TL_Ultrasonic = 0;
Delay();
TR_Ultrasonic=1;
FrontTrig = 0;
}
float GetDistance(void)//always return value ,unit:mm
{
static unsigned char DisTestStep,DisDelayTime;
unsigned int FrontTime;
static float DistanceData=0;
switch(DisTestStep)
{
case 0:
{
StartCheckDistance();
DisTestStep = 1;
break;
}
case 1:
{
DisDelayTime++;
if(DisDelayTime >= 30/CycleTime_Ultrasonic)
{
DisDelayTime = 0;
DisTestStep = 2;
}
break;
}
case 2:
{
TR0 = 0;
FrontTime = TH_Ultrasonic;
FrontTime = FrontTime<<8;
FrontTime = FrontTime+TL_Ultrasonic;
DistanceData = FrontTime;
DistanceData = DistanceData*0.17;
DisTestStep = 3;
break;
}
case 3:
{
DisDelayTime++;
if(DisDelayTime >= 300/CycleTime_Ultrasonic)
{
DisDelayTime = 0;
DisTestStep = 0;
}
break;
}
}
return DistanceData;
}
main()
{
InitTimer2();
//InitSci();
InitDistance();
for(;;)
{
StartPro(0);
SoundAdc = ReadADC(3);
DistanceData = GetDistance();
if((OldKey0==0)&&(Key0==1))
{
DisMode = ~DisMode;
}
OldKey0 = Key0;
if(DisMode == 0)
{
P25 = 0;
if(DistanceData < 200)
{
NumToShow = 0;
}
else if(DistanceData > 800)
{
NumToShow = 12;
}
else
{
NumToShow = (DistanceData-200)/50;
}
}
else
{
P25 = 1;
if(SoundAdc < 62)
{
NumToShow = 0;
}
else if(SoundAdc > 110)
{
NumToShow = 12;
}
else
{
NumToShow = (SoundAdc-62)>>2;
}
}
LedShowData = (0x0FFF>>NumToShow);
P36 = LedShowData>>11;
P35 = LedShowData>>10;
P34 = LedShowData>>9;
P33 = LedShowData>>8;
P10 = LedShowData>>7;
P11 = LedShowData>>6;
P12 = LedShowData>>5;
P13 = LedShowData>>4;
P14 = LedShowData>>3;
P15 = LedShowData>>2;
P16 = LedShowData>>1;
P17 = LedShowData;
EndPro(10);
}
}