找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机蓝牙小车代码和超声波测距报警系统代码放一起后,蓝牙小车就不起作用了

[复制链接]
跳转到指定楼层
楼主
ID:959083 发表于 2021-10-2 15:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
60黑币
  蓝牙小车代码和超声波测距报警系统代码放一起后,蓝牙小车就不起作用了,请大佬看下问题出在哪?


代码如下:

#include "reg52.h"     //此文件中定义了单片机的一些特殊功能寄存器
#include <intrins.h>
#define uchar unsigned char        // 以后unsigned char就可以用uchar代替
#define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

sfr ISP_DATA  = 0xe2;                        // 数据寄存器
sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
sfr ISP_CMD   = 0xe5;                        // 命令寄存器
sfr ISP_TRIG  = 0xe6;                        // 命令触发寄存器
sfr ISP_CONTR = 0xe7;                        // 命令寄存器


sbit LcdRs_P   = P2^7;                // 1602液晶的RS管脚      
sbit LcdRw_P   = P2^6;                // 1602液晶的RW管脚
sbit LcdEn_P   = P2^5;                // 1602液晶的EN管脚
sbit Trig_P    = P3^5;                // 超声波模块的Trig管脚
sbit Echo_P    = P3^6;                // 超声波模块的Echo管脚
sbit KeySet_P  = P3^2;                // “设置”按键的管脚
sbit KeyDown_P = P3^3;                // “减”按键的管脚
sbit KeyUp_P   = P3^4;                // “加”按键的管脚
sbit Buzzer_P  = P2^1;                // 蜂鸣器的管脚
sbit Led_P     = P2^0;                // LED报警灯的管脚
sbit DQ        = P2^4;                // 温度传感器的引脚定义


uint  gAlarm;                                                        // 报警距离变量
float gSpeed;                                                        // 保存超声波的速度值
sbit output_0=P1^0;           //将单片机的P1.0端口定义为output_0
sbit output_1=P1^1;           
sbit output_2=P1^2;           
sbit output_3=P1^3;         
sbit output_4=P1^4;         
sbit output_5=P1^5;           
sbit output_6=P1^6;         
sbit output_7=P1^7;         
sbit LED_1=P2^3;
sbit LED_2=P2^2;
sbit laba=P3^7;

/*********************************************************/
// 单片机内部EEPROM不使能
/*********************************************************/
void ISP_Disable()
{
        ISP_CONTR = 0;
        ISP_ADDRH = 0;
        ISP_ADDRL = 0;
}


/*********************************************************/
// 从单片机内部EEPROM读一个字节,从0x2000地址开始
/*********************************************************/
unsigned char EEPROM_Read(unsigned int add)
{
        ISP_DATA  = 0x00;
        ISP_CONTR = 0x83;
        ISP_CMD   = 0x01;
        ISP_ADDRH = (unsigned char)(add>>8);
        ISP_ADDRL = (unsigned char)(add&0xff);
        // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
        ISP_TRIG  = 0x46;           
        ISP_TRIG  = 0xB9;
        _nop_();
        ISP_Disable();
        return (ISP_DATA);
}


/*********************************************************/
// 往单片机内部EEPROM写一个字节,从0x2000地址开始
/*********************************************************/
void EEPROM_Write(unsigned int add,unsigned char ch)
{
        ISP_CONTR = 0x83;
        ISP_CMD   = 0x02;
        ISP_ADDRH = (unsigned char)(add>>8);
        ISP_ADDRL = (unsigned char)(add&0xff);
        ISP_DATA  = ch;
        ISP_TRIG  = 0x46;
        ISP_TRIG  = 0xB9;
        _nop_();
        ISP_Disable();
}


/*********************************************************/
// 擦除单片机内部EEPROM的一个扇区
// 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
/*********************************************************/
void Sector_Erase(unsigned int add)         
{
        ISP_CONTR = 0x83;
        ISP_CMD   = 0x03;
        ISP_ADDRH = (unsigned char)(add>>8);
        ISP_ADDRL = (unsigned char)(add&0xff);
        ISP_TRIG  = 0x46;
        ISP_TRIG  = 0xB9;
        _nop_();
        ISP_Disable();
}



/*********************************************************/
// 毫秒级的延时函数,time是要延时的毫秒数
/*********************************************************/
void DelayMs(uint time)
{
        uint i,j;
        for(i=0;i<time;i++)
                for(j=0;j<112;j++);
}


/*********************************************************/
// 延时15微秒
/*********************************************************/
void Delay15us(void)
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}


/*********************************************************/
// 1602液晶写命令函数,cmd就是要写入的命令
/*********************************************************/
void LcdWriteCmd(uchar cmd)
{
        LcdRs_P = 0;
        LcdRw_P = 0;
        LcdEn_P = 0;
        P0=cmd;
        DelayMs(2);
        LcdEn_P = 1;   
        DelayMs(2);
        LcdEn_P = 0;        
}


