假定兩個位元組變數A和B,兩者進行某種邏輯運算後結果爲F。
以下爲邏輯運算子(按變數整體值進行運算)
以下爲按位元運算子(按變數的每一個位進行運算)
以下圖爲數位電路常用電路符號,重點認識國外流行符號,通過查閱來記住即可。
微控制器中定時器和計數器是內部的同一模組,計數器功能讀者自己去瞭解,我們來介紹定時器功能。
定時器:用於定時,標準51微控制器有T0和T1兩個定時器。定時器內部有一個暫存器,該暫存器的值每通過一個機器週期自動加1,可以把機器週期理解爲定時器的計數週期,如同鐘錶,每經過一秒,數位自動加1,而暫存器每通過12/11059200秒,數值自動加1。當鐘錶加到60秒後,秒自動跳爲0,這種情況在微控制器和計算機中叫溢位,定時器不同工作模式,溢位的情況也不同,假如16位元定時器,加到65535後,再加1就溢位,溢位後值直接變爲0。
定時器這模組有6個暫存器,下面 下麪來一一介紹,讀者用到這些暫存器查手冊即可。
表 5-2 是定時器控制暫存器 TCON 的位分配,表 5-3 是則是對每一位的具體含義的描述。TCON暫存器中TF0和TR0用於定時器0,TF1和TR1用於定時器1。我們以定時器1爲例講解,定時器0同理,TR1等於1,定時器值每過一個機器週期加1,若等於0,則停止加1。 TF1的作用是告訴們定時器溢位了,比如定時器16位元模式下,每經過一個機器週期會使TL1加1,加到255後,再加1後,TL1變爲0,而TH1加1,如此回圈,待TL1和TH1爲255後,再加1就會溢位,此時TL1和TH1變爲0,TF1自動變成1,提供給讀者一個溢位信號。
(注:不可位定址指的是不可以對該暫存器的每個位單獨操作,對 TMOD 裡的位比如M1 (T1)= 1 這樣的操作就是錯誤的。我們要操作就必須一次操作這整個位元組,也就是必須一次性對 TMOD 所有位元運算)
上表爲TMOD的位分配。
表5-5爲TMOD的位描述,GATE位讀者自行瞭解,C/T位爲選擇定時器或計數器功能,T=0爲選擇定時器功能,C/T=1爲選擇計數器功能。
表5-6爲TMOD4中模式介紹,模式0和3現在很少應用,讀者自行瞭解,下面 下麪介紹模式1和2。
模式1: 是 THn 和 TLn 組成了一個 16 位的定時器,計數範圍是 0~65535,溢位後,只要不對 THn 和 TLn 重新賦值,則從 0 開始計數。
模式2: 是 8 位自動重灌載模式,只有 TLn做加 1 計數,計數範圍 0~255,THn 的值並不發生變化,而是保持原值,TLn 溢位後,TFn就直接置 1 了,並且 THn 原先的值直接賦給 TLn,然後 TLn 從新賦值的這個數位開始計數。 比如該模式下,TH1 = 0x66,TL1=0x00,每經過一個機器週期TL1加1,當TL1=0xFF時,再加1後TF1就會變爲1,並且TL1會被賦值爲TH1的值後計數,即TL1從0x66開始計數,而TH1的值保持不變。
講解:以定時器1爲講解,定時器0同理,OSC爲時鐘源頻率,d爲微控制器機器週期對於時鐘週期的倍數。
下面 下麪以使用定時器0爲例,定時器1同理。
我們知道標準51微控制器機器週期爲12個時鐘週期,以STC89C52RC微控制器爲例,它的機器週期爲:12/11059200秒,如果定時0.02s,設要經過x個機器週期,那麼 x* (12/11059200) =0.02, 通過計算x等於18432,因16位元定時器溢位值爲65536,那麼先讓TH0和TL0等於初值y,經過18432個機器週期後溢位,這樣就實現了定時0.02s,y值通過65536- 18432計算出爲47104,轉換爲十六進制就是0xB800(鏈接:進位制轉換方法),即TH0 = 0xB8,TL0 = 0x00。
#include<reg52.h>
sbit LED = P0^7;
sbit ADDR3 = P1^3;
sbit ADDR2 = P1^2;
sbit ADDR1 = P1^1;
sbit ADDR0 = P1^0;
sbit ENLED = P1^4;
void main()
{
unsigned char cnt = 0;//定義一個計數變數,記錄T1的溢位次數
ENLED = 0;
ADDR3 = 1;
ADDR2 = 1;
ADDR1 = 1;
ADDR0 = 0;
TMOD = 0x10;//設定T1的工作模式
TH1 = 0xB8;
TL1 = 0x00;//爲T1賦初值
TR1 = 1;//啓動T1
while(1)
{
if(TF1 == 1)//判斷T1是否溢位
{
cnt++;// 計數值自加1
TF1 = 0;//T1溢位後,清零中斷標誌
TH1 = 0xB8;//並在重新賦初值
TL1 = 0x00;
if(cnt >= 50)//判斷是否溢位50次
{
LED = ~LED;//LED取反,1--->0、0--->1
cnt = 0;//達到50次後計數值清零
}
}
}
}
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void main()
{
unsigned char cnt = 0;//定義計數變數,記錄溢位次數
unsigned char dir = 0;//定義移位方向變數,用於改變流水燈流向
unsigned char shift = 0x01;//定義回圈移位變數shift,並賦初值0x01
ENLED = 0;//使能U3
ADDR3 = 1;
ADDR2 = 1;
ADDR1 = 1;
ADDR0 = 0;
TMOD = 0x10;//設定T1爲模式一
TH1 = 0xB8;//爲T1賦初值
TL1 = 0x00;
TR1 = 1;//開啓T1
while(1)//主回圈,程式無限執行該回圈
{
P0 = ~shift;//P0等於回圈移位變數shift取反,控制8個LED小燈
while(TF1 == 0);//當TF1=0時回圈執行空語句,直到定時器溢位
TF1 = 0;//TF1清零
TH1 = 0xB8;//重新爲T1賦初值
TL1 = 0x00;
cnt++;//每溢位一次,cnt加一
if(cnt >= 10)//判斷是否溢位10次
{
cnt = 0;//溢位次數置零
if(dir == 0)//移位方向變數爲0時,左移
{
shift = shift << 1;//回圈移位變數shift左移一位
if(shift == 0x80) //左移到最左端,改變移位方向變數
{
dir = 1;
}
}else //移位方向變數不爲零時,右移
{
shift = shift >> 1;//回圈移位變數右移一位
if(shift == 0x01) //右移到最右端,改變移位方向變數
{
dir = 0;
}
}
}
}
}
一個數碼管由8個LED小燈組成。數碼管分爲共陽數碼管和共陰數碼管,共陽數碼管的8個LED小燈陽極連在一起, 陽極爲公共端,由陰極控制單個小燈亮滅。共陰數碼管同理,數碼管內部結構見下圖5-4。
下圖5-3爲數碼管的原理圖
com引腳爲公共端,圖中有兩個com公共端,爲什麼有兩個公共端呢? 一方面,爲了起對稱效果,剛好10個引腳,另一方面,因並聯電流之和等於總電流,可以降低單條線路承受的電流。
下圖爲KST-51開發板中數碼管電路圖
從上圖可以知道數碼管每個LED小燈陽極都接在5v(VCC)上,所以上圖6個數碼管都是共陽數碼管,下面 下麪講解數碼管點亮原理。
數碼管的 8 個段,我們直接當成 8 個 LED 小燈來控制,那就是 a、b、c、d、e、f、g、dp 一共 8 個 LED 小燈。我們控制這8個小燈來讓數碼管顯示不同數值,而數碼管顯示的數位字元對應給 P0 的賦值,我們叫做數碼管的真值表。 數碼管真值表見下表5-7。
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void main()
{
ENLED = 0;//使能U3,導通三極管Q9,
ADDR3 = 1;
ADDR2 = 0;
ADDR1 = 1;
ADDR0 = 1;
P0 = 0x80;//點亮數碼管DS4的a、b、c、d、e、f和g段,讓數碼管顯示字元8
while(1);//讓數碼管DS4一直顯示字元8
}
先介紹C51中的關鍵字code,前面定義變數時使用關鍵字unsigned char或unsigned int,這樣定義的變數都是放在微控制器RAM中,並且程式中可以隨意更改這些變數的值,而運用code關鍵字修飾下定義的變數,則可以儲存到程式空間FLASH中,大大節省微控制器RAM空間,但程式中不能更改這些變數的值。下面 下麪我們來看看運用了code關鍵字的程式。
#include<reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
//用陣列儲存數碼管真值表,陣列將在下一章詳細介紹
unsigned char code Ledchar[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
void main()
{
unsigned char cnt = 0;//定義溢位計數變數,記錄溢位次數
signed char sec = 0;//記錄經過的秒數
unsigned char dir = 0;//定義選擇變數,0代表秒錶,1代表倒計時
ENLED = 0;//使能U3,導通三極管Q8,準備點亮數碼管DS5
ADDR3 = 1;
ADDR2 = 1;
ADDR1 = 0;
ADDR0 = 0;
TMOD = 0x01;//設定T0爲工作模式一
TH0 = 0xB8;//爲T0賦初值
TL0 = 0x00;
TR0 = 1;//開啓定時器T0
while(1)
{
if(TF0 == 1)//判斷T0是否溢位
{
TF0 = 0;//軟體將溢位標誌清零
TH0 = 0xB8;//爲T0重新賦值
TL0 = 0x00;
cnt++;//計數值自加1,
if(cnt >= 50)//判斷T0是否溢位50次
{
cnt = 0;//達到50次後計數值清零
if(dir == 0)//選擇變數dir等於0,實現秒錶功能
{
P0 = Ledchar[sec];//當前秒數對應的真值表中的值送到P0口
sec++;//秒數記錄自加一
if(P0 == 0x8E)//當P0值使數碼管顯示字元F時,
{
dir = 1;//將選擇變數置爲1,準備實現倒計時功能
sec = 14;//將秒數置爲14
}
}else //實現倒計時功能
{
P0 = Ledchar[sec];//當前秒數對應的真值表中的值送到P0口
sec--;//秒數記錄自減一
if(sec < 0)//當秒數小於0後
{
dir = 0;//將選擇變數置爲0,準備實現秒錶功能
sec = 1;//將秒數置爲1
}
}
}
}
}
}
重溫第五章對定時器的使用無疑更加熟悉了,程式設計上沒有啥問題,前幾天忙家裏的一些事耽誤了進度,一天一章的目標也啪啪打臉,接下來會加倍學習的。奧裡給奧裡給!!!