STC51(點燈+五向開關(guān))
mini DSO STC15 開源示波器
中景園STC89C52資料
其實本來不是寫定時器的文章,而是想寫一篇長長的文章把單片機說完。但是我寫的寫的后悔了,實在是有點多,寫完定時器就餓了,SO,最后起了這個名字。

nop是一個空指令的時間

對我們使用引腳的定義

沒什么好說的,就是記住0是低電平,1是高電平。再者就是nop是一個空的時鐘時間。注意上面函數(shù)的聲明。
模塊化編程,是怎么回事?考慮變與不變的藝術(shù),注意分層的藝術(shù)。

dev是外設(shè)傳感器的封裝,寫函數(shù)接口。sys是單片機本身的資源。

C是具體的實現(xiàn),H是暴露的接口。

寫函數(shù)聲明,各種可變的參數(shù)

sys里面寫關(guān)于操作寄存器的頭文件,還有數(shù)據(jù)類型的重新定義。

需要注意的是,引腳也是一種資源,所以也放在配置的文件夾。

然后一個main文件作為邏輯的實現(xiàn),完事。
函數(shù)與邏輯和模塊之間的聯(lián)系就是頭文件。

關(guān)于按鍵檢測,是永遠不會缺席的功能。這里就先說查詢法,這個查詢我感覺有點掃描的味道,不就是一個循環(huán)里面判斷一次和IO口相關(guān)聯(lián)的狀態(tài)標志。
看我代碼,在死循環(huán)里面調(diào)用按下的語句。

消抖什么的,老生常談了,不說了。功能就是如果按下按鍵就返回一個1.

也就是if為真,那就繼續(xù)運行。不就是把燈開了。

這就是燈的IO

另外注意五向開關(guān),也是需要占用好多IO的。
說下設(shè)計的邏輯,一定要在這個按鍵的狀態(tài)前先查詢,這個按鍵的當前情況,就好像你去買東西,先知道哪個地方還賣你要的東西嗎?

因為我們想的是沒有,
key1 = 1; //設(shè)置成輸入狀態(tài)所以要:
!key1 = !1是真!
開始延時,窮人做法,跳過抖動。

接著再判斷一下這個狀態(tài),因為一直是準備讀取,你還沒有讀取,對吧!不停的為真,一直就按著。一直IO為0.不繼續(xù)運行,直到你放開,這個循環(huán)條件變假了。因為是你摁的時候有抖動,你松開的時候也有,所以處理方法一樣。

是一樣的

處理過后,相當于你讀取了這個信息,相當于你取走了東西,這個東西你要還愿。flag=0,后面用return把它這個函數(shù)得到的信息傳出去,給上層的函數(shù)使用。

就是這樣。

STC51(LCD1602全解析.上),我以前寫過,但是覺得不深刻,這里重新寫。

使用外設(shè),倆步走,先初始化,接著就是通信過程。
數(shù)字器械就是活的個時序,就是IO的電平變化+時間。

這是LCD1602的初始化代碼,別問為什么我也不知道,先用。不是我不求甚解,其實我是真的不知道。
這里你也看見了,讀寫操作。怎么實現(xiàn)?用IO的電平變化:

寫指令

寫數(shù)據(jù)

時序
還有一個事情,就是在寫操作前要看看LCD忙不忙:


忙信號檢測

初始化而已。接下來看下連線問題:

8個線


接著就是

那么操作這個LCD,你就讓IO口搭配的輸出不同電平就行。

對于顯示器件,知道在哪里顯示什么就ok了~

高(0100)+低(0001)
這才是一個字符,如果一個串呢?

也是有函數(shù)的.
其實本來是要寫應(yīng)用的,但是我覺得太早了,不如再寫幾下相關(guān)的硬件。
這里先說定時器這個東西,前面的延時實現(xiàn)都是空語句浪費時間,這樣很不好,至少不精確。
定時器的一些通俗解釋我就不說了,我覺得這個地方可以是喲個數(shù)學建模里面的一些方法說明:
假設(shè):
我們先認為一個可以記錄的事情的兩個相鄰間隔的時間是相同的。
要記錄的事情可以被記錄
有個容器可以裝我們記錄的事情
定時器的工作就是這樣:就好像你拿一個羽毛球往羽毛球桶里面塞,你一秒鐘可以塞一個。10s后一個桶滿了,然后你把這個桶里面的球倒入一個大桶里面,你順手在本子上面劃一道。
其實我們就可以計算了,你一個人塞了多少球?以及塞球用了多少時間。仔細想想還有進位的知識。就像表一樣!
下面我找了一個土的要死的視頻截圖:

