51單片機(jī)入門教程(2)——實(shí)現(xiàn)流水燈
一、搭建流水燈電路
在Proteus中搭建流水燈電路如圖 
二、流水燈程序
我們可以把流水燈看作依次點(diǎn)亮若干個(gè)燈。 程序如下:
#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
void main()
{
//點(diǎn)亮第一個(gè)燈
led1 = 1;
led2 = 0;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//點(diǎn)亮第二個(gè)燈
led1 = 0;
led2 = 1;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//點(diǎn)亮剩余的燈
//省略……
while(1);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
編譯并下載程序到仿真中,觀察現(xiàn)象發(fā)現(xiàn)只有第二個(gè)燈是亮的??? 什么鬼???
2.1 延時(shí)程序
單片機(jī)的執(zhí)行指令速度非常快,一個(gè)晶振是12MHz的單片機(jī)執(zhí)行一條指令的速度是微秒級(jí)的,所以點(diǎn)亮第一個(gè)燈的時(shí)間太短了,以至于我們根本沒(méi)有察覺(jué)。 因此我們需要一個(gè)延時(shí)的語(yǔ)句。 實(shí)現(xiàn)延時(shí)的方法就是循環(huán)執(zhí)行很多次空指令。程序如下:
//延時(shí)一秒的程序
int i,j;
for(i = 0;i < 110; ++i)
{
for(j = 0; j < 1000; ++j)
{
;//什么也不做
}
}
然后我們就可以把流水燈的程序改成這樣的:
#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
void main()
{
int i,j;
//點(diǎn)亮第一個(gè)燈
led1 = 1;
led2 = 0;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//延時(shí)1秒
for(i = 0;i < 110; ++i)
{
for(j = 0; j < 1000; ++j)
{
;//什么也不做
}
}
//點(diǎn)亮第二個(gè)燈
led1 = 0;
led2 = 1;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//點(diǎn)亮剩余的燈
//省略……
while(1);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
編譯并下載程序到仿真中,觀察現(xiàn)象發(fā)現(xiàn)首先第一個(gè)燈亮,過(guò)了一會(huì)兒第二個(gè)燈亮。
2.2 延時(shí)函數(shù)
我們剩下的任務(wù)就是依次點(diǎn)亮每個(gè)燈,但是每次點(diǎn)亮一個(gè)燈就需要寫(xiě)一段延時(shí)程序,很麻煩! 為了程序的可讀性(toulan),可以把延時(shí)程序?qū)懗梢粋€(gè)子函數(shù),隨時(shí)供我們使用。 C語(yǔ)言中子函數(shù)的定義方式如下
返回值類型 函數(shù)名 (參數(shù)1,參數(shù)2,……)
{
函數(shù)體;
}
這樣我們就可以把延時(shí)函數(shù)寫(xiě)成這樣:
void delay1s()
{
int i,j;
for(i = 0; i<110;++i)
{
for(j = 0; j<1000;++j)
{
//什么也不做
}
}
}
幾點(diǎn)說(shuō)明:
void :因?yàn)樵撗訒r(shí)函數(shù)不需要返回值,所以寫(xiě)為void delay1s :該函數(shù)的函數(shù)名,命名需要符合C語(yǔ)言的標(biāo)識(shí)符命名規(guī)則。() : 不需要傳入?yún)?shù),所以括號(hào)中為空 至此我們可以把流水燈程序?qū)憺橐韵滦问剑?/li>
#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^1;
sbit led3 = P2^2;
sbit led4 = P2^3;
sbit led5 = P2^4;
sbit led6 = P2^5;
sbit led7 = P2^6;
sbit led8 = P2^7;
//延時(shí)1s
void delay1s()
{
int i ,j;
for(i = 0;i<110; ++i){
for(j = 0;j<1000;++j){
;
}
}
}
void main()
{
//點(diǎn)亮第一個(gè)燈
led1 = 1;
led2 = 0;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//延時(shí)1s
delay1s();
//點(diǎn)亮第二個(gè)燈
led1 = 0;
led2 = 1;
led3 = 0;
led4 = 0;
led5 = 0;
led6 = 0;
led7 = 0;
led8 = 0;
//點(diǎn)亮剩余的燈
//省略……
while(1);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
2.3 按字節(jié)尋址
我們可以看到,上面的代碼十分冗長(zhǎng),每次點(diǎn)亮一個(gè)燈需要8條語(yǔ)句,那么如何簡(jiǎn)化? 比如把 led1 = 1;led2 = 0; led3 = 0; led4 = 0; led5 = 0; led6 = 0; led7 = 0; led8 = 0; 這8條語(yǔ)句替代為P2 = 0000 0001 ??? 答案是可以的。代碼如下
unsigned char a = 0x01; //0x01是0000 0001的16進(jìn)制形式
P2 = a;//相當(dāng)于led1 = 1;led2 = 0; led3 = 0; led4 = 0; led5 = 0; led6 = 0; led7 = 0; led8 = 0;
至此,我們可以把流水的代碼優(yōu)化為如下形式:
#include <reg52.h>
//延時(shí)1s
void delay1s()
{
int i ,j;
for(i = 0;i<110; ++i){
for(j = 0;j<1000;++j){
;
}
}
}
void main()
{
unsigned char a1 = 0x01 ; // 0000 0001
unsigned char a2 = 0x02; // 0000 0010
//點(diǎn)亮第一個(gè)燈
P2 = a1;
//延時(shí)1s
delay1s();
//點(diǎn)亮第二個(gè)燈
P2 = a2;
//點(diǎn)亮剩余的燈
//省略……
while(1);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
2.4 邏輯移位
依次點(diǎn)亮8個(gè)燈,每點(diǎn)亮一個(gè)燈都需要一句賦值語(yǔ)句還是很麻煩 。 所以可以使用邏輯移位語(yǔ)句,每次賦值后,將數(shù)值左移一位。 C語(yǔ)言邏輯左移代碼如下:
unsigned char a = 0x01; //a = 0000 0001
unsigned char b = a<<1; // b = 0000 0010
usingned char c = a<<3; //c = 0000 1000
至此,我們可以把流水燈的代碼優(yōu)化如下:
#include <reg52.h>
//延時(shí)1s
void delay1s()
{
int i ,j;
for(i = 0;i<110; ++i){
for(j = 0;j<1000;++j){
;
}
}
}
void main()
{
//初始化
unsigned char a = 0x01;
while(1)
{
//循環(huán)點(diǎn)亮流水燈
P2 = a;
a = a<<1;
delay1s();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
編譯并下載程序到仿真中,觀察現(xiàn)象發(fā)現(xiàn)8個(gè)燈依次亮過(guò)之后不再亮了。
2.5 條件判斷
因?yàn)樵谝莆徊僮髦?,?dāng)變量a 的值為1000 0000 時(shí),再次執(zhí)行左移操作,a 中的1就溢出了,因此a的值變?yōu)?code>0000 0000,此時(shí)我們需要加一個(gè)判斷,使a再次恢復(fù)為0000 0001 C語(yǔ)言中,if條件判斷使用方式如下
當(dāng)判斷條件為真時(shí),執(zhí)行{ } 中的語(yǔ)句。 至此,流水燈代碼可改成如下形式:
#include <reg52.h>
//延時(shí)1s
void delay1s()
{
int i ,j;
for(i = 0;i<110; ++i){
for(j = 0;j<1000;++j){
;
}
}
}
void main()
{
unsigned char a = 0x01;
while(1)
{
if(a == 0x00) //如果高位溢出
{
a = 0x01; //則恢復(fù)
}
//循環(huán)點(diǎn)亮led燈
P2 = a;
a = a<<1;
delay1s();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
|