free性丰满hd毛多多,久久综合给合久久狠狠狠97色69 ,欧美成人乱码一区二区三区,国产美女久久久亚洲综合,7777久久亚洲中文字幕

0
問(wèn)答首頁(yè) 最新問(wèn)題 熱門問(wèn)題 等待回答標(biāo)簽廣場(chǎng)
我要提問(wèn)

單片機(jī)

手把手教你單片機(jī)程序框架

      大家好,我叫吳堅(jiān)鴻,從事單片機(jī)項(xiàng)目開(kāi)發(fā)已經(jīng)有快十年了。現(xiàn)在借21IC這個(gè)平臺(tái)把我認(rèn)為最有價(jià)值的東西分享給大家。我這個(gè)技術(shù)貼每個(gè)星期更新一兩篇,直到我江郎才盡為止。再次感謝21IC給我們提供這個(gè)交流分享的平臺(tái)。

第一節(jié):吳堅(jiān)鴻談初學(xué)單片機(jī)的誤區(qū)。

第二節(jié):delay()延時(shí)實(shí)現(xiàn)LED燈的閃爍。

第三節(jié):累計(jì)主循環(huán)次數(shù)使LED燈閃爍。

第四節(jié):累計(jì)定時(shí)中斷次數(shù)使LED燈閃爍。

第五節(jié):蜂鳴器的驅(qū)動(dòng)程序。

第六節(jié):在主函數(shù)中利用累計(jì)主循環(huán)次數(shù)來(lái)實(shí)現(xiàn)獨(dú)立按鍵的檢測(cè)。

第七節(jié):在主函數(shù)中利用累計(jì)定時(shí)中斷的次數(shù)來(lái)實(shí)現(xiàn)獨(dú)立按鍵的檢測(cè)。

第八節(jié):在定時(shí)中斷函數(shù)里執(zhí)行獨(dú)立按鍵的掃描程序。

第九節(jié):獨(dú)立按鍵的雙擊按鍵觸發(fā)。

第十節(jié):兩個(gè)獨(dú)立按鍵的組合按鍵觸發(fā)。

第十一節(jié):同一個(gè)按鍵短按與長(zhǎng)按的區(qū)別觸發(fā)。

第十二節(jié):按住一個(gè)獨(dú)立按鍵不松手的連續(xù)步進(jìn)觸發(fā)。

第十三節(jié):按住一個(gè)獨(dú)立按鍵不松手的加速勻速觸發(fā)。

第十四節(jié):矩陣鍵盤的單個(gè)觸發(fā)。

第十五節(jié):矩陣鍵盤單個(gè)觸發(fā)的壓縮代碼編程。

第十六節(jié):矩陣鍵盤的組合按鍵觸發(fā)。

第十七節(jié):兩片聯(lián)級(jí)74HC595驅(qū)動(dòng)16個(gè)LED燈的基本驅(qū)動(dòng)程序。

.第十八節(jié):把74HC595驅(qū)動(dòng)程序翻譯成類似單片機(jī)IO口直接驅(qū)動(dòng)的方式。

第十九節(jié):依次逐個(gè)點(diǎn)亮LED之后,再依次逐個(gè)熄滅LED的跑馬燈程序。

第二十節(jié):依次逐個(gè)亮燈并且每次只能亮一個(gè)燈的跑馬燈程序。

第二十一節(jié):多任務(wù)并行處理兩路跑馬燈。

第二十二節(jié):獨(dú)立按鍵控制跑馬燈的方向。

第二十三節(jié):獨(dú)立按鍵控制跑馬燈的速度。

第二十四節(jié):獨(dú)立按鍵控制跑馬燈的啟動(dòng)和暫停。

第二十五節(jié):用LED燈和按鍵來(lái)模擬工業(yè)自動(dòng)化設(shè)備的運(yùn)動(dòng)控制。

第二十六節(jié):在主函數(shù)while循環(huán)中驅(qū)動(dòng)數(shù)碼管的動(dòng)態(tài)掃描程序。

第二十七節(jié):在定時(shí)中斷里動(dòng)態(tài)掃描數(shù)碼管的程序。

第二十八節(jié):數(shù)碼管通過(guò)切換窗口來(lái)設(shè)置參數(shù)。

第二十九節(jié):數(shù)碼管通過(guò)切換窗口來(lái)設(shè)置參數(shù),并且不顯示為0的高位。

第三十節(jié):數(shù)碼管通過(guò)閃爍來(lái)設(shè)置數(shù)據(jù)。

第三十一節(jié):數(shù)碼管通過(guò)一二級(jí)菜單來(lái)設(shè)置數(shù)據(jù)的綜合程序。  

第三十二節(jié):數(shù)碼管中的倒計(jì)時(shí)程序。

第三十三節(jié):能設(shè)置速度檔位的數(shù)碼管倒計(jì)時(shí)程序。

第三十四節(jié):在數(shù)碼管中實(shí)現(xiàn)iphone4S開(kāi)機(jī)密碼鎖的程序。

第三十五節(jié):帶數(shù)碼管顯示的象棋比賽專用計(jì)時(shí)器。

第三十六節(jié):帶數(shù)碼管顯示的加法簡(jiǎn)易計(jì)算器。

第三十七節(jié):數(shù)碼管作為儀表盤顯示跑馬燈的方向,速度和運(yùn)行狀態(tài)。

第三十八節(jié):判斷數(shù)據(jù)尾來(lái)接收一串?dāng)?shù)據(jù)的串口通用程序框架。

第三十九節(jié):判斷數(shù)據(jù)頭來(lái)接收一串?dāng)?shù)據(jù)的串口通用程序框架。

第四十節(jié):常用的自定義串口通訊協(xié)議。

第四十一節(jié):在串口接收中斷里即時(shí)解析數(shù)據(jù)頭的特殊程序框架。

第四十二節(jié):通過(guò)串口用delay延時(shí)方式發(fā)送一串?dāng)?shù)據(jù)。

第四十三節(jié):通過(guò)串口用計(jì)數(shù)延時(shí)方式發(fā)送一串?dāng)?shù)據(jù)。

第四十四節(jié):從機(jī)的串口收發(fā)綜合程序框架

第四十五節(jié):主機(jī)的串口收發(fā)綜合程序框架

第四十六節(jié):利用AT24C02進(jìn)行掉電后的數(shù)據(jù)保存。

第四十七節(jié):操作AT24C02時(shí),利用“一氣呵成的定時(shí)器延時(shí)”改善數(shù)碼管的閃爍現(xiàn)象。

第四十八節(jié):利用DS1302做一個(gè)實(shí)時(shí)時(shí)鐘  。

第四十九節(jié):利用DS18B20做一個(gè)溫控器  。

第五十節(jié):利用ADC0832采集電壓信號(hào),用平均法和區(qū)間法進(jìn)行軟件濾波處理。

第五十一節(jié):利用ADC0832采集電壓信號(hào),用連續(xù)N次一致性的方法進(jìn)行濾波處理。

第五十二節(jié):程序后續(xù)升級(jí)修改的利器,return語(yǔ)句鮮為人知的用法。