/*********************************************************/
// 1602液晶写数据函数,dat就是要写入的数据
/*********************************************************/
void LcdWriteData(uchar dat)
{
        LcdRs_P = 1;
        LcdRw_P = 0;
        LcdEn_P = 0;
        P0=dat;
        DelayMs(2);
        LcdEn_P = 1;   
        DelayMs(2);
        LcdEn_P = 0;
}


/*********************************************************/
// 1602液晶初始化函数
/*********************************************************/
void LcdInit()
{
        LcdWriteCmd(0x38);        // 16*2显示,5*7点阵,8位数据口
        LcdWriteCmd(0x0C);        // 开显示,不显示光标
        LcdWriteCmd(0x06);        // 地址加1,当写入数据后光标右移
        LcdWriteCmd(0x01);        // 清屏
}


/*********************************************************/
// 液晶光标定位函数
/*********************************************************/
void LcdGotoXY(uchar line,uchar column)
{
        // 第一行
        if(line==0)        
                LcdWriteCmd(0x80+column);
        // 第二行
        if(line==1)        
                LcdWriteCmd(0x80+0x40+column);
}



/*********************************************************/
// 液晶输出字符串函数
/*********************************************************/
void LcdPrintStr(uchar *str)
{
        while(*str!='\0')
                        LcdWriteData(*str++);
}


/*********************************************************/
// 液晶输出数字
/*********************************************************/
void LcdPrintNum(uint num)
{
        LcdWriteData(num/100+0x30);                                // 百位
        LcdWriteData(num%100/10+0x30);                // 十位
        LcdWriteData(num%10+0x30);                                // 个位
}


/*********************************************************/
// 在液晶上显示温度
/*********************************************************/
void LcdPrintTemp(int temp)
{
        if(temp<0)                                                                 
        {
                LcdWriteData('-');                                                        // 负号        
                temp=0-temp;                                                                                // 负数转为正数
        }
        if(temp>999)                                                                  
        {
                LcdWriteData(temp/1000+0x30);                // 百位        
        }
        LcdWriteData(temp%1000/100+0x30);        // 十位
        LcdWriteData(temp%100/10+0x30);                // 个位
        LcdWriteData('.');                                                                 // 小数点
        LcdWriteData(temp%10+0x30);                                // 小数后一位
        LcdWriteData(0xdf);                                                                // 摄氏度符号
        LcdWriteData('C');
        LcdWriteData(' ');
}



/*********************************************************/
// 复位DS18B20(初始化)
/*********************************************************/
void DS18B20_ReSet(void)
{
        uchar i;
        DQ=0;
        i=240;
        while(--i);
        DQ=1;
        i=30;
        while(--i);
        while(~DQ);
        i=4;
        while(--i);
}


/*********************************************************/
// 向DS18B20写入一个字节
/*********************************************************/
void DS18B20_WriteByte(uchar dat)
{
        uchar j;
        uchar btmp;
        
        for(j=0;j<8;j++)
        {
                btmp=0x01;
                btmp=btmp<<j;
                btmp=btmp&dat;
               
                if(btmp>0)                // 写1
                {
                        DQ=0;
                        Delay15us();
                        DQ=1;
                        Delay15us();
                        Delay15us();
                        Delay15us();
                        Delay15us();
                }
                else                        // 写0
                {
                        DQ=0;
                        Delay15us();
                        Delay15us();
                        Delay15us();
                        Delay15us();
                        DQ=1;
                        Delay15us();
                }
        }
}


/*********************************************************/
// 读取温度值
/*********************************************************/
int DS18B20_ReadTemp(void)
{
        uchar j;
        int b,temp=0;        

        DS18B20_ReSet();                                                        // 产生复位脉
        DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
        DS18B20_WriteByte(0x44);                        // 启动温度转换指令

        DS18B20_ReSet();                                                        // 产生复位脉
        DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
        DS18B20_WriteByte(0xbe);                        // 读取温度指令

        for(j=0;j<16;j++)                                                        // 读取温度数量
        {                                                
                DQ=0;
                _nop_();
                _nop_();
                DQ=1;        
                Delay15us();
                b=DQ;
                Delay15us();
                Delay15us();
                Delay15us();
                b=b<<j;
                temp=temp|b;
        }
        
        temp=temp*0.0625*10;                                        // 合成温度值并放大10倍                                       
        return (temp);                                                                // 返回检测到的温度值
}



