第12章 應用案例設計_第1頁
第12章 應用案例設計_第2頁
第12章 應用案例設計_第3頁
第12章 應用案例設計_第4頁
第12章 應用案例設計_第5頁
已閱讀5頁,還剩123頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1第12章單片機的各種控制與檢測應用設計

介紹各種常用的單片機測控應用設計案例,通過案例使讀者了解單片機系統(tǒng)的的各種常見的應用設計。12.1單片機控制步進電機的設計

步進電機是將脈沖信號轉變?yōu)榻俏灰苹蚓€位移的開環(huán)控制元件。

非超載的情況下,電機轉速、停止位置只取決于脈沖信號的頻率和脈沖數(shù),而不受負載變化的影響,給電機加一脈沖信號,電機則轉過一個步距角。因而步進電機只有周期性誤差而無累積誤差,在速度、位置等控制領域有較為廣泛的應用。2312.1.1控制步進電機的工作原理

驅動步進電機由單片機通過對每組線圈中的電流的順序切換來使電機作步進式旋轉,切換是單片機輸出脈沖信號來實現(xiàn)。

調節(jié)脈沖信號頻率就可改變步進電機轉速;改變各相脈沖先后順序,就可改變電機旋轉方向。

步進電機驅動可采用雙四拍(AB→BC→CD→DA→AB)方式,也可采用單四拍(A→B→C→D→A)方式。為使步進電機旋轉平穩(wěn),還可采用單、雙八拍方式(A→AB→B→BC→C→CD→D→DA→A)。各種工作方式時序見圖12-1。

4

圖12-1

各種工作方式時序圖5

圖12-1脈沖信號是高電平有效,但實際控制時公共端是接在VCC上,所以實際控制脈沖是低電平有效。12.1.2電路設計與編程

【例12-1】單片機對步進電機控制的原理電路見圖12-1。編寫程序,用四路I/O口輸出實現(xiàn)環(huán)形脈沖分配,控制步進電機按固定方向連續(xù)轉動。同時,通過“正轉”和“反轉”兩個按鍵來控制電機的正轉與反轉。按下“正轉”按鍵,步進電機正轉;按下“反轉”按鍵,步進電機反轉;松開按鍵,電機停止轉動。ULN2003是高耐壓、大電流達林頓陣列系列產品,7個NPN達林頓管組成。多用于單片機、智能儀表、PLC等控制電路6圖12-2

單片機控制步進電機接口電路7中。在5V電壓下能與TTL和CMOS電路直接相連,可直接驅動繼電器等負載。具有電流增益高、工作電壓高、溫度范圍寬、帶負載能力強等特點。輸入5V的TTL電平,輸出可達500mA/50V。適于各類高速大功率驅動的系統(tǒng)。參考程序:#include"reg51.h"#defineucharunsignedchar#defineuintunsignedint#defineoutP2sbitpos=P0^0; //定義檢測正轉控制位P0.0sbitneg=P0^1; //定義檢測反轉控制位P0.1voiddelayms(uint);

8ucharcodeturn[]={0x02,0x06,0x04,0x0c,0x08,0x09,0x01,0x03};//步進脈沖數(shù)組voidmain(void){ uchari; out=0x03; while(1) { if(!pos)//如果正轉按鍵按下 { i=i<8?i+1:0;//如果i<8,則i=i+1;否則i=0 out=turn[i]; delayms(50); }9elseif(!neg) { i=i>0?i-1:7; out=turn[i]; delayms(50); } }}voiddelayms(uintj) //函數(shù)功能:延時{ uchari; for(;j>0;j--) { i=250; while(--i); i=249; while(--i); }}1012.2單片機控制直流電機

直流電機多用在無交流電源、方便移動場合,具有低速大力矩等特點。如何用單片機控制直流電機。12.2.1控制直流電機的工作原理

對直流電機可精確控制其旋轉速度或轉矩,通過兩個磁場相互作用產生旋轉。結構見圖12-3(a),定子裝設一對直流勵磁的靜止主磁極N和S,在轉子上裝設電樞鐵心。定子與轉子間有一氣隙。在電樞鐵心上放置了由兩根導體連成的電樞線圈,線圈首端和末端分別連到兩個圓弧形銅片上,此銅片稱為換向片。由換向片構成的整體稱為換向器。11

換向器固定在轉軸上,換向片與轉軸間互相絕緣。在換向片上放置一對固定不動的電刷B1和B2,當電樞旋轉時,電樞線圈通過換向片和電刷與外電路接通。

定子通過永磁體或受激勵電磁鐵產生一固定磁場,由于轉子由一系列電磁體構成,當電流通過其中一個繞組時會產生一個磁場。

對有刷直流電機,轉子上換向器和定子電刷在電機旋轉時為每個繞組供給電能。通電轉子繞組與定子磁體有相反極性,因而相互吸引,使轉子轉動至與定子磁場對準的位置。當轉子到達對準位置時,電刷通過換向器為下一組繞組供電,從而使轉子維持旋轉運動,見圖12-3(b)。12(a)有刷直流電機結構示意圖(i)導體ad處于N極下(ii)導體ad處于S極下(b)有刷直流電機工作示意圖圖12-3

直流電機工作示意圖13

直流電機轉速與施加電壓成正比,轉矩與電流成正比。由于必須在工作期間改變直流電機的速度,直流電機控制是一較困難問題。直流電機高效運行的常見方法是施加一個PWM(脈寬調制)脈沖波,其占空比對應于所需速度。電機起到了一個低通濾波器作用,PWM信號相對容易產生,這種驅動方式使用更為廣泛。12.2.2電路設計與編程

【例12-2】原理電路見圖12-4。使用單片機兩個I/O腳控制直流電機轉速和旋轉方向。其中P3.7腳輸出PWM信號控制直流電機轉速;P3.6腳控制直流電機旋轉方向。14圖12-4

單片機控制直流電機的接口電路

當P3.6=1時,P3.7發(fā)送PWM波,直流電機正轉。且可通過“INC”和“DEC”兩個按鍵來增大和減少直流電機轉速。反之,P3.6=0時,P3.7發(fā)送PWM信號,直流電機反轉。

