找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1017|回复: 5
打印 上一主题 下一主题
收起左侧

单片机超声波程序无法实现报警 求大佬看看哪里错了?

[复制链接]
跳转到指定楼层
楼主

#include<reg51.h>
#include<intrins.h>
#define uint  unsigned int
#define uchar unsigned char
#define NOP() {_nop_();_nop_();_nop_();_nop_();}

//------LCD引脚------
sbit lcd_rs=P2^0;
sbit lcd_en=P2^2;
sbit BUZZ=P3^7;

//------超声波引脚-------
sbit TR=P3^2;              //触发控制信号输入
sbit ECHO=P3^3;            //回响信号输出

uchar code table[]={" Distance Test:"};                //LCD第一行显示
uchar temp_dis[]= {"    000.0 cm"};                    //LCD第二行
long int t,distance;
uchar cache[4]={0,0,0,0};

//--------延时-------
void delay(uint ms)
{
        uint t;
        while(ms--)
        for(t=0;t<30;t++);
}

void write_com(uchar com);//init_lcd()函数需要用到,所以先提前声明

//************LCD1602初始化函数************************
void init_lcd()
{
        write_com(0x38);           //设置16*2显示,5*7点阵,8位数据接口
        write_com(0x08);           //写一个字符后地址指针加1
        write_com(0x01);           //显示清零,数据指针清零
        write_com(0x06);           //写一个字符后地址指针加1
        write_com(0x0c);           //关显示,光标不显示不闪烁
}

//************LCD1602写指令函数************************
void write_com(uchar com)   //lcd1602写指令:rs低电平,rw低电平,en从高电平变为低电平
{
        delay(5);
        lcd_rs = 0;                           // 选择写指令
        lcd_en = 0;                           // 将使能端置0
        P0 = com;                           // 将要写的命令送到数据总线上
        delay(5);                           // 延时5ms,待数据稳定
        lcd_en = 1;                           // 由于初始化已将lcd_en置为0,使能端给一个高脉冲,
        delay(5);                           // 延时5ms,待数据稳定
        lcd_en = 0;                           // 将使能端置0以完成脉冲
}

//************LCD1602写数据函数************************
void write_data(uchar date)//lcd1602写数据:rs高电平,rw低电平,en从高电平变低电平
{
        delay(5);
        lcd_rs = 1;                           // 选择写数据
        lcd_en = 0;                           // 将使能端置0
        P0 = date;                           // 将要写的数据送到数据总线上
        delay(5);                           // 延时5ms,待数据稳定
        lcd_en = 1;                           // 由于初始化已将lcd_en置为0,使能端给一个高脉冲,
        delay(5);                           // 延时5ms,待数据稳定
        lcd_en = 0;                           // 将使能端置0以完成脉冲
}

//************LCD1602显示函数******************
void lcd1602_display(uchar *q,uchar *p)//*通过指针p和q分别指向两个数组的第一个数,然后进行数组扫描显示,一次性显示两行字符
{
        write_com(0x80);             // 现将数据指针定位到第一行第一个字处
        while(*q!='\0')
        {
                write_data(*q);
                q++;
                delay(1);      
        }
        write_com(0xc0);           // 现将数据指针定位到第二行第一个字处
        while(*p!='\0')
        {
                write_data(*p);
                p++;
                delay(1);      
        }
}
//************超声波指令函数************************
void HC05_Init()                          //超声波模块初始化函数
{
        ECHO=1;                                 //触发脉冲
        NOP();NOP();NOP();NOP();
        ECHO=0;
        distance=0.1725*t;                       //距离计算
}

void distance_convert(long int t)             //距离计算函数
{                 
        cache[0]=t/1000;
        cache[1]=t/100%10;
        cache[2]=t/10%10;
        cache[3]=t%10;
        temp_dis[4]=cache[0]+'0';
        temp_dis[5]=cache[1]+'0';
        temp_dis[6]=cache[2]+'0';
        temp_dis[8]=cache[3]+'0';
}                                 

//************主程序******************
void main()
{              
        init_lcd();
        delay(5);
        TMOD=0x09;                    //定时器T0工作方式1  GATE0=1
        EA=1;                        //开总中断
        TR0=1;                        //启动定时器
        EX0=1;                        //开外部中断
        IT0=1;                        //设置为下降沿中断方式
        while(1)
        {                                
                HC05_Init();
                distance_convert(distance);
                lcd1602_display(table,temp_dis);
                                if(distance<30)                         //报警
                                {
                                 BUZZ=0;
                                }
                                else
                                {
                                 BUZZ=1;
                                }                                
        }
}

//外部中断0
void int0() interrupt 0
{
        t=(TH0*256+TL0);  //计算高电平持续的时间,上升沿到来时候开始计时,下降沿到来进入外部中断,关闭计时器,停止计时
        TH0=0;
        TL0=0;
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:688692 发表于 2022-3-28 23:17 | 只看该作者
你这个数据300对应的才是30cm。所以if那里的30改成300
回复

使用道具 举报

板凳
ID:1013861 发表于 2022-3-29 00:03 | 只看该作者
30改成300
回复

使用道具 举报

地板
ID:985137 发表于 2022-3-30 14:27 | 只看该作者
cnos 发表于 2022-3-28 23:17
你这个数据300对应的才是30cm。所以if那里的30改成300

有一点不太明白,TR和EC口,你看程序跟仿真反着来,接别的口还不行      
回复

使用道具 举报

5#
ID:1014303 发表于 2022-3-31 02:40 来自触屏版 | 只看该作者
你可以试试把两个报警器分开,分别作用
回复

使用道具 举报

6#
ID:161164 发表于 2022-3-31 16:24 | 只看该作者
2248373991 发表于 2022-3-30 14:27
有一点不太明白,TR和EC口,你看程序跟仿真反着来,接别的口还不行

因为你的程序定义IO口的时候弄反了
然后之后的代码用着错误的IO名来写

你这程序还用了外中断来检测EC口的下降沿
所以不能用其他口

你的程序有些错误
应该等待EC口的上升沿来到后才开始计时
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表