/*********************************************************/
// 计算测到的距离
/*********************************************************/
uint GetDistance(void)
{
        uint ss;                                        // 用于记录测得的距离

        TH0=0;
        TL0=0;

        Trig_P=1;                                        // 给超声波模块一个开始脉冲
        DelayMs(1);
        Trig_P=0;

        while(!Echo_P);                // 等待超声波模块的返回脉冲
        TR0=1;                                                // 启动定时器,开始计时
        while(Echo_P);                // 等待超声波模块的返回脉冲结束
        TR0=0;                                                // 停止定时器,停止计时

        ss=((TH0*256+TL0)*gSpeed)/2;                // 距离cm=(时间us * 速度cm/us)/2

        if(ss>999)                                // 把检测结果限制999厘米内
                ss=999;
        
        return ss;
}


/*********************************************************/
// 按键扫描
/*********************************************************/
void KeyScanf()
{
        uchar i;
        uchar dat1,dat2;

        if(KeySet_P==0)                                                                // 判断是否有按键按下
        {
                LcdGotoXY(1,0);                                                        // 液晶第二行刷新显示
                LcdPrintStr("  alarm=   cm   ");
                LcdGotoXY(1,8);                                                        // 显示当前的报警值
                LcdPrintNum(gAlarm);                                
               
                DelayMs(10);                                                                // 消除按键按下的抖动
                while(!KeySet_P);                                                // 等待按键释放
                DelayMs(10);                                                                // 消除按键松开的抖动

                i=1;

                while(i)
                {                                                         
                        if(KeyDown_P==0)                // 报警值减的处理
                        {
                                if(gAlarm>2)
                                        gAlarm--;
                                LcdGotoXY(1,8);
                                LcdPrintNum(gAlarm);        
                                DelayMs(300);
                        }

                        if(KeyUp_P==0)                        // 报警值加的处理
                        {
                                if(gAlarm<400)
                                        gAlarm++;
                                LcdGotoXY(1,8);
                                LcdPrintNum(gAlarm);
                                DelayMs(300);
                        }
                        
                        if(KeySet_P==0)                        // 再次按下设置键的判断
                        {
                                LcdGotoXY(1,0);                                                // 液晶恢复测量时的内容显示
                                LcdPrintStr("  dist=   cm    ");
                                DelayMs(10);                                                  // 消除按键按下的抖动
                                while(!KeySet_P);                                        // 等待按键释放
                                DelayMs(10);                                                  // 消除按键松开的抖动
                                i=0;
                        }                           
                }
               
                dat1=gAlarm/100;
                dat2=gAlarm%100;
                Sector_Erase(0x2000);
                EEPROM_Write(0x2000,dat1);
                EEPROM_Write(0x2001,dat2);
        }        
}


/*********************************************************/
// 报警判断
/*********************************************************/
void AlarmJudge(uint ss)
{
        uchar i;
        float alr1,alr2,alr3,alr4;

        alr1=gAlarm/4.00*1;
        alr2=gAlarm/4.00*2;
        alr3=gAlarm/4.00*3;
        alr4=gAlarm/4.00*4;


        // 报警频率最快
        if(ss<alr1)                        
        {
                for(i=0;i<10;i++)
                {
                        Led_P=0;
                        Buzzer_P=0;
                        DelayMs(50);
                        Led_P=1;
                        Buzzer_P=1;
                        DelayMs(50);
                        KeyScanf();
                }
        }
        // 报警频率第二快
        else if(ss<alr2)               
        {
                for(i=0;i<5;i++)
                {
                        Led_P=0;
                        Buzzer_P=0;
                        DelayMs(100);
                        Led_P=1;
                        Buzzer_P=1;
                        DelayMs(100);
                        KeyScanf();
                }        
        }
        // 报警频率第三快
        else if(ss<alr3)         
        {
                for(i=0;i<2;i++)
                {
                        Led_P=0;
                        Buzzer_P=0;
                        DelayMs(200);
                        Led_P=1;
                        Buzzer_P=1;
                        DelayMs(200);
                        KeyScanf();
                }        
        }
        // 报警频率最慢
        else if(ss<alr4)        
        {
                for(i=0;i<2;i++)
                {
                        Led_P=0;
                        Buzzer_P=0;
                        DelayMs(300);
                        Led_P=1;
                        Buzzer_P=1;
                        DelayMs(300);
                        KeyScanf();
                }        
        }
        // 不报警
        else
        {
                Led_P=1;
                Buzzer_P=1;
                for(i=0;i<100;i++)
                {
                        KeyScanf();
                        DelayMs(10);
                }        
        }
}
void UART_INIT()
{
        SM0 = 0;
        SM1 = 1;//串口工作方式1
        REN = 1;//允许串口接收
        EA = 1;//开总中断
        ES = 1;//开串口中断
        TMOD = 0x20;//8位自动重装模式
        TH1 = 0xfd;
        TL1 = 0xfd;//9600波特率
        TR1 = 1;//启动定时器1
}