因此,增大和減小電機轉速,實際上是通過按下“INC”或“DEC”按鍵來改變輸出PWM信號占空比,控制直流電機轉速。圖12-4中驅動電路使用了NPN低頻、低噪聲小功率達林頓管

2SC2547。參考程序如下:1516#include"reg51.h"#include"intrins.h"#defineucharunsignedchar#defineuintunsignedint sbitINC=P3^4;sbitDEC=P3^5;sbitDIR=P3^6; sbitPWM=P3^7;voiddelay(uint);intPWM=900;voidmain(void){ DIR=1; while(1) { if(!INC) PWM=PWM>0?PWM-1:0;//如果PWM>0,則PWM=PWM-1;否則PWM=01712.3電機轉速測量12.3.1電機轉速測量的工作原理

用光電管、單片機及LED數(shù)碼管可測量直流電機轉速并顯示。

光電對管,也稱光電開關,內部結構就是一發(fā)光二極管和一個光敏三極管,分為反射式和直射式,工作原理都是光電轉化,即通過集聚光線來控制光敏三極管的導通與截止。

因此,測量電機轉速實質是利用光電對管對直流電機葉片底部的白色小帶進行檢測,當檢測到白色小帶時將產生一個脈沖信號。電機轉一圈對應一個脈沖,然后對脈沖信號放大并進行計數(shù),計算單位時間內測得的脈沖數(shù),也就測出電機轉速,并送LED數(shù)碼管顯示。1812.3.2電路設計與編程

【例12-3】測量電機轉速電路見圖12-5。Z-OPTOCOULER-NPN為光電管,電機旋轉時,使光電管輸出脈沖信號,然后脈沖信號經過放大,并對其計數(shù),經計算,把轉速數(shù)據(jù)送到LED數(shù)碼管顯示。

模擬直流電機轉速脈沖由數(shù)字時鐘發(fā)生器產生,在電路中添加數(shù)字時鐘發(fā)生器方法是,點擊圖4-2中左側工具箱中的圖標

,出現(xiàn)選擇菜單,選擇“DCLOCK”項,然后把其放入原理圖編輯窗口中進行連線。鼠標右鍵單擊“DCLOCK”圖標,出現(xiàn)屬性設置窗口,選擇“數(shù)字類型”欄中的“時鐘”項,在右面的“時間”欄中,手動修改輸出的數(shù)字時鐘脈沖的頻率,這相當于改變電機轉速。19 if(!DEC) PWM=PWM<1000?PWM+1:1000;//如PWM<1000,則PWM=PWM+1;//否則PWM=1000 PWM=1; //產生PWM的信號高電平 delay(PWM); //延時 PWM=0; //產生PWM的信號低電平 delay(1000-PWM); //延時 }}voiddelay(uintj){ for(;j>0;j--) { _nop_(); }}20圖12-5測量電機轉速的原理電路與仿真21

仿真運行后,電機轉速(即每秒計得的脈沖數(shù))顯示在LED數(shù)碼管上。在手動設置數(shù)字時鐘頻率時,選擇“600”,經過單片機測得的轉數(shù)值(轉數(shù)/秒)在數(shù)碼管上顯示,與設置的數(shù)字脈沖頻率相一致。參考程序如下。#include"reg51.h"#include"intrins.h"#defineucharunsignedchar#defineuintunsignedint#defineoutP0ucharcodeseg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x01};22inti=0; voidmain(void){ intj; TMOD=0x15; //T0方式1計數(shù),T1方式1定時 TH0=0; //T0計數(shù)器清零

TH1=0x3C; //12MHz晶振,T1定時50ms TL1=0xB0; TR0=1; //啟動T0計數(shù)器

TR1=1; //啟動T1 IE=0x88; //允許T1中斷和總中斷允許

