#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); } }