void straight()
{
   //右边后轮正转
    output_0=1;                           
    output_1=0;
    //左边后轮正转
    output_2=0;
    output_3=1;
    //左边前轮正转
    output_4=1;
    output_5=0;
    //右边前轮正转
    output_6=0;
    output_7=1;
}

void backward()
{
    //右边后轮反转
    output_0=0;
    output_1=1;
    //左边后轮反转
    output_2=1;
    output_3=0;
    //左边前轮反转
    output_4=0;
    output_5=1;
    //右边前轮反转
    output_6=1;
    output_7=0;
}

void stop()
{

    output_0=0;
    output_1=0;

    output_2=0;
    output_3=0;

    output_4=0;
    output_5=0;

    output_6=0;
    output_7=0;
}


//这里用的时差速转向,即左边的轮子不转或者反转,右边的轮子正转,就能达到向左转向
void turn_left()
{

    output_0=1;
    output_1=0;

    output_2=1;
    output_3=0;

    output_4=0;
    output_5=1;

    output_6=0;
    output_7=1;
}

void turn_right()
{

    output_0=0;
    output_1=1;

    output_2=0;
    output_3=1;

    output_4=1;
    output_5=0;

    output_6=1;
    output_7=0;
}

void Btutto1()
{
LED_1=0;
}

void onled()
{
LED_1=1;
LED_2=1;
}

void Btutto2()
{
LED_2=0;
}
void labasy()
{
laba=0;

}
void guanbilaba()
{
laba=1;
}

//串口中断
void UART_SER() interrupt 4
{
        if(RI)//当硬件接收到一个数据时,RI会置位
        {
                RI = 0;//清除接收标志
                switch(SBUF)
                {
                        case 0x01: straight(); break;//前
                        case 0x02: backward(); break;//后
                        case 0x03: turn_left(); break;//左
                        case 0x04: turn_right(); break;//右                          
                        case 0x05: stop(); break;//停止
                        case 0x06: Btutto1();break;//远光灯
                        case 0x07: Btutto2();break;//近光灯
                        case 0x08: onled();break;//关闭灯
                        case 0x09: labasy();break;//喇叭
                        case 0x10: guanbilaba();break;//喇叭关
                }



        }
}


void main()
{        uchar dat1,dat2;
        uint dist;                                                                                                // 保存超声波模块测量到的结果
        int  temp;                                                                                                // 保存温度传感器测量到的结果-
        Trig_P=0;
        UART_INIT();//串口初始化
        LcdInit();                                                                                                // 执行液晶初始化
        TMOD = 0x01;                                                                                        // 选择定时器0,并且确定是工作方式1(为了超声波模块测量距离计时用的)
        LcdGotoXY(0,0);                                                                    // 定位到第0行第0列
        LcdPrintStr("  temp=         ");        // 第0行显示“  temp=         ”
        LcdGotoXY(1,0);                                                                    // 定位到第1行第0列
        LcdPrintStr("  dist=   cm    ");        // 第1行显示“  dist=   cm    ”

        while(DS18B20_ReadTemp()==850)                // 等待温度传感器初始化完成
        {
                DelayMs(10);
        }
        
        dat1=EEPROM_Read(0x2000);                                        // 从EEPROM读取报警值
        dat2=EEPROM_Read(0x2001);
        gAlarm=dat1*100+dat2;

        if((gAlarm==0)||(gAlarm>400))                        // 如果读取到的报警值异常(等于0或大于400则认为异常)
        {
                gAlarm=25;                                                                                        // 重新赋值报警值为25
        }

        while(1)
        {        
                temp=DS18B20_ReadTemp();                                // 获取温度传感器的温度值
                LcdGotoXY(0,7);                                                                        // 定位到第0行第7列
                LcdPrintTemp(temp);                                                        // 显示当前的温度值
               
                gSpeed=0.607*(temp/10)+331.4;                // 根据公式 v=0.607T+331.4 计算出当前温度值对应的超声波速度,这时的单位是“米/秒”
                gSpeed=gSpeed/10000;                                                // 将超声波的速度从单位“m/s”转为“cm/us”,方便后面的计算
               
                dist=GetDistance();                                                        // 通过超声波模块获取距离
                LcdGotoXY(1,7);                                                            // 光标定位
                LcdPrintNum(dist);                                                        // 将获取到的距离在液晶上面显示
                AlarmJudge(dist);
                                                                                // 判断一下是否需要报警,是的话则报警        
        }
                        
}


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

使用道具 举报

沙发
ID:142045 发表于 2021-10-3 12:36 | 只看该作者
中断没有设置好吧,定时器和串口中断的优先级

评分

参与人数 1黑币 +30 收起 理由
小白玩c51 + 30

查看全部评分

回复

使用道具 举报

板凳
ID:639106 发表于 2021-10-3 15:11 | 只看该作者
也许是超声波的延时导致蓝牙不能正常接收。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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