標(biāo)題: 為什么這個(gè)單片機(jī)程序打開(kāi)之后,出現(xiàn)很多未定義的錯(cuò)誤啊,有大佬幫忙看看么 [打印本頁(yè)]

作者: 233ccc-    時(shí)間: 2023-6-27 18:10
標(biāo)題: 為什么這個(gè)單片機(jī)程序打開(kāi)之后,出現(xiàn)很多未定義的錯(cuò)誤啊,有大佬幫忙看看么
#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char        // 以后unsigned char就可以用uchar代替
#define uint  unsigned int        // 以后unsigned int 就可以用uint 代替

sfr ISP_DATA  = 0xe2;                        // 數(shù)據(jù)寄存器
sfr ISP_ADDRH = 0xe3;                        // 地址寄存器高八位
sfr ISP_ADDRL = 0xe4;                        // 地址寄存器低八位
sfr ISP_CMD   = 0xe5;                        // 命令寄存器
sfr ISP_TRIG  = 0xe6;                        // 命令觸發(fā)寄存器
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    = P2^2;                // 超聲波模塊的Trig管腳
sbit Echo_P    = P2^3;                // 超聲波模塊的Echo管腳
sbit KeySet_P  = P3^2;                // “設(shè)置”按鍵的管腳
sbit KeyDown_P = P3^3;                // “減”按鍵的管腳
sbit KeyUp_P   = P3^4;                // “加”按鍵的管腳
sbit Buzzer_P  = P2^1;                // 蜂鳴器的管腳
sbit Led_P     = P2^0;                // LED報(bào)警燈的管腳
sbit DQ        = P1^0;                // 溫度傳感器的引腳定義


uint  gAlarm;                                                        // 報(bào)警距離變量
float gSpeed;                                                        // 保存超聲波的速度值



/*********************************************************/
// 單片機(jī)內(nèi)部EEPROM不使能
/*********************************************************/
void ISP_Disable()
{
        ISP_CONTR = 0;
        ISP_ADDRH = 0;
        ISP_ADDRL = 0;
}


/*********************************************************/
// 從單片機(jī)內(nèi)部EEPROM讀一個(gè)字節(jié),從0x2000地址開(kāi)始
/*********************************************************/
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);
        // 對(duì)STC89C51系列來(lái)說(shuō),每次要寫(xiě)入0x46,再寫(xiě)入0xB9,ISP/IAP才會(huì)生效
        ISP_TRIG  = 0x46;           
        ISP_TRIG  = 0xB9;
        _nop_();
        ISP_Disable();
        return (ISP_DATA);
}


/*********************************************************/
// 往單片機(jī)內(nèi)部EEPROM寫(xiě)一個(gè)字節(jié),從0x2000地址開(kāi)始
/*********************************************************/
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();
}


/*********************************************************/
// 擦除單片機(jī)內(nèi)部EEPROM的一個(gè)扇區(qū)
// 寫(xiě)8個(gè)扇區(qū)中隨便一個(gè)的地址,便擦除該扇區(qū),寫(xiě)入前要先擦除
/*********************************************************/
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();
}



/*********************************************************/
// 毫秒級(jí)的延時(shí)函數(shù),time是要延時(shí)的毫秒數(shù)
/*********************************************************/
void DelayMs(uint time)
{
        uint i,j;
        for(i=0;i<time;i++)
                for(j=0;j<112;j++);
}


/*********************************************************/
// 延時(shí)15微秒
/*********************************************************/
void Delay15us(void)
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}


/*********************************************************/
// 1602液晶寫(xiě)命令函數(shù),cmd就是要寫(xiě)入的命令
/*********************************************************/
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液晶寫(xiě)數(shù)據(jù)函數(shù),dat就是要寫(xiě)入的數(shù)據(jù)
/*********************************************************/
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液晶初始化函數(shù)
/*********************************************************/
void LcdInit()
{
        LcdWriteCmd(0x38);        // 16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)口
        LcdWriteCmd(0x0C);        // 開(kāi)顯示,不顯示光標(biāo)
        LcdWriteCmd(0x06);        // 地址加1,當(dāng)寫(xiě)入數(shù)據(jù)后光標(biāo)右移
        LcdWriteCmd(0x01);        // 清屏
}


