91视频免费?看_蜜芽MY188精品TV在线观看_国产免费无遮挡在线观看视频_深夜国产_亚洲精品欧洲精品_欧美黑人粗暴多交

ReCclay
認證:VIP會員
所在專題目錄 查看專題
【藍橋杯單片機組模塊】5、EEPROM模塊
【藍橋杯單片機組模塊】6、AD/DA轉換模塊
【藍橋杯單片機組模塊】7、DS18B20溫度傳感器模塊
【藍橋杯單片機組模塊】8、DS1302時鐘模塊
【藍橋杯單片機組模塊】9、超聲波模塊
【藍橋杯單片機組模塊】10、NE555模塊
作者動態 更多
【FPGA基礎】基于 Pango Design Suite(PDS) 的FPGA開發流程
2021-05-14 11:22
【FPGA基礎】基于Quartus Prime 17.1 的FPGA開發流程
2021-05-08 17:49
【AD快速入門】8051最小系統繪制
2021-04-22 10:03
藍橋嵌入式之 ADC電壓采集與顯示
2021-04-14 11:48
藍橋嵌入式之 實時時鐘RTC
2021-04-13 14:50

【藍橋杯單片機組模塊】9、超聲波模塊

導讀:《藍橋杯單片機組》專欄文章是博主2018年參加藍橋杯的單片機組比賽所做的學習筆記,在當年的比賽中,博主是獲得了省賽一等獎,國賽二等獎的成績。成績雖談不上最好,但至少問心無愧。如今2021年回頭再看該系列文章,仍然感觸頗多。為了能更好地幫助到單片機初學者,今年特地抽出時間對當年的文章邏輯和結構進行重構,以達到初學者快速上手的目的。需要指出的是,由于本人水平有限,如有錯誤還請讀者指出,非常感謝。那么,接下來讓我們一起開始愉快的學習吧。

代碼下載可到Github<傳送門>

一、基礎理論

超聲波模塊的工作原理:單片機供給超聲波信號端Trig一個最少10us長的高電平觸發信號,模塊自動發射8個40khz的方波,同時自動檢測到信號是否返回,一旦有信號返回,Echo端輸出一個高電平高電平持續的實踐就是超聲波從發射到返回的時間。 對應的測試距離計算方法 :(高電平時間*聲速(340m/s))/2

超聲波模塊原理圖

雖然我們板子上的不再是集成模塊了,但是原理還是一樣的。只是沒有了Trig即不需要觸發信號,同時需要程序實現連續發送8個40khz的方波,然后計算接收端持續為1的時間即可。

二、動手實驗

程序中有幾點需要注意的:

  • 40Khz的方波實現方法,方波就是占空比為1/2的矩形波,40k對應25us,所以我們可以通過發送引腳為高低電平分別持續13us實現40khz的方波!
  • 我是們是用定時器計數來實現計時的,所以還要考慮定時器溢出的問題,對應顯示的距離也應處理!
  • 一般上如果我們使用成品模塊的話都會把接收引腳放到外部中斷,一旦收到低電平信號就進入外部中斷停止計時,這樣做更精確!但是不盡人意的是藍橋的板子并不是接在了外部中斷(突然讓我想起來惡心的紅外也不是接在外部中斷)!
  • 不要刷太快,200ms即可!!
  • time*0.17是帶一個小數點位的,別忘了小數點

這里寫圖片描述

JS2 - 超聲波發送端

用的是反相器推挽輸出,這樣可以加大發射頻率。

JS1 - 超聲波接收端

用的CX20106X這個紅外芯片接收40KHz的方波。這個典型電路的優點就是誤差小,1m內為mm級,2m內1cm左右,5m內3cm左右。

貼出超聲波相關的代碼。

/*
*******************************************************************************
* 文件名:sonic.c
* 描  述:
* 作  者:CLAY
* 版本號:v1.0.0
* 日  期: 
* 備  注:
*         
*******************************************************************************
*/

#include "config.h"
#include <intrins.h>
#include "main.h"


void Delay13us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}

void InitSonic()
{
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TF1 = 0;
	TR1 = 0;		
}

void SendWave()
{
 	u8 i = 8;
	
	while(i--)
	{
		Sonic_Txd = 1;
		Delay13us();
		Sonic_Txd = 0;
		Delay13us();
	}
}

