實(shí)驗(yàn)準(zhǔn)備
課程內(nèi)容
使用第一課已裝配好的實(shí)驗(yàn)板
LED 增加7只
電阻 10k ,增加7只
參照原理圖,類似在P1.0上接LED的方法,把P1.1到P1.7的7只LED和電阻也接好。
這時(shí),為實(shí)驗(yàn)板加電,可見到只有P1.0對應(yīng)的D1這只LED在閃,如果按之前的編程思路,就是使用如下的程序方式:
sbit P10= P1^0;
sbit P11= P1^1;
sbit P12= P1^2;
sbit P13= P1^3;
sbit P14= P1^4;
sbit P15= P1^5;
sbit P16= P1^6;
sbit P17= P1^7;
同時(shí)main()程序中使用
P10=!P10;
P11=!P11;
P12=!P12;
P13=!P13;
P14=!P14;
P15=!P15;
P16=!P16;
P17=!P17;
這方式可行嗎?當(dāng)然可行,只要能達(dá)到效果,哪一種方式都行,其實(shí)這也是編程最先采用的方法,就是先用最容易理解,最簡單的實(shí)現(xiàn)方法去編程,達(dá)到要求結(jié)果后,再去做程序優(yōu)化,否則沒達(dá)到結(jié)果 什么精簡高效的程序都是沒用的。
好了,現(xiàn)在可以同時(shí)控制8 LED了,但看上去很繁,那么就做優(yōu)化。
單片機(jī)雖然只認(rèn)0與1,但可以一次同時(shí)處理多個(gè)位,例如C51系列就是8位單片機(jī),同時(shí)可以處理8位,更高級的處理器可以同時(shí)處理16位、32位、64位或128位等等。
89C52單片機(jī)可一次同時(shí)處理8位,這單片機(jī)把控制數(shù)據(jù)輸入輸出的管腳(簡稱IO口)分成4組,每組8個(gè)IO口,分別命名為P1、P2、P3、P4,這在 reg52.h 文件中預(yù)先做好定義,方便我們直接操控。
本次實(shí)驗(yàn)中8 只LED接在P1的8個(gè)IO口處,所以,可以直接一次性控制8只LED。
修改控制,只須改到一行代碼。
主程序main()中,把
P10=!P10;
改成
P1=~P1;
下載,觀看實(shí)驗(yàn)效果,可以見到8只LED同時(shí)閃動(dòng)。
上一課中所用的運(yùn)算符號!,只對一位數(shù)起效,不能同時(shí)控制8位,如果把
P1=~P1;
改成
P1=!P1;
那么只有LED1閃,其他不閃,這個(gè)可以下載實(shí)踐下。
而運(yùn)算符~則是8位同時(shí)運(yùn)算
00000000 做~取反,對每個(gè)位取反,結(jié)果就是11111111
同理,11111111 做~取反,對每個(gè)位取反,結(jié)果就是00000000
如果8個(gè)LED燈想玩下花樣,做出特效,有的LED發(fā)光,有的不發(fā)光,或者做流水燈等廣告效果,這時(shí),需要對不同的LED控制它所在位設(shè)0或設(shè)1,于是 11110000,10101010等這樣的結(jié)果就出現(xiàn)了,這些數(shù)不方便記憶,也不方便編程,于是采用『數(shù)制』來實(shí)驗(yàn)簡化。11110000或10101010這純機(jī)器碼表現(xiàn)形式你為二進(jìn)制數(shù),每位只能是0或1,逢2進(jìn)1,與平常用的10進(jìn)制數(shù)類似,10進(jìn)制每位可用0至9個(gè)數(shù),逢10進(jìn)1。還有十六進(jìn)制的數(shù),成語『半斤八兩』中所用的是十六進(jìn)制,中國古代的重量計(jì)量方式是一斤是十六兩。
二進(jìn)制數(shù)太長不好寫不好記,一般采用十六進(jìn)制方式表示,
二進(jìn)制11110000 ---> 十六進(jìn)制 0xF0
二進(jìn)制10101010 ---> 十六進(jìn)制 0xAA
注意,每個(gè)十六制數(shù)前要加 0x,如果不加,是當(dāng)成10進(jìn)制數(shù)的。
如果轉(zhuǎn)換,很簡單,電腦中有只工具軟件『計(jì)算器』能幫我們。
在電腦程序附件中可以找到『計(jì)算器』這個(gè)工具軟件。
可以通過 查看 – 科學(xué)型 ,切換到 數(shù)制轉(zhuǎn)換模式
點(diǎn)二進(jìn)制,輸入11110000,再點(diǎn)十六進(jìn)制,就自動(dòng)顯示F0
現(xiàn)在,可以實(shí)驗(yàn)LED花樣特效了,
間閃效果一:(這里僅修改主程序main())
void main()
{
P1=0xAA;//二進(jìn)制對應(yīng)是 10101010
mDelay(200);
P1=0x55;//二進(jìn)制對應(yīng)是 01010101
mDelay(200);
}
間閃效果二:(這里僅修改主程序main())
void main()
{
P1=0x36;//二進(jìn)制對應(yīng)是 01101101
mDelay(200);
P1=0x5B;//二進(jìn)制對應(yīng)是 10110110
mDelay(200);
P1=0xDB;//二進(jìn)制對應(yīng)是 11011011
mDelay(200);
}
#include 'reg52.h'
#define uchar unsigned char
#define uint unsigned int
sbit P10=P1^0;
void mDelay(uint Delay)
{
uint i;
for(;Delay>0;Delay--)
for(i=0;i<>
}
void main()
{
uchar a = 0x01; // 二進(jìn)制00000001
for(;;)
{
P1 = ~a; // 首次循環(huán)時(shí)把a(bǔ)取反的值給P1,11111110
//控制P1.0的LED,注意這時(shí) a 值本身是沒有變化的
a = a < 1;="" 首次循環(huán)時(shí)="" a左移一位,a值變成="">
if (a==0x00) a=0x01; //如果 a 變成了00000000,那么設(shè)成00000001
mDelay(200); //延時(shí),之后繼續(xù)循環(huán) 分別控制 各只LED
}
}
程序分析:
第一:uchar 定義的數(shù)據(jù),剛好是8位,直接適用于IO的控制。
第二:< 左移運(yùn)算符,a中的8個(gè)位同時(shí)向左移,最后一個(gè)用0補(bǔ)上。(同理="">>右移運(yùn)算類似), a=a<1;>1;>
第三:if (a==0x00) a=0x01;這是判斷結(jié)構(gòu),if 就是『如果』,由于循環(huán)結(jié)構(gòu)for(;;)是無限循環(huán),所以其中 a 每左移8次后會(huì)變成0,這時(shí)讓a設(shè)成0x01,可以讓重新讓第一位的LED受控。
注意if (a==0x00)中的 a==0x00 是兩個(gè)等于號,這是C語言中的,判斷運(yùn)算符中的一個(gè),類似,還有 >=(小于或等于)、<><(小于)、>( 大于)、!=(不等于) 這些運(yùn)算符。
C51單片機(jī)開發(fā)的前輩已編有一些方便我們使用的功能模塊,我們直接按需調(diào)用,于是程序可以再簡化。在文件intrins.h中定義有循環(huán)左移位函數(shù)_crol_(),使用方法直接看以下修改后的程序。(類似有循環(huán)右移位函數(shù)_cror_())
#include 'reg52.h'
#include 'intrins.h'
#define uchar unsigned char
#define uint unsigned int
sbit P10=P1^0;
void mDelay(uint Delay)
{
uint i;
for(;Delay>0;Delay--)
for(i=0;i<>
}
void main()
{
uchar a = 0x01; // 二進(jìn)制00000001
for(;;)
{
P1 = ~a; // 首次循環(huán)時(shí)把a(bǔ)取反的值給P1,11111110
//控制P1.0的LED,注意這時(shí) a 值本身是沒有變化的
a = _crol_(a,1); // a 循環(huán)左移位,左邊移出的放回右邊的移空位
mDelay(200); //延時(shí),之后繼續(xù)循環(huán) 分別控制 各只LED
}
}
注意:
1.增加了 #include 'intrins.h' 這一行,
2.循環(huán)左移位函數(shù) _crol_(),函數(shù)名前面與后面是下劃線。
(小于)、>