while(1) { P2=0x00; //輸出百位顯示值 out=seg[i/100]; P2=0x02; for(j=0;j<100;j++);

P2=0x00; out=seg[i%100/10]; //輸出十位顯示值23 P2=0x04; for(j=0;j<100;j++); P2=0x00; out=seg[i%10]; //輸出個位顯示值 P2=0x08; for(j=0;j<100;j++); } }voidTimer1_ISR()interrupt3//T1中斷程序,產生50ms定時{ staticcharj=0; TH1=0x3C; //重設定時器值,50ms定時,12MHz晶振 TL1=0xB0; if(++j==20) //是否中斷20次,即50msx20次=1s { j=0; i=(TH0<<8)|TH00;//1s內的計數(shù)值即為電機轉動速度,單位:轉/秒 TH0=0; //T0清零 TL0=0; }}2412.4頻率計的制作12.4.1工作原理

利用單片機定時器/計數(shù)器可實現(xiàn)信號頻率測量。頻率測量有測頻法和測周法兩種。測頻法利用外部電平變化引發(fā)的外部中斷,測算1s內出現(xiàn)的次數(shù),從而實現(xiàn)對頻率測量;測周法是通過測算某兩次電平變化引發(fā)的中斷間的時間,再求倒數(shù),從而實現(xiàn)對頻率測定??傊瑴y頻法是直接根據(jù)定義來測定頻率,測周法是通過測定周期間接測定頻率。理論上,測頻法適于較高頻率測量,測周法適于較低頻率測量。本例采用測頻法。

12.4.2電路設計與軟件編程【例12-4】設計以單片機為核心的頻率測量裝置,測量加在P3.4腳上數(shù)字時鐘信號頻率,并在外部擴展的6位LED數(shù)碼管上顯示測量頻率值。原理電路與仿真見圖12-6。

本頻率計測量的信號由數(shù)字時鐘源“DCLOCK”產生,在電路中添加數(shù)字時鐘源的具體操作與設置見【例12-3】。手動改變被測時鐘信號源頻率,觀察是否與LED數(shù)碼管上顯示的測量結果相同。26圖12-6

頻率計原理電路與仿真27參考程序如下。#include<reg51.h>sfr16DPTR=0x82; //定義寄存器DPTRunsignedcharcnt_t0,cnt_t1,qian,bai,shi,ge,bb,wan,shiwan;unsignedlongfreq; //定義頻率unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //共陰數(shù)碼管段碼表voiddelay_1ms(unsignedintz) //函數(shù)功能:延時約1ms{ unsignedchari,j; for(i=0;i<z;i++) for(j=0;j<110;j++);}28voidinit() //函數(shù)功能:定時器/計數(shù)器及中斷系統(tǒng)初始化{ freq=0; //頻率賦初值 cnt_t1=0; cnt_t0=0; IE=0x8a; //開中斷,T0,T1中斷 TMOD=0x15; //T0為定時器方式1,T1為計數(shù)器于方式1 TH1=0x3c; //T1定時50ms TL1=0xb0; TR1=1; //開啟定時器T1 TH0=0; //T0清0 TL0=0; TR0=1; //開啟定時器T0}voiddisplay(unsignedlongfreq_num)//函數(shù)功能:驅動數(shù)碼管顯示{shiwan=freq_num%1000000/100000;wan=freq_num%100000/10000;29

qian=freq_num%10000/1000; //顯示千位 bai=freq_num%1000/100; //顯示百位 shi=freq_num%100/10; //顯示十位 ge=freq_num%10; //顯示個位 P0=0xdf; //P0口是位選 P2=table[shiwan]; //顯示十萬位 delay_1ms(5); P0=0xef; P2=table[wan]; //顯示萬位 delay_1ms(3); P0=0xf7; P2=table[qian]; //顯示千位 delay_1ms(3);30P0=0xfb; P2=table[bai]; //顯示百位 delay_1ms(3); P0=0xfd; P2=table[shi]; //顯示十位 delay_1ms(3); P0=0xfe; P2=table[ge]; //顯示個位 delay_1ms(3);}voidmain() //主函數(shù){ P0=0xff; //初始化P0口 init(); //計數(shù)器初始化 while(1) { if(cnt_t1==19) //定時1s {31

cnt_t1=0; //定時完成后清0 TR1=0; //關閉T1定時器,定時1S完成 delay_1ms(141); //延時較正誤差,通過實驗獲得 TR0=0; //關閉T0 DPL=TH00; //利用DPTR讀入其值 DPH=TH0; freq=cnt_t0*65535; freq=freq+DPTR; //計數(shù)值放入變量}display(freq); //調用顯示函數(shù) }

}voidt1_func()interrupt3 //定時器T1的中斷函數(shù){ TH1=0x3c; TL1=0xb0;

cnt_t1++;}

32voidt0_func()interrupt1 //定時器T0的中斷函數(shù){ cnt_t0++;}

在單片機應用系統(tǒng)中,有時往往需要一個實時時鐘/日歷作為測控時間基準。時鐘/日歷集成電路芯片多種,設計者只需選擇合適芯片即可。本節(jié)介紹最為常見的時鐘/日歷芯片DS1302的功能、特性以及單片機的硬件接口設計及軟件編程。12.5基于時鐘/日歷芯片DS1302的電子鐘設計

時鐘/日歷芯片DS1302是美國DALLAS公司推出的涓流充電時鐘芯片,功能特性如下。(1)能計算2100年前的年、月、日、星期、時、分、秒的信息;每月的天數(shù)和閏年天數(shù)可自動調整;時鐘可設置為24或12小時格式。(2)與單片機間采用單線同步串行通信。12.5.1DS1302的工作原理1.基本性能34(3)31字節(jié)的8位靜態(tài)RAM。(4)功耗低,保持數(shù)據(jù)和時鐘信息時功率小于1mW;可選的涓流充電能力。(5)讀/寫時鐘或RAM數(shù)據(jù)有單字節(jié)和多字節(jié)兩種傳送方式。DS1302引腳見圖12-7。圖12-7DS1302的引腳35各引腳功能如下:I/O:數(shù)據(jù)輸入/輸出。SCLK:同步串行時鐘輸入。RST*:芯片復位,1—芯片的讀/寫使能,0—芯片復位并被禁止讀/寫。VCC2:主電源輸入,接系統(tǒng)電源。VCC1:備份電源輸入引腳,通常接2.7~3.5V電源。當VCC2>VCC1+0.2V時,芯片由VCC2供電;當VCC2<VCC1時,芯片由VCC1供電。GND:地X1,X2:接32.768KHz晶振引腳。

單片機與DS1302間無數(shù)據(jù)傳輸時,SCLK保持低電平,此時如果

從低變?yōu)楦邥r,即啟動數(shù)據(jù)傳輸,此時SCLK的上升沿將數(shù)據(jù)寫入DS1302,而在SCLK的下降沿從DS1302讀出數(shù)據(jù)。

為低時,則禁止數(shù)據(jù)傳輸,讀/寫時序如圖12-8所示。數(shù)據(jù)傳輸時,低位在前,高位在后。2.DS1302的命令字格式單片機對DS1302的讀/寫,都必須由單片機先向DS1302寫入一個命令字(8位)發(fā)起,命令字的格式見表12-1。37圖12-8DS1302讀/寫時序命令字各位功能:D7:必須為邏輯1,如為0,則禁止寫入DS1302。D6:1—讀/寫RAM數(shù)據(jù),0—讀/寫時鐘/日歷數(shù)據(jù)。D5~D1:為讀/寫單元的地址;D0:1—對DS1302讀操作,0—對DS1302寫操作。注意,命令字(8位)總是低位在先,命令字每1位都是在SCLK上升沿送出。383.DS1302的內部寄存器片內各時鐘/日歷寄存器以及其它的功能寄存器見表12-2。通過向寄存器寫入命令字實現(xiàn)對DS1302操作。例如,如要設置秒寄存器的初始值,需要先寫入命令字80H(見表12-2),然后再向秒寄存器寫入初始值;如要讀出某時刻秒值,需要先寫入命令字81H,然后再從秒寄存器讀取秒值。表12-2中各寄存器“取值范圍”1列存放的數(shù)據(jù)均為BCD碼。39表12-2