void SonicDriver()//數碼管顯示
{
	u16 time, distance;

	SendWave();//發送8個40Khz脈沖信號
	TH1 = 0; //清零計數值準備開始
	TL1 = 0;
	TR1 = 1;
	while((Sonic_Rxd) && (TF1==0));
	TR1 = 0;
	
	if(TF1 == 1)
	{
	 	TF1 = 0;
		LedBuff[0] = 0xBF; //對應顯示橫線
		LedBuff[1] = 0xBF;
		LedBuff[2] = 0xBF;
		LedBuff[3] = 0xBF;
	}
	else 
	{
	 	time = (TH1 * 256) + TL1;
		distance = (u16)((time * 0.17 * 12) / 11.0592); //[機器周期*定時器計時*10^(-6)](s) * 340(m/s)/2 * 10^(2); 單位厘米,且有一位小數點!
		LedBuff[0] = LedChar[distance%10];				  
		LedBuff[1] = LedChar[distance/10%10];
		LedBuff[1] &= 0x7F;	//點亮小數點
		LedBuff[2] = LedChar[distance/100%10];
		LedBuff[3] = LedChar[distance/1000%10];
	}
}

需要再次強調的一段代碼

time = (TH1 * 256) + TL1;
distance = (u16)((time * 0.17 * 12) / 11.0592); 
//[機器周期*定時器計時*10^(-6)](s) * 340(m/s)/2 * 10^(2); 單位厘米,且有一位小數點!

算出的是單位cm后還帶一個小數位!如果直接用12M晶振的話就是1us,一個機器周期。

distance = (u16)(time * 0.17 ); 

記錄一點網上提到的小錯誤:

time = (TH1 * 256) + TL1;有人這樣寫time = TH1 << 8 | TL1沒問題!<<運算符優先級比|高! 但是如果你這樣寫time = TH1 << 8 + TL1看著是對的!但是,你可以在C語言相關編程環境下試試!得到的答案是錯的,原因也很簡單,+的優先級比<<高!所以很有必要自己寫程序的時候隨手加上括號,不要想當然地寫優先級!


可直接使用的程序(超聲波數據保留小數點后一位)

#include "config.h"

sbit Sonic_Txd = P1^0;
sbit Sonic_Rxd = P1^1;

u8 LedChar[] = {
	0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90
};
u8 LedBuff[] = {
	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};

u32 cnt = 0;
u8 T1RH, T1RL;
bit flag200ms = 1;

void CloseFucker();
void ConfigTimer0();
void ConfigTimer1(u16 ms);
void ShowNumber(u16 num);
void SendWave();

void main()
{
	u16 time, distance=0;

	EA = 1;
	CloseFucker();
	ConfigTimer0();
	ConfigTimer1(1);

	while(1)
	{
		if(flag200ms)
		{
			flag200ms = 0;

			TH0 = 0;
			TL0 = 0;
			TF0 = 0;
			SendWave();
			TR0 = 1;
			while((Sonic_Rxd) && (TF0==0));
			TR0 = 0;
			
			if(TF0)
			{
			 	LedBuff[3] = 0xBF;
				LedBuff[2] = 0xBF;
				LedBuff[1] = 0xBF;
				LedBuff[0] = 0xBF;
			}
			else
			{
				time = ((u16)TH0<<8)+TL0;
				distance = 0.17 * time;
				ShowNumber(distance);	
			}	
		}					
	}
			
}

void Delay13us()		//@11.0592MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 33;
	while (--i);
}


void SendWave()
{
 	u8 i=8;
	
	while(i--)
	{
	 	Sonic_Txd = 1;
		Delay13us();
		Sonic_Txd = 0;
		Delay13us();	
	}	
}

void ShowNumber(u16 num)
{
 	u8 buf[8];
	char i;
	
	for(i=0; i<4; i++)
	{
	 	buf[i] = num%10;
		num /= 10;
	} 	
	for(i=3; i>0; i--)
	{
	 	if(buf[i] == 0)
		{
		 	LedBuff[i] = 0xFF;
		}
		else
		{
		 	break;
		}
	}
	for( ; i>=0; i--)
	{
		LedBuff[i] = LedChar[buf[i]];
	}
	LedBuff[1] &= 0x7F;
}

void CloseFucker()
{
 	P2 = (P2&0x1F)|0xA0;
	P0 = P0&0xAF;
	P2 = P2&0x1F;
}