第五十三節(jié):指針的第一大好處,讓一個(gè)函數(shù)可以封裝多個(gè)相當(dāng)于return語(yǔ)句返回的參數(shù)。

第五十四節(jié):指針的第二大好處,指針作為數(shù)組在函數(shù)中的輸入接口。

第五十五節(jié):指針的第三大好處,指針作為數(shù)組在函數(shù)中的輸出接口。

第五十六節(jié):指針的第四大好處,指針作為數(shù)組在函數(shù)中的輸入輸出接口。

第五十七節(jié):為指針加上緊箍咒const,避免意外修改了只做輸入接口的數(shù)據(jù)。

第五十八節(jié):指針的第五大好處,指針在眾多數(shù)組中的中轉(zhuǎn)站作用。

第五十九節(jié):串口程序第40,44,45節(jié)中存在一個(gè)bug,特此緊急公告。

第六十節(jié):用關(guān)中斷和互斥量來(lái)保護(hù)多線程共享的全局變量。

第六十一節(jié):組合BCD碼,非組合BCD碼,以及數(shù)值三者之間的相互轉(zhuǎn)換和關(guān)系。

第六十二節(jié):大數(shù)據(jù)的加法運(yùn)算。

第六十三節(jié):大數(shù)據(jù)的減法運(yùn)算。

第六十四節(jié):大數(shù)據(jù)的乘法運(yùn)算。

第六十五節(jié):大數(shù)據(jù)的除法運(yùn)算。

第六十六節(jié):?jiǎn)纹瑱C(jī)外部中斷的基礎(chǔ)。

第六十七節(jié):利用外部中斷實(shí)現(xiàn)模擬串口數(shù)據(jù)的收發(fā)。

第六十八節(jié):?jiǎn)纹瑱C(jī)C語(yǔ)言的多文件編程技巧。

第六十九節(jié):使用static關(guān)鍵字可以減少全局變量的使用。

第七十節(jié):深入講解液晶屏的構(gòu)字過(guò)程。

第七十一節(jié):液晶屏的字符,16點(diǎn)陣,24點(diǎn)陣和32點(diǎn)陣的顯示程序。

第七十二節(jié):在液晶屏中把字體順時(shí)針旋轉(zhuǎn)90度顯示的算法程序。

第七十三節(jié):在液晶屏中把字體鏡像顯示的算法程序。

第七十四節(jié):在液晶屏中讓字體可以跨區(qū)域無(wú)縫對(duì)接顯示的算法程序。

第七十五節(jié):在12864液晶屏中讓字體以1個(gè)點(diǎn)陣為單位進(jìn)行移動(dòng)顯示的算法程序。

第七十六節(jié):如何把一個(gè)任意數(shù)值的變量顯示在液晶屏上。

第七十七節(jié):在1個(gè)窗口里通過(guò)移動(dòng)光標(biāo)來(lái)設(shè)置不同參數(shù)的液晶屏菜單程序。

第七十八節(jié):在多個(gè)窗口里通過(guò)移動(dòng)光標(biāo)來(lái)設(shè)置不同參數(shù)的液晶屏菜單程序。

第七十九節(jié):通過(guò)主菜單移動(dòng)光標(biāo)來(lái)進(jìn)入子菜單窗口的液晶屏程序。

第八十節(jié):調(diào)用液晶屏內(nèi)部字庫(kù)來(lái)顯示漢字或字符的坐標(biāo)體系和本質(zhì)。

第八十一節(jié):液晶屏顯示串口發(fā)送過(guò)來(lái)的任意漢字和字符。

第八十二節(jié):如何通過(guò)調(diào)用液晶屏內(nèi)部字庫(kù)把一個(gè)任意數(shù)值的變量顯示出來(lái)。

第八十三節(jié):矩陣鍵盤輸入任意數(shù)字或小數(shù)點(diǎn)的液晶屏顯示程序。

第八十四節(jié):實(shí)時(shí)同步把鍵盤輸入的BCD碼數(shù)組轉(zhuǎn)換成數(shù)值的液晶屏顯示程序。

第八十五節(jié):實(shí)時(shí)同步把加減按鍵輸入的數(shù)值轉(zhuǎn)換成BCD碼數(shù)組的液晶屏顯示程序。

第八十六節(jié):數(shù)字鍵盤與液晶菜單的綜合程序。

第八十七節(jié):鄭文顯捐贈(zèng)的工控項(xiàng)目源代碼。

第八十八節(jié):電子稱連續(xù)不斷從串口對(duì)外發(fā)送數(shù)據(jù),單片機(jī)靠關(guān)鍵字快速截取有效數(shù)據(jù)串。

第八十九節(jié):用單片機(jī)內(nèi)部定時(shí)器做一個(gè)時(shí)鐘。

第九十節(jié):針對(duì)行程開(kāi)關(guān)感應(yīng)器,分享一種既能及時(shí)響應(yīng),又能抗干擾處理的識(shí)別思路。

提問(wèn)者:w13756941107 地點(diǎn):- 瀏覽次數(shù):6604 提問(wèn)時(shí)間:10-26 13:48
我有更好的答案
提 交
11條回答
huzp_123 06-18 08:45
第一節(jié):吳堅(jiān)鴻談初學(xué)單片機(jī)的誤區(qū)。

(1)很難記住繁雜的寄存器?寄存器不用死記硬背,鴻哥我行走江湖多年,連一個(gè)寄存器都記不住。需要配置寄存器的時(shí)候,直接在網(wǎng)上或者書本上參考別人現(xiàn)成的配置程序是上策,查找芯片數(shù)據(jù)手冊(cè)是中策,死記硬背寄存器是最最下策。

(2)很難記住繁雜的匯編語(yǔ)言指令?除非是在校學(xué)生要應(yīng)付考試或者少數(shù)工作中繞不開(kāi)匯編,否則學(xué)匯編就是浪費(fèi)時(shí)間。鴻哥我行走江湖多年,從來(lái)就沒(méi)有用匯編幫客戶做過(guò)一個(gè)項(xiàng)目。