主要寄存器、命令字與取值范圍及各位內容40CH:時鐘暫停位,1-振蕩器停止,DS1302為低功耗方式;0-時鐘開始工作。10SEC:秒的十位數(shù)字,SEC為秒的個位數(shù)字10MIN:分的十位數(shù)字,MIN為分的個位數(shù)字12/24:12或24小時方式選擇位AP:小時格式設置位,0-上午模式(AM);1-下午模式(PM)10DATE:日期的十位數(shù)字,DATE為日期的個位數(shù)字10M:月的十位數(shù)字,MONTH為日期的個位數(shù)字DAY:星期的個位數(shù)字4110YEAR:年的十位數(shù)字,YEAR為年的十位數(shù)字

表12-2中后3個寄存器的功能及特殊位符號的意義說明如下。寫保護寄存器:該寄存器的D7位WP是寫保護位,其余7位(D0~D6)置為0。在對時鐘/日歷單元和RAM單元進行寫操作前,WP必須為0,即允許寫入。當WP為1時,用來防止對其它寄存器進行寫操作。涓流充電寄存器:慢充電寄存器,用于管理對備用電源的充電。TCS:當4位TCS=1010時,才允許使用涓流充電寄存器,其他任何狀態(tài)都將禁止使用涓流充電器。DS:兩DS位用于選擇連接在VCC2和VCC1間的二極管數(shù)目。01-選擇1個二極管;10-選擇2個二極管;11或00-涓流充電器被禁止。RS:兩位RS位用于選擇涓流充電器內部在VCC2和VCC1之間的連接電阻。RS=01,選擇R1(2kΩ);RS=10時,選擇R2(4kΩ);RS=11時,選擇R3(8kΩ);RS=00時,不選擇任何電阻。43時鐘突發(fā)寄存器:單片機對DS1302除單字節(jié)數(shù)據(jù)讀/寫外,還可采用突發(fā)方式,即多字節(jié)連續(xù)讀/寫。在多字節(jié)連續(xù)讀/寫中,只要對地址為3EH的時鐘突發(fā)寄存器進行讀/寫操作,即把對時鐘/日歷或RAM單元的讀/寫設定為多字節(jié)方式。該方式,讀/寫都開始于地址0的D0位。當多字節(jié)方式寫時鐘/日歷時,必須按照數(shù)據(jù)傳送的次序寫入最先的8個寄存器;但是以多字節(jié)方式寫RAM時,沒有必要寫入所有的31個字節(jié),每個被寫入的字節(jié)都被傳輸?shù)絉AM,無論31個字節(jié)是否都被寫入。12.5.2電路設計與編程44(2)閏年自動判別。(3)鍵盤采用動態(tài)掃描方式查詢,參量應能進行增1修改,由“啟動日期與時間修改”功能鍵k1與6個參量修改鍵組合來完成增1修改。即先按一下k1,然后按一下被修改參量鍵,即可使該參量增1,修改完畢,再按一下k1表示修改結束確認。本例時鐘/日歷原理電路與仿真見圖12-9。LCD1602分兩行顯示日歷與時鐘。45

【例12-5】制作一個使用時鐘/日歷芯片DS1302并采用LCD1602顯示的日歷/時鐘,基本功能如下。(1)顯示6個參量的內容,第一行顯示:年、月、日;第二行顯示:時、分、秒。46圖12-9LCD顯示的時鐘/日歷原理電路及仿真47圖12-9的4×3矩陣鍵盤,只用到了其中2行鍵共6個,余下的按鍵,本例未使用,可用于將來鍵盤功能擴展。參考程序如下:#include<reg51.h>#include"LCD1602.h" //液晶顯示器LCD1602頭文件#include"DS1302.h" //時鐘/日歷芯片DS1302頭文件#defineucharunsignedchar#defineuintunsignedintbitkey_flag1=0,key_flag2=0;SYSTEMTIMEadjusted; //此處為結構體定義48ucharsec_add=0,min_add=0,hou_add=0;ucharday_add=0,mon_add=0,yea_add=0;uchardata_alarm[7]={0};intkey_scan() //函數(shù)功能:鍵盤掃描,判是否有鍵按下{ inti=0; uinttemp; P1=0xf0; temp=P1; if(temp!=0xf0) { i=1; } else { i=0; }

returni;}49ucharkey_value() //函數(shù)功能:獲取按下的按鍵值{uintm=0,n=0,temp;ucharvalue;ucharv[4][3]={'2','1','0','5','4','3','8','7','6','b','a','9'};P1=0xfe;temp=P1;if(temp!=0xfe)m=0;//采用分行、分列掃描的形式獲取按鍵鍵值

P1=0xfd;temp=P1;if(temp!=0xfd)m=1;P1=0xfb;temp=P1;if(temp!=0xfb)m=2;P1=0xf7;temp=P1;if(temp!=0xf7)m=3;P1=0xef;temp=P1;if(temp!=0xef)n=0;P1=0xdf;temp=P1;if(temp!=0xdf)n=1;P1=0xbf;temp=P1;if(temp!=0xbf)n=2;50value=v[m][n];returnvalue;}voidadjust(void) //函數(shù)功能:修改各參量{ if(key_scan()&&key_flag1) switch(key_value()) { case'0':sec_add++;break; case'1':min_add++;break; case'2':hou_add++;break; case'3':day_add++;break; case'4':mon_add++;break; case'5':yea_add++;break;51 default:break; }adjusted.Second+=sec_add;adjusted.Minute+=min_add;adjusted.Hour+=hou_add;adjusted.Day+=day_add;adjusted.Month+=mon_add;adjusted.Year+=yea_add;if(adjusted.Second>59) { adjusted.Second=adjusted.Second%60; adjusted.Minute++; } if(adjusted.Minute>59) { adjusted.Minute=adjusted.Minute%60; adjusted.Hour++; }52if(adjusted.Hour>23) { adjusted.Hour=adjusted.Hour%24; adjusted.Day++; } if(adjusted.Day>31) adjusted.Day=adjusted.Day%31; if(adjusted.Month>12) adjusted.Month=adjusted.Month%12; if(adjusted.Year>100) adjusted.Year=adjusted.Year%100;} 53voidchanging(void)interrupt0using0//中斷處理函數(shù),修改參量,或修改確認{ if(key_flag1) key_flag1=0; else key_flag1=1;}