void ConfigTimer0()
{	
	TMOD &= 0xF0;
	TMOD |= 0x01;
	TR0 = 0;
	TF0 = 0; 	
}

void ConfigTimer1(u16 ms)
{
	u32 tmp;
	
	tmp = 11059200/12;
	tmp	= (tmp*ms)/1000;
	tmp = 65536 - tmp;
	T1RH = (u8)(tmp>>8);
	T1RL = (u8)tmp;
	TMOD &= 0x0F;
	TMOD |= 0x10;
	TH1 = T1RH;
	TL1 = T1RL;
	ET1 = 1;
	TR1 = 1;
}

void LedScan()
{
 	static u8 index = 0;
	
	P2 = (P2&0x1F)|0xE0;
	P0 = 0xFF;
	P2 = P2&0x1F;
	P2 = (P2&0x1F)|0xC0;
	P0 = 0x80>>index;
	P2 = P2&0x1F;
	P2 = (P2&0x1F)|0xE0;
	P0 = LedBuff[index];
	P2 = P2&0x1F;

	index++;
	index &= 0x07;
}


void InterruptTimer1() interrupt 3
{
	static u16 tmr200ms = 0;
	TH1 = T1RH;
	TL1 = T1RL;
	tmr200ms++;

	if(tmr200ms >= 200)
	{
	 	tmr200ms = 0;
		flag200ms = 1;
	}
	
	LedScan();
}

小結:本篇文章主要介紹了單片機學習中的一個進階模塊:超聲波模塊。從基礎理論到試驗以及試驗踩坑,都有涉及。在該部分也并沒有太難的知識點,多多練習該模塊對比賽名次大有裨益。

希望大家多多支持我的原創文章。如有錯誤,請大家及時指正,非常感謝。

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 346
收藏 348
關注 431
成為作者 賺取收益
全部留言
0/200
  • dy-i2UfRuvP 2021-05-19 13:22
    感謝分享
    回復
  • dy-iipPZRPN 2021-05-13 22:45
    期待繼續
    回復
  • dy-3EbVR6Ei 2021-05-13 22:36
    大開眼界,真是好文
    回復
  • dy-Xq2JxpfN 2021-05-13 22:18
    對我很有幫助
    回復
  • dy-9g42stbW 2021-05-13 22:07
    大開眼界,真是好文
    回復
  • dy-mLj7kl5v 2021-05-13 20:43
    圍觀學習
    回復
  • dy-apcih3c1 2021-05-13 20:26
    圍觀學習
    回復
  • dy-k78ZHtFD 2021-05-13 20:09
    不亞于看了一篇高質量論文
    回復
  • dy-nAWdnPGS 2021-05-13 18:55
    對我很有幫助
    回復
  • dy-prSX6RBY 2021-05-13 18:47
    對我很有幫助
    回復
  • dy-jqGVYqsF 2021-05-13 16:52
    對我很有幫助
    回復
  • dy-VIQ9auhf 2021-05-13 15:06
    什么時候更新
    回復
  • dy-7mura2gg 2021-05-13 14:50
    大開眼界,真是好文
    回復
  • dy-YN3DYTeH 2021-05-13 14:41
    大開眼界,真是好文
    回復
  • dy-9hjGevyn 2021-05-13 13:58
    思路清晰,受益匪淺
    回復
  • dy-H1WY5jXH 2021-05-13 13:25
    圍觀學習
    回復
  • dy-wVQjSHHX 2021-05-13 13:09
    圍觀學習
    回復
  • dy-88VlYaFf 2021-05-12 15:53
    講的真好!
    回復
  • dy-9QTV6UZW 2021-05-12 15:30
    精彩,很多東西還沒接觸到
    回復
  • dy-WYS5BCmB 2021-05-12 15:15
    大開眼界,真是好文
    回復
主站蜘蛛池模板: 石景山区| 扎鲁特旗| 望都县| 双桥区| 隆回县| 玛沁县| 高雄市| 芷江| 彝良县| 广宁县| 汶上县| 赤城县| 岳西县| 比如县| 武川县| 固镇县| 广东省| 郸城县| 拉孜县| 涿州市| 多伦县| 合肥市| 松阳县| 铁力市| 清水河县| 巴里| 晋城| 淳化县| 濉溪县| 安龙县| 邓州市| 马公市| 云梦县| 天水市| 金溪县| 五指山市| 宕昌县| 棋牌| 桃园市| 揭西县| 自贡市|