(3)C語(yǔ)言很難學(xué)?你不用學(xué)指針,你不用學(xué)帶形參的函數(shù),你不用學(xué)結(jié)構(gòu)體,你不用學(xué)宏定義,你不用學(xué)文件操作,你也不用死記繁瑣的數(shù)據(jù)類型。你只要會(huì):
? ?? ?5條指令語(yǔ)句switch語(yǔ)句,if else語(yǔ)句,while語(yǔ)句,for語(yǔ)句,=賦值語(yǔ)句。
? ?? ?7個(gè)運(yùn)算符+,-,*,/,|,&,!。
? ?? ?4個(gè)邏輯關(guān)系符||,&&,!=,==.
? ?? ?3個(gè)數(shù)據(jù)類型unsigned char, unsigned int, unsigned long。
? ?? ?3個(gè)進(jìn)制相互轉(zhuǎn)化,二進(jìn)制,十六進(jìn)制,十進(jìn)制。
? ?? ?1個(gè)void函數(shù)。? ?? ?? ?? ?
? ?? ?1個(gè)一維數(shù)組code(或const) unsigned char array[]。
? ?? ?那么世界上任何一種邏輯功能的單片機(jī)軟件你都能做出來(lái)。
? ?? ?鴻哥我當(dāng)年剛畢業(yè)出來(lái)工作的時(shí)候才知道可以用C語(yǔ)言開(kāi)發(fā)單片機(jī),一開(kāi)始只用if語(yǔ)句就把項(xiàng)目做出來(lái)了,沒(méi)有用指針,沒(méi)有用帶形參的函數(shù)等復(fù)雜的功能。再到后來(lái)才慢慢開(kāi)始用C語(yǔ)言其他的高級(jí)功能,但是我發(fā)現(xiàn)C語(yǔ)言其他的高級(jí)功能,本質(zhì)上都是用我前面列舉出來(lái)的最基本功能集合而成,只是書寫更加簡(jiǎn)單方便了一點(diǎn),編譯后的機(jī)器碼都大同小異。所以不會(huì)指針等高級(jí)功能你不用自卑,恰恰相反,當(dāng)你會(huì)最簡(jiǎn)單的幾個(gè)語(yǔ)句,就把這些高級(jí)功能的程序都做出來(lái)了,你才發(fā)現(xiàn)你對(duì)底層了解得更加透切,再學(xué)那些高級(jí)功能輕而易舉。當(dāng)你裸機(jī)跑的程序都能夠協(xié)調(diào)得很好的時(shí)候,你才發(fā)現(xiàn)所謂高深的操作系統(tǒng)也不過(guò)如此,只要給你時(shí)間和金錢你也可以寫個(gè)操作系統(tǒng)來(lái)玩玩。

(4)很難記住精確時(shí)間的計(jì)算公式?經(jīng)??吹綍r(shí)間公式等于晶振,時(shí)鐘周期,執(zhí)行指令次數(shù)他們之間的乘除關(guān)系式。鴻哥我認(rèn)為這些都是浮云,不用糾結(jié)也不用去記,大概了解一下就可以了。不管你對(duì)公式掌握得有多精確,你都不可能做出非常精確的時(shí)間。想用單片機(jī)做一個(gè)非常精確的時(shí)間這種想法一開(kāi)始就是錯(cuò)的,不可能的。真想做一個(gè)比較精確的時(shí)間,應(yīng)該用外圍時(shí)鐘芯片或者FPGA和CPLD,而不是單片機(jī)。

(5)很難記住繁雜的各種通信協(xié)議?什么IIC,SPI,232串口通訊,CAN,USB等等。這些都是浮云,你不用記那么多,你只要理解兩種通訊方式就夠了,那就是串行通訊方式和并行通訊方式。不管世界上有多少種通訊協(xié)議,物理世界上只有這兩種通訊方式,其他各種名稱的通訊協(xié)議都基于此兩種方式演變而來(lái)。

(6)很難寫短小精悍的程序?初學(xué)者不要糾結(jié)于此。做項(xiàng)目開(kāi)發(fā),程序容量不是刻意追求的目標(biāo),程序多一點(diǎn)少一點(diǎn)沒(méi)關(guān)系,現(xiàn)在大容量的單片機(jī)品種非常多,容量不會(huì)是寸土寸金的事情,我們更加要關(guān)注程序的運(yùn)行效率,可讀性和可修改性。

? ?? ?既然鴻哥列出了那么多誤區(qū),那么什么才是初學(xué)者關(guān)注的核心?預(yù)知詳情,請(qǐng)聽(tīng)下回分解----delay()延時(shí)實(shí)現(xiàn)LED燈的閃爍。

(未完待續(xù),下節(jié)更精彩,不要走開(kāi)哦)
電路學(xué)友 06-21 18:01
第二節(jié):delay()延時(shí)實(shí)現(xiàn)LED燈的閃爍。

開(kāi)場(chǎng)白:
? ? 上一節(jié)鴻哥列出了初學(xué)者七大誤區(qū),到底什么才是初學(xué)者關(guān)注的核心?那就是裸機(jī)奔跑的程序結(jié)構(gòu)。一個(gè)好的程序結(jié)構(gòu),本身就是一個(gè)微型的多任務(wù)操作系統(tǒng)。鴻哥教給大家的就是如何編寫這個(gè)簡(jiǎn)單的操作系統(tǒng)。在main函數(shù)循環(huán)中用switch語(yǔ)句實(shí)現(xiàn)多任務(wù)并行處理的任務(wù)切換,再外加一個(gè)定時(shí)器中斷,這兩者的結(jié)合就是鴻哥多年來(lái)所有實(shí)戰(zhàn)項(xiàng)目的核心。鴻哥的程序結(jié)構(gòu)看似簡(jiǎn)單,實(shí)際上就是那么簡(jiǎn)單。大家不用著急,本篇連載文章現(xiàn)在才正式開(kāi)始,這一節(jié)我要教會(huì)大家兩個(gè)知識(shí)點(diǎn):
第一點(diǎn):鴻哥首次提出的“三區(qū)一線”理論。此理論把程序代碼分成三個(gè)區(qū),一個(gè)延時(shí)分割線。
第二點(diǎn):delay()延時(shí)的用途。

(1)硬件平臺(tái):基于朱兆祺51單片機(jī)學(xué)習(xí)板。

(2)實(shí)現(xiàn)功能:讓一個(gè)LED閃爍。

(3)源代碼講解如下:

#include "REG52.H"

void initial_myself();? ?
void initial_peripheral();

void delay_short(unsigned int uiDelayshort);
void delay_long(unsigned int uiDelaylong);
void led_flicker();

/* 注釋一:
* 吳堅(jiān)鴻個(gè)人的命名風(fēng)格:凡是輸出后綴都是_dr,凡是輸入后綴都是_sr。
* dr代表drive驅(qū)動(dòng),sr代表sensor感應(yīng)器
*/
sbit led_dr=P3^5;??

void main()??//學(xué)習(xí)要點(diǎn):深刻理解鴻哥首次提出的三區(qū)一線理論
??{
/* 注釋二:
* initial_myself()函數(shù)屬于鴻哥三區(qū)一線理論的第一區(qū),
* 專門用來(lái)初始化單片機(jī)自己的寄存器以及個(gè)別外圍要求響應(yīng)速度快的輸出設(shè)備,
* 防止剛上電之后,由于輸出IO口電平狀態(tài)不確定而導(dǎo)致外圍設(shè)備誤動(dòng)作,
* 比如繼電器的誤動(dòng)作等等。
*/
? ?initial_myself();

/* 注釋三:
* 此處的delay_long()延時(shí)函數(shù)屬于第一區(qū)與第二區(qū)的分割線,
* 延時(shí)時(shí)間一般是0.3秒到2秒之間,等待外圍芯片和模塊上電穩(wěn)定。
* 比如液晶模塊,AT24C02存儲(chǔ)芯片,DS1302時(shí)鐘芯片,
* 這類芯片有個(gè)特點(diǎn),一般都是跟單片機(jī)進(jìn)行串口或并口通訊的,
* 并且不要求上電立即處理的。
*/
? ?delay_long(100);

/* 注釋四:
* initial_peripheral()函數(shù)屬于鴻哥三區(qū)一線理論的第二區(qū),
* 專門用來(lái)初始化不要求上電立即處理的外圍芯片和模塊.
* 比如液晶模塊,AT24C02存儲(chǔ)芯片,DS1302時(shí)鐘芯片。
* 本程序基于朱兆祺51單片機(jī)學(xué)習(xí)板。
*/
? ?initial_peripheral();

/* 注釋五:
* while(1){}主函數(shù)循環(huán)區(qū)屬于鴻哥三區(qū)一線理論的第三區(qū),
* 專門用來(lái)編寫被循環(huán)掃描到的非中斷應(yīng)用程序
*/
? ?while(1)
? ?{
? ?? ?led_flicker();? ?//LED閃爍應(yīng)用程序
? ?}

}