main() //主函數(shù){

uinti; ucharp1[]="D:",p2[]="T:"; SYSTEMTIMET;

EA=1; EX0=1; IT0=1; EA=1;54

EX1=1; IT1=1; init1602(); Initial_DS1302();

while(1){ write_com(0x80); write_string(p1,2); write_com(0xc0); write_string(p2,2); DS1302_GetTime(&T); adjusted.Second=T.Second; adjusted.Minute=T.Minute; adjusted.Hour=T.Hour; adjusted.Week=T.Week;55 adjusted.Day=T.Day; adjusted.Month=T.Month; adjusted.Year=T.Year; for(i=0;i<9;i++){ adjusted.DateString[i]=T.DateString[i]; adjusted.TimeString[i]=T.TimeString[i]; } adjust(); DateToStr(&adjusted); TimeToStr(&adjusted); write_com(0x82); write_string(adjusted.DateString,8); write_com(0xc2); write_string(adjusted.TimeString,8); delay(10); } }

56程序中,使用了自行編寫的液晶顯示器LCD1602的頭文件“LCD1602.h”,由于液晶顯示器LCD1602是單片機應用系統(tǒng)經常用到的器件,因此將其常用到的驅動函數(shù)等函數(shù),寫成一個頭文件,如果以后在其他項目中也用到LCD1602,只需將該頭文件包含進來即可,這樣程序的編寫提供了方便。同理涉及對時鐘/日歷芯片DS1302的控制,也可自行編寫頭文件“DS1302.h”,以后在其他項目中將該頭文件包含進來即可。上述兩個頭文件清單見附錄1與附錄2。12.6電話撥號的模擬12.6.1模擬電話撥號的設計要求57設計模擬電話撥號時的狀況,把模擬電話鍵盤撥出的某一電話號碼,顯示在LCD顯示屏上。電話鍵盤除了0~9的10個數(shù)字鍵外,還有“*”鍵用于實現(xiàn)刪除功能,即刪除一位最后輸入的號碼;“#”鍵用于清除顯示屏上所有的數(shù)字顯示。此外還要求每按下一個鍵,發(fā)出聲響,表示按下該鍵。還有LCD顯示器,顯示所撥的電話號碼。12.6.2電路設計與編程【例12-6】設計一模擬電話撥號時的電話鍵盤及顯示裝置,把電話鍵盤撥出的電話號碼及其他信息,顯示在LCD顯示屏上。電話鍵盤共12個鍵,除了0~9的10個數(shù)字鍵外,還有58“*”鍵用于刪除最后輸入的1位號碼的功能;“#”鍵用于清除顯示屏上所有的數(shù)字顯示。此外還要求每按下一個鍵,蜂鳴器要發(fā)出聲響,以表示按下該鍵。顯示信息共2行,第1行為設計者信息,第2行顯示所撥的電話號碼。本例的電話撥號鍵盤采用4×3矩陣鍵盤,共12個鍵。撥號號碼顯示采用LCD1602液晶顯示模塊。因此涉及了單片機與4×3矩陣式鍵盤以及與16×2的液晶顯示屏的接口設計,還有各種驅動程序的編制。液晶顯示屏采用LCD1602

(即Proteus中的LM016L)。本設計原理電路及仿真見圖12-10。59圖12-10

電話撥號的模擬60參考程序如下。#include<reg51.h>#defineuintunsignedint#defineucharunsignedcharucharkeycode,DDram_value=0xc0;sbitrs=P2^0;sbitrw=P2^1;sbite=P2^2;sbitspeaker=P2^3;ucharcodetable[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20};ucharcodetable_designer[]="HITZYGDesign";//第1行顯示設計者信息61voidlcd_delay();voiddelay(uintn);voidlcd_init(void);voidlcd_busy(void);voidlcd_wr_con(ucharc);voidlcd_wr_data(uchard);ucharcheckkey(void);ucharkeyscan(void);voidmain(){ucharnum; lcd_init(); lcd_wr_con(0x80);62for(num=0;num<=14;num++) { lcd_wr_data(table_designer[num]); } while(1) { keycode=keyscan(); if((keycode>=0)&&(keycode<=9)){ lcd_wr_con(0x06); lcd_wr_con(DDram_value); lcd_wr_data(table[keycode]); DDram_value++; }63elseif(keycode==0x0b) { uchari,j; j=0xc0; for(i=0;i<=15;i++) { lcd_wr_con(j); lcd_wr_data(table[10]); }voidlcd_delay() //函數(shù)功能:液晶顯示延時{uchary;for(y=0;y<0xff;y++){ ;}}64

voidlcd_init(void) //函數(shù)功能:液晶初始化{lcd_wr_con(0x01);lcd_wr_con(0x38);

65lcd_wr_con(0x0c);lcd_wr_con(0x06);}voidlcd_busy(void) //函數(shù)功能:判液晶是否忙{ P0=0xff; rs=0; rw=1; e=1; e=0; while(P0&0x80) { e=0;66e=1; } lcd_delay();}

voidlcd_wr_con(ucharc) //函數(shù)功能:向液晶顯示器寫入命令{lcd_busy(); e=0; rs=0; rw=0; e=1;

67 P0=c; e=0; lcd_delay();}voidlcd_wr_data(uchard)//函數(shù)功能:/向液晶寫數(shù)據(jù){ lcd_busy(); e=0; rs=1; rw=0; e=1; P0=d; e=0; lcd_delay();}68voiddelay(uintn) //函數(shù)功能:延時{ uchari; uintj; for(i=50;i>0;i--)for(j=n;j>0;j--);}

