久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2974|回復: 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 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久操福利 | 久久久国产一区二区 | 久久狠狠 | 欧美激情综合 | 中文字幕在线免费视频 | 国产96在线 | 天天在线操 | 国产精品视频在线播放 | 毛片一区| 国产91丝袜在线18 | jdav视频在线观看免费 | 91黄色片免费看 | 亚洲欧美在线视频 | 一区二区高清不卡 | 麻豆av网站 | 99视频| 99re6在线视频精品免费 | 成人免费黄视频 | 少妇无套高潮一二三区 | 天天操操操操操 | 成人免费视频在线观看 | 国产91在线 | 中日 | 国产二区在线播放 | 中文字幕一区二区三区乱码图片 | 久久精品一级 | 国产精品一区一区 | 日韩一级黄色毛片 | 天堂一区 | 色婷婷综合久久久中字幕精品久久 | 午夜视频一区二区 | 成人av电影免费在线观看 | av在线视 | 久久欧美高清二区三区 | 一级欧美 | 亚洲欧美精品在线 | 久久精品aaa | 久久亚洲视频 | 天天亚洲| 午夜视频免费在线观看 | 国产亚洲一区二区三区 | 亚洲一区二区三区四区五区中文 |