這是我之前做的基于STM32的超聲波測距系統,
附件里面包含了keil仿真代碼以及Proteus仿真工程
請大家多多指教
屏幕截圖 2025-01-05 110902.png (87.36 KB, 下載次數: 0)
下載附件
2025-1-5 11:09 上傳
單片機源程序如下:
- //頭文件包含
- #include <reg52.h> //提供單片機寄存器地址
- #include <intrins.h> //提供_nop_()函數
- unsigned int code duan_ma[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, //0~9
- 0x77,0x7c,0x39,0x5e,0x79,0x71}; //A~F
- unsigned int dis_buf[4]; //顯示緩存的數組
- unsigned int S = 0; //距離緩存變量
- unsigned long time = 0; //時間緩存變量
- unsigned int S_H = 400, S_L = 10; //S_H:報警上限值,默認400cm,S_L:報警下限值,默認10cm
- //引腳定義
- sbit BEEP = P3^7; //蜂鳴器控制端口,低電平有效,無源蜂鳴器
-
- #define digDuan P0 //數碼管段控制端口,高電平有效
- sbit digWei1 = P2^4; //第1位數碼管控制端口,低電平有效
- sbit digWei2 = P2^5; //第2位數碼管控制端口,低電平有效
- sbit digWei3 = P2^6; //第3位數碼管控制端口,低電平有效
- sbit digWei4 = P2^7; //第4位數碼管控制端口,低電平有效
-
- sbit KEY1 = P1^0; //設置鍵
- sbit KEY2 = P1^1; //加鍵
- sbit KEY3 = P1^2; //減鍵
-
- sbit Ttig = P1^3; //觸發信號控制端口
- sbit Echo = P1^4; //回響信號接收端口
-
- /* 定時器0和1初始化,定時1ms */
- void InitTimer0(void)
- {
- TMOD = 0x11; //配置定時器0為工作方式1,定時器1位工作方式1
- TH0 = 0;
- TL0 = 0;
- TH1 = 0x0EC; //定時5ms
- TL1 = 0x78;
- EA = 1; //打開總中斷
- ET1 = 1; //打開定時器0中斷
- TR1 = 1; //打開定時器1
- TR0 = 0; //打開定時器0
- }
- /*
- * 數碼管掃描
- * *dat:以數組的方式傳值,使用的時候直接填入數組名即可
- */
- void dig_scan(unsigned int *dat)
- {
- static unsigned char i = 0; //循環變量
- /* 數碼管掃描處理 */
- digDuan = 0x00; //消隱
- digWei1 = 1;
- digWei2 = 1;
- digWei3 = 1;
- digWei4 = 1;
- switch(i)
- {
- case 0:
- {
- digWei1 = 0; //選通第1位數碼管
- digDuan = dat[0]; //顯示第1位數碼管的內容
- break;
- }
- case 1:
- {
- digWei2 = 0; //選通第2位數碼管
- digDuan = dat[1]; //顯示第2位數碼管的內容
- break;
- }
- case 2:
- {
- digWei3 = 0; //選通第3位數碼管
- digDuan = dat[2] + 0x80; //顯示第3位數碼管的內容,順便也顯示小數點
- break;
- }
- case 3:
- {
- digWei4 = 0; //選通第4位數碼管
- digDuan = dat[3]; //顯示第4位數碼管的內容
- break;
- }
- default: break;
- }
- ++i; //數碼管位選變量循環
- if(i >= 4)
- i = 0;
- }
- /* 按鍵延時函數,單位:ms */
- static void key_delayms(unsigned int ms)
- {
- unsigned char a,b,c;
- while(--ms)
- {
- for(c=1;c>0;c--)
- for(b=142;b>0;b--)
- for(a=2;a>0;a--);
- }
- }
- /* 按鍵掃描 */
- unsigned char key_scan(void)
- {
- if(KEY1 == 0) //如果按鍵1按下
- {
- key_delayms(10); //延時10ms,去除按鍵抖動
- if(KEY1 == 0) //再判斷一次按鍵按下
- {
- return 1; //輸出鍵值1
- }
- }
- if(KEY2 == 0) //如果按鍵2按下
- {
- key_delayms(10); //延時10ms,去除按鍵抖動
- if(KEY2 == 0) //再判斷一次按鍵按下
- {
- return 2; //輸出鍵值2
- }
- }
- if(KEY3 == 0) //如果按鍵3按下
- {
- key_delayms(10); //延時10ms,去除按鍵抖動
- if(KEY3 == 0) //再判斷一次按鍵按下
- {
- return 3; //輸出鍵值3
- }
- }
- return 0; //如果沒有按鍵按下,則輸出0
- }
- /* 啟動超聲波程序 */
- void StartModule(void)
- {
- Ttig = 1; //啟動一次模塊
- _nop_(); //延時一段時間,至少10us以上
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- Ttig = 0;
- }
- /* 延時,單位:ms */
- void delayms(unsigned int ms)
- {
- unsigned char a,b,c;
- while(--ms)
- {
- for(c=1;c>0;c--)
- for(b=142;b>0;b--)
- for(a=2;a>0;a--);
- }
- }
- /* 計算測距 */
- void count(void)
- {
- StartModule(); //啟動一次超聲波
- while(!Echo); //等待超聲波模塊輸出IO拉高
- TR0 = 1; //開啟定時器計時
- while(Echo); //等待超聲波模塊輸出IO拉低
- TR0 = 0; //關閉定時器計時
-
- /* 計算距離 */
- time = TH0 * 256 + TL0; //得到的時間,專業寫法應該是這樣:time = TH0 << 8 | TL0
- TH0 = 0; //定時計數器清零
- TL0 = 0;
-
- S = (time * 1.7) / 100; //算出來是M
- }
- /* 顯示距離 */
- void dis_distance(void)
- {
- dis_buf[3] = 0x00;
- dis_buf[2] = duan_ma[S / 100 %10]; //取出百位數,并在數碼管的第3位顯示,從右往左數
- dis_buf[1] = duan_ma[S / 10 %10]; //取出十位數,并在數碼管的第2位顯示,從右往左數
- dis_buf[0] = duan_ma[S % 10]; //取出個位數,并在數碼管的第1位顯示,從右往左數
- }
- /* 設置報警功能 */
- void key_fuction(void)
- {
- unsigned char mode_flag = 1; //模式切換標記位,1:設置上限值,2:設置下限值,3:退出
- while(1)
- {
- if(key_scan() == 1)
- {
- BEEP = 0; //按鍵提示音
- delayms(50);
- BEEP = 1;
- delayms(1000);
- ++mode_flag;
- if(mode_flag >= 3) //如果滿3了,則退出
- break;
- }
- if(key_scan() == 2) //如果加鍵按下
- {
- BEEP = 0; //按鍵提示音
- delayms(50);
- BEEP = 1;
- delayms(1000);
- if(mode_flag == 1) //設置上限值
- {
- ++S_H;
- if(S_H > 400)
- S_H = 2;
- }
- if(mode_flag == 2) //設置下限值
- {
- ++S_L;
- if(S_L > 400)
- S_L = 2;
- }
- }
- if(key_scan() == 3) //如果減鍵按下
- {
- BEEP = 0; //按鍵提示音
- delayms(50);
- BEEP = 1;
- delayms(1000);
- if(mode_flag == 1) //設置上限值
- {
- --S_H;
- if(S_H < 2)
- S_H = 400;
- }
- if(mode_flag == 2) //設置下限值
- {
- --S_L;
- if(S_L < 2)
- S_L = 400;
- }
- }
- /* 報警設置顯示 */
- if(mode_flag == 1) //顯示設置上限值內容
- {
- dis_buf[3] = 0x76; //第4位數碼管顯示字母 H
- dis_buf[2] = duan_ma[S_H / 100 % 10]; //顯示百位數
- dis_buf[1] = duan_ma[S_H / 10 % 10]; //顯示十位數
- dis_buf[0] = duan_ma[S_H % 10]; //顯示個位數
- }
- if(mode_flag == 2) //顯示設置下限值內容
- {
- dis_buf[3] = 0x38; //第4位數碼管顯示字母 L
- dis_buf[2] = duan_ma[S_L / 100 % 10]; //顯示百位數
- dis_buf[1] = duan_ma[S_L / 10 % 10]; //顯示十位數
- dis_buf[0] = duan_ma[S_L % 10]; //顯示個位數
- }
- }
- }
- /* 主函數 */
- void main(void)
- {
- digDuan = 0x40; //顯示"----"
- digWei1 = 0;
- digWei2 = 0;
- digWei3 = 0;
- digWei4 = 0;
- delayms(1000); //延時大約1s
- InitTimer0(); //定時器0初始化
- while(1)
- {
- count(); //計算距離
- if(S>=S_H || S<=S_L) //如果超出設定的范圍,則顯示"---"
- {
- dis_buf[3] = 0x00;
- dis_buf[2] = 0x40; //顯示"---"
- dis_buf[1] = 0x40;
- dis_buf[0] = 0x40;
- BEEP = 0; //蜂鳴器鳴叫
- delayms(1000);
- }
- else
- {
- BEEP = 1; //關閉蜂鳴器
- dis_distance(); //顯示距離
- }
- if(key_scan() == 1) //如果按下設置鍵,則進入設置報警功能
- {
- BEEP = 0; //按鍵提示音
- delayms(50);
- BEEP = 1;
- delayms(100);
- key_fuction(); //進入設置報警功能
- }
- }
- }
- /* 定時器0中斷服務函數,5ms進一次本中斷,用于數碼管掃描 */
- void Timer1Interrupt(void) interrupt 3
- {
- TH1 = 0x0EC; //定時5ms,重新賦值
- TL1 = 0x78;
- dig_scan(dis_buf); //數碼管顯示距離
- }
復制代碼
Proteus8.17仿真程序:
單片機超聲波.zip
(149.3 KB, 下載次數: 0)
2025-1-5 11:07 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|