ucharcheckkey(void) //函數(shù)功能:檢測鍵有無按下{ uchartemp; P1=0xf0; temp=P1;69temp=temp&0xf0; if(temp==0xf0) { return(0); } else{ return(1); }}ucharkeyscan(void) //函數(shù)功能:鍵盤掃描并返回所按下的鍵盤號{ucharhanghao,liehao,keyvalue,buff;if(checkkey()==0)70{ return(0xff); //無鍵按下,返回0xff}else //無鍵按下,返回0xff{ ucharsound; for(sound=50;sound>0;sound--){ speaker=0; delay(1); speaker=1; delay(1); } P1=0x0f;71 buff=P1; if(buff==0x0e) { hanghao=0; } elseif(buff==0x0d) { hanghao=3; } elseif(buff==0x0b) { hanghao=6; }

72elseif(buff==0x07) { hanghao=9; } P1=0xf0; buff=P1; if(buff==0xe0) { liehao=2; } elseif(buff==0xd0) { liehao=1; }73elseif(buff==0xb0) { liehao=0; } keyvalue=hanghao+liehao; while(P1!=0xf0); return(keyvalue);}}7412.7簡易音符發(fā)生器的制作12.7.1設計要求及工作原理

設計一個音樂音符發(fā)生器。利用分別按下鍵盤的1,2,3,4,5,6,7,1(高音)8個鍵,可發(fā)出8個不同音符的聲音,即發(fā)出“哆”、“唻”、“咪”、“發(fā)”、“嗽”、“拉”、“西”、“哆”(高音)的聲音,并且要求按下按鍵松開后延遲一段時間停止,如果再按別的鍵則發(fā)出另一音符的聲音。當掃描到鍵盤上有鍵按下,則快速檢測是哪鍵按下,然后單片機定時器啟動,發(fā)出相應音符頻率的脈沖,該音符脈沖輸入到蜂鳴器后,就會發(fā)出相應的音調。如在前一個按下的鍵發(fā)聲的同時有另一個鍵被按下,則啟用中斷系統(tǒng),75前面鍵的發(fā)音停止,轉到后按下鍵的發(fā)音程序,發(fā)出相應的音符聲音。發(fā)出不同音符聲音原理,就是發(fā)出對應不同音符頻率的方波,即給定時器T0載入不同的定時時間常數(shù),從而產生對應頻率的方波,驅動蜂鳴器發(fā)出音符聲音。12.7.2電路設計與編程音樂音符發(fā)生器的原理電路與仿真如圖12-11所示。在“ClockFrequency”欄中輸入晶振頻率為11.0592MHz。依次按下不同的音符選擇按鍵就可發(fā)出不同聲音。76

圖12-11簡易音樂音符發(fā)生器原理電路與仿真77參考程序如下://本例晶振頻率為11.0592MHz,計算各音符頻率,可得哆、唻、咪、發(fā)、嗽、拉、西、哆(高音)8個音符,應賦給定時器的初值(十進制)為:6440964604647056475164837649146498265032,通過定時器T0輸出不同頻率的方波#include<reg51.h>sbitP3_3=P3^3;unsignedcharidatai,TL0_temp=0,TH0_temp=0,counter=0;voidT0_func()interrupt1{ //定時器T0中斷服務程序,T0產生方波 counter++; TH0=TH0_temp; //裝載時間常數(shù)

TL0=TL0_temp; P3_3=~P3_3; //P3.3腳求反,輸出方波}78main() //主函數(shù) { P1=0xff; //向P1口寫入全1,輸入口

TMOD=0x01; //設定時器T0為方式1定時

ET0=1; //允許T0中斷

EA=1; //總中斷允許

TH0=0; //T0清0 TL0=0; TCON=0x10; //總中斷允許 while(1){

i=P1; if((i==0xff)||(counter>=100))//無鍵按下,或發(fā)音結束,則//停止計數(shù)79

{ TR0=0; counter=0; }//對不同音階加載不同的初值。如已在發(fā)音,則打斷當前發(fā)音,重加載if(i==0xfe),“哆”鍵按下,加載“哆”初值

{ TR0=0; counter=0; TH0_temp=0xfb; TL0_temp=0xe9; TR0=1; //T0啟動

} if(i==0xfd) //“唻”鍵按下,加載“唻”初值80{ TR0=0; counter=0; TH0_temp=0xfc; TL0_temp=0x5c; TR0=1; //T0啟動

} if(i==0xfb) //“咪”鍵按下,加載“咪”初值

{ TR0=0; //停止T0 counter=0; TH0_temp=0xfc; TL0_temp=0xc1; TR0=1; 81 //T0啟動

} if(i==0xf7) //“發(fā)”鍵按下,加載“發(fā)”初值

{ TR0=0; //停止T0 counter=0; TH0_temp=0xfc; TL0_temp=0xef; TR0=1; //T0啟動

} if(i==0xef) 82 //“嗽”鍵按下,加載“嗽”初值

{ TR0=0; //停止T0 counter=0; TH0_temp=0xfd; TL0_temp=0x45;

TR0=1; //T0啟動

} if(i==0xdf) //“拉”鍵按下,加載“拉”初值

{ TR0=0; //停止T0 counter=0; TH0_temp=0xfd; TL0_temp=0x92; TR0=1; }83if(i==0xbf) //“西”鍵按下,加載“西”初值

{ TR0=0; counter=0; TH0_temp=0xfd; TL0_temp=0xd6; TR0=1; }if(i==0x7f)//“哆(高音)”鍵按下,加載其初值

{ TR0=0; counter=0; TH0_temp=0xfe; TL0_temp=0x08; TR0=1; } }}8412.88位競賽搶答器設計目前,各類競賽中大多用到競賽搶答器,以單片機為核心配上搶答按鈕開關以及數(shù)碼管顯示器并結合編寫的軟件,很容易制作一個競賽搶答器,且修改方便。12.8.1設計要求設計一個以單片機為核心8位競賽搶答器,要求如下:(1)搶答器同時供8名選手或8個代表隊比賽,分別用8個按鈕S0~S7表示。(2)設置一個系統(tǒng)清除和搶答控制開關S,該開關由主持人控制。(3)搶答器具有鎖存與顯示功能。即選手按動按鈕,鎖存相應的編號,且優(yōu)先搶答選手的編號一直保持到主持人將系統(tǒng)清除為止。(4)搶答器具有定時搶答功能,且一次搶答時間由主持人設定(如30秒)。當主持人啟動“開始”鍵后,定時器進行減計時,同時揚聲器發(fā)出短暫聲響,聲響持續(xù)時間為0.5s左右。(5)參賽選手在設定的時間內進行搶答,搶答有效,定時器停止工作,顯示器上顯示選手的編號和搶答剩余時間,并保持到主持人將系統(tǒng)清除為止。86(6)如定時時間已到,無人搶答,本次搶答無效,系統(tǒng)報警并禁止搶答,定時顯示器上顯示00。