/*********************************************************/
// 液晶光標(biāo)定位函數(shù)
/*********************************************************/
void LcdGotoXY(uchar line,uchar column)
{
        // 第一行
        if(line==0)        
                LcdWriteCmd(0x80+column);
        // 第二行
        if(line==1)        
                LcdWriteCmd(0x80+0x40+column);
}



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


/*********************************************************/
// 液晶輸出數(shù)字
/*********************************************************/
void LcdPrintNum(uint num)
{
        LcdWriteData(num/100+0x30);                                // 百位
        LcdWriteData(num%100/10+0x30);                // 十位
        LcdWriteData(num%10+0x30);                                // 個(gè)位
}


/*********************************************************/
// 在液晶上顯示溫度
/*********************************************************/
void LcdPrintTemp(int temp)
{
        if(temp<0)                                                                 
        {
                LcdWriteData('-');                                                        // 負(fù)號(hào)        
                temp=0-temp;                                                                                // 負(fù)數(shù)轉(zhuǎn)為正數(shù)
        }
        if(temp>999)                                                                  
        {
                LcdWriteData(temp/1000+0x30);                // 百位        
        }
        LcdWriteData(temp%1000/100+0x30);        // 十位
        LcdWriteData(temp%100/10+0x30);                // 個(gè)位
        LcdWriteData('.');                                                                 // 小數(shù)點(diǎn)
        LcdWriteData(temp%10+0x30);                                // 小數(shù)后一位
        LcdWriteData(0xdf);                                                                // 攝氏度符號(hào)
        LcdWriteData('C');
        LcdWriteData(' ');
}



/*********************************************************/
// 復(fù)位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寫(xiě)入一個(gè)字節(jié)
/*********************************************************/
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)                // 寫(xiě)1
                {
                        DQ=0;
                        Delay15us();
                        DQ=1;
                        Delay15us();
                        Delay15us();
                        Delay15us();
                        Delay15us();
                }
                else                        // 寫(xiě)0
                {
                        DQ=0;
                        Delay15us();
                        Delay15us();
                        Delay15us();
                        Delay15us();
                        DQ=1;
                        Delay15us();
                }
        }
}


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

        DS18B20_ReSet();                                                        // 產(chǎn)生復(fù)位脈
        DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
        DS18B20_WriteByte(0x44);                        // 啟動(dòng)溫度轉(zhuǎn)換指令

        DS18B20_ReSet();                                                        // 產(chǎn)生復(fù)位脈
        DS18B20_WriteByte(0xcc);                        // 忽略ROM指令
        DS18B20_WriteByte(0xbe);                        // 讀取溫度指令

        for(j=0;j<16;j++)                                                        // 讀取溫度數(shù)量
        {                                                
                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);                                                                // 返回檢測(cè)到的溫度值
}



/*********************************************************/
// 計(jì)算測(cè)到的距離
/*********************************************************/
uint GetDistance(void)
{
        uint ss;                                        // 用于記錄測(cè)得的距離

        TH0=0;
        TL0=0;

        Trig_P=1;                                        // 給超聲波模塊一個(gè)開(kāi)始脈沖
        DelayMs(1);
        Trig_P=0;

        while(!Echo_P);                // 等待超聲波模塊的返回脈沖
        TR0=1;                                                // 啟動(dòng)定時(shí)器,開(kāi)始計(jì)時(shí)
        while(Echo_P);                // 等待超聲波模塊的返回脈沖結(jié)束
        TR0=0;                                                // 停止定時(shí)器,停止計(jì)時(shí)

        ss=((TH0*256+TL0)*gSpeed)/2;                // 距離cm=(時(shí)間us * 速度cm/us)/2

        if(ss>999)                                // 把檢測(cè)結(jié)果限制999厘米內(nèi)
                ss=999;
        
        return ss;
}