void led_flicker() //LED閃爍應(yīng)用程序
{
??led_dr=1;??//LED亮
??delay_short(50000);??//延時(shí)50000個(gè)空指令的時(shí)間

/* 注釋六:
* delay_long(100)延時(shí)50000個(gè)空指令的時(shí)間,因?yàn)閮?nèi)嵌了一個(gè)500次的for循環(huán)
*/
??led_dr=0;??//LED滅
??delay_long(100);? ? //延時(shí)50000個(gè)空指令的時(shí)間??
}


/* 注釋七:
* delay_short(unsigned int uiDelayShort)是小延時(shí)函數(shù),
* 專門用在時(shí)序驅(qū)動(dòng)的小延時(shí),一般uiDelayShort的數(shù)值取10左右,
* 最大一般也不超過(guò)100.本例為了解釋此函數(shù)的特點(diǎn),取值范圍超過(guò)100。
* 此函數(shù)的特點(diǎn)是時(shí)間的細(xì)分度高,延時(shí)時(shí)間不宜過(guò)長(zhǎng)。uiDelayShort數(shù)值
* 的大小就代表里面執(zhí)行了多少條空指令的時(shí)間。數(shù)值越大,延時(shí)越長(zhǎng)。
* 時(shí)間精度不要刻意去計(jì)算,感覺(jué)差不多就行。
*/
void delay_short(unsigned int uiDelayShort)
{
? ?unsigned int i;??
? ?for(i=0;i? ?{
? ???;? ?//一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語(yǔ)句
? ?}
}


/* 注釋八:
* delay_long(unsigned int uiDelayLong)是大延時(shí)函數(shù),
* 專門用在上電初始化的大延時(shí),
* 此函數(shù)的特點(diǎn)是能實(shí)現(xiàn)比較長(zhǎng)時(shí)間的延時(shí),細(xì)分度取決于內(nèi)嵌for循環(huán)的次數(shù),
* uiDelayLong的數(shù)值的大小就代表里面執(zhí)行了多少次500條空指令的時(shí)間。
* 數(shù)值越大,延時(shí)越長(zhǎng)。時(shí)間精度不要刻意去計(jì)算,感覺(jué)差不多就行。
*/
void delay_long(unsigned int uiDelayLong)
{
? ?unsigned int i;
? ?unsigned int j;
? ?for(i=0;i? ?{
? ?? ?for(j=0;j<500;j++)??//內(nèi)嵌循環(huán)的空指令數(shù)量
? ?? ?? ? {
? ?? ?? ?? ? ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語(yǔ)句
? ?? ?? ? }
? ?}
}



void initial_myself()??//初始化單片機(jī)
{
??led_dr=0;??//LED滅
}
void initial_peripheral() //初始化外圍
{
??;? ?//本例為空
}

總結(jié)陳詞:
鴻哥首次提出的“三區(qū)一線”理論概況了各種項(xiàng)目程序的基本分區(qū)。我后續(xù)的程序就按此分區(qū)編寫。
Delay()函數(shù)的長(zhǎng)延時(shí)適用在上電初始化。
Delay()函數(shù)的短延時(shí)適用在驅(qū)動(dòng)時(shí)序的脈沖延時(shí),此時(shí)的時(shí)間不能太長(zhǎng),本例中暫時(shí)沒(méi)有列出這方面的例子,在后面的章節(jié)中會(huì)提到。
在本例源代碼中,在led_flicker()閃爍應(yīng)用程序里用到的兩個(gè)延時(shí)delay,它們的延時(shí)時(shí)間都太長(zhǎng)了,在實(shí)戰(zhàn)項(xiàng)目中肯定不能用這種延時(shí),因?yàn)橄牡臅r(shí)間太長(zhǎng)了,其它任務(wù)根本沒(méi)有機(jī)會(huì)執(zhí)行。那怎么辦呢?我們應(yīng)該如何改善?欲知詳情,請(qǐng)聽(tīng)下回分解-----累計(jì)主循環(huán)次數(shù)使LED燈閃爍。

(未完待續(xù),下節(jié)更精彩,不要走開(kāi)哦)
yiqiao18 06-18 10:02
第三節(jié):累計(jì)主循環(huán)次數(shù)使LED燈閃爍。

開(kāi)場(chǎng)白:
上一節(jié)鴻哥提到delay()延時(shí)函數(shù)消耗的時(shí)間太長(zhǎng)了,其它任務(wù)根本沒(méi)有機(jī)會(huì)執(zhí)行,我們?cè)撛趺锤纳疲勘竟?jié)教大家利用累計(jì)主循環(huán)次數(shù)的方法來(lái)解決這個(gè)問(wèn)題。這一節(jié)要教會(huì)大家兩個(gè)知識(shí)點(diǎn):
第一點(diǎn):利用累計(jì)主循環(huán)次數(shù)的方法實(shí)現(xiàn)時(shí)間延時(shí)
第二點(diǎn):switch核心語(yǔ)句之初體驗(yàn)。 鴻哥所有的實(shí)戰(zhàn)項(xiàng)目都是基于switch語(yǔ)句實(shí)現(xiàn)多任務(wù)并行處理。
(1)硬件平臺(tái):基于朱兆祺51單片機(jī)學(xué)習(xí)板。
(2)實(shí)現(xiàn)功能:讓一個(gè)LED閃爍。
(3)源代碼講解如下:
#include "REG52.H"


/* 注釋一:
* const_time_level是統(tǒng)計(jì)循環(huán)次數(shù)的設(shè)定上限,數(shù)值越大,LED延時(shí)的時(shí)間越久
*/
#define const_time_level 10000??

void initial_myself();? ?
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void led_flicker();

sbit led_dr=P3^5;??

/* 注釋二:
* 吳堅(jiān)鴻個(gè)人的命名風(fēng)格:凡是switch語(yǔ)句里面的步驟變量后綴都是Step.
* 前綴帶uc,ui,ul分別表示此變量是unsigned char,unsigned int,unsigned long.
*/
unsigned char ucLedStep=0; //步驟變量
unsigned int??uiTimeCnt=0; //統(tǒng)計(jì)循環(huán)次數(shù)的延時(shí)計(jì)數(shù)器
void main()
??{
? ?initial_myself();??
? ?delay_long(100);? ?
? ?initial_peripheral();
? ?while(1)? ?
? ?{
? ?? ?led_flicker();? ?
? ?}

}