通過鍵盤改變可搶答時間,可把定時時間變量設為全局變量,通過鍵盤掃描程序使每按下一次按鍵,時間加1(超過30時置0)。同時單片機不斷進行按鍵掃描,當參賽選手的按鍵按下時,用于產生時鐘信號的定時計數(shù)器停止計數(shù),同時將選手編號(按鍵號)和搶答時間分別顯示在LED上。12.8.2電路設計與仿真8位競賽搶答器的原理電路與仿真見圖12-12。晶振頻率為12MHz。圖中為剩余18秒時,7號選手搶答成功。87圖中MAX7219是一串行接收數(shù)據(jù)的動態(tài)掃描顯示驅動器。MAX7219驅動8位以下LED顯示器時,它的DIN、LOAD、CLK端分別與單片機三條口線(P3.0~P3.2)相連。

MAX7219采用16位數(shù)據(jù)串行移位接收方式,即單片機將16位二進制數(shù)逐位發(fā)送到DIN端,在CLK的每個上升沿將一位數(shù)據(jù)移入MAX7219內移位寄存器,當16位數(shù)據(jù)移入完后,在LOAD腳信號上升沿將16位數(shù)據(jù)裝入MAX7219內相應位置,能對送入的數(shù)據(jù)進行BCD譯碼并顯示。本例對MAX7219進行相應的初始化設置,具體請查閱有關MAX7219技術資料。88圖12-128位競賽搶答器原理電路與仿真89參考程序如下:#include<reg51.h>sbitDIN=P3^0; //與max7219接口定義sbitLOAD=P3^1;sbitCLK=P3^2;sbitkey0=P1^0; //8路搶答器按鍵sbitkey1=P1^1;sbitkey2=P1^2;sbitkey3=P1^3;sbitkey4=P1^4;sbitkey5=P1^5;sbitkey6=P1^6;sbitkey7=P1^7;sbitkey_clear=P2^0; //主持人時間設置、清除sbitbegin=P2^1; //主持人開始按鍵90sbitsounder=P3^7; //蜂鳴器unsignedcharsecond=30; //秒表計數(shù)值unsignedcharcounter=0; //counter每100,minite加1unsignedcharpeople=0; //搶答結果unsignedcharnum_add[]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};//max7219讀寫地址、內容unsignedcharnum_dat[]={0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89};unsignedcharkeyscan()//鍵盤掃描函數(shù){unsignedcharkeyvalue,temp;keyvalue=0;P1=0xff;temp=P1;91 if(~(P1&temp)) { switch(temp) { case0xfe: keyvalue=1; break; case0xfd: keyvalue=2; break; case0xfb: keyvalue=3; break; case0xf7: keyvalue=4; break;92 case0xef: keyvalue=5; break; case0xdf: keyvalue=6; break; case0xbf: keyvalue=7;

break; case0x7f: keyvalue=8; break; default: keyvalue=0; break; } } returnkeyvalue; }93voidmax7219_send(unsignedcharadd,unsignedchardat)//函數(shù)功能:向max7219寫命令{ unsignedchar ADS,i,j;

LOAD=0; i=0; while(i<16) {

if(i<8) { ADS=add; } else { ADS=dat; }94 for(j=8;j>=1;j--) { DIN=ADS&0x80; ADS=ADS<<1; CLK=1; CLK=0; } i=i+8; } LOAD=1; }

voidmax7219_init() //函數(shù)功能:max7219初始化{ max7219_send(0x0c,0x01); max7219_send(0x0b,0x07); max7219_send(0x0a,0xf5); max7219_send(0x09,0xff);}95voidtime_display(unsignedcharx) //函數(shù)功能:時間顯示{ unsignedchari,j; i=x/10; j=x%10; max7219_send(num_add[1],num_dat[j]); max7219_send(num_add[0],num_dat[i]);}

voidscare_display(unsignedcharx)//函數(shù)功能:搶答結果顯示{ unsignedchari,j; i=x/10; j=x%10;96 max7219_send(num_add[3],num_dat[j]); max7219_send(num_add[2],num_dat[i]);}voidholderscan() //函數(shù)功能:搶答時間設置,0-60s{ time_display(second); scare_display(people); if(~key_clear) //如果有鍵按下,改變搶答時間

{ while(~key_clear); if(people) //如果搶答結果沒有清空,搶答器重置

{ second=30;97 people=0; } if(second<60) { second++; } else { second=0; } }}voidtimer_init() //定時器T0初始化{ EA=1; ET0=1; TMOD=0x01; //定時器T0方式0定時98TH0=0xd8; //裝入定時器定時常數(shù),設定10ms中斷一次TL0=0xef;}

voidmain(){while(1){do{holderscan();}while(begin); //開始前進行設置,若未按下開始鍵

while(~begin); //防抖max7219_init(); //芯片初始化

timer_init(); //中斷初始化

TR0=1; //開始中斷

do99{time_display(second);scare_display(people);people=keyscan();}while((!people)&&(second)); //運行直到搶答結束或時間結束

TR0=0;}}voidtimer0()interrupt1 //定時器T0中斷函數(shù){ if(counter<100) { counter++; if(counter==50) { sounder=0; }100}else{ sounder=1; counter=0; second=second-1;} TH0=0xd8; //重新裝載

TL0=0xef; TR0=1;}101

