第一篇:具有实时语音播报功能的超声波测距仪(C程序)
#include
//调用单片机头文件
#define uchar unsigned char //无符号字符型 宏定义 变量范围0~255 #define uint unsigned int //无符号整型 宏定义 变量范围0~65535 #include
//数码管段选定义
0
7
uchar code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};//断码 //数码管位选定义
uchar code smg_we[]={0xe0,0xd0,0xb0,0x70};uchar dis_smg[8]
={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
sbit smg_we1 = P3^4;
//数码管位选定义 sbit smg_we2 = P3^5;sbit smg_we3 = P3^6;sbit smg_we4 = P3^7;
sbit c_send
= P3^2;//超声波发射 sbit c_recive = P3^3;//超声波接收
uchar smg_i = 3;
//显示数码管的个位数 bit flag_300ms;
long distance;
//距离 uint set_d;
//距离
uchar flag_csb_juli;
//超声波超出量程
uint flag_time0;
//用来保存定时器0的时候的/***********************语音模块控制IO口的定义************************/ sbit VRST = P2^3;sbit VBUSY= P2^7;sbit VSDA = P2^6;sbit VCS = P2^5;
sbit VSCL = P2^4;uchar yujing[3];
/***************************
语音地址的安排 0-9 :
对应数字0到9 0b
: 点 0c
: 米
0d
: 已超出量程 **************************/
/***********************1ms延时函数*****************************/ void delay_1ms(uint q){ uint i,j;for(i=0;i for(j=0;j<120;j++);} /***********************小延时函数**************************/ void delay_us(unsigned int us){ while(us--){ _nop_();} } /***********************三线发码子程序************************/ void Send_threelines(unsigned char addr){ unsigned char i;VRST=0;delay_1ms(5);VRST=1;delay_1ms(20);/* 复位拉高20ms*/ VCS=0;delay_1ms(5);/* 片选拉低5ms */ for(i=0;i<8;i++){ VSCL=0; if(addr&0x01) { VSDA=1; } else VSDA=0; addr>>=1; delay_us(150);/* 150us */ VSCL=1; delay_us(150);/* 150us */ } VCS=1;delay_1ms(200);while(VBUSY == 0); //忙等待 } /***********************数码位选函数*****************************/ void smg_we_switch(uchar i){ switch(i){ case 0: smg_we1 = 0;smg_we2 = 1;smg_we3 = 1;smg_we4 = 1;break; case 1: smg_we1 = 1;smg_we2 = 0;smg_we3 = 1;smg_we4 = 1;break; case 2: smg_we1 = 1;smg_we2 = 1;smg_we3 = 0;smg_we4 = 1;break; case 3: smg_we1 = 1;smg_we2 = 1;smg_we3 = 1;smg_we4 = 0;break;} } /***********************数码显示函数*****************************/ void display(){ static uchar i; i++;if(i >= smg_i) i = 0; smg_we_switch(i);//位选 P1 = dis_smg[i]; //段选 } /******************小延时函数*****************/ void delay(){ _nop_(); //执行一条_nop_()指令就是1us _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();} /*********************超声波测距程序*****************************/ void send_wave(){ c_send = 1; //10us的高电平触发 delay();c_send = 0; TH0 = 0; //给定时器0清零 TL0 = 0;TR0 = 0; //关定时器0定时 while(!c_recive); //当c_recive为零时等待 TR0=1;while(c_recive) //当c_recive为1计数并等待 { flag_time0 = TH0 * 256 + TL0; if((flag_time0 > 40000)) //当超声波超过测量范围时,显示3个888 { TR0 = 0; flag_csb_juli = 2; distance = 888; break; } else { flag_csb_juli = 1; } } if(flag_csb_juli == 1){ TR0=0; //关定时器0定时 distance =flag_time0; //读出定时器0的时间 distance *= 0.017; // 0.017 = 340M / 2 = 170M = 0.017M 算出来是米 if((distance > 500)) //距离 = 速度 * 时间 { distance = 888; //如果大于3.8m就超出超声波的量程 } } } /***********************处理距离函数****************************/ void smg_display(){ dis_smg[0] = smg_du[distance % 10]; //距离取出来放在缓冲区了 dis_smg[1] = smg_du[distance / 10 % 10];dis_smg[2] = smg_du[distance / 100 % 10] & 0x7f;yujing[0] = distance % 10; //距离放到语音的变量里 yujing[1] = distance / 10 % 10; yujing[2] = distance / 100 % 10;} /*********************定时器0、定时器1初始化******************/ void time_init() { EA = 1; //开总中断 TMOD = 0X11; //定时器0、定时器1工作方式1 ET0 = 0; //关定时器0中断 TR0 = 1; //允许定时器0定时 ET1 = 1; //开定时器1中断 TR1 = 1; //允许定时器1定时 } /***************主函数*****************/ void main(){ static uchar value = 5;P0 = P1 = P2 = P3 = 0xff; //初始化单片机IO口为高电平 send_wave();//测距离函数 smg_display();//处理距离显示函数 time_init();//定时器初始化程序 send_wave();//测距离函数 send_wave();//测距离函数 while(1){ if(flag_300ms == 1) { flag_300ms = 0; send_wave();//测距离函数 smg_display();//处理距离显示函数 value ++; if(value > 10)//3秒钟自动播放一次 { value = 0; if(distance == 888) { Send_threelines(0x0d); //语音播放已超出量程 } else { Send_threelines(yujing[2]); //语音播放 Send_threelines(0x0b); Send_threelines(yujing[1]); Send_threelines(yujing[0]); Send_threelines(0x0c); } } } } } /*********************定时器1中断服务程序************************/ void time1_int()interrupt 3 { static uchar value; //定时2ms中断一次 TH1 = 0xf8;TL1 = 0x30; //2ms display();//数码管显示函数 value++;if(value >= 150){ value = 0; flag_300ms = 1;} }