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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5369|回復: 1
打印 上一主題 下一主題
收起左側

超聲波測距儀,設置的報警距離不能保存,求解答

[復制鏈接]
跳轉到指定樓層
樓主
                我的超聲波測距儀有個設置報警距離功能,當測得的距離小于設定時蜂鳴器報警。問題是更改報警距離后,再開機,報警距離就又是初始化的值,不是更改后的值,不知道哪里出了問題。
以下是源程序:
#include <reg52.h>          //調用單片機頭文件
#define uchar unsigned char  //無符號字符型 宏定義 變量范圍0~255
#define uint  unsigned int  //無符號整型 宏定義 變量范圍0~65535
#include <intrins.h>
sbit c_send   = P1^5;  //超聲波發射
sbit c_recive = P3^2;  //超聲波接收
//這三個引腳參考資料
sbit rs=P1^0;  //1602數據/命令選擇引腳 H:數據       L:命令
sbit rw=P1^1;  //1602讀寫引腳          H:數據寄存器   L:指令寄存器
sbit e =P2^5;  //1602使能引腳          下降沿觸發
uchar code table_num[]="0123456789abcdefg";
/***********************語音模塊控制IO口的定義************************/
sbit  VBUSY= P2^0;
sbit  VSDA = P2^1;
sbit  VCS  = P2^2;  
sbit  VSCL = P2^6;
sbit  VRST = P2^4;
uchar yujing[3];
sbit beep = P2^3;   //蜂鳴器IO口定義
bit flag_300ms ;
long distance;         //距離
uint set_d;             //距離
bit flag_csb_juli;        //超聲波超出量程
uint  flag_time0;     //用來保存定時器0的時候的
//  按鍵的IO變量的定義
uchar key_can;   //按鍵值的變量
uchar menu_1;        //菜單設計的變量
uchar a_a;

#define RdCommand 0x01 //定義ISP的操作命令
#define PrgCommand 0x02
#define EraseCommand 0x03
#define Error 1
#define Ok 0
#define WaitTime 0x07 //定義CPU的等待時間
sfr ISP_DATA=0xe6;  //寄存器申明
sfr ISP_ADDRH=0xe5;
sfr ISP_ADDRL=0xe4;
sfr ISP_CMD=0xe3;
sfr ISP_TRIG=0xe2;
sfr ISP_CONTR=0xe1;