void led_flicker() ////第三區(qū) LED閃爍應(yīng)用程序
{
??
??switch(ucLedStep)
??{
? ???case 0:
/* 注釋三:
* uiTimeCnt累加循環(huán)次數(shù),只有當(dāng)它的次數(shù)大于或等于設(shè)定上限const_time_level時(shí),
* 才會(huì)去改變LED燈的狀態(tài),否則CPU退出led_flicker()任務(wù),繼續(xù)快速掃描其他的任務(wù),
* 這樣的程序結(jié)構(gòu)就可以達(dá)到多任務(wù)并行處理的目的。
* 本程序基于朱兆祺51單片機(jī)學(xué)習(xí)板
*/
? ?? ?? ? uiTimeCnt++;??//累加循環(huán)次數(shù),
? ?? ?? ?? ?? ?? ?if(uiTimeCnt>=const_time_level) //時(shí)間到
? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?uiTimeCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ? led_dr=1;? ? //讓LED亮
? ?? ?? ?? ?? ?? ?? ?? ? ucLedStep=1; //切換到下一個(gè)步驟
? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???break;
? ???case 1:
? ?? ?? ? uiTimeCnt++;??//累加循環(huán)次數(shù),
? ?? ?? ?? ?? ?? ?if(uiTimeCnt>=const_time_level) //時(shí)間到
? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ?? ?? ?? ?uiTimeCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ? led_dr=0;? ? //讓LED滅
? ?? ?? ?? ?? ?? ?? ?? ? ucLedStep=0; //返回到上一個(gè)步驟
? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???break;
??
??}

}


void delay_long(unsigned int uiDelayLong)
{
? ?unsigned int i;
? ?unsigned int j;
? ?for(i=0;i? ?{
? ?? ?for(j=0;j<500;j++)??//內(nèi)嵌循環(huán)的空指令數(shù)量
? ?? ?? ? {
? ?? ?? ?? ? ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語(yǔ)句
? ?? ?? ? }
? ?}
}


void initial_myself()??//第一區(qū) 初始化單片機(jī)
{
??led_dr=0;??//LED滅
}
void initial_peripheral() //第二區(qū) 初始化外圍
{
??;? ?//本例為空
}

總結(jié)陳詞:
? ? 在實(shí)際項(xiàng)目中,用累計(jì)主循環(huán)次數(shù)實(shí)現(xiàn)時(shí)間延時(shí)是一個(gè)不錯(cuò)的選擇。這種方法能勝任多任務(wù)處理的程序框架,但是它本身也有一個(gè)小小的不足。隨著主函數(shù)里任務(wù)量的增加,我們?yōu)榱吮WC延時(shí)時(shí)間的準(zhǔn)確性,要不斷修正設(shè)定上限const_time_level 。我們?cè)撛趺唇鉀Q這個(gè)問(wèn)題呢?欲知詳情,請(qǐng)聽(tīng)下回分解-----累計(jì)定時(shí)中斷次數(shù)使LED燈閃爍。

(未完待續(xù),下節(jié)更精彩,不要走開(kāi)哦)
Mryan1996 06-19 19:16
第四節(jié):累計(jì)定時(shí)中斷次數(shù)使LED燈閃爍。

開(kāi)場(chǎng)白:
上一節(jié)提到在累計(jì)主循環(huán)次數(shù)來(lái)實(shí)現(xiàn)計(jì)時(shí),隨著主函數(shù)里任務(wù)量的增加,為了保證延時(shí)時(shí)間的準(zhǔn)確性,要不斷修正設(shè)定上限閥值const_time_level 。我們?cè)撛趺唇鉀Q這個(gè)問(wèn)題呢?本節(jié)教大家利用累計(jì)定時(shí)中斷次數(shù)的方法來(lái)解決這個(gè)問(wèn)題。這一節(jié)要教會(huì)大家四個(gè)知識(shí)點(diǎn):
第一點(diǎn):利用累計(jì)定時(shí)中斷次數(shù)的方法實(shí)現(xiàn)時(shí)間延時(shí)
第二點(diǎn):展現(xiàn)鴻哥最完整的實(shí)戰(zhàn)程序框架。在主函數(shù)循環(huán)里用switch語(yǔ)句實(shí)現(xiàn)狀態(tài)機(jī)的切換,在定時(shí)中斷里累計(jì)中斷次數(shù),這兩個(gè)的結(jié)合就是我寫代碼最本質(zhì)的框架思想。
第三點(diǎn):提醒大家C語(yǔ)言中的int ,long變量是由幾個(gè)字節(jié)構(gòu)成的數(shù)據(jù),凡是在main函數(shù)和中斷函數(shù)里有可能同時(shí)改變的變量,這個(gè)變量應(yīng)該在主函數(shù)中被更改之前,先關(guān)閉相應(yīng)的中斷,更改完了此變量,再打開(kāi)中斷,否則會(huì)留下不宜察覺(jué)的漏洞。當(dāng)然在大部分的項(xiàng)目中可以不用這么操作,但是在一些要求非常高的項(xiàng)目中,有一些核心變量必須這么做。
第四點(diǎn):定時(shí)中斷的初始值該怎么設(shè)置。不用嚴(yán)格按公式來(lái)計(jì)算時(shí)間,一般取個(gè)經(jīng)驗(yàn)值是最大初始值減去1000就可以了。
具體內(nèi)容,請(qǐng)看源代碼講解。

(1)硬件平臺(tái):基于朱兆祺51單片機(jī)學(xué)習(xí)板。

(2)實(shí)現(xiàn)功能:讓一個(gè)LED閃爍。

(3)源代碼講解如下:

#include "REG52.H"

#define const_time_level 200??

void initial_myself();? ?
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void led_flicker();
void T0_time();??//定時(shí)中斷函數(shù)

sbit led_dr=P3^5;??

unsigned char ucLedStep=0; //步驟變量
unsigned int??uiTimeCnt=0; //統(tǒng)計(jì)定時(shí)中斷次數(shù)的延時(shí)計(jì)數(shù)器


void main()
??{
? ?initial_myself();??
? ?delay_long(100);? ?
? ?initial_peripheral();
? ?while(1)? ?
? ?{
? ?? ?led_flicker();? ?
? ?}

}