/*********************************************************/
// 按鍵掃描
/*********************************************************/
void KeyScanf()
{
        uchar i;
        uchar dat1,dat2;

        if(KeySet_P==0)                                                                // 判斷是否有按鍵按下
        {
                LcdGotoXY(1,0);                                                        // 液晶第二行刷新顯示
                LcdPrintStr("  alarm=   cm   ");
                LcdGotoXY(1,8);                                                        // 顯示當(dāng)前的報(bào)警值
                LcdPrintNum(gAlarm);                                
               
                DelayMs(10);                                                                // 消除按鍵按下的抖動(dòng)
                while(!KeySet_P);                                                // 等待按鍵釋放
                DelayMs(10);                                                                // 消除按鍵松開(kāi)的抖動(dòng)

                i=1;

                while(i)
                {                                                         
                        if(KeyDown_P==0)                // 報(bào)警值減的處理
                        {
                                if(gAlarm>2)
                                        gAlarm--;
                                LcdGotoXY(1,8);
                                LcdPrintNum(gAlarm);        
                                DelayMs(300);
                        }

                        if(KeyUp_P==0)                        // 報(bào)警值加的處理
                        {
                                if(gAlarm<400)
                                        gAlarm++;
                                LcdGotoXY(1,8);
                                LcdPrintNum(gAlarm);
                                DelayMs(300);
                        }
                        
                        if(KeySet_P==0)                        // 再次按下設(shè)置鍵的判斷
                        {
                                LcdGotoXY(1,0);                                                // 液晶恢復(fù)測(cè)量時(shí)的內(nèi)容顯示
                                LcdPrintStr("  dist=   cm    ");
                                DelayMs(10);                                                  // 消除按鍵按下的抖動(dòng)
                                while(!KeySet_P);                                        // 等待按鍵釋放
                                DelayMs(10);                                                  // 消除按鍵松開(kāi)的抖動(dòng)
                                i=0;
                        }                           
                }
               
                dat1=gAlarm/100;
                dat2=gAlarm%100;
                Sector_Erase(0x2000);
                EEPROM_Write(0x2000,dat1);
                EEPROM_Write(0x2001,dat2);
        }        
}


/*********************************************************/
// 報(bào)警判斷
/*********************************************************/
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;


        // 報(bào)警頻率最快
        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();
                }
        }
        // 報(bào)警頻率第二快
        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();
                }        
        }
        // 報(bào)警頻率第三快
        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();
                }        
        }
        // 報(bào)警頻率最慢
        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();
                }        
        }
        // 不報(bào)警
        else
        {
                Led_P=1;
                Buzzer_P=1;
                for(i=0;i<100;i++)
                {
                        KeyScanf();
                        DelayMs(10);
                }        
        }
}


/*********************************************************/
// 主函數(shù)
/*********************************************************/
void main()
{
        uchar dat1,dat2;
        uint dist;                                                                                                // 保存超聲波模塊測(cè)量到的結(jié)果
        int  temp;                                                                                                // 保存溫度傳感器測(cè)量到的結(jié)果

        Trig_P=0;
        
        LcdInit();                                                                                                // 執(zhí)行液晶初始化
        TMOD = 0x01;                                                                                        // 選擇定時(shí)器0,并且確定是工作方式1(為了超聲波模塊測(cè)量距離計(jì)時(shí)用的)
        
        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讀取報(bào)警值
        dat2=EEPROM_Read(0x2001);
        gAlarm=dat1*100+dat2;

        if((gAlarm==0)||(gAlarm>400))                        // 如果讀取到的報(bào)警值異常(等于0或大于400則認(rèn)為異常)
        {
                gAlarm=25;                                                                                        // 重新賦值報(bào)警值為25
        }

        while(1)
        {
                temp=DS18B20_ReadTemp();                                // 獲取溫度傳感器的溫度值
                LcdGotoXY(0,7);                                                                        // 定位到第0行第7列
                LcdPrintTemp(temp);                                                        // 顯示當(dāng)前的溫度值
               
                gSpeed=0.607*(temp/10)+331.4;                // 根據(jù)公式 v=0.607T+331.4 計(jì)算出當(dāng)前溫度值對(duì)應(yīng)的超聲波速度,這時(shí)的單位是“米/秒”
                gSpeed=gSpeed/10000;                                                // 將超聲波的速度從單位“m/s”轉(zhuǎn)為“cm/us”,方便后面的計(jì)算
               
                dist=GetDistance();                                                        // 通過(guò)超聲波模塊獲取距離
                LcdGotoXY(1,7);                                                            // 光標(biāo)定位
                LcdPrintNum(dist);                                                        // 將獲取到的距離在液晶上面顯示

                AlarmJudge(dist);                                                                // 判斷一下是否需要報(bào)警,是的話(huà)則報(bào)警        
        }
}


作者: lkc8210    時(shí)間: 2023-6-27 22:01
沒(méi)有錯(cuò)誤






歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1