#include <STC12C5A.h> //包括一个51标准内核的头文件
#include "intrins.h"
#define uchar unsigned char //定义一下方便使用
#define uint unsigned int
#define ulong unsigned long
#define NULL 0
//********管脚定义
sbit Trig = P3^3; //产生脉冲引脚
sbit Echo = P3^2; //回波引脚
sbit test = P0^0; //测试用引脚,灯表示超声波有无测距
sbit HC595_SCK = P0^4;
sbit HC595_RCK = P0^5;
sbit HC595_RST = P0^6;
sbit HC595_DAT = P0^7;
sbit beep=P1^3;
//********变量定义
/***数字编码表0~9***/
unsigned char const seg[10] = {0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; //段选
unsigned char const position[]={1,2,4,8}; //位选
uint distance[4]; //测距接收缓冲区
uchar temp,flag,outcomeH,outcomeL,i,k; //自定义寄存器
bit succeed_flag; //测量成功标志
uint b; //b定义为全局变量
unsigned char Count=0;
/************************************************************************
音乐编码存储区
**************************************************************************/
unsigned char const code SONG[] ={ //祝你平安
0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x10,0x20,0x10,0x20,0x80,0x26,
0x20,0x30,0x20,0x30,0x20,0x39,0x10,0x30,0x10,0x30,0x80,0x26,0x0,
0x20,0x20,0x20,0x20,0x1c,0x20,0x20,0x80,0x2b,0x20,0x26,0x20,0x20,
0x20,0x2b,0x10,0x26,0x10,0x2b,0x80,0x26,0x20,0x30,0x20,0x30,0x20,
0x39,0x10,0x26,0x10,0x26,0x60,0x40,0x10,0x39,0x10,0x26,0x20,0x30,
0x20,0x30,0x20,0x39,0x10,0x6,0x10,0x26,0x80,0x26,0x20,0x2b,0x10,
0x2b,0x10,0x2b,0x20,0x30,0x10,0x39,0x10,0x26,0x10,0x2b,0x10,0x2b,
0x20,0x2b,0x40,0x40,0x20,0x20,0x10,0x20,0x10,0x2b,0x10,0x26,0x30,
0x30,0x80,0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,0x40,0x26,
0x20,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,0x20,0x80,
0x1c,0x20,0x1c,0x20,0x1c,0x20,0x30,0x20,0x30,0x60,0x39,0x10,0x30,
0x10,0x20,0x20,0x2b,0x10,0x26,0x10,0x2b,0x10,0x26,0x10,0x26,0x10,
0x2b,0x10,0x2b,0x80,0x18,0x20,0x18,0x20,0x26,0x20,0x20,0x20,0x20,
0x60,0x26,0x10,0x2b,0x20,0x30,0x20,0x30,0x20,0x1c,0x20,0x20,0x20,
0x20,0x80,0x26,0x20,0x30,0x10,0x30,0x10,0x30,0x20,0x39,0x20,0x26,
0x10,0x2b,0x10,0x2b,0x20,0x2b,0x40,0x40,0x10,0x40,0x10,0x20,0x10,
0x20,0x10,0x2b,0x10,0x26,0x30,0x30,0x80,0x00
};
//********函数声明
void conversion(uint temp_data);
void delay_us(unsigned int t);
void delay_20us();
void delay_ms(unsigned int time);
void delay_isd(uint time);
void delay(int x);
void HC595_send_byte(unsigned char byte);
void SMG_ShowNum(unsigned char num);
void SMG_Display(unsigned int dat);
void Delay(unsigned char x);
void beeping(unsigned char frequence,unsigned char length);
void Play_Song();
void main(void) // 主程序
{
uint distance_data,a;
uchar CONT_1;
unsigned int num=0; //数码管的参量
unsigned char time=0;
uint distance[20]; //距离缓冲数组
i=0;
k=0;
flag=0;
Trig=0; //首先拉低脉冲输入引脚
TMOD=0x11; //定时器0,定时器1,16位工作方式
IT0=0; //由高电平变低电平,触发外部中断IT0=0,INT0/P3.2引脚上的低电平可触发外部中断0
ET0=1; //打开定时器0中断
TH0 = 0xB1;
TL0 = 0xE0;
EX0=0; //关闭INT0外部中断
EA=1; //打开总中断0
//对数码管驱动初始化
P0=0X00; //初始化低四位为高电平,使能四位数码管
HC595_RST=0; //HC595的复位端,不能让他复位
while(1) //程序循环
{
EA=0;
Trig=1;
delay_20us();
Trig=0; //产生一个20us的脉冲,在Trig引脚
while(Echo==0); //等待Echo回波引脚变高电平
succeed_flag=0; //清测量成功标志
EX0=1; //打开外部中断
TH1=0; //定时器1清零
TL1=0; //定时器1清零
TF1=0; //定时器1中断请求标志位清0
TR1=1; //启动定时器1
EA=1;
while(TH1 < 30); //等待测量的结果,周期65.535毫秒(可用中断实现)
TR1=0; //关闭定时器1
EX0=0; //关闭外部中断
if(succeed_flag==1)
{
distance_data=outcomeH; //测量结果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//与低8位合并成为16位结果数据
distance_data=distance_data;
distance_data=(distance_data*1.7)/100; //微秒的单位除以58等于厘米
} //Y米=(X秒*344)/2
if(succeed_flag==0)
{
distance_data=0; //没有回波则清零
test = !test; //测试灯变化
}
distance[i]=distance_data;
i++;
if(i==19)
{
/* uint min,t,k,j; //选择排序法,将距离数据排序
for(k=0;k<9;k++)
{
t=k;
for(j=k+1;j<9;j++)
if(distance[j]<distance[t]) t=j;
if(t!=k)
{
min=distance[k];
distance[k]=distance[t];
distance[t]=min;
}
}
distance_data=(distance[4]+distance[5])/2; //取中间平均值
*/
uint k,sum=0;
for(k=0;k<20;k++)
sum=sum+distance[k];
distance_data=sum/20;
a=distance_data; //距离变化时,数码管更新数据,减10校正
if(b==a) {CONT_1=0;} //数码管显示超声波测距}
if(b!=a) CONT_1++;
if(CONT_1>=2)
{
CONT_1=0;
b=a;
conversion(b);
}
i=0;
}
}
}
/**********************************平均距离*********************************/
/********************************延迟函数*******************************/
void delay_us(unsigned int t)
{
while(t--)
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
}
void delay_20us(unsigned int t)
{
delay_us(20);
}
//延时函数(24M晶振下延时1ms)
void delay_ms(unsigned int time)
{
unsigned int t;
for(;time>0;time--)
{
t = 1500;
while(t--);
}
}
void Delay(unsigned char x)
{
unsigned char i,j;
for( i =0;i < x;i++ )for( j =0;j<36;j++ );
}
/************************************定时器0中断**************************/
//******************************************************************
INTO_() interrupt 0 // 外部中断是0号
{
outcomeH =TH1; //取出定时器的值
outcomeL =TL1; //取出定时器的值
succeed_flag=1; //至成功测量的标志
EX0=0; //关闭外部中断
}
timer0() interrupt 1 // 定时器0中断是1号
{
TH0 = 0xB1;
TL0 = 0xE0; //24MZ晶振,10ms
Count++; //长度加1
}
/**********************数码管驱动与显示模块**********************/
//向HC595发送一个字节
void HC595_send_byte(unsigned char byte)
{
unsigned char i,temp;
for(i=0;i<=7;i++)
{
temp = byte&1<<i;
if(temp)
{
HC595_DAT = 1; //数据线
}
else
{
HC595_DAT=0;
}
//下面是写时序
HC595_SCK=1; //SCK(11脚)
HC595_SCK=0;
}
HC595_RCK=0; //RCK(12脚)
HC595_RCK=1;
}
//显示一个数num
void SMG_ShowNum(unsigned char num)
{
HC595_send_byte(seg[num]);
}
void SMG_Display(unsigned int dat)
{
SMG_ShowNum(dat/1000);
P0 = (P0&0xf0)|position[0];
delay_ms(2);
SMG_ShowNum((dat%1000)/100);
P0 = (P0&0xf0)|position[1];
delay_ms(2);
SMG_ShowNum(dat%100/10);
P0 = (P0&0xf0)|position[2];
delay_ms(2);
SMG_ShowNum(dat%10);
P0 = (P0&0xf0)|position[3];
delay_ms(2);
}
//显示数据转换程序
void conversion(uint temp_data)
{
unsigned i=0;
EX0=0; //关闭INT0外部中断=0;
delay_us(30);
for(i=0;i<300;i++)
{
SMG_Display(temp_data); //数码管显示超声波测距
}
if(temp_data<30){Play_Song(); } //距离小于30cm报警
EX0=1; //关闭INT0外部中断=1;
}
/*********************************************************************************
放音子函数
参数:frequence 决定音乐声调的变量
length 决定某个音调播放的时间
*********************************************************************************/
void beeping(unsigned char frequence,unsigned char length)
{
TR0=1;
while(1)
{
beep = !beep;