/* ================ 打開 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
  EA = 0;       /* 關中斷   */
  ISP_CONTR = ISP_CONTR & 0x18;       /* 0001,1000 */
  ISP_CONTR = ISP_CONTR | WaitTime; /* 寫入硬件延時 */
  ISP_CONTR = ISP_CONTR | 0x80;       /* ISPEN=1  */
}
/* =============== 關閉 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
  ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */
  ISP_TRIG = 0x00;
  EA   =   1;   /* 開中斷 */
}
/* ================ 公用的觸發代碼 ==================== */
void ISPgoon(void)
{
  ISP_IAP_enable();   /* 打開 ISP,IAP 功能 */
  ISP_TRIG = 0x46;  /* 觸發ISP_IAP命令字節1 */
  ISP_TRIG = 0xb9;  /* 觸發ISP_IAP命令字節2 */
  _nop_();
}
/* ==================== 字節讀 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
EA = 0;
  ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址賦值 */
  ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  ISP_CMD   = ISP_CMD & 0xf8;   /* 清除低3位  */
  ISP_CMD   = ISP_CMD | RdCommand; /* 寫入讀命令 */
  ISPgoon();       /* 觸發執行  */
  ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
  EA  = 1;
  return (ISP_DATA);    /* 返回讀到的數據 */
}
/* ================== 扇區擦除 ======================== */
void SectorErase(unsigned int sector_addr)
{
  unsigned int iSectorAddr;
  iSectorAddr = (sector_addr & 0xfe00); /* 取扇區地址 */
  ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
  ISP_ADDRL = 0x00;
  ISP_CMD = ISP_CMD & 0xf8;   /* 清空低3位  */
  ISPgoon();       /* 觸發執行  */
  ISP_IAP_disable();    /* 關閉ISP,IAP功能 */
}
/* ==================== 字節寫 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
  EA  = 0;
  SectorErase(byte_addr);
  ISP_ADDRH = (unsigned char)(byte_addr >> 8);  /* 取地址  */
  ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);
  ISP_CMD  = ISP_CMD & 0xf8;    /* 清低3位 */
  ISP_DATA = original_data;   /* 寫入數據準備 */
  ISPgoon();       /* 觸發執行  */
  ISP_IAP_disable();     /* 關閉IAP功能 */
  EA =1;
}
/***********************1ms延時函數*****************************/
void delay_1ms(uint q)
{
uint i,j;
for(i=0;i<q;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_uint()
* 功能 : 小延時。
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void delay_uint(uint q)
{
while(q--);
}
/********************************************************************
* 名稱 : write_com(uchar com)
* 功能 : 1602命令函數
* 輸入 : 輸入的命令值
* 輸出 : 無
***********************************************************************/
void write_com(uchar com)
{
e=0;
rs=0;
rw=0;
P0=com;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名稱 : write_data(uchar dat)
* 功能 : 1602寫數據函數
* 輸入 : 需要寫入1602的數據
* 輸出 : 無
***********************************************************************/
void write_data(uchar dat)
{
e=0;
rs=1;
rw=0;
P0=dat;
delay_uint(25);
e=1;
delay_uint(100);
e=0;
}
/********************************************************************
* 名稱 : write_string(uchar hang,uchar add,uchar *p)
* 功能 : 改變液晶中某位的值,如果要讓第一行,第五個字符開始顯示"ab cd ef" ,調用該函數如下
    write_string(1,5,"ab cd ef;")
* 輸入 : 行,列,需要輸入1602的數據
* 輸出 : 無
***********************************************************************/
void write_string(uchar hang,uchar add,uchar *p)
{
if(hang==1)   
  write_com(0x80+add);
else
  write_com(0x80+0x40+add);
while(1)
{
  if(*p == '\0')  break;
  write_data(*p);
  p++;
}
}
/***********************lcd1602上顯示兩位十進制數************************/
void write_sfm3(uchar hang,uchar add,uint date)
{
if(hang==1)   
  write_com(0x80+add);
else
  write_com(0x80+0x40+add);
write_data(0x30+date/100%10);
write_data('.');
write_data(0x30+date/10%10);
write_data(0x30+date%10);
}

/********************************************************************
* 名稱 : init_1602()
* 功能 : 初始化1602液晶
* 輸入 : 無
* 輸出 : 無
***********************************************************************/
void init_1602()      //1602初始化
{
write_com(0x38);
write_com(0x0c);
write_com(0x06);
delay_uint(1000);
write_string(1,0,"  juli:0.00m      ");
write_string(2,0,"   set:0.00m      ");
}
/******************把數據保存到單片機內部eepom中******************/
void write_eeprom() //保存數據
{
SectorErase(0x2000);
byte_write(0x2000, set_d % 256);
byte_write(0x2001, set_d / 256);
byte_write(0x2058, a_a);
}
/******************把數據從單片機內部eepom中讀出來*****************/
void read_eeprom()  //讀出保存數據
{
set_d  = byte_read(0x2001);
set_d <<= 8;
set_d  |= byte_read(0x2000);
a_a      = byte_read(0x2058);
}
///**************開機自檢eeprom初始化*****************/
void init_eeprom()  ////開始初始化保存的數據
{
read_eeprom();  //讀出保存數據
if(a_a != 15)  //新的單片機初始單片機內問EEPOM
{
  set_d = 50;
  a_a = 15;
  write_eeprom(); //保存數據
}
}
/********************獨立按鍵程序*****************/
uchar key_can;  //按鍵值
void key()  //獨立按鍵程序
{
static uchar key_new;
key_can = 20;                   //按鍵值還原
P3 |= 0xf0;
if((P3 & 0xf0) != 0xf0)  //按鍵按下
{
  delay_1ms(1);       //按鍵消抖動
  if(((P3 & 0xf0) != 0xf0) && (key_new == 1))
  {      //確認是按鍵按下
   key_new = 0;
   switch(P3 & 0xf0)
   {
    //case 0xb0: key_can = 3; break;    //得到k3鍵值
    case 0xb0: key_can = 3; break;
    //case 0x70: key_can = 2; break;    //得到k2鍵值
    case 0xd0: key_can = 2; break;
    //case 0x30: key_can = 1; break;    //得到k4鍵值
    case 0x70: key_can = 1; break;
   }
  }   
}
else
  key_new = 1;
}

/****************按鍵處理顯示函數***************/
void key_with()
{
if(key_can == 1)  //設置鍵
{
  menu_1 ++;
  if(menu_1 >= 2)
  {
   menu_1 = 0;
   init_1602() ;     //1602初始化
   write_sfm3(2,7,set_d);  //顯示設置的距離
  }
}
if(menu_1 == 1)   //設置距離報警
{
  if(key_can == 2)
  {
   set_d ++ ;  //加1
   if(set_d > 500)
    set_d = 500;
  }
  if(key_can == 3)
  {
   set_d -- ;  //減1
   if(set_d <= 1)
    set_d = 1;
  }
  write_sfm3(2,7,set_d);  //顯示設置的距離
  write_com(0x80+0x40+6);  //將光標顯示地址
  write_com(0x0f);         //顯示光標并且閃爍
  write_eeprom(); //保存數據
}
}  
/**************10us延時函數***************/
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;
   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 > 600))     //距離 = 速度 * 時間
  {
   distance = 888;     //如果大于3.8m就超出超聲波的量程
  }
}  
}