12.9電梯運行控制的樓層顯示12.9.1工作原理與設計要求設計采用單片機控制8×8LED點陣屏來模仿電梯運行的樓層顯示裝置。單片機的P1口的8只引腳接有8只按鍵開關K1~K8,這8只按鍵開關K1~K8分別代表1樓~8樓。如果某一樓層的按鍵按下,單片機控制的點陣屏將從當前位置向上或向下平滑滾動顯示到指定樓層的位置。電梯樓層顯示器初始顯示0。單片機的P1口的8只引腳接有8只按鍵開關K1~K8,這8只按鍵開關K1~K8分別代表1樓~8樓。如果按下代表某一樓層的按鍵,單片機控制的點陣屏將從當前位置向上或向下平滑滾動顯示到指定樓層的位置。12.9電梯運行控制的樓層顯示

12.9.1工作原理與設計要求設計采用單片機控制8×8LED點陣屏來模仿電梯運行的樓層顯示裝置。單片機的P1口的8只引腳接有8只按鍵開關K1~K8,這8只按鍵開關K1~K8分別代表1樓~8樓。如果某一樓層的按鍵按下,單片機控制的點陣屏將從當前位置向上或向下平滑滾動顯示到指定樓層的位置。

電梯樓層顯示器初始顯示0。單片機的P1口的8只引腳接有8只按鍵開關K1~K8,這8只按鍵開關K1~K8分別代表1樓~8樓。如果按下代表某一樓層的按鍵,單片機控制的點陣屏將從當前位置向上或向下平滑滾動顯示到指定樓層的位置。在上述功能基礎上,還設有LED指示燈和蜂鳴器,在到達指定樓層后蜂鳴器發(fā)出短暫聲音且LED閃爍片刻。系統(tǒng)還應同時識別依次按下的多個按鍵,例如,當前位置在1層時,用戶依次按下1046、5時,則數(shù)字分別向上滾動到5、6時暫停且LED閃爍片刻,同時蜂鳴器發(fā)出提示音。如在待去樓層的數(shù)字中,有的在當前運行的反方向,則數(shù)字先在當前方向運行完畢后,再依次按順序前往反方向的樓層位置。12.9.2電路設計與仿真本例原理電路與仿真見圖12-13。電路中采用P2口做8×8點陣的行選通控制,P1口完成對樓層按鍵的讀取及確認。105圖12-138×8LED點陣屏模仿電梯數(shù)字滾動顯示電路原理圖與仿真106參考程序如下:#include"reg51.h"#include"intrins.h"#defineucharunsignedchar#defineuintunsignedintsbitp36=P3^6;sbitp37=P3^7;voiddelay(uintt);//定義全局變量uintterminal;uintoutset=0;uintflag=0;uintflag1=0;uintflag2=0;ucharcodescan[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //掃描代碼//以下為顯示“0,1,2,3,4,5,6,7,8”的8×8點陣代碼ucharcodezm[]={1070x00,0x18,0x24,0x24,0x24,0x24,0x18,0x00,0x00,0x10,0x1c,0x10,0x10,0x10,0x3c,0x00,0x00,0x38,0x44,0x40,0x20,0x10,0x7c,0x00,0x00,0x38,0x44,0x30,0x40,0x44,0x38,0x00,0x00,0x20,0x30,0x28,0x24,0x7e,0x20,0x00,0x00,0x7c,0x04,0x3c,0x40,0x40,0x3c,0x00,0x00,0x38,0x44,0x3c,0x44,0x44,0x38,0x00,0x00,0x7e,0x40,0x40,0x20,0x10,0x10,0x00,0x00,0x38,0x44,0x38,0x44,0x44,0x38,0x00};voidsoundandled(uintj)//函數(shù):提示樓層到,蜂鳴器發(fā)聲及LED閃亮{ uinti,k; P0=0xff;P2=0xff; for(i=0;i<20;i++) {108 p36=0; delay(10); p36=1; for(k=0;k<8;k++) { P0=scan[k]; P2=~zm[j*8+k]; p37=1; delay(5); p37=0; } } }unsignedintkeyscan(void) //函數(shù):鍵盤掃描{ if(P1!=0xff) {109switch(P1){ case0x7f:{return(8);break;} case0xbf:{return(7);break;} case0xdf:{return(6);break;} case0xef:{return(5);break;} case0xf7:{return(4);break;} case0xfb:{return(3);break;} case0xfd:{return(2);break;} case0xfe:{return(1);break;} default:return(0); }}}voiddownmove(uintm,uintn) //函數(shù):電梯下行{ uintk,j,i; for(k=m*8;k>n*8;k--)110{ for(j=0;j<30;j++){ for(i=7;i>=0&&i<8;i--){ if(P1!=0xff){ outset=keyscan(); if((outset>n)&&(outset<m)) {111 flag1=outset; outset=n; n=flag1; terminal=n; }while(P1!=0xff);}//在最里面循環(huán)中加判別,可增加按鍵靈敏度如果不加則只能是運行//完所有循環(huán)后才進入下一步P0=scan[i];P2=~zm[(i+k)%72];delay(1); }}}}112voidupmove(unsignedintm,unsignedintn)//函數(shù):電梯上行{ uintk,j,i; for(k=m*8;k<n*8;k++) { for(j=0;j<30;j++) { for(i=0;i<8;i++) { if(P1!=0xff) { outset=keyscan(); if((outset>m)&&(outset<n)) { flag1=outset; outset=n; n=flag1;113terminal=n; }while(P1!=0xff);}//在最里面循環(huán)中加入判別可增加按鍵靈敏度如不加則只能運行完所//有循環(huán)才進入下一步

P0=scan[i]; P2=~zm[(i+k)%72]; delay(1); } }}}114voidshow(unsignedinti) //函數(shù):電梯靜止,并等待鍵盤{ uintk; while(P1!=0xff); while(P1==0xff) { for(k=0;k<8;k++) { P0=scan[k]; P2=~zm[i*8+k]; delay(1); } }}115voidmain() //主程序{ p37

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論