2.1主控模塊的選型和論證 方案一: 采用MSP430系列單片機(jī),該單片機(jī)是TI公司1996年開(kāi)始推向市場(chǎng)的一種16位超低功耗的混合信號(hào)處理器。其內(nèi)部集成了很多模擬電路、數(shù)字電路和微處理器,提供強(qiáng)大的功能。不過(guò)該芯片昂貴不適合一般的設(shè)計(jì)開(kāi)發(fā)[3]。 方案二 采用51系列的單片機(jī),該單片機(jī)是一個(gè)高可靠性,超低價(jià),無(wú)法解密,高性能的8位單片機(jī),32個(gè)IO口,且STC系列的單片機(jī)可以在線編程、調(diào)試,方便地實(shí)現(xiàn)程序的下載與整機(jī)的調(diào)試。 因此選用方案二中的51系列單片機(jī)作為主控芯片。 2.2顯示模塊的選型和論證 方案一: 采用點(diǎn)陣式數(shù)碼管顯示,點(diǎn)陣式數(shù)碼管是由八行八列的發(fā)光二極管組成,對(duì)于顯示文字比較合適,如采用在顯示數(shù)字顯得太浪費(fèi),且價(jià)格也相對(duì)較高,所以不用此種作為顯示。 方案二: 采用LED數(shù)碼管動(dòng)態(tài)掃描,LED數(shù)碼管價(jià)格雖適中,對(duì)于顯示數(shù)字也最合適,而且采用動(dòng)態(tài)掃描法與單片機(jī)連接時(shí),占用單片機(jī)口線少。但是由于數(shù)碼管動(dòng)態(tài)掃描需要借助74LS164移位寄存器進(jìn)行移位,該芯片在電路調(diào)試時(shí)往往有很多障礙,所以不采用LED數(shù)碼管作為顯示。 方案三: 采用LCD液晶顯示屏,液晶顯示屏的顯示功能強(qiáng)大,可顯示大量文字,圖形,顯示多樣,清晰可見(jiàn),對(duì)于本設(shè)計(jì)而言一個(gè)LCD1602的液晶屏即可,價(jià)格也還能接受,需要的接口線較多,但會(huì)給調(diào)試帶來(lái)諸多方便。 所以本設(shè)計(jì)中方案三中的LCD1602液顯示屏作為顯示模塊。 2.3脈搏檢測(cè)傳感器的選型和論證 方案一: 采用壓電傳感器用來(lái)提取人的脈搏信號(hào),壓電傳感器是利用某些電介質(zhì)受力后產(chǎn)生的壓電效應(yīng)制成的傳感器。所謂壓電效應(yīng)是指某些電介質(zhì)在受到某一方向的外力作用而發(fā)生形變(包括彎曲和伸縮形變)時(shí),由于內(nèi)部電荷的極化現(xiàn)象,會(huì)在其表面產(chǎn)生電荷的現(xiàn)象。通過(guò)此現(xiàn)象可以提取出人的脈搏信號(hào)。 方案二: 采用光電傳感器提取人體脈搏信號(hào),授予手指組織可以分成皮膚、肌肉、骨骼等非血液組織和血液組織,其中非血液組織的光吸收量是恒定的,而在血液中,靜脈血的搏動(dòng)相對(duì)動(dòng)脈血是十分微弱的,可以忽略,因此可以認(rèn)為光透過(guò)手指后的變化僅由動(dòng)脈血的充盈而引起,那么在恒定波長(zhǎng)的光源的照射下,通過(guò)檢測(cè)透過(guò)手指的光強(qiáng)將可以間接測(cè)量到人體的脈搏信號(hào)[4]。 由于光電傳感器較壓電傳感器容易在一般的地方可以買(mǎi)得到,因此這里選用光電傳感器來(lái)提取人體脈搏信號(hào)。 2.4溫度傳感器的選型方案一 由于本設(shè)計(jì)是測(cè)溫電路,可以使用熱敏電阻之類(lèi)的器件,將隨被測(cè)溫度變化的電壓或電流采樣,進(jìn)行A/D轉(zhuǎn)換后就可以用單片機(jī)進(jìn)行數(shù)據(jù)處理,實(shí)現(xiàn)溫度顯示。這種設(shè)計(jì)需要用到A/D轉(zhuǎn)換電路,增大了電路的復(fù)雜性,而且要做到高精度也比較困難。
方案二 考慮到在單片機(jī)屬于數(shù)字系統(tǒng),容易想到數(shù)字溫度傳感器,可選用DS18B20數(shù)字溫度傳感器,此傳感器為單總線數(shù)字溫度傳感器,起體積小、構(gòu)成的系統(tǒng)結(jié)構(gòu)簡(jiǎn)單,它可直接將溫度轉(zhuǎn)化成串行數(shù)字信號(hào)給單片機(jī)處理,即可實(shí)現(xiàn)溫度顯示。另外DS18B20具有3引腳的小體積封裝,測(cè)溫范圍為-55~+125攝氏度,測(cè)溫分辨率可達(dá)0.0625攝氏度,其測(cè)量范圍與精度都能符合設(shè)計(jì)要求。 以上兩種方案相比較,第二種方案的電路、軟件設(shè)計(jì)更簡(jiǎn)單,此方案設(shè)計(jì)的系統(tǒng)在功耗、測(cè)量精度、范圍等方面都能很好地達(dá)到要求,故本設(shè)計(jì)采用方案二。
2.5系統(tǒng)整體設(shè)計(jì)概述
系統(tǒng)總體設(shè)計(jì)由STC89C52、按鍵、LCD1602、光電傳感器、時(shí)鐘模塊、運(yùn)放等構(gòu)成,如圖2.1所示,系統(tǒng)設(shè)有四個(gè)按鍵,可以設(shè)置上下限脈搏數(shù),當(dāng)超過(guò)范圍的時(shí)候單片機(jī)會(huì)驅(qū)動(dòng)蜂鳴器發(fā)響,脈搏測(cè)量的時(shí)候需要人把手輕輕的按在光電傳感器上面,由于人脈搏跳動(dòng)的時(shí)候,血液的透光性不一樣會(huì)導(dǎo)致接收器那邊接收的信號(hào)強(qiáng)弱不一樣,間接的把人脈搏信號(hào)傳回,通過(guò)運(yùn)放對(duì)其進(jìn)行放大、整形后連接到單片機(jī)的IO口,單片機(jī)利用外部中斷對(duì)其進(jìn)行計(jì)數(shù),最終換算成人一分鐘脈搏的跳動(dòng)次數(shù),最終顯示在液晶屏上。
3.1.3單片機(jī)最小系統(tǒng)設(shè)計(jì) 圖3.3 單片機(jī)最小系統(tǒng)電路圖 圖3.3為單片機(jī)最小系統(tǒng)電路圖,單片機(jī)最小系統(tǒng)有單片機(jī)、時(shí)鐘電路、復(fù)位電路組成,時(shí)鐘電路選用了12MHZ的晶振提供時(shí)鐘,作用為給單片機(jī)提供一個(gè)時(shí)間基準(zhǔn),其中執(zhí)行一條基本指令需要的時(shí)間為一個(gè)機(jī)器周期,單片機(jī)的復(fù)位電路,按下復(fù)位按鍵之后可以使單片機(jī)進(jìn)入剛上電的起始狀態(tài)。圖中10K排阻為P0口的上拉電阻,由于P0口跟其他IO結(jié)構(gòu)不一樣為漏極開(kāi)路的結(jié)構(gòu),因此要加上拉電阻才能正常使用。
3.2.3液晶顯示部分與STC89C52的接口 如圖3.5所示。用STC89C52的P0口作為數(shù)據(jù)線,用P1.2、P1.1、P1.0分別作為L(zhǎng)CD的EN、R/W、RS。其中EN是下降沿觸發(fā)的片選信號(hào),R/W是讀寫(xiě)信號(hào),RS是寄存器選擇信號(hào)本模塊設(shè)計(jì)要點(diǎn)如下:顯示模塊初始化:首先清屏,再設(shè)置接口數(shù)據(jù)位為8位,顯示行數(shù)為1行,字型為5×7點(diǎn)陣,然后設(shè)置為整體顯示,取消光標(biāo)和字體閃爍,最后設(shè)置為正向增量方式且不移位[10]。向LCD的顯示緩沖區(qū)中送字符,程序中采用2個(gè)字符數(shù)組,一個(gè)顯示字符,另一個(gè)顯示電壓數(shù)據(jù),要顯示的字符或數(shù)據(jù)被送到相應(yīng)的數(shù)組中,完成后再統(tǒng)一顯示.首先取一個(gè)要顯示的字符或數(shù)據(jù)送到LCD的顯示緩沖區(qū),程序延時(shí)2.5ms,判斷是否夠顯示的個(gè)數(shù),不夠則地址加一取下一個(gè)要顯示的字符或數(shù)據(jù)。 圖3.5 LCD1602與STC89C52的引腳連接圖
3.3信號(hào)采集電路設(shè)計(jì) 此部分電路的功能是由傳感器將脈搏信號(hào)轉(zhuǎn)換為電信號(hào),一般為幾十毫伏,必須加以放大,以達(dá)到整形電路所需的電壓,一般為幾伏。放大后的信號(hào)波形是不規(guī)則的脈沖信號(hào),因此必須加以濾波整形,整形電路的輸出電壓應(yīng)滿足計(jì)數(shù)器的要求。選擇電路:所選放大整形電路框圖如圖3.8所示。 圖3.8 放大整形電路框圖 3.3.1傳感器簡(jiǎn)介 傳感器采用了紅外光電轉(zhuǎn)換器,作用是通過(guò)紅外光照射人的手指的血脈流動(dòng)情況,把脈搏跳動(dòng)轉(zhuǎn)換為電信號(hào),其原理電路如圖3.9所示。 圖3.9 傳感器信號(hào)調(diào)節(jié)原理電路 如圖3.9中,紅外管VD采用ST188。用+5V電源供電,R1取150Ω,R2取33kΩ,當(dāng)人把手指放在發(fā)光二極管和光電二極管之間的時(shí)候,光電二極管接收到的信號(hào)會(huì)隨人脈搏強(qiáng)度的變化而變化[11]。 3.3.2濾波電路 圖3.10 放大濾波電路 圖3.10為脈搏計(jì)的放大濾波信號(hào),由于脈搏信號(hào)輸出的信號(hào)十分微弱,一般在uV級(jí)別,除此外輸出的信號(hào)一般會(huì)伴隨很大的噪聲干擾,因此在這里用LM358搭建起一個(gè)放大和濾波電路。 3.3.3放大整形電路 經(jīng)過(guò)放大濾波后的脈搏信號(hào)仍是不規(guī)則的脈沖信號(hào),且有低頻干擾,仍不滿足計(jì)數(shù)器的要求,必須采用整形電路,這里選用了滯回電壓比較器,如圖3.11所示,其目的是為了提高抗干擾能力。集成運(yùn)放采用了LM358,除此外LM358還接上了一個(gè)LED用作指示脈搏跳動(dòng)的狀態(tài)。 圖3.11波形整形電路 3.4 數(shù)字溫度傳感器模塊3.4.1 DS18B20性能- 獨(dú)特的單線接口僅需一個(gè)端口引腳進(jìn)行通信
- 簡(jiǎn)單的多點(diǎn)分布應(yīng)用
- 無(wú)需外部器件
- 可通過(guò)數(shù)據(jù)線供電
- 零待機(jī)功耗
- 測(cè)溫范圍-55~+125℃,以0.5℃遞增
- 可編程的分辨率為9~12位,對(duì)應(yīng)的可分辨溫度分別為0.5℃、0.25℃、0.125℃和0.0625℃
- 溫度數(shù)字量轉(zhuǎn)換時(shí)間200ms,12位分辨率時(shí)最多在750ms內(nèi)把溫度轉(zhuǎn)換為數(shù)字
- 應(yīng)用包括溫度控制、工業(yè)系統(tǒng)、消費(fèi)品、溫度計(jì)和任何熱感測(cè)系統(tǒng)
- 負(fù)壓特性:電源極性接反時(shí),傳感器不會(huì)因發(fā)熱而燒毀,但不能正常工作
3.4.2 DS18B20外形及引腳說(shuō)明
圖3 DS18B20外形及引腳
- GND:地
- DQ:?jiǎn)尉運(yùn)用的數(shù)據(jù)輸入/輸出引腳
- VD:可選的電源引腳
3.4.3 DS18B20接線原理圖單總線通常要求接一個(gè)約10K左右的上拉電阻,這樣,當(dāng)總線空閑時(shí),其狀態(tài)為高電平。
圖4 DS18B20接線原理圖
3.4.4 DS18B20時(shí)序圖 主機(jī)使用時(shí)間隙來(lái)讀寫(xiě)DS18B20的數(shù)據(jù)位和寫(xiě)命令字的位。
圖5 DS18B20初始化時(shí)序
圖6 DS18B20讀寫(xiě)時(shí)序 3.4.5 數(shù)據(jù)處理 高速暫存存儲(chǔ)器由9個(gè)字節(jié)組成,其分配如表5所示。當(dāng)溫度轉(zhuǎn)換命令發(fā)布后,經(jīng)轉(zhuǎn)換所得的溫度值以二字節(jié)補(bǔ)碼形式存放在 高速暫存存儲(chǔ)器的第0和第1個(gè)字節(jié)。單片機(jī)可通過(guò)單線接口讀到該數(shù)據(jù),讀取時(shí)低位在前,高位在后。 圖7 字節(jié)分配
下表為12位轉(zhuǎn)化后得到的12位數(shù)據(jù),存儲(chǔ)在18B20的兩個(gè)8比特的RAM中,二進(jìn)制中的前面5位是符號(hào)位,如果測(cè)得的溫度大于0, 這5位為0,只要將測(cè)到的數(shù)值乘于0.0625即可得到實(shí)際溫度;如果溫度小于0,這5位為1,測(cè)到的數(shù)值需要取反加1再乘于0.0625即可得到實(shí)際 溫度。 例如+125℃的數(shù)字輸出為07D0H, 實(shí)際溫度=07D0H*0.0625=2000*0.0625=125℃。 例如-55℃的數(shù)字輸出為FC90H,則應(yīng)先將11位數(shù)據(jù)位取反加1得370H(符號(hào)位不變,也不作運(yùn)算), 實(shí)際溫度=370H*0.0625=880*0.0625=55℃。 可見(jiàn)其中低四位為小數(shù)位。
圖8 DS18B20溫度數(shù)據(jù)表 第四章 系統(tǒng)軟件設(shè)計(jì) 4.1系統(tǒng)軟件總體設(shè)計(jì) 圖4.1系統(tǒng)流程圖 主程序流程圖如圖4.1所示,單片機(jī)上電后先進(jìn)行初始化,清楚一些參數(shù)的初值,然后等待用戶按下對(duì)應(yīng)的按鍵并進(jìn)入對(duì)應(yīng)的功能,當(dāng)用戶按下測(cè)量按鍵的時(shí)候流程如圖4.1(c)所示,單片機(jī)通過(guò)定時(shí)15s測(cè)量人體的脈搏次數(shù)流程如圖4.1(b)所示,然后再換算出對(duì)應(yīng)的真實(shí)的脈搏次數(shù)再在液晶屏幕上顯示流程如圖4.1(a)所示,當(dāng)用戶按下設(shè)置脈搏范圍設(shè)定按鍵后,單片機(jī)根據(jù)用戶按下的按鍵進(jìn)行增加或減少范圍。 首先先調(diào)用液晶自定義的字庫(kù),設(shè)置好DDRAM地址后在第一行顯示,根據(jù)程序中的數(shù)據(jù)設(shè)置顯示數(shù)據(jù)的首地址并設(shè)置循環(huán)量,在循環(huán)過(guò)程中不斷的取字符代碼直到終止,第二行的顯示過(guò)程同一行的顯示過(guò)程一樣,兩行顯示完畢后便結(jié)束子程序,如圖4.2所示[15]。 圖4.2 LCD1602初始化子函數(shù)流程圖 4.2程序設(shè)計(jì)原理 軟件任務(wù)分析和硬件電路設(shè)計(jì)結(jié)合進(jìn)行,哪些功能由硬件完成,哪些任務(wù)由軟件完成,在硬件電路設(shè)計(jì)基本定型后,也就基本上決定下來(lái)了。 軟件任務(wù)分析環(huán)節(jié)是為軟件設(shè)計(jì)做一個(gè)總體規(guī)劃。從軟件的功能來(lái)看可分為兩大類(lèi):一類(lèi)是執(zhí)行軟件,它能完成各種實(shí)質(zhì)性的功能,如測(cè)量,計(jì)算,顯示,打印,輸出控制和通信等,另一類(lèi)是監(jiān)控軟件,它是專(zhuān)門(mén)用來(lái)協(xié)調(diào)各執(zhí)行模塊和操作者的關(guān)系,在系統(tǒng)軟件中充當(dāng)組織調(diào)度角色的軟件。這兩類(lèi)軟件的設(shè)計(jì)方法各有特色,執(zhí)行軟件的設(shè)計(jì)偏重算法效率,與硬件關(guān)系密切,千變?nèi)f化。 軟件任務(wù)分析時(shí),應(yīng)將各執(zhí)行模塊一一列出,并為每一個(gè)執(zhí)行模塊進(jìn)行功能定義和接口定義(輸入輸出定義)。在各執(zhí)行模塊進(jìn)行定義時(shí),將要牽扯到的數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)類(lèi)型問(wèn)題也一并規(guī)劃好。 各執(zhí)行模塊規(guī)劃好后,就可以監(jiān)控程序了。首先根據(jù)系統(tǒng)功能和鍵盤(pán)設(shè)置選擇一種最適合的監(jiān)控程序結(jié)構(gòu)。相對(duì)來(lái)講,執(zhí)行模塊任務(wù)明確單純,比較容易編程,而監(jiān)控程序較易出問(wèn)題。這如同當(dāng)一名操作工人比較容易,而當(dāng)一個(gè)廠長(zhǎng)就比較難了。 軟件任務(wù)分析的另一個(gè)內(nèi)容是如何安排監(jiān)控軟件和各執(zhí)行模塊。整個(gè)系統(tǒng)軟件可分為后臺(tái)程序(背景程序)和前臺(tái)程序。后臺(tái)程序指主程序及其調(diào)用的子程序,這類(lèi)程序?qū)?shí)時(shí)性要求不是太高,延誤幾十ms甚至幾百ms也沒(méi)關(guān)系,故通常將監(jiān)控程序(鍵盤(pán)解釋程序),顯示程序和打印程序等與操作者打交道的程序放在后臺(tái)程序中執(zhí)行;而前臺(tái)程序安排一些實(shí)時(shí)性要求較高的內(nèi)容,如定時(shí)系統(tǒng)和外部中斷(如掉電中斷)。也可以將全部程序均安排在前臺(tái),后臺(tái)程序?yàn)椤笆瓜到y(tǒng)進(jìn)入睡眠狀態(tài)”,以利于系統(tǒng)節(jié)電和抗干擾。
第五章 系統(tǒng)調(diào)試
5.1軟件調(diào)試 基于單片機(jī)的脈搏計(jì)系統(tǒng)是多功能的數(shù)字型設(shè)計(jì),,所以對(duì)于它的程序也較為復(fù)雜,所以在編寫(xiě)程序和調(diào)試時(shí)出現(xiàn)了相對(duì)較多的問(wèn)題。最后經(jīng)過(guò)多次的模塊子程序的修改,一步一步的完成,最終解決了軟件。在軟件的調(diào)試過(guò)程中主要遇到的問(wèn)題如下: 問(wèn)題1:燒入程序后,LCD液晶顯示閃動(dòng),而且亮度不均勻。 解決:首先對(duì)調(diào)用的延時(shí)進(jìn)行逐漸修改,可以解決顯示閃動(dòng)問(wèn)題。其次,由于本作品使作動(dòng)態(tài)掃描方式顯示的數(shù)字,動(dòng)態(tài)掃描很快,人的肉眼是無(wú)法看出,但是調(diào)用的顯示程序時(shí),如果不在反回時(shí)屏蔽掉最后的附值,則會(huì)出現(xiàn)很亮的現(xiàn)象,所以在顯示的后面加了屏蔽子令,最后解決了此問(wèn)題。 問(wèn)題2:當(dāng)用戶按下按鍵的時(shí)候,單片機(jī)讀取的數(shù)值跟設(shè)定的數(shù)值不對(duì)。 解決:重新檢查矩陣鍵盤(pán)電路的連接,重新建立一個(gè)新的對(duì)應(yīng)關(guān)系。 5.2硬件調(diào)試 基于單片機(jī)的脈搏計(jì)系統(tǒng)的電路較大,對(duì)于焊接方面更是不可輕視,龐大的電路系統(tǒng)中只要出于一處的錯(cuò)誤,則會(huì)對(duì)檢測(cè)造成很大的不便,而且電路的交線較多,對(duì)于各種鋒利的引腳要注意處理,否則會(huì)刺破帶有包皮的導(dǎo)線,則會(huì)對(duì)電路造成短路現(xiàn)象[14]。 在本脈搏計(jì)的設(shè)計(jì)調(diào)試中遇到了很多的問(wèn)題。回想這些問(wèn)題只要認(rèn)真多思考都是可以避免的,以下為主要的問(wèn)題: 問(wèn)題1:最開(kāi)始的時(shí)候以為單片機(jī)IO口直接可以驅(qū)動(dòng)蜂鳴器發(fā)聲,后來(lái)調(diào)試的時(shí)候久久不能出聲音(見(jiàn)附錄C)。 解決:經(jīng)過(guò)查找相關(guān)資料,知道揚(yáng)聲器需要三極管來(lái)驅(qū)動(dòng),后來(lái)把三極管放大器加上系統(tǒng)便可以正常工作。 問(wèn)題2:開(kāi)始的時(shí)候由于沒(méi)想到脈搏信號(hào)十分微弱大概在uV級(jí)別,因此沒(méi)有放大足夠的倍數(shù),單片機(jī)最后沒(méi)有檢測(cè)到脈搏的信號(hào)(見(jiàn)附錄C)。 解決:經(jīng)過(guò)查找相關(guān)資料,確定脈搏信號(hào)的幅值范圍后,增加放大器的放大倍數(shù)就解決問(wèn)題。 5.3調(diào)試結(jié)果 1.放大倍數(shù)的增加 傳感器的輸出端經(jīng)示波器觀察有幅度很小的正弦波,但經(jīng)整形輸出后檢測(cè)到的脈沖還是很弱,在確定電路沒(méi)有問(wèn)題的情況下,加強(qiáng)信號(hào)的放大倍數(shù),調(diào)整電阻R23和R27的阻值。 2.時(shí)鐘的調(diào)試 根據(jù)晶體振蕩頻率計(jì)算出內(nèi)部定時(shí)器的基本參數(shù),通過(guò)運(yùn)行一段時(shí)間可通過(guò)秒表來(lái)校正后,看時(shí)間誤差的量,以這個(gè)量為依據(jù)改變程序中的內(nèi)部定時(shí)器基本參數(shù),就可使時(shí)鐘調(diào)準(zhǔn)確。 3.開(kāi)機(jī)后無(wú)顯示 首先檢查交流電源部分,有無(wú)交流,若無(wú)則可能保險(xiǎn)管或變壓器燒壞,如有繼續(xù)查直流有無(wú),如無(wú)則電源已燒壞,可更換解決。 4.顯示正常但經(jīng)適當(dāng)運(yùn)動(dòng)后測(cè)量,脈搏次數(shù)沒(méi)有增加 可能是前置放大級(jí)有問(wèn)題,可采用更換的辦法判斷并排除。 5.進(jìn)人測(cè)量狀態(tài), 但測(cè)量值不穩(wěn)定 主要是光電傳感器受到電磁波等干擾,其次是損壞或有虛焊。 6.開(kāi)機(jī)后顯示不正常或按鍵失靈 可查手指擺放的位置或按鍵電路,若無(wú)故障則是硬件損壞。 經(jīng)過(guò)一系列的問(wèn)題查找后系統(tǒng)最終能正常工作,并完成所有的功能。 5.4誤差分析
注:實(shí)際的脈搏次數(shù)以聽(tīng)診器測(cè)出的脈搏次數(shù)為參考值。 表3.1列出了測(cè)量值,但存在誤差,由于傳感器和其他器件本身并非理想線性,實(shí)測(cè)數(shù)據(jù)進(jìn)行了線性補(bǔ)償。 由均方差公式得: =0.59
誤差分析:經(jīng)校準(zhǔn),非線性補(bǔ)償后,誤差以基本達(dá)到要求。 附錄A:系統(tǒng)整體原理圖:
附錄B:系統(tǒng)源程序 - #include <reg52.h> //調(diào)用單片機(jī)頭文件
- #define uchar unsigned char //無(wú)符號(hào)字符型 宏定義 變量范圍0~255
- #define uint unsigned int //無(wú)符號(hào)整型 宏定義 變量范圍0~65535
- #include<DS18N02.h>
- #include <intrins.h>
- #include "eeprom52.h"
-
-
- #define DBPort P0
-
- unsigned char i=0,timecount=0,displayOK=0,rate=0,rate1=0,aa=0,time1=0,flat300ms=0;
- unsigned int time[6]={0};
- unsigned int oneminte=0;
- unsigned int ReadTempDate;
- unsigned char S_temp_H,S_temp_L,S_heart_H,S_heart_L;
- unsigned char yemian=0,biaozhi=0;
-
-
- sbit K1 = P1^0; //菜單
- sbit K2 = P1^1; //加
- sbit K3 = P1^2; //減
- sbit Buzzer= P1^7; //控制端
-
-
- sbit rs = P2^5 ;
- sbit rw = P2^6 ;
- sbit ep = P2^7 ;
-
-
- bit flag=1;
-
-
- /******************把數(shù)據(jù)保存到單片機(jī)內(nèi)部eeprom中******************/
- void write_eeprom()
- {
- SectorErase(0x2000);
- byte_write(0x2000, S_heart_H);
- byte_write(0x2001, S_heart_L);
- byte_write(0x2002, S_temp_H);
- byte_write(0x2003, S_temp_L);
-
-
- byte_write(0x2060, a_a);
- }
-
- /******************把數(shù)據(jù)從單片機(jī)內(nèi)部eeprom中讀出來(lái)*****************/
- void read_eeprom()
- {
- S_heart_H = byte_read(0x2000);
- S_heart_L = byte_read(0x2001);
- S_temp_H = byte_read(0x2002);
- S_temp_L = byte_read(0x2003);
- a_a = byte_read(0x2060);
- }
-
- /**************開(kāi)機(jī)自檢eeprom初始化*****************/
- void init_eeprom()
- {
- read_eeprom(); //先讀
- if(a_a != 2) //新的單片機(jī)初始單片機(jī)內(nèi)問(wèn)eeprom
- {
- S_heart_H = 120;
- S_heart_L = 60;
- S_temp_H = 38;
- S_temp_L = 5;
- a_a = 2;
- write_eeprom();
- }
- }
-
- /***********************1ms延時(shí)函數(shù)*****************************/
- void delay_1ms(uint q)
- {
- uint i,j;
- for(i=0;i<q;i++)
- for(j=0;j<110;j++);
- }
-
-
- /********************************************************************
- * 名稱 : delay_uint()
- * 功能 : 小延時(shí)。
- * 輸入 : 無(wú)
- * 輸出 : 無(wú)
- ***********************************************************************/
- void delay_uint(uint q)
- {
- while(q--);
- }
-
-
- typedef bit BOOL ;
-
-
- uchar data_byte;
-
- void delay(uchar ms)
- { // 延時(shí)子程序
- uchar i ;
- while(ms--)
- {
- for(i = 0 ; i<250;i++) ;
- }
- }
-
-
- /************************LCD模塊******************************************/
-
- BOOL lcd_bz()//測(cè)試LCD忙碌狀態(tài)
- {
- BOOL result ;
- rs = 0 ;
- rw = 1 ;
- ep = 1 ;
- result = (BOOL)(P0 & 0x80) ;
- ep = 0 ;
- return result ;
- }
-
- void lcd_init()// 初始化
- {
- write_cmd(0x38) ;
- delay(1);
- write_cmd(0x08) ;
- delay(1);
- write_cmd(0x01) ;
- delay(1);
- write_cmd(0x06) ;
- delay(1);
- write_cmd(0x0c) ;
- delay(1);
- }
-
- display(uchar addr, uchar q)//在某一地址上顯示一字節(jié)
- {
- delay(1) ;
- write_addr(addr) ;
- write_byte(q) ;
- // longdelay(1) ;
-
- }
-
-
- void show1()
- {
- lcd_init();// 初始化
- // Welcome
-
-
- display(0x05,'W');
- display(0x06,'e');
- display(0x07,'l');
- display(0x08,'c');
- display(0x09,'o');
- display(0x0a,'m');
- display(0x0b,'e');
- longdelay(50);//短暫延時(shí)
-
-
- display(0x42,' ');
- display(0x43,' ');
- display(0x44,' ');
- display(0x45,' ');
- display(0x46,' ');
- display(0x48,' ');
- display(0x49,' ');
- display(0x4a,' ');
- display(0x4b,' ');
- longdelay(50);//短暫延時(shí)
-
- /*
- //2012283443
- display(0x02,'2');
- display(0x03,'0');
- display(0x04,'1');
- display(0x05,'2');
- display(0x06,'2');
- display(0x07,'8');
- display(0x08,'3');
- display(0x09,'4');
- display(0x0a,'4');
- display(0x0b,'3');
- longdelay(50);//短暫延時(shí)
-
- //TEL:18268256180
- display(0x40,'T');
- display(0x41,'e');
- display(0x42,'l');
- display(0x43,':');
- display(0x44,'1');
- display(0x45,'8');
- display(0x46,'2');
- display(0x47,'6');
- display(0x48,'8');
- display(0x49,'2');
- display(0x4a,'5');
- display(0x4b,'6');
- display(0x4c,'1');
- display(0x4d,'8');
- display(0x4e,'0');
- longdelay(50);//短暫延時(shí)
- */
- }
-
-
-
-
-
- void shezhi() //對(duì)里面的數(shù)值進(jìn)行修改
- {
- if(!K2) //按下按鍵
- {
- delay_1ms(20);
- if(!K2)
- {
- if(yemian==1)
- {
- S_heart_H+=1; //沒(méi)按下一次,數(shù)值加1
- if(S_heart_H>=200) {S_heart_H=200;}
- write_eeprom(); //保存數(shù)據(jù)
-
- display(0x46,S_heart_H/100+'0');
- display(0x47,S_heart_H%100/10+'0');
- display(0x48,S_heart_H%100%10+'0');
- }
-
- if(yemian==2)
- {
- S_heart_L+=1; //沒(méi)按下一次,數(shù)值加1
- if(S_heart_L>=200) {S_heart_L=200;}
- write_eeprom(); //保存數(shù)據(jù)
-
- display(0x46,S_heart_L/100+'0');
- display(0x47,S_heart_L%100/10+'0');
- display(0x48,S_heart_L%100%10+'0');
- }
-
- if(yemian==3)
- {
- S_temp_H+=1; //沒(méi)按下一次,數(shù)值加1
- if(S_temp_H>=125) {S_temp_H=125;}
- write_eeprom(); //保存數(shù)據(jù)
-
- display(0x46,S_temp_H/100+'0');
- display(0x47,S_temp_H%100/10+'0');
- display(0x48,S_temp_H%100%10+'0');
- }
-
- if(yemian==4)
- {
- S_temp_L+=1; //沒(méi)按下一次,數(shù)值加1
- if(S_temp_L>=125) {S_temp_L=125;}
- write_eeprom(); //保存數(shù)據(jù)
-
- display(0x46,S_temp_L/100+'0');
- display(0x47,S_temp_L%100/10+'0');
- display(0x48,S_temp_L%100%10+'0');
- }
-
- }
- // while(!K2); //等待按鍵 彈起 屏蔽此句,可以實(shí)現(xiàn)按鍵按下不放開(kāi)時(shí),連加技術(shù)功能,
- // 不過(guò)需要將上面延時(shí)去抖時(shí)間延長(zhǎng)效果才好。建議改為: delay_LCD(50);
- }
-
-
- if(!K3) //按下按鍵
- {
- delay_1ms(20);
- if(!K3)
- {
- if(yemian==1)
- {
-
- if(S_heart_H<=1) {S_heart_H=1;}
- S_heart_H-=1; //沒(méi)按下一次,數(shù)值加1
- write_eeprom(); //保存數(shù)據(jù)
-
- display(0x46,S_heart_H/100+'0');
- display(0x47,S_heart_H%100/10+'0');
- display(0x48,S_heart_H%100%10+'0');
-
- }
-
-
- if(yemian==4)
- {
- if(S_temp_L<=1) {S_temp_L=1;}
- S_temp_L-=1; //沒(méi)按下一次,數(shù)值加1
- write_eeprom(); //保存數(shù)據(jù)
-
- display(0x46,S_temp_L/100+'0');
- display(0x47,S_temp_L%100/10+'0');
- display(0x48,S_temp_L%100%10+'0');
-
-
- }
- }
- // while(!K3); //等待按鍵 彈起 //等待按鍵 彈起 屏蔽此句,可以實(shí)現(xiàn)按鍵按下不放開(kāi)時(shí),連加技術(shù)功能,
- // 不過(guò)需要將上面延時(shí)去抖時(shí)間延長(zhǎng)效果才好。建議改為: delay_LCD(50);
- }
-
-
- }
-
- void wendumaibo()
- {
-
- if(displayOK==0)//如果顯示關(guān)
- {
- display(0x06,'W');
- display(0x07,'a');
- display(0x08,'i');
- display(0x09,'t');
- display(0x0a,'i');
- display(0x0b,'n');
- display(0x0c,'g');
- flag=1;
- oneminte=0;//加上這個(gè),當(dāng)displayOK標(biāo)志位沒(méi)有置1時(shí),都清零計(jì)數(shù),等待重新檢測(cè)中計(jì)數(shù)。
- }
-
- if(displayOK==1 && oneminte<=200)//如果顯示開(kāi)
- {
- flag=0;
- display(0x06,'T');
- display(0x07,'e');
- display(0x08,'s');
- display(0x09,'t');
- display(0x0a,'i');
- display(0x0b,'n');
- display(0x0c,'g');
- }
-
- ReadTempDate=ReadTemperature();
- display(0x46,ReadTempDate/100+'0');
- display(0x47,ReadTempDate%100/10+'0');
- display(0x48,'.');
- display(0x49,ReadTempDate%100%10+'0');
- display(0x4a,0xdf);
- display(0x4b,'C');
- }
-
-
- void baojin()
- {
- if( ( (rate*6<S_heart_L || rate*6>S_heart_H) && oneminte>200 ) || ReadTempDate>=S_temp_H*10 || ReadTempDate<=S_temp_L*10 ) { Buzzer=0; }
-
- if( oneminte>=0 && oneminte<200 && ReadTempDate<S_temp_H*10 && ReadTempDate>S_temp_L*10 ) { Buzzer=1; }
- }
-
- /*************定時(shí)器0初始化程序***************/
- void time_init()
- {
- EA = 1; //開(kāi)總中斷
- TMOD = 0X01; //定時(shí)器0、定時(shí)器1工作方式1
- ET0 = 1; //開(kāi)定時(shí)器0中斷
- TR0 = 1; //允許定時(shí)器0定時(shí)
- }
-
-
- /***********外部中斷0初始化程序****************/
- void init_int0() //外部中斷0初始化程序
- {
- EX0=1; //允許外部中斷0中斷
- EA=1; //開(kāi)總中斷
- IT0 = 1; //外部中斷0負(fù)跳變中斷
- }
-
- /****************主函數(shù)***************/
- void main()
- {
- ReadTemperature();
- show1();//顯示問(wèn)候語(yǔ)和其他信息
- time_init(); //初始化定時(shí)器
- init_int0(); //外部中斷0初始化程序
- init_eeprom(); //讀eeprom數(shù)據(jù)
- while(1)
- {
- key(); //按鍵掃描
- if(flat300ms>=4) //200ms
- {
- flat300ms=0;
- //==================主界面===================
- if(yemian==0)
- {
- if(biaozhi==0)
- {
- biaozhi=1;
-
- lcd_init();// 初始化
- display(0x00,'H');
- display(0x01,'e');
- display(0x02,'a');
- display(0x03,'r');
- display(0x04,'t');
- display(0x05,':');
-
- display(0x40,'T');
- display(0x41,'e');
- display(0x42,'m');
- display(0x43,'p');
- display(0x44,':');
- }
- wendumaibo();
- baojin();
- }
-
- //==================脈搏報(bào)警上限 設(shè)置===================
- if(yemian==1)
- {
- if(biaozhi==1)
- {
- biaozhi=2;
- Buzzer=1;
- lcd_init();// 初始化
- display(0x04,'H');
- display(0x05,'e');
- display(0x06,'a');
- display(0x07,'r');
- display(0x08,'t');
- display(0x09,'-');
- display(0x0a,'H');
-
- display(0x46,S_heart_H/100+'0');
- display(0x47,S_heart_H%100/10+'0');
- display(0x48,S_heart_H%100%10+'0');
- }
- shezhi();
- }
-
- //==================脈搏報(bào)警下限 設(shè)置===================
- if(yemian==2)
- {
- if(biaozhi==2)
- {
- biaozhi=3;
- Buzzer=1;
- lcd_init();// 初始化
- display(0x04,'H');
- display(0x05,'e');
- display(0x06,'a');
- display(0x07,'r');
- display(0x08,'t');
- display(0x09,'-');
- display(0x0a,'L');
-
- display(0x46,S_heart_L/100+'0');
- display(0x47,S_heart_L%100/10+'0');
- display(0x48,S_heart_L%100%10+'0');
- }
- shezhi();
- }
-
- //==================溫度報(bào)警 上限設(shè)置===================
- if(yemian==3)
- {
- if(biaozhi==3)
- {
- biaozhi=4;
- Buzzer=1;
- lcd_init();// 初始化
-
- display(0x05,'T');
- display(0x06,'e');
- display(0x07,'m');
- display(0x08,'p');
- display(0x09,'-');
- display(0x0a,'H');
-
- display(0x46,S_temp_H/100+'0');
- display(0x47,S_temp_H%100/10+'0');
- display(0x48,S_temp_H%100%10+'0');
- }
- shezhi();
- }
-
- //==================溫度報(bào)警 下限設(shè)置===================
- if(yemian==4)
- {
- if(biaozhi==4)
- {
- biaozhi=0;
- Buzzer=1;
- lcd_init();// 初始化
-
- display(0x05,'T');
- display(0x06,'e');
- display(0x07,'m');
- display(0x08,'p');
- display(0x09,'-');
- display(0x0a,'L');
-
- display(0x46,S_temp_L/100+'0');
- display(0x47,S_temp_L%100/10+'0');
- display(0x48,S_temp_L%100%10+'0');
- }
- shezhi();
- }
-
-
- }
- }
- }
-
-
- void int0() interrupt 0
- {
- if(time1>=8)
- {
- time1=0;
- timecount=0;//50ms計(jì)數(shù)清零
- i++;
- if(i==3)//記錄到超過(guò)等于3次時(shí)間
- {
- i=1;//計(jì)數(shù)從1開(kāi)始
- displayOK=1; //測(cè)得3次開(kāi)始顯示
- }
-
- if(displayOK==1 && oneminte<=200 &&yemian==0) { rate1=0; rate ++; } //10s
- if( oneminte>200 && flag==0 && yemian==0)
- {
- flag=1;
- rate1=rate*6;
-
- display(0x09,'/');
- display(0x0a,'m');
- display(0x0b,'i');
- display(0x0c,'n');
-
- display(0x06,rate1/100+'0');
- display(0x07,rate1%100/10+'0');
- display(0x08,rate1%100%10+'0');
- }
-
- }
-
- }
-
-
- /*************定時(shí)器0中斷服務(wù)程序***************/
- void time0_int() interrupt 1
- {
- TH0 = 0x3c;
- TL0 = 0xb0; // 50ms 12M
- timecount++;//每50ms一次計(jì)數(shù)
- time1++;
-
- oneminte++;
- flat300ms++;
- if(timecount>50 &&yemian==0 ) //當(dāng)超過(guò)50*50ms=2.5s左右沒(méi)有檢測(cè)到信號(hào)停止顯示
- {
- i=0;//數(shù)據(jù)個(gè)數(shù)清零
- timecount=0;//50ms計(jì)數(shù)清零
- displayOK=0;//顯示關(guān)
- oneminte=0;
- rate=0;
- display(0x06,'W');
- display(0x07,'a');
- display(0x08,'i');
- display(0x09,'t');
- display(0x0a,'i');
- display(0x0b,'n');
- display(0x0c,'g');
-
-
- }
- }
復(fù)制代碼
以上的Word格式文檔51黑下載地址:
參考文檔.doc
(895.27 KB, 下載次數(shù): 18)
2020-11-12 10:19 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|