1 緒論 1
1.1 選題的背景及意義 1
1.2 國內外的研究現狀以及發展趨勢 1
1.3 工作的預期成果 2
1.4 主要研究內容 2
2 系統總體設計方案 2
3語音識別功能 3
3.1 LD3320語音模塊的介紹 3
3.2 LD3320主要特色功能 4
3.3 內部單元模塊 4
3.4 關鍵詞的錄入 5
4 單片機及各個模塊的介紹 5
4.1 STC單片機簡介 5
4.2 電機驅動模塊 6
4.2.1 L298N芯片 6
4.2.2 PWM調速 6
4.3數碼管 7
4.3.1 數碼管的應用 7
4.3.2 數碼管的結構 7
4.4 穩壓電路 8
4.5 加速、減速 9
5 系統軟、硬件設計 9
5.1 系統仿真及軟件設計 9
5.2 實物圖 12
結論 12
參考文獻 14
附錄 15
致謝 22
1 緒論
1.1 選題的背景及意義
當前,機器人只是能夠對人類進行簡單模仿。這遠遠達不到人類所需求的功能。人們一直都在尋求一種方式能讓機器識別出人類語言。因此,為了適應人類科學技術的發展與對于人機交流日益增長的需求,語音識別技術應運而生。比如玩具市場,擁有高科技技術的智能化玩具發展迅速。電子化的玩具逐漸取代傳統的玩具成為發展潮流。雖然我國是玩具生產大國,但在高科技玩具領域依然有很大的發展空間。所以,增加對該方面研究的重視程度,在技術的創新方面和推動我國經濟快速發展的方面,都有其現實的意義。除此之外,機器人還能夠取代我們完成危險性的工作或者具有重復性以及精確度高的工作。利用語音識別的方法,機器人可以把人類所說的話轉化為機器人可識別命的令。與機器人進行語音交互是人類夢寐以求的事情。最近幾年,語音識別技術的發展迅猛,成績顯著且逐漸步入市場。
1.2 國內外的研究現狀以及發展趨勢
近幾年,單片機越來越便宜,使用的數量越來越多。國外機器人性能越來越強,器件集成化,模塊化逐漸成為發展趨勢。其不僅方便使用還在很大程度上減小維修時的工作量。基于PC機的開放型控制器逐漸代替傳統的模式成為新型的高科技技術。目前機器人的特點不再是追求全自治系統而是追求人機交互技術。除此之外,新興起的VR技術也在機器人中得到很大的應用。
機器人的制造及應用水平,代表了一個國家的制造業水平,發展機器人產業應上升到國家戰略高度。機器人的廣泛使用是我國從制造業大國走向制造業強國的重要手段和途徑。
我國對機器人的學習起步時間相比于國外較晚,但發展迅猛,在國內外占據了一定的市場。從1970-1980的剛剛開始起步,到1980-1990進行逐步探索,再到1990至今開始應用,我國機器人發展越來越快。蛇形機器人的問世表明我國制造機器人的能力又向前邁進了一大步。
對于我國來說,機器人的制造還存在局限性。在機器人的制造時還有部分零件需要進口,不能實現獨立自主的創造。所以未來的工作主要是研究機器人的核心控制器。該控制器還需具有自主性,實現從中國制造向中國創造的轉變。除此之外,還應形成一個完善的標準,實現模塊化的結構,以便于后期的改造集成。更好的與傳感器結合,結合VR技術以及正在蓬勃發展的人機交互技術才能更好的實現智能化。
綜合國內外機器人研究和應用現狀,機器人的研究正在超智能化、模塊化、系統化、微型化、多功能化及高性能、自診斷、自修復趨勢發展,以適應多樣化、個性化的需求向更大更寬廣的應用領域發展。
1.3 工作的預期成果
本次設計希望能夠通過LD3320語音識別模塊識別語音指令并把相似度最高的關鍵字所代表的內容發送給單片機,以達到控制機器人前進,后退,左轉,右轉和加減速的目的,同時可以使數碼管顯示“1”,“2”,“3” 或“4”。
1.4 主要研究內容
本文主要研究當機器人加入了語音識別功能時出現的問題及解決辦法。語音識別的實現分為3部分:關鍵字的寫入,ID的設置,識別過程。除此之外,還詳細描述語音識別系統將識別結果傳遞給主控單片機后,單片機是如何驅動電機以及如何對數碼管進行控制。
根據以上內容,我們可以大致了解本次設計所需要做的工作。下面,我們著重介紹該語音識別機器人系統的總體設計方案。
2 系統總體設計方案
本次設計中,首先通過麥克風將語音信號傳入語音識別芯片,當語音模塊與參考模式庫中的關鍵詞列表相比對后,將識別結果傳送給主控制器。然后,主控制器分別控制數碼管的顯示和直流電機轉動。
語音識別機器人原理圖如下:
圖2-1 語音識別機器人原理
本次設計分為兩個大的部分:語音識別部分和由STC控制的電路部分。第一步,語音識別模塊部分和由STC控制的電路部分都進行初始化工作,主要包括變量的設定,設置定時器的工作方式,還有關于中斷的設置等。然后對語音模塊寫入關鍵詞列表,打開循環系統,檢測是否有信號觸發系統工作,如果是,則開始定時。在此次定時結束之前,檢測是否有聲音的輸入,如果有,就進行匹配;沒有的話,就開始下一次的循環。通過頻譜分析的方法檢測是否為關鍵詞列表中的詞,不是的話就進行下一次循環,是的話就作為最佳的結果輸出給單片機的P3^0到P3^7引腳,并由單片機控制數碼管和電機。
圖2-2為實現該語音識別機器人的流程圖。
圖2-2 語音識別機器人流程圖
接下來,介紹本次設計中的語音識別部分的知識。
3語音識別功能
3.1 LD3320語音模塊的介紹
LD3320芯片的優勢是其采用了非特定人語音識別技術。即任何人在指令正確的前提下,都可以控制。基于LD3320可以輕松實現多人使用的功能。
語音識別是完成語音控制的核心技術。通過語音實現人機交互成為目前研究的難點和熱點。這次設計所用到的語音模塊是運用STC11L08XE單片機,配合ICRoute公司的高性能LD3320語音識別芯片,分別實現語言控制系統的主控制模塊、總體結構和語音識別模塊的軟硬件設計。運用該模塊實現了基于非特定人語音識別系統的設計。
語音的識別過程主要有兩個階段:訓練階段與識別階段。無論是訓練還是識別階段,輸入的語音都必須經過預處理和特征提取兩個過程。其中訓練階段是利用用戶輸入的多次訓練語音,通過預處理和特征提取兩個過程,得到特征參數,最后利用特征參數建模,完成訓練語音參考模型庫的建立。識別階段是將輸入的語音特征矢量參數和參考模式庫中的參考模型進行相似性度量比較,然后把相似度最高的輸入特征矢量作為識別結果輸出,從而達到語音識別的目的。
工作原理圖如圖3-1所示:
圖3-1語音識別原理框圖
3.2 LD3320主要特色功能
1、非特定人語音識別技術:不需要用戶進行錄音訓練。
2、可動態編輯的識別關鍵詞語列表:只需要把識別的關鍵詞語以字符串的形式傳送進芯片,即可以在下次識別中立即生效。比如,用戶在單片機的編程中,簡單地通過設置芯片的寄存器,把諸如“你好”這樣的識別關鍵詞的內容動態地傳入芯片中,芯片就可以識別這樣設定的關鍵詞語了。
3、真正單芯片解決方案:不需要任何外接的輔助Flash和RAM,真正降低系統成本。
4、內置高精度A/D和D/A通道:不需要外接AD芯片,只需要把麥克風接在芯片的AD引腳上。
5、高準確度和實用的語音識別效果。
6、支持用戶自由編輯50條關鍵詞語:在同一時刻,最多在50條關鍵詞語中進行識別,終端用戶可以根據場景需要,隨時編輯和更新這50條關鍵詞語的內容。
3.3 內部單元模塊
LD3320語音識別模塊的主控制單元STC11L08XE能更好的處理數據且輸入輸出端口方便控制。其內部就包含一個很可靠的復位電路,適用于干擾大,速度要求快的環境。其內部包含CPU、程序存儲器、數據存儲器、定時器、計數器、輸入輸出接口、看門狗、片內\片外振蕩電路、UART串口等。
3.4 關鍵詞的錄入
關鍵詞列表的形成是LD3320中關鍵的部分。STC11L08XE單片機可以在收到外部一個觸發后,啟動定時識別過程并且在這個時間段內說出想要識別的關鍵詞語。超過這個時間后,需要用戶再次觸發才能啟動一個識別過程。也可以使用反復識別的方法,沒有語音時,則識別過程定時結束后再啟動一個新的識別過程。有語音時,則在根據識別作相應處理后,再次開啟新的識別過程。當需要的關鍵詞語錄入完畢后,可以適當錄入一些類似的詞語。這些類似的詞被稱作“垃圾關鍵詞語”,這是為了減少錯誤識別的情況。例如,針對“北京”這個詞,我們可以在補充“北方”,“南京”這種類似的詞。當識別出“北京”后,我們可以斷定結果是正確的。如果出現“北方”,“南京”,就可以判斷是由于雜音造成的錯誤,并且接著啟動一次檢測。采用該方法,可以很大程度上減少錯誤識別出現的情況。因為只有識別結果在所指定的關鍵詞中才被認為是有效的詞語。
關鍵詞語的錄入是通過拼音串的形式錄入模塊中的。在錄入拼音串時要同步錄入相應的ID。用這個ID指代該關鍵詞語。相應的,語音模塊識別出相似度最高的詞也是通過該ID傳出。終端用戶在說語音指令時,可能對同一詞匯有不同的發音習慣。比如“打開電燈”和“開燈”,“打開燈”,“把燈打開”。我們可以用同一個ID來指代這些意思相同的詞匯。另外,還可以把添加的垃圾關鍵詞語的ID都標記為一個值。這樣在程序中就很容易識別錯誤的詞匯。
充分利用LD3320的50條可動態編輯的關鍵詞語,開發者可以把這些習慣發音都設置進芯片,這樣無論用戶怎么說,都會被識別出來,進一步增加終端用戶的良好體驗。
4 單片機及各個模塊的介紹
4.1 STC單片機簡介
單片機全稱是單片微型計算機,內部主要是將5個部分集成在芯片內,這5個部分分別為中央處理器、定時/計數器、只讀存儲器、隨機存儲器以及輸入和輸出接口電路。
隨著單片機的發展,適用于不同領域的單片機逐漸出現。單片機的優勢是其在計算方面很強大并且計算用的時間很短。單片機的優勢確保了其能夠應用的行業非常全面,早就作為各行各業中的智能化器件,對各行各業的產品技術改造起到了不容忽視的作用。
在眾多的51系列單片機中,要算國內STC公司的1T增強系列更具有競爭力,因他不但和8051指令、管腳完全兼容,而且其片內的具有FLASH工藝的大容量程序存儲器。STC89C52是STC公司生產的一種低功耗、高性能CMOS8位微控制器,具有8K在系統可編程Flash存儲器。STC89C52使用經典的MCS-51內核,但做了很多的改進使得芯片具有傳統51單片機不具備的功能。在單芯片上,擁有靈巧的8位CPU和在系統可編程Flash,使得STC89C52為眾多嵌入式控制應用系統提供高靈活、超有效的解決方案。具有以下標準功能:8k字節Flash,512字節RAM,32位I/O口線,看門狗定時器,內置4KBEEPROM,MAX810復位電路,3個16位定時器/計數器,4個外部中斷,一個7向量4級中斷結構(兼容傳統51的5向量2級中斷結構),全雙工串行口。另外STC89C52可降至0Hz靜態邏輯操作,支持2種軟件可選擇節電模式。空閑模式下,CPU停止工作,允許RAM、定時器/計數器、串口、中斷繼續工作。掉電保護方式下,RAM內容被保存,振蕩器被凍結,單片機一切工作停止,直到下一個中斷或硬件復位為止。
4.2 電機驅動模塊
4.2.1 L298N芯片
電機驅動模塊部分所用的芯片為L298N芯片,有4通道邏輯驅動電路。內含2個H橋的高電壓大電流雙全橋式驅動器,接受標準TTL邏輯電平信號,可驅動46V、2A以下的電機。該芯片所采用的SMT工藝具有穩定性高的特點。該模塊可以直接控制兩路直流電機,方便控制直流電機速度和方向。
L298N有邏輯電源和動力電源兩路電源,5V為邏輯電源,7.2V為動力電源。EN_A、EN_B控制電機是否使能,IN1、IN2、IN3、IN4控制電機的正轉反轉以及轉速。本次使用的電機是線圈式的,從運行狀態突然轉換到停止狀態和從順時針狀態突然轉到逆時針狀態時會形成很大的反向電流,在電路中加上二極管的作用就是在產生反向電流的時候進行泄流,保護芯片安全。
L298N的邏輯功能為當EN_A,EN_B均為低電平時,兩個電機沒有通電而不會工作或者斷電處于一種剎停狀態。當EN_A,EN_B均為高電平時,兩個電機使能,會根據IN1、IN2、IN3、IN4的狀態控制電機旋轉的方向以及速度。當把“1”傳進IN1端口,IN2為“0”時,電動機順著時間指針轉,當IN1為“0”,“1”信號傳進IN2時,電動機就會以相反的方向轉。
4.2.2 PWM調速
PWM(脈沖寬度調制)是通過控制固定電壓的直流電源開關頻率,改變負載兩端的電壓,從而達到控制要求的一種電壓調整方法。PWM可以應用在許多方面,比如:電機調速、溫度控制、壓力控制等等。
在PWM驅動控制的調整系統中,按一個固定的頻率來接通和斷開電源,并且根據需要改變一個周期內“接通”和“斷開”時間的長短。通過改變直流電機電樞上電壓的“占空比”來達到改變平均電壓大小的目的,從而來控制電動機的轉速。
圖4-1 PWM調速方波圖
上圖的方波周期為10ms,由圖顯而易見每個周期的脈沖寬度并不同。這是由于每個周期的占空比不同。明顯可以看出上圖為數字信號,為了使其能控制模擬電路,我們可以改變該方波的周期。假設方波的周期很小很小,這時電機的轉速就會顯示不同的狀態。假設一個時間段內都是“1”時,輪子順時針旋轉,那么如果一個時間段內“1”持續的時長是9ms,轉速就會小于該時間段內都是“1”時的轉速。這樣就能夠通過改變電平高低持續的時間來達到改變輪子轉速的目的。該方法不僅化簡了硬件電路而且降低設計成本。
4.3數碼管
4.3.1 數碼管的應用
共陰極數碼管是一類數字形式的顯示屏,通過對其不同的管腳輸入不同的電流,會使其發亮,從而能夠顯示時間、日期、溫度等所有可用數字表示的參數。由于它的價格便宜、使用簡單、在電器,特別是家電領域應用極為廣泛,空調、熱水器等等。絕大多數熱水器用的都是數碼管,部分家電使用液晶屏與熒光屏。
4.3.2 數碼管的結構
在共陰極數碼管結構中,各段發光二極管的陰極連在一起并且接地,某段發光二極管輸入為高電平時,該段發光。一位數碼管的每一段劃都由一個發光二極管點亮,所以,一位數碼管有7個發光二極管構成(加上小數點有8位)。
在a-dp各個引腳分別輸送高低電平,可以使數碼管分別表現出“0”-“9”,如要顯示“1”時,要求b、c引腳輸入為高電平,a、d、e、f、g、dp輸入為低電平, 16進制表示方式為“0x06”。
共陰極數碼管中的0-9的16進制表示方法如下:
字符: 0 1 2 3 4 5 6 7 8 9
字段碼:0x3f 0x06 0x5b 0x4f 0x66 0x6d 0x7d 0x07 0x7f 0x6f
下圖即為數碼管的結構:
圖4-2 數碼管原理圖
4.4 穩壓電路
三端穩壓集成電路LM7805。顧名思義,三端IC是指這種穩壓用的集成電路,只有三條引腳輸出,分別是輸入端、接地端和輸出端。
圖4-3 電源模塊原理圖
外接一個電容用于穩定LM7805內部放大器的工作狀態,同時改善電壓調整的過渡響應。它的數值為生產廠家規定值,不得小于0.1微法,它的連接必須盡可能緊連LM7805的3腳。
4.5 加速、減速
整個系統的加速減速主要是通過兩個按鍵進行控制,按鍵按下時,系統的速度就會改變。下圖即為原理圖,當按下上邊的按鍵時,系統減速,按下下邊按鍵時,系統加速。
圖4-4 加、減速原理圖
下一章,我們將會介紹各個模塊如何相連接,并且通過什么方式控制機器人的各種狀態顯示。
5 系統軟、硬件設計
語音控制機器人的結構中,占首要地位的電子元器件為STC89C52單片機。其次為LD3320語音模塊,兩個直流電機和L298N模塊,以LM7805芯片為核心的穩壓電路模塊,以共陰極數碼管為主的顯示電路和各種小器件。
5.1 系統仿真及軟件設計
該系統中麥克風收到的語音指令傳入到LD3320芯片后,通過頻譜分析進行特征提取,然后與關鍵詞列表進行對比。最后,將識別結果傳輸給STC單片機,然后由主控單片機控制數碼管的顯示以及兩個電機,使機器人完成設計所要求的前進,后退,左轉,右轉,加減速等運動狀態并且同步顯示“1”,“2”,“3”或“4”。
圖5-1 LD3320功能框圖
下面介紹的是我的設計中,編程的主函數的一部分。
while(1)
{
if(Y1==0&&Y2==1&&Y3==1&&Y4==1&&Y5==1){car_go(20+level*10,20+level*10);num=1;}//前進
else
if(Y1==1&&Y2==0&&Y3==1&&Y4==1&&Y5==1){car_back(20+level*10,20+level*10);num=2;}//后退
else
if(Y1==1&&Y2==1&&Y3==0&&Y4==1&&Y5==1){car_go(20+level*10,0+level*10);num=3;}//左轉
else
if(Y1==1&&Y2==1&&Y3==1&&Y4==0&&Y5==1){car_go(0+level*10,20+level*10);num=4;}//右轉
}
該程序的含義為設置一個無限循環,對Y1、Y2、Y3、Y4、Y5進行實時監測,不同狀態執行不同命令。Y1、Y2、Y3、Y4、Y5即為LD3320芯片接收到指令并且識別正確后向主控單片機輸出的信號。比如當Y1=0、Y2=1、Y3=1、Y4=1、Y5=1時,執行car_go(20+level*10,20+level*10)命令,機器人前進。
如下圖5-3即為仿真中Y1=0、Y2=1、Y3=1、Y4=1、Y5=1時的運動狀態和數碼管的顯示:
圖5-2 語音識別機器人仿真
圖5-3 語音模塊輸出實際仿真
語音識別部分的實質也是通過輸入指令后,模塊輸出相應的二進制字符串。如上圖可以看出語音識別模塊的輸出分別與主控單片機的P3^0,P3^1,P3^2,P3^3,P3^6連接,并向其輸入Y1、Y2、Y3、Y4、Y5的值。
電機驅動模塊的實物中2個電動機分別分布于機器人底部的左右兩邊,而且可以在底部的前端加上一個萬向輪,其中電機支配的是位于前端2個輪子,后端輪子的功能主要是固定,撐起整個硬件。由下圖中右圖可以看出,L298N芯片的IN1與主控單片機的P1^2連接,IN2與P1^3連接,IN3與P1^4連接,IN4與P1^5連接,達到控制電機的轉向與速度的目的。控制電機是否已經通電的EN_A,EN_B引腳與主控單片機的P1^0,P1^1連接。
下圖中,左圖為單片機最小系統。單片機的最小系統就是由盡可能簡單的電子元器件搭配起一個能夠正常工作的系統。本次單片機最小系統應用的電子器件有晶振,電容,電阻等。
圖5-4 單片機最小系統及電機模塊仿真圖
圖5-5 數碼管顯示電路
通過P0口輸出的值控制數碼管的顯示。主控單片機的2^4引腳,2^5引腳,2^6引腳,2^7引腳與數碼管的1,2,3,4相連來選擇數碼管是否通電。
5.2 實物圖
圖5-6 實物圖
結論
人工智能正在逐漸改變人類周圍的環境,不再只是電影上的設想。不管是一個小小的快遞分揀機器人,還是可以簡單與人類交流的機器人,都對人類的生活起到了不可小覷的作用。浙江是我國快遞流動量最大的地方,最近在網絡上大量被轉載的一個視頻中,小小的機器人每小時可以處理將近2000個快遞包裹。這種小機器人能夠井然有序的將快遞搬到需要投遞的地方,大大增加了快遞運輸的時效性。它們不僅能夠減少人工分揀時容易出現的錯誤情況,還能大大減少人類的工作量。這個例子很好的說明智能機器人緊緊圍繞我們的生活,而且越來越大眾化。機器人的使用讓生產力大大地提高,能夠幫助人類完成一些復雜重復性的工作。
通過仿真結果,可以看出當顯示“1”,電動機均正轉,機器人前進,顯示“2”,電動機均反轉,機器人后退,顯示“3”或“4”,電動機一個正轉一個反轉,機器人左轉或右轉,顯示“0”,機器人剎停。本次設計利用了LD3320芯片去完成語音識別的機器人的設計,省去了復雜的鍵盤輸入控制。并且可以實現非特定人控制的目的,大大提高了實用性,以便于以后投入市場。
畢業設計是對大學對好的總結,不但考核了我們對于大學知識的學習是否牢固,而且考驗了我們對于已經掌握的知識使用是否靈活。同樣,這也是我們學習知識的過程,在完成畢業設計的同時,我們能接觸到我們沒有接觸過的領域。這也是我們完善知識儲備的一個過程。
參考文獻
[1] 李磊.移動機器人技術研究現狀與未來[J].機器人,2002,24(5):475-480.
[2] 趙勻,武傳宇,胡旭東等.智能機器人的研究發展及存在的問題[J].農業工程學報,2003,19(1):20-22.
[3] 劉幺和,宋庭新.語音識別與控制應用技術[M].北京:科學出版社,2008,24-30.
[4] 涂時亮.單片微機軟件設計技術[M].北京:科學技術文獻出版社重慶社分社,1988,24-25.
[5] 朱謹強,王宣因.機器人技術及其應用[J].計算機應用與軟件,2004,21(2):47-49.
[6] 陸子明.單片機設計與應用教程[M]. 電子工業出版社.2003.5
[7] 張晨燕,孫成立.非特定人孤立詞語音識別系統的片上實現[J].計算機工程與應用,2007(13):194-196.
[8] 丁向榮.STC系列增強型8051單片機原理與應用[M].北京:電子工業出版社.2011.6
[9] 陳國呈編著.PWM逆變技術及應用[M].中國電力出版社.2007.7.
[10] 謝自美.電子線路設計.實驗.測試[M]. 華中理工大學出版社.2006.9
[11] 宋慶環,才衛國,高志.89C51單片機在直流電動機調速系統中的應用[M]。唐山學院,2008.4.
[12] 陳錕,危立輝.基于單片機的直流電機調速器控制電路[J],中南民族大學學報(自然科學版),2003.9.
[13] 李維軍,韓小剛,李晉.基于單片機用軟件實現直流電機PWM調速系統[J],維普資訊,2007.9.
[14] 張鑫.單片機原理與應用[M]. 電子工業出版社.2001.5
[15] 耿德根,詹衛前,李青. 單片機創新開發與機器人制作[M]. 北京航天航天大學.2004.7
[16]潘永雄.新編單片機原理與應用[M]. 西安電子科技大學出版社.2002.9
附錄
//主函數
#include <STC12C5A60S2.h>
#include <intrins.h>
#include <DELAY.h>
#include <Robot_car.h>
#include <shumaguan.h>
#define uchar unsigned char
#define uint unsigned int
sbit Y1=P3^0;
sbit Y2=P3^1;
sbit Y3=P3^2;
sbit Y4=P3^3;
sbit Y5=P3^6;
sbit K1=P2^1;
sbit K2=P2^0;
char num=0;
char level=1;
void main(void)
{
car_init();
Y1=Y2=Y3=Y4=Y5=1;
while(1)
{
if(Y1==0&&Y2==1&&Y3==1&&Y4==1&&Y5==1){car_go(20+level*10,20+level*10);num=1;}//前進
else
if(Y1==1&&Y2==0&&Y3==1&&Y4==1&&Y5==1){car_back(20+level*10,20+level*10);num=2;}//后退
else
if(Y1==1&&Y2==1&&Y3==0&&Y4==1&&Y5==1){car_go(20+level*10,0+level*10);num=3;}//左轉
else
if(Y1==1&&Y2==1&&Y3==1&&Y4==0&&Y5==1){car_go(0+level*10,20+level*10);num=4;}//右轉
else
if(Y1==1&&Y2==1&&Y3==1&&Y4==1&&Y5==0){car_go(20+level*10,0);num=5;delayus(100000);
car_back(20+level*10,20+level*10);num=6; delayus(100000);
car_go(0,20+level*10);num=7; delayus(100000);
car_go (20+level*10,20+level*10);num=8; delayus(100000); }//停止
xianshi2(level,num);
if(K1==0)
{ level++;if(level>3) level=1;
while(K1==0);
}
if(K2==0)
{ level--;if(level<1) level=3;
while(K2==0);
}
}
}
//延時函數
#ifndef __delay_H__
#define __delay_H__
#define uchar unsigned char
#define uint unsigned int
unsigned char flag=0;
uchar l2=0;
uchar l3=0;
void DELAY_MS(unsigned int a)//延時函數 1MS/次
{unsigned int i;
while( --a != 0)
{
for(i = 0; i < 600; i++); //一個 ; 表示空語句,CPU空轉。
} //i 從0加到125,CPU大概就耗時1毫秒
}
void delayus(uint a) //延時1us左右
{
uchar b;
for(;a>0;a--)
for(b=12;b>0;b--);
}
void delay(int num)
{//延時函數
while(num--) ;
}
#endif
//數碼管顯示部分
#ifndef _shumaguan_H_
#define _shumaguan_H_
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit qian=P2^7;
sbit bai=P2^6;
sbit shi=P2^5;
sbit ge=P2^4;
uchar TB[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};
void delay1(uchar tt)
{
uchar i,j;
while(tt!=0)
{
for(i=0;i<10;i++)
for(j=10;j>0;j--);
tt--;
}
}
void xianshi1(uint TT,uint YY)
{
qian=0;
P0=TB[TT%100/10];
delay1(5);
qian=1;
bai=0;
P0=TB[TT%10];
delay1(5);
bai=1;
if(YY==1) //H
{
ge=0;
P0=0x76; // 0111 0110
delay1(5);
ge=1;
}
else //L
{
ge=0;
P0=0X38; // 0 0011 1000
delay1(5);
ge=1;
}
}
void xianshi(uchar x,uint S)
{
qian=0;
P0=TB[x%10];
delay1(5);
qian=1;
bai=0;
P0=0x40;
delay1(10);
bai=1;
shi=0;
P0=0x40;
delay1(10);
shi=1;
ge=0;
P0=TB[S%10];
delay1(10);
ge=1;
}
void xianshi2(uint x,uint y)
{
qian=0;
P0=TB[x%10];
delay1(10);
qian=1;
ge=0;
P0=TB[y%10];
delay1(10);
ge=1;
}
#endif
//電機函數
#ifndef _robot_car_H_
#define _robot_car__H_
#include "delay.h"
#define uchar unsigned char //0~255
#define uint unsigned int //0-65536
sbit PWM1=P1^2;
sbit PWM2=P1^3;
sbit PWM3=P1^4;
sbit PWM4=P1^5;
sbit EN1=P1^0;
sbit EN2=P1^1;
uchar data t_0;
uchar data motor_r;
uchar data motor_l;
uchar data Value;
uchar data mid;
void motor_r_z(void)//右邊電動機正轉
{
motor_r=0x64+Value;
EN1=1;
}
void motor_l_z(void)//左邊電動機正轉
{
motor_l=0x64-Value;
EN2=1;
}
void motor_r_f(void)//右邊電動機反轉
{
motor_r=0x64-Value;
EN1=1;
}
void motor_l_f(void)//左邊電動機反轉
{
motor_l=0x64+Value;
EN2=1;
}
void car_go(uchar left_motor,uchar right_motor)//直行
{
Value=right_motor;
motor_r_z();
Value=left_motor;
motor_l_z();
}
void car_back(uchar left_motor,uchar right_motor)//后退
{
Value=right_motor;
motor_r_f();
Value=left_motor;
motor_l_f();
}
void car_stop(void)//停止
{
EN2=0;
EN1=0;
}
void car_init(void)//小車初始化函數
{
TMOD=0x10; //T1工作在方式1
TH1=0xff; //裝入T1初值
TL1=0xf6;
TR1=1;//開T0中斷
ET1=1;//T0允許中斷
EA=1;
t_0=0;
EN1=EN2=0;
}
void time1(void) interrupt 3 using 2
{
TR1=0;
TH1=0xff;
TL1=0xf6;
++t_0;
ACC=t_0;
CY=0;
ACC-=motor_r;
if(CY==1)
{
PWM1=1;
PWM2=0;
goto PWM_2;
}
PWM1=0;
PWM2=1;
PWM_2:
ACC=t_0;
CY=0;
ACC-=motor_l;
if(CY==1)
{
PWM3=1;
PWM4=0;
goto HIGHT;
}
PWM3=0;
PWM4=1;
HIGHT:
ACC=t_0;
|