void led_flicker() ////第三區(qū) LED閃爍應(yīng)用程序
{
??
??switch(ucLedStep)
??{
? ???case 0:
/* 注釋一:
* uiTimeCnt累加定時(shí)中斷的次數(shù),每一次定時(shí)中斷它都會(huì)在中斷函數(shù)里自加一。
* 只有當(dāng)它的次數(shù)大于或等于設(shè)定上限const_time_level時(shí),
* 才會(huì)去改變LED燈的狀態(tài),否則CPU退出led_flicker()任務(wù),繼續(xù)快速掃描其他的任務(wù),
* 這樣的程序結(jié)構(gòu)就可以達(dá)到多任務(wù)并行處理的目的。這就是鴻哥在所有開(kāi)發(fā)項(xiàng)目中的核心框架。
*/
? ?? ?? ?? ?? ?? ?if(uiTimeCnt>=const_time_level) //時(shí)間到
? ?? ?? ?? ?? ?? ?{

/* 注釋二:
* ET0=0;uiTimeCnt=0;ET0=1;----在清零uiTimeCnt之前,為什么要先禁止定時(shí)中斷?
* 因?yàn)閡iTimeCnt是unsigned int類型,本質(zhì)上是由兩個(gè)字節(jié)組成。
* 在C語(yǔ)言中uiTimeCnt=0看似一條指令,實(shí)際上經(jīng)過(guò)編譯之后它不只一條匯編指令。
* 由于定時(shí)中斷函數(shù)里也對(duì)這個(gè)變量進(jìn)行累加操作,如果不禁止定時(shí)中斷,
* 那么uiTimeCnt這個(gè)變量在main()函數(shù)中還沒(méi)被完全清零的時(shí)候,如果這個(gè)時(shí)候
* 突然來(lái)一個(gè)定時(shí)中斷,并且在中斷里又更改了此變量,這種情況在某些要求高的
* 項(xiàng)目上會(huì)是一個(gè)不容易察覺(jué)的漏洞,為項(xiàng)目帶來(lái)隱患。當(dāng)然,大部分的普通項(xiàng)目,
* 都可以不用那么嚴(yán)格,可以不用禁止定時(shí)中斷。在這里只是提醒各位初學(xué)者有這種情況。
*/
? ?? ?? ?? ? ET0=0;??//禁止定時(shí)中斷
? ?? ?? ?? ?? ?? ?? ?uiTimeCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ? ET0=1; //開(kāi)啟定時(shí)中斷
? ?? ?? ?? ? led_dr=1;? ? //讓LED亮
? ?? ?? ?? ?? ?? ?? ?? ? ucLedStep=1; //切換到下一個(gè)步驟
? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???break;
? ???case 1:
? ?? ?? ?? ?? ?? ?if(uiTimeCnt>=const_time_level) //時(shí)間到
? ?? ?? ?? ?? ?? ?{
? ?? ?? ?? ? ET0=0;??//禁止定時(shí)中斷
? ?? ?? ?? ?? ?? ?? ?uiTimeCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ? ET0=1;? ?//開(kāi)啟定時(shí)中斷
? ?? ?? ?? ? led_dr=0;? ? //讓LED滅
? ?? ?? ?? ?? ?? ?? ?? ? ucLedStep=0; //返回到上一個(gè)步驟
? ?? ?? ?? ?? ?? ?}
? ?? ?? ?? ???break;
??
??}

}


/* 注釋三:
* C51的中斷函數(shù)格式如下:
* void 函數(shù)名() interrupt 中斷號(hào)
* {
*? ? 中斷程序內(nèi)容
* }
* 函數(shù)名可以隨便取,只要不是編譯器已經(jīng)征用的關(guān)鍵字。
* 這里最關(guān)鍵的是中斷號(hào),不同的中斷號(hào)代表不同類型的中斷。
* 定時(shí)中斷的中斷號(hào)是 1.至于其它中斷的中斷號(hào),大家可以查找
* 相關(guān)書籍和資料。大家進(jìn)入中斷時(shí),必須先清除中斷標(biāo)志,并且
* 關(guān)閉中斷,然后再寫代碼,最后出來(lái)時(shí),記得重裝初始值,并且
* 打開(kāi)中斷。
*/
void T0_time() interrupt 1
{
??TF0=0;??//清除中斷標(biāo)志
??TR0=0; //關(guān)中斷

??if(uiTimeCnt<0xffff)??//設(shè)定這個(gè)條件,防止uiTimeCnt超范圍。
??{
? ?? ?uiTimeCnt++;??//累加定時(shí)中斷的次數(shù),
??}

TH0=0xf8;? ?//重裝初始值(65535-2000)=63535=0xf82f
TL0=0x2f;
TR0=1;??//開(kāi)中斷
}


void delay_long(unsigned int uiDelayLong)
{
? ?unsigned int i;
? ?unsigned int j;
? ?for(i=0;i? ?{
? ?? ?for(j=0;j<500;j++)??//內(nèi)嵌循環(huán)的空指令數(shù)量
? ?? ?? ? {
? ?? ?? ?? ? ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語(yǔ)句
? ?? ?? ? }
? ?}
}


void initial_myself()??//第一區(qū) 初始化單片機(jī)
{

/* 注釋四:
* 單片機(jī)有幾個(gè)定時(shí)器,每個(gè)定時(shí)器又有幾種工作方式,
* 那么多種變化,我們記不了那么多,怎么辦?
* 大家記住鴻哥的話,無(wú)論一個(gè)單片機(jī)有多少內(nèi)置資源,
* 我們做系統(tǒng)框架的,只需要一個(gè)定時(shí)器,一種工作方式。
* 開(kāi)定時(shí)器越多這個(gè)系統(tǒng)越不好。需要哪種定時(shí)工作方式呢?
* 就需要響應(yīng)定時(shí)中斷后重裝一下初始值繼續(xù)跑那種。
* 在51單片機(jī)中就是工作方式1。其它的工作方式很少項(xiàng)目能用到。
*/
??TMOD=0x01;??//設(shè)置定時(shí)器0為工作方式1


??/* 注釋五:
* 裝定時(shí)器的初始值,就像一個(gè)水桶里裝的水。如果這個(gè)桶是空桶,那么想
* 把這個(gè)桶灌滿水的時(shí)間就很長(zhǎng),如果是里面已經(jīng)裝了大半的水,那么想
* 把這個(gè)桶灌滿水的時(shí)間就相對(duì)比較短。也就是定時(shí)器初始值越小,產(chǎn)生一次
* 定時(shí)中斷的時(shí)間就越長(zhǎng)。如果初始值太小了,每次產(chǎn)生定時(shí)中斷
* 的時(shí)間分辨率太粗,如果初始值太大了,雖然每次產(chǎn)生定時(shí)中斷的時(shí)間分辨率很細(xì),
* 但是太頻繁的產(chǎn)生中斷,不但會(huì)影響主函數(shù)main()的執(zhí)行效率,而且累記中斷次數(shù)
* 的時(shí)間誤差也會(huì)很大。憑鴻哥多年的江湖經(jīng)驗(yàn),
* 我覺(jué)得最大初始值減去2000是比較好的經(jīng)驗(yàn)值。當(dāng)然,大一點(diǎn)小一點(diǎn)沒(méi)關(guān)系。不要走
* 兩個(gè)極端就行。
*/
TH0=0xf8;? ?//重裝初始值(65535-2000)=63535=0xf82f
TL0=0x2f;

??led_dr=0;??//LED滅
}
void initial_peripheral() //第二區(qū) 初始化外圍
{
??EA=1;? ???//開(kāi)總中斷
??ET0=1;? ? //允許定時(shí)中斷
??TR0=1;? ? //啟動(dòng)定時(shí)中斷

}

總結(jié)陳詞:
本節(jié)程序麻雀雖小五臟俱全。在本節(jié)中已經(jīng)展示了我最完整的實(shí)戰(zhàn)程序框架。
本節(jié)程序只有一個(gè)LED燈閃爍的單任務(wù),如果要多增加一個(gè)任務(wù)來(lái)并行處理,該怎么辦?
欲知詳情,請(qǐng)聽(tīng)下回分解-----蜂鳴器的驅(qū)動(dòng)程序。

(未完待續(xù),下節(jié)更精彩,不要走開(kāi)哦)
joifjiasfdi 06-18 07:31
5條指令語(yǔ)句switch語(yǔ)句,if else語(yǔ)句,while語(yǔ)句,for語(yǔ)句,=賦值語(yǔ)句。
? ?? ?7個(gè)運(yùn)算符+,-,*,/,|,&,!。
? ?? ?4個(gè)邏輯關(guān)系符||,&&,!=,==.
? ?? ?3個(gè)數(shù)據(jù)類型unsigned char, unsigned int, unsigned long。
? ?? ?3個(gè)進(jìn)制相互轉(zhuǎn)化,二進(jìn)制,十六進(jìn)制,十進(jìn)制。
? ?? ?1個(gè)void函數(shù)。? ?? ?? ?? ?
? ?? ?1個(gè)一維數(shù)組code(或const) unsigned char array[]。
? ?? ?那么世界上任何一種邏輯功能的單片機(jī)軟件你都能做出來(lái)。
我還停留在這種初級(jí)階段。。。
chnq1984 06-22 03:09
第五節(jié):蜂鳴器的驅(qū)動(dòng)程序。

開(kāi)場(chǎng)白:
上一節(jié)講了利用累計(jì)定時(shí)中斷次數(shù)實(shí)現(xiàn)LED燈閃爍,這個(gè)例子同時(shí)也第一次展示了我最完整的實(shí)戰(zhàn)程序框架:用switch語(yǔ)句實(shí)現(xiàn)狀態(tài)機(jī),外加定時(shí)中斷。這個(gè)框架看似簡(jiǎn)單,實(shí)際上就是那么簡(jiǎn)單。我做的所有開(kāi)發(fā)項(xiàng)目都是基于這個(gè)簡(jiǎn)單框架,但是非常好用。上一節(jié)只有一個(gè)單任務(wù)的LED燈在閃爍,這節(jié)開(kāi)始,我們多增加一個(gè)蜂鳴器報(bào)警的任務(wù),要教會(huì)大家四個(gè)知識(shí)點(diǎn):
第一點(diǎn):蜂鳴器的驅(qū)動(dòng)程序框架編寫。
第二點(diǎn):多任務(wù)處理的程序框架。
第三點(diǎn):如何控制蜂鳴器聲音的長(zhǎng)叫和短叫。
第四點(diǎn):如何知道1秒鐘需要多少個(gè)定時(shí)中斷,也就是如何按比例修正時(shí)間精度。

具體內(nèi)容,請(qǐng)看源代碼講解。

(1)硬件平臺(tái):基于朱兆祺51單片機(jī)學(xué)習(xí)板。

(2)實(shí)現(xiàn)功能:同時(shí)跑兩個(gè)任務(wù),第一個(gè)任務(wù)讓一個(gè)LED燈1秒鐘閃爍一次。第二個(gè)任務(wù)讓蜂鳴器在前面3秒發(fā)生一次短叫報(bào)警,在后面6秒發(fā)生一次長(zhǎng)叫報(bào)警,反復(fù)循環(huán)。

(3)源代碼講解如下:

#include "REG52.H"

/* 注釋一:
* 如何知道1秒鐘需要多少個(gè)定時(shí)中斷?
* 這個(gè)需要編寫一段小程序測(cè)試,得到測(cè)試的結(jié)果后再按比例修正。
* 步驟:
* 第一步:在程序代碼上先寫入1秒鐘大概需要200個(gè)定時(shí)中斷。
* 第二步:基于以上1秒鐘的基準(zhǔn),編寫一個(gè)60秒的簡(jiǎn)單測(cè)試程序(如果編寫超過(guò)
* 60秒的時(shí)間,這個(gè)精度還會(huì)更高)。比如,編寫一個(gè)用蜂鳴器的聲音來(lái)識(shí)別計(jì)時(shí)的
* 起始和終止的測(cè)試程序。
* 第三步:把程序燒錄進(jìn)單片機(jī)后,上電開(kāi)始測(cè)試,手上同步打開(kāi)手機(jī)里的秒表。
*? ?? ?? ?如果單片機(jī)僅僅跑了27秒。
* 第四步:那么最終得出1秒鐘需要的定時(shí)中斷次數(shù)是:const_time_1s=(200*60)/27=444
*/
#define const_time_05s 222? ?//0.5秒鐘的時(shí)間需要的定時(shí)中斷次數(shù)
#define const_time_1s 444? ?//1秒鐘的時(shí)間需要的定時(shí)中斷次數(shù)
#define const_time_3s 1332? ?//3秒鐘的時(shí)間需要的定時(shí)中斷次數(shù)
#define const_time_6s 2664? ?//6秒鐘的時(shí)間需要的定時(shí)中斷次數(shù)

#define const_voice_short??40? ?//蜂鳴器短叫的持續(xù)時(shí)間
#define const_voice_long? ?200??//蜂鳴器長(zhǎng)叫的持續(xù)時(shí)間

void initial_myself();? ?
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void led_flicker();
void alarm_run();? ?
void T0_time();??//定時(shí)中斷函數(shù)

sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動(dòng)IO口
sbit led_dr=P3^5;??//LED燈的驅(qū)動(dòng)IO口

unsigned char ucLedStep=0; //LED燈的步驟變量
unsigned int??uiTimeLedCnt=0; //LED燈統(tǒng)計(jì)定時(shí)中斷次數(shù)的延時(shí)計(jì)數(shù)器

unsigned char ucAlarmStep=0; //報(bào)警的步驟變量
unsigned int??uiTimeAlarmCnt=0; //報(bào)警統(tǒng)計(jì)定時(shí)中斷次數(shù)的延時(shí)計(jì)數(shù)器

unsigned int??uiVoiceCnt=0;??//蜂鳴器鳴叫的持續(xù)時(shí)間計(jì)數(shù)器

void main()
??{
? ?initial_myself();??
? ?delay_long(100);? ?
? ?initial_peripheral();
? ?while(1)??
? ?{
? ?? ?led_flicker();??//第一個(gè)任務(wù)LED燈閃爍
? ?? ?? ? alarm_run();? ? //第二個(gè)任務(wù)報(bào)警器定時(shí)報(bào)警
? ?}

}

void led_flicker() //第三區(qū) LED閃爍應(yīng)用程序
{
??
??switch(ucLedStep)
??{
? ???case 0:

? ?? ?? ???if(uiTimeLedCnt>=const_time_05s) //時(shí)間到
? ?? ?? ???{
? ?? ?? ?? ? uiTimeLedCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ? led_dr=1;? ? //讓LED亮
? ?? ?? ?? ? ucLedStep=1; //切換到下一個(gè)步驟
? ?? ?? ???}
? ?? ?? ???break;
? ???case 1:
? ?? ?? ???if(uiTimeLedCnt>=const_time_05s) //時(shí)間到
? ?? ?? ???{
? ?? ?? ?? ???uiTimeLedCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ???led_dr=0;? ? //讓LED滅
? ?? ?? ?? ???ucLedStep=0; //返回到上一個(gè)步驟
? ?? ?? ???}
? ?? ?? ???break;
??}

}

void alarm_run() //第三區(qū) 報(bào)警器的應(yīng)用程序
{
??
??switch(ucAlarmStep)
??{
? ???case 0:

? ?? ?? ???if(uiTimeAlarmCnt>=const_time_3s) //時(shí)間到
? ?? ?? ???{
? ?? ?? ?? ? uiTimeAlarmCnt=0; //時(shí)間計(jì)數(shù)器清零
/* 注釋二:
* 只要變量uiVoiceCnt不為0,蜂鳴器就會(huì)在定時(shí)中斷函數(shù)里啟動(dòng)鳴叫,并且自減uiVoiceCnt
* 直到uiVoiceCnt為0時(shí)才停止鳴叫。因此控制uiVoiceCnt變量的大小就是控制聲音的長(zhǎng)短。
*/
? ?? ?? ?? ? uiVoiceCnt=const_voice_short;??//蜂鳴器短叫
? ?? ?? ?? ? ucAlarmStep=1; //切換到下一個(gè)步驟
? ?? ?? ???}
? ?? ?? ???break;
? ???case 1:
? ?? ?? ???if(uiTimeAlarmCnt>=const_time_6s) //時(shí)間到
? ?? ?? ???{
? ?? ?? ?? ???uiTimeAlarmCnt=0; //時(shí)間計(jì)數(shù)器清零
? ?? ?? ?? ???uiVoiceCnt=const_voice_long;??//蜂鳴器長(zhǎng)叫
? ?? ?? ?? ???ucAlarmStep=0; //返回到上一個(gè)步驟
? ?? ?? ???}
? ?? ?? ???break;
??}

}

void T0_time() interrupt 1
{
??TF0=0;??//清除中斷標(biāo)志
??TR0=0; //關(guān)中斷

??if(uiTimeLedCnt<0xffff)??//設(shè)定這個(gè)條件,防止uiTimeLedCnt超范圍。
??{
? ?? ?uiTimeLedCnt++;??//LED燈的時(shí)間計(jì)數(shù)器,累加定時(shí)中斷的次數(shù),
??}

??if(uiTimeAlarmCnt<0xffff)??//設(shè)定這個(gè)條件,防止uiTimeAlarmCnt超范圍。
??{
? ?? ?uiTimeAlarmCnt++;??//報(bào)警的時(shí)間計(jì)數(shù)器,累加定時(shí)中斷的次數(shù),
??}


/* 注釋三:
* 為什么不把驅(qū)動(dòng)蜂鳴器這段代碼放到main函數(shù)的循環(huán)里去?
* 因?yàn)榉旁诙〞r(shí)中斷里,能保證蜂鳴器的聲音長(zhǎng)度是一致的,
* 如果放在main循環(huán)里,聲音的長(zhǎng)度就有可能受到某些必須
* 一氣呵成的任務(wù)干擾,得不到及時(shí)響應(yīng),影響聲音長(zhǎng)度的一致性。
*/


??if(uiVoiceCnt!=0)
??{
? ???uiVoiceCnt--; //每次進(jìn)入定時(shí)中斷都自減1,直到等于零為止。才停止鳴叫
? ?? ?? ?beep_dr=0;??//蜂鳴器是PNP三極管控制,低電平就開(kāi)始鳴叫。
??}
??else
??{
? ???; //此處多加一個(gè)空指令,想維持跟if括號(hào)語(yǔ)句的數(shù)量對(duì)稱,都是兩條指令。不加也可以。
? ?? ?? ???beep_dr=1;??//蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
??}


??TH0=0xf8;? ?//重裝初始值(65535-2000)=63535=0xf82f
??TL0=0x2f;
??TR0=1;??//開(kāi)中斷
}


void delay_long(unsigned int uiDelayLong)
{
? ?unsigned int i;
? ?unsigned int j;
? ?for(i=0;i? ?{
? ?? ?for(j=0;j<500;j++)??//內(nèi)嵌循環(huán)的空指令數(shù)量
? ?? ?? ? {
? ?? ?? ?? ? ; //一個(gè)分號(hào)相當(dāng)于執(zhí)行一條空語(yǔ)句
? ?? ?? ? }
? ?}
}


void initial_myself()??//第一區(qū) 初始化單片機(jī)
{
??beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時(shí)不叫。
??led_dr=0;??//LED滅

??TMOD=0x01;??//設(shè)置定時(shí)器0為工作方式1


??TH0=0xf8;? ?//重裝初始值(65535-2000)=63535=0xf82f
??TL0=0x2f;

}
void initial_peripheral() //第二區(qū) 初始化外圍
{
??EA=1;? ???//開(kāi)總中斷
??ET0=1;? ? //允許定時(shí)中斷
??TR0=1;? ? //啟動(dòng)定時(shí)中斷

}

總結(jié)陳詞:
本節(jié)程序已經(jīng)展示了一個(gè)多任務(wù)處理的基本思路,假如要實(shí)現(xiàn)一個(gè)獨(dú)立按鍵檢測(cè),能不能也按照這種思路來(lái)處理呢?欲知詳情,請(qǐng)聽(tīng)下回分解-----在主函數(shù)中利用累計(jì)主循環(huán)次數(shù)來(lái)實(shí)現(xiàn)獨(dú)立按鍵的檢測(cè)。

(未完待續(xù),下節(jié)更精彩,不要走開(kāi)哦)
gaofang36 06-21 00:00

? ?? ???MOV??A,31H? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ???XRL??A,41H? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ???JNZ??LOOP? ?//A=1跳轉(zhuǎn)LOOP? ?? ?? ?? ?? ?? ?? ???
? ?? ???MOV??A,30H? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ???XRL??A,40H? ?? ?? ?? ?? ?? ?? ?? ?

LOOP:? ?JZ? ?LOOP2??//A=0跳轉(zhuǎn)LOOP2? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ???MOV??40,30H? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?
? ?? ???MOV??41,31H? ?? ?? ?? ?? ?? ?? ?? ?
LOOP2:??SETB P1_0
====================================
請(qǐng)教這段如何用C實(shí)現(xiàn)
胡政鵬測(cè)試號(hào)碼2 06-23 16:43
頂一個(gè),樓主辛苦了
Ehunt 06-23 18:45
頂起來(lái)? ?嘿嘿
胡政鵬測(cè)試bbs 06-26 06:17
頂起來(lái),非常感謝分享,我需要認(rèn)真閱讀完?。?
上海汽車055 06-19 10:49
果然是好東東
撰寫答案
提 交
1 / 3
1 / 3
相關(guān)單片機(jī)
具有音調(diào)控制的單片機(jī)立體聲前置放大器
用于單片機(jī)與電子裝置中的開(kāi)關(guān)電源
單片機(jī)軟硬件復(fù)位的條件都有啥
電動(dòng)機(jī)的單片機(jī)控制
單片機(jī)應(yīng)用系統(tǒng)開(kāi)發(fā)實(shí)例導(dǎo)航