|
項目要求
1、設置三種模式,
第一種模式:超聲波測距,測距距離不在設置范圍內蜂鳴器發出響聲,測距距離在設置范圍內,蜂鳴器不響,
第二種模式:設置超聲波最大測距距離,該模式下不能進行超聲波測距,
第三種模式:設置超聲波最小測距距離,該模式下不能進行超聲波測距,
2、四位數碼管:最高位表示模式,其余三位數碼管顯示數據
3、三個按鍵,
第一個按鍵:按下跳換模式,
第二個按鍵:第一種模式不能按下,第二種模式按下最大值加1,第三種模式按下最小值加1,
第三個按鍵:第一種模式不能按下,第二種模式按下最大值減1,第三種模式按下最小值減1,
設計思路
1、首先點亮一個數碼管,然后實現動態掃描所有數碼管,
2、實現按鍵按下變換數碼管,設置出三種模式,
3、實現超聲波測距,蜂鳴器發出響聲,
4、將所有模塊結合,完成項目要求,
單片機程序:
- #include <reg52.h>
- #include <intrins.h>
- /* 全局運行參數定義 */
- #define OSC_FREQ (11059200) //振蕩器頻率值,單位Hz
- #define SYS_MCLK (OSC_FREQ/12) //系統主時鐘頻率,即振蕩器頻率÷12
- //數碼管io口定義
- sbit TUBE4=P3^4;
- sbit TUBE3=P3^5;
- sbit TUBE2=P3^6;
- sbit TUBE1=P3^7;
- //按鍵io口定義
- sbit KEY0=P2^0;
- sbit KEY1=P2^1;
- sbit KEY2=P2^2;
- //蜂鳴器io口定義
- sbit BUZZ=P2^3;
- sbit trig = P3^2;//超聲波發射
- sbit echo = P3^3; //超聲波接收
- static unsigned char index=0;//模式選擇的索引
- unsigned int flag1s = 0; //1s定時標志
- unsigned char T0RH = 0; //T0重載值的高字節
- unsigned char T0RL = 0; //T0重載值的低字節
- unsigned int HIGHEST = 400; //超聲波最大測距距離(cm)
- unsigned int LOWEST = 2; //超聲波最小測距距離(cm)
- static unsigned int testHighest = 100; //超聲波最高測距距離(設置值)
- static unsigned int testLowest = 10; //超聲波最低測距距離(設置值)
- unsigned char pdata KeySta[3] = { 1, 1, 1}; //全部矩陣按鍵的當前狀態
- unsigned char code LedChar[] = { //數碼管顯示字符轉換表
- 0x28,0xee,0x32,0xa2,0xe4,0xa1,0x21,0xea,0x20,
- 0xa0,0x60,0x25,0x39,0x26,0x31,0x71,0xff
- };
- unsigned char LedBuff[4] = { //數碼管顯示緩沖區,初值0xFF確保啟動時都不亮
- 0xFF,0xFF,0xFF,0xFF
- };
- /* 數碼管初始化函數 */
- void TUBE_Init();
- /* 數碼管顯示函數 */
- void TUBE_Display(unsigned int dis);
- /* 數碼管按鍵顯示函數 */
- void TUBE_KeyDisplay(unsigned int key);
- /* 按鍵驅動函數,檢測按鍵動作,調度相應動作函數,需在主循環中調用 */
- void KeyDriver();
- /* 按鍵掃描函數,需在定時中斷中調用,推薦調用間隔1ms */
- void KeyScan();
- /* 超聲波測距函數 */
- unsigned int GetDistance(void);
- /* 蜂鳴器警報函數 */
- void IfDistance(void);
- /* 配置并啟動T0,ms-T0定時時間 */
- void ConfigTimer0(unsigned int ms)
- {
- unsigned long tmp;
- tmp = (SYS_MCLK*ms)/1000; //計算所需的計數值
- tmp = 65536 - tmp; //計算定時器重載值
- tmp = tmp + 33; //補償中斷響應延時造成的誤差
- T0RH = (unsigned char)(tmp>>8); //定時器重載值拆分為高低字節
- T0RL = (unsigned char)tmp;
- TMOD &= 0xF0; //清零T0的控制位
- TMOD |= 0x01; //配置T0為模式1
- TH0 = T0RH; //加載T0重載值
- TL0 = T0RL;
- ET0 = 1; //使能T0中斷
- TR0 = 1; //啟動T0
- }
- /* 配置并啟動T1,用于超聲波測距 */
- void ConfigTimer1()
- {
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x10; //配置T1為模式1
- TH1 = 0; //加載T1重載值
- TL1 = 0;
- ET1 = 1; //使能T1中斷
- }
- /*mian函數*/
- void main()
- {
- EA = 1; //開總中斷
- ConfigTimer0(1); //配置T0定時1ms
- ConfigTimer1(); //配置T1
- TUBE_Display(0);//數碼管初始化
- BUZZ=0;//蜂鳴器提示,程序開啟,
- while(1)
- {
- KeyDriver();//按鍵驅動函數,
- }
- }
- /* T0中斷服務函數,實現系統定時和按鍵掃描 */
- void InterruptTimer0() interrupt 1
- {
- static unsigned int tmr1000ms = 0;
- TH0 = T0RH; //重新加載重載值
- TL0 = T0RL;
- TUBE_Init(); //數碼管掃描函數
- KeyScan(); //按鍵掃描函數
- tmr1000ms++; //定時1000ms
- if (tmr1000ms >= 1000)//tmr1000ms=1000,時間為1S
- {
- tmr1000ms = 0;
- flag1s ++;
- if(flag1s>=2)BUZZ=1;//兩秒后,蜂鳴器停止,
- if(0==index)//模式=1,開啟超聲波測距
- {
- TUBE_Display(GetDistance());
- IfDistance();//蜂鳴器警報
- }
- }
- }
- /* 數碼管初始化函數 */
- void TUBE_Init()
- {
- static unsigned char choice=0;
- //P1=0XFF;
- switch(choice)//數碼管掃描
- {
- case 0: TUBE4=0;TUBE3=1;TUBE2=1;TUBE1=1;choice++;P1=LedBuff[0];break;
- case 1: TUBE4=1;TUBE3=0;TUBE2=1;TUBE1=1;choice++;P1=LedBuff[1];break;
- case 2: TUBE4=1;TUBE3=1;TUBE2=0;TUBE1=1;choice++;P1=LedBuff[2];break;
- case 3: TUBE4=1;TUBE3=1;TUBE2=1;TUBE1=0;choice=0;P1=LedBuff[3];break;
- default:break;
- }
- }
- /* 數碼管顯示函數 */
- void TUBE_Display(unsigned int dis)
- {
- //更改顯示數碼管數據
- LedBuff[0]=LedChar[dis%10];
- LedBuff[1]=LedChar[dis/10%10];
- LedBuff[2]=LedChar[dis/100%10];
- //判斷模式,最高位數碼管表示模式
- if(0==index)LedBuff[3]=LedChar[10];
- if(1==index)LedBuff[3]=LedChar[11];
- if(2==index)LedBuff[3]=LedChar[12];
- }
- /* 數碼管按鍵顯示函數 */
- void TUBE_KeyDisplay(unsigned int key)
- {
-
- switch(index)//判斷模式
- {
- case 0://模式一,超聲波測距
- if(0==key)//按下按鍵一,模式+1
- {
- ++index;
- TUBE_Display(testHighest);
- }
- break;
- case 1://模式二,設置超聲波最高測距距離
- if(0==key)//按下按鍵一,模式+1
- {
- ++index;
- TUBE_Display(testLowest);
- }
- if(1==key)//按下按鍵二,超聲波設置的最高測距距離+1
- {
- if(HIGHEST>testHighest)testHighest++;
- TUBE_Display(testHighest);
- }
- if(2==key)//按下按鍵三,超聲波設置的最高測距距離-1
- {
- if(LOWEST<testHighest)testHighest--;
- TUBE_Display(testHighest);
- }
- break;
- case 2://模式三,設置超聲波最低測距距離
- if(0==key)//按下按鍵一,模式+1
- {
- ++index;
- TUBE_Display(GetDistance());
- }
- if(1==key)//按下按鍵二,超聲波設置的最低測距距離+1
- {
- if(HIGHEST>testLowest)testLowest++;
- TUBE_Display(testLowest);
- }
- if(2==key)//按下按鍵三,超聲波設置的最低測距距離-1
- {
- if(LOWEST<testLowest)testLowest--;
- TUBE_Display(testLowest);
- }
- break;
- default:break;
- }
- if(index>=3)index=0;
- }
- /* 按鍵驅動函數,檢測按鍵動作,調度相應動作函數,需在主循環中調用 */
- void KeyDriver()
- {
- unsigned char i;
- static unsigned char pdata backup[3] = { 1, 1, 1}; //按鍵值備份,保存前一次的值
- for (i=0; i<3; i++) //循環檢測按鍵
- {
- if (backup[i] != KeySta[i]) //檢測按鍵動作
- {
- if (backup[i] != 0) //按鍵按下時執行動作
- {
- TUBE_KeyDisplay(i);//調用按鍵動作函數
- }
- backup[i] = KeySta[i]; //刷新前一次的備份值
- }
- }
- }
- /* 按鍵掃描函數,需在定時中斷中調用,推薦調用間隔1ms */
- void KeyScan()
- {
- unsigned char i;
- static unsigned char keyout = 0; //矩陣按鍵掃描輸出索引
- static unsigned char keybuf[3] = {0xFF, 0xFF, 0xFF}; //矩陣按鍵掃描緩沖區
- //將3個按鍵值移入緩沖區
- keybuf[0] = (keybuf[0] << 1) | KEY0;
- keybuf[1] = (keybuf[1] << 1) | KEY1;
- keybuf[2] = (keybuf[2] << 1) | KEY2;
- //消抖后更新按鍵狀態
- for (i=0; i<3; i++) //3個按鍵,循環3次
- {
- if (keybuf[i] == 0x00)
- { //連續8次掃描值為0,即8ms內都是按下狀態時,可認為按鍵已穩定的按下
- KeySta[i] = 0;
- }
- else if (keybuf[i] == 0xFF)
- { //連續8次掃描值為1,即8ms內都是彈起狀態時,可認為按鍵已穩定的彈起
- KeySta[i] = 1;
- }
- }
- //執行下一次的掃描輸出
- keyout++; //輸出索引遞增
- if(keyout>=3)keyout = 0; //索引值加到3即歸零
- }
- /* 超聲波測距函數 */
- unsigned int GetDistance(void)
- {
- unsigned int ss;//用于記錄測得的距離
- trig = 1;//給IO口trig高電平
- _nop_();//延時 時間要大于10us
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- trig = 0;//給IO口trig低電平
- while(!echo);//當echo為高電平的時候,跳出循環
- TH1 = 0;//定時器清零
- TL1 = 0;
- TR1 = 1;//啟動定時器1,開啟計時
- while(echo);//echo不為0,即脈沖返回結束,計時結束
- TR1 = 0;//停止計時
- //ss = ((TH1 * 256 + TL1) * 0.34) / 2;//計算距離
- ss = (TH1 * 256 + TL1) /58;//計算距離,公式= us/58 單位是cm 或 us/148 單位是英寸
- if(ss<HIGHEST && ss>LOWEST)return ss; //判斷距離是否在超聲波測距的最大值和最小值范圍內,“是”返回SS
-
- return 0; // “否”返回0
- }
- /* 蜂鳴器警報函數 */
- void IfDistance(void)
- {
- unsigned int ss;//用于記錄測得的距離
- ss=GetDistance();//得到超聲波測得的距離
- //判斷超聲波測到的距離是否在超聲波設置測距的最大值和最小值范圍內
- if(ss>testHighest || ss<testLowest)BUZZ=0;//蜂鳴器發聲
- }
復制代碼 全部資料51hei下載地址:
|
評分
-
查看全部評分
|