/*********************定時器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 clock_h_l()
{
static uchar value;
if(distance <= set_d)
{
  value ++;  //消除實際距離在設定距離左右變化時的干擾
  if(value >= 2)
  {
   beep = ~beep;    //蜂鳴器報警
  }
}
else
{
  value = 0;
  beep = 1;  //取消報警
}
}
/***************主函數*****************/
void main()
{
static uchar value = 5;
beep = 0;   //開機蜂鳴器響一下
delay_1ms(200);
P0 = P1 = P2 = P3 = 0xff;    //初始化單片機IO口為高電平
init_eeprom();  //開機自檢eeprom初始化
init_1602();      //1602初始化
time_init();
send_wave(); //測距離函數
write_sfm3(2,7,set_d);  //顯示設置的距離
while(1)
{
  if(flag_300ms == 1)
  {
   flag_300ms = 0;
   if((beep == 1))
    send_wave(); //測距離函數
   if(menu_1 == 0)
    write_sfm3(1,7,distance);  //顯示距離
   yujing[0] = distance % 10;
   yujing[1] = distance / 10 % 10;
   yujing[2] = distance / 100 % 10;
   
   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);
    }
   }                 
  }
  key();      //按鍵函數
  if(key_can < 10)
  {
   key_with();    //按鍵處理函數
  }
}
}   
/*********************定時器1中斷服務程序************************/
void time1_int() interrupt 3
{
static uchar value;    //定時10ms中斷一次
TH1 = 0xf8;
TL1 = 0x30;     //2ms
value++;
if(value >= 150)
{
  value = 0;
  flag_300ms = 1;
  clock_h_l();    //報警函數
}
}


IMG_20150510_184742.jpg (1.52 MB, 下載次數: 186)

更改

更改

IMG_20150510_184759.jpg (1.73 MB, 下載次數: 185)

重啟后 更改的數據沒了

重啟后 更改的數據沒了
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:80976 發表于 2015-5-24 22:11 | 只看該作者
等待高手解答
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩一区二区三区在线视频 | 日本一道本视频 | 久久久久久久国产精品视频 | 青青久在线视频 | 国产精品一区一区三区 | 亚洲欧美日韩精品久久亚洲区 | 天天干夜夜操 | 男人天堂网址 | 中文字幕日韩三级 | 日本久久网站 | 国产精品夜夜夜一区二区三区尤 | 亚洲精品一区二区三区 | 国产高清视频在线观看播放 | 在线免费观看毛片 | 91精品国产91久久久 | 国产精品夜夜夜一区二区三区尤 | 色综合天天天天做夜夜夜夜做 | 91视频免费在观看 | 国产日韩精品在线 | 精品国产欧美一区二区三区不卡 | 91视频日本 | 日本在线看片 | 久久久久亚洲精品 | 欧美一级黄色片在线观看 | 欧美一级视频免费看 | 亚洲欧美综合精品另类天天更新 | 国产一级久久久久 | 国产精品视频偷伦精品视频 | 国产又爽又黄的视频 | 欧美精品片 | 国产午夜视频 | 黄色一级免费 | 日本小电影网站 | 国产视频黄色 | 精品国产一区二区在线 | 中文一区 | 亚洲在线中文字幕 | 亚洲视频在线看 | 福利视频一区二区 | 日韩毛片在线免费观看 | 91久久精品|