上面的水滴就是你塞球,時間是1秒一顆

滿了以后就倒出去,是個容器就會滿

初值重裝,就是你一開始的羽毛球桶里面有幾個。其實就是為了可控這個過程
可惡啊,讓這么丑的示意圖說明白了
我們開始抽象一下,一個定時器有什么構(gòu)成:
要求事件之間的間隔時間相同
這個裝事件的箱子多大
這個事件該怎么表示?
差不多啦!
因為我們說的是51單片機(我是覺得你51玩不明白就去玩ARM,STM32這些,笑話一樣,不可否認你會用,但是你深刻嗎?)。
一般51單片機的定時器名字叫TIMER,然后寄存器就是箱子,起個名字叫TL0,TH0. 也就是說定時器有兩個箱子,名字分別是tl,th。
有箱子放啥?放事件,不論是什么事件無非就是發(fā)生了!然后在單片機里面就是1,0,相當于一個事件的發(fā)生標志。發(fā)生一個在TL的最低位寫一個1,在發(fā)生就再放1.
其實有一個事情是,這個事件怎么觸發(fā),你看它本身很無聊,就是一個一個的。所以在單片機里面有晶振搬磚。
其實你要深刻的理解這個東西,所有的單片機定時器都是這樣的。

那定時器怎么樣用?其實就是鬧鐘的用法

我們先看怎么打開,鬧鐘是按鈕打開。在單片機里面都是0,1,所以很容易就是0,1.
剩下是多長時間?鬧鐘的話我們是看走了多少格子,那單片機也是這樣的原理,就是TH,TL這兩個箱子如何組合的事情。
這個如何組合是一種模式,所以有個寄存器叫TMOD(time mode)干這個事情。

你看
一個格子有兩個狀態(tài),0或1.那這么多格子,就是00、01,11,10.
4個工作模式哇。里面的時間夠了,怎么傳出去這個時間到了的意思呢?

使用TCON寄存器里面的TF,full滿的意思,上面滿了TF(0->1),告訴CPU滿了。

你看是不是

你看

TF就是滿了以后是中斷。
接下來看怎么用!首先定時器我們要解決定時時長的問題。通過TH,TL控制。這里選16bit

先開啟定時器1,都設(shè)置1.

然后就是M1,M0,設(shè)置01.這就OK了。
TMOD =?0000? ?0001??= 0x01.
一開始要計數(shù)了,TH,TL都為0,16bit,就是2的16次方,65535這么多。
有溢出,所以2^16+1,每次裝一個值需要12/11.0592?微秒,裝65536需要
UnitT=65536x(12/11.0592)= 71000微秒 = 71ms,那我要定時1s。
明顯TH,TL都不夠,兄弟別慌,循環(huán)幾次就OK。
比如UnitT = 10ms,循環(huán)100次就1s啦!
那UnitT=10000us,也就是UnitT=(65536-X)x(12/11.0592)=10000us.
X就是我們的TH,TL的初始化的值。


算不來的自己用軟件
繼續(xù),初始值為19456,然后不停的++,那么到65535,這是TL滿了,然后不停的增長到TH到65535,兩個都放不下了,TF變1,告訴CPU時間到了。
要注意TF變1 是溢出了一次,時間還沒有到。要TF溢出20次,這才到1s。

這就是我們的框圖,當TF為1時,我們要記錄這個溢出事件,而且要把寄存器TLTH,清零,接著裝值,拍拍屁股開始干活。
我覺得我講的最清晰了,再聽不懂可以考慮不用學了。

這里學點數(shù)字電路小知識。


學會了嗎?

我們來分析一個,這個定時器的本質(zhì)就是一個加減法的計數(shù)器,本質(zhì)就是對脈沖計數(shù)。
只不過這個來源不一樣,系統(tǒng)時鐘的脈沖,就是定時,12或者6時鐘得到一個計數(shù)脈沖.
如果是外部引腳那就是計數(shù)。一個脈沖+1

很清晰吧
6T肯定是快啊,你以前2個點吃一個,現(xiàn)在一個點吃一個。

看這個,3開關(guān)是由4,5,6控制的。
6為非門,GATE=0,輸出1,5為或門,5,6搭配必出一,由高電平就全高了。4為與門這個時候,從56上來的信號是確定的1.要想4輸出1,那就要TR0為1就行,其實側(cè)面說明,TR0是開關(guān)了。巧妙

這不就開始了