本次實驗使用的是普中51-單核-A2開發板。
一、原理圖
1.1 單片機核心

1.2 LED模塊

RP9/RP10 是這塊電路板上第幾個排阻的意思。
471是其阻值,47*10^1=470歐姆。
二、程序代碼
2.1 實驗目的
根據原理圖我們可以知道,8個led燈在P2上,低位亮起。
我們可以根據這個原理進行實現各式各樣的跑馬燈。
2.2 編寫程序
2.2.1 亮起1個燈
#include<reg51.h>
void main()
{
P2 = ~0x01;
while(1){}
}
在這個例子中,我們將最低位置1然后取反,也就是將最低位設為0,低電位亮起。
加一個while死循環是為了讓程序困在我們的代碼中,防止跑到未知代碼擾亂電位狀態。

開頭引用的reg51.h其實也沒什么神秘的,在keil中編寫代碼的時候,可以在reg51上面右鍵查看其內容。
我們可以看到這里面無非就是定義了一些端口或者寄存器什么的。
而我們的這個程序就用到了一個P2,所以我們可以直接在程序里面寫而不引用文件嗎?
當然可以的!
所以我們的程序可以寫為:
sfr P2 = 0xA0;
void main()
{
P2 = ~0x01;
while(1){}
}
編譯之后,就可以燒錄進板子了。
2.2.2 亮起兩個燈,再閃一下
要想亮起燈,我們就要把8個燈相應的位置0
| D8 | D7 | D6 | D5 | D4 | D3 | D2 | D1 |
|---|---|---|---|---|---|---|---|
| 8 | 4 | 2 | 1 | 8 | 4 | 2 | 1 |
比如我們想讓兩端的燈亮起,則需要將D8&D1對應的位置0
在這里我們將其設置為0x81然后取反即可。
#include "reg51.h"
void delay(unsigned int z)
{
while(--z);
}
void main()
{
P2 = 0x81;
while(1)
{
delay(10000);
P2 = ~P2;
}
}

2.2.3 跑馬燈
實驗現象:燈左右來回跑動。
程序編寫:使用置0位移實現。
#include "reg51.h"
void delay(unsigned int z)
{
while(--z);
}
void main()
{
P2 = 0xfe;
while(1)
{
P2 <<= 1;
P2 |= 0x01;
delay(10000);
if (P2 == 0x7f)
{
while(1)
{
P2 >>= 1;
P2 |= 0x80;
delay(10000);
if (P2 == 0xfe)
{
break;
}
}
}
}
}
優化版:
#include "reg51.h"
#include "intrins.h"
void delay(unsigned int z)
{
while(--z);
}
void main()
{
unsigned char i;
P2 = ~0x01;
while(1)
{
for(i = 0; i < 7; i++)
{
delay(10000);
P2 = _crol_(P2, 1);
}
for(i = 0; i < 7; i++)
{
delay(10000);
P2 = _cror_(P2, 1);
}
}
}
在此程序中:
P2 = _crol_(P2, 1);
相當於:
P2 = 0x01;
P2 <<= 1;
P2 |= 0x01;
P2 = _cror_(P2, 1)
相當於:
P2 = 0x7f;
P2 >>= 1;
P2 |= 0x80;
2.2.4 其他參考程序
單向跑馬燈:
#include "reg51.h"
#include "intrins.h"
void delay(unsigned int z)
{
while(--z);
}
void main()
{
delay(10000);
// 左循環移位
P2 = _crol_(P2, 1);
// 右循環移位
//P2 = _cror_(P2, 1);
}
雙向跑馬燈:
/**************************************************************************************
實驗現象:下載程序后"LED&交通燈模塊"的D1-D8呈現流水燈效果
接線說明: 單片機-->LED&交通燈模塊(具體接線圖可見開發攻略對應實驗的“實驗現象”章節)
P00-->D1
P01-->D2
...
P07-->D8
注意事項:
***************************************************************************************/
#include "reg52.h" //此文件中定義了單片機的一些特殊功能寄存器
#include<intrins.h> //因為要用到左右移函數,所以加入這個頭文件
typedef unsigned int u16; //對數據類型進行聲明定義
typedef unsigned char u8;
#define led P2 //將P2口定義為led 后面就可以使用led代替P2口
/*******************************************************************************
* 函 數 名 : delay
* 函數功能 : 延時函數,i=1時,大約延時10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 數 名 : main
* 函數功能 : 主函數
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
void main()
{
u8 i;
led=~0x01;
delay(50000); //大約延時450ms
while(1)
{
for(i=0;i<8;i++)
{
P2=~(0x01<<i); //將1右移i位,然后將結果賦值到P2口
delay(50000); //大約延時450ms
}
/* for(i=0;i<7;i++) //將led左移一位
{
led=_crol_(led,1);
delay(50000); //大約延時450ms
}
for(i=0;i<7;i++) //將led右移一位
{
led=_cror_(led,1);
delay(50000); //大約延時450ms
}
*/
}
}
附:reg51.h的內容:
/*--------------------------------------------------------------------------
REG51.H
Header file for generic 80C51 and 80C31 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __REG51_H__
#define __REG51_H__
/* BYTE Register */
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* BIT Register */
/* PSW */
sbit CY = 0xD7;
sbit AC = 0xD6;
sbit F0 = 0xD5;
sbit RS1 = 0xD4;
sbit RS0 = 0xD3;
sbit OV = 0xD2;
sbit P = 0xD0;
/* TCON */
sbit TF1 = 0x8F;
sbit TR1 = 0x8E;
sbit TF0 = 0x8D;
sbit TR0 = 0x8C;
sbit IE1 = 0x8B;
sbit IT1 = 0x8A;
sbit IE0 = 0x89;
sbit IT0 = 0x88;
/* IE */
sbit EA = 0xAF;
sbit ES = 0xAC;
sbit ET1 = 0xAB;
sbit EX1 = 0xAA;
sbit ET0 = 0xA9;
sbit EX0 = 0xA8;
/* IP */
sbit PS = 0xBC;
sbit PT1 = 0xBB;
sbit PX1 = 0xBA;
sbit PT0 = 0xB9;
sbit PX0 = 0xB8;
/* P3 */
sbit RD = 0xB7;
sbit WR = 0xB6;
sbit T1 = 0xB5;
sbit T0 = 0xB4;
sbit INT1 = 0xB3;
sbit INT0 = 0xB2;
sbit TXD = 0xB1;
sbit RXD = 0xB0;
/* SCON */
sbit SM0 = 0x9F;
sbit SM1 = 0x9E;
sbit SM2 = 0x9D;
sbit REN = 0x9C;
sbit TB8 = 0x9B;
sbit RB8 = 0x9A;
sbit TI = 0x99;
sbit RI = 0x98;
#endif
附:reg52.h
/*--------------------------------------------------------------------------
REG52.H
Header file for generic 80C52 and 80C32 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __REG52_H__
#define __REG52_H__
/* BYTE Registers */
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* 8052 Extensions */
sfr T2CON = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2 = 0xCC;
sfr TH2 = 0xCD;
/* BIT Registers */
/* PSW */
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit P = PSW^0; //8052 only
/* TCON */
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;
/* IE */
sbit EA = IE^7;
sbit ET2 = IE^5; //8052 only
sbit ES = IE^4;
sbit ET1 = IE^3;
sbit EX1 = IE^2;
sbit ET0 = IE^1;
sbit EX0 = IE^0;
/* IP */
sbit PT2 = IP^5;
sbit PS = IP^4;
sbit PT1 = IP^3;
sbit PX1 = IP^2;
sbit PT0 = IP^1;
sbit PX0 = IP^0;
/* P3 */
sbit RD = P3^7;
sbit WR = P3^6;
sbit T1 = P3^5;
sbit T0 = P3^4;
sbit INT1 = P3^3;
sbit INT0 = P3^2;
sbit TXD = P3^1;
sbit RXD = P3^0;
/* SCON */
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0;
/* P1 */
sbit T2EX = P1^1; // 8052 only
sbit T2 = P1^0; // 8052 only
/* T2CON */
sbit TF2 = T2CON^7;
sbit EXF2 = T2CON^6;
sbit RCLK = T2CON^5;
sbit TCLK = T2CON^4;
sbit EXEN2 = T2CON^3;
sbit TR2 = T2CON^2;
sbit C_T2 = T2CON^1;
sbit CP_RL2 = T2CON^0;
#endif
附intrins.h
/*--------------------------------------------------------------------------
INTRINS.H
Intrinsic functions for C51.
Copyright (c) 1988-2010 Keil Elektronik GmbH and ARM Germany GmbH
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __INTRINS_H__
#define __INTRINS_H__
#pragma SAVE
#if defined (__CX2__)
#pragma FUNCTIONS(STATIC)
/* intrinsic functions are reentrant, but need static attribute */
#endif
extern void _nop_ (void);
extern bit _testbit_ (bit);
extern unsigned char _cror_ (unsigned char, unsigned char);
extern unsigned int _iror_ (unsigned int, unsigned char);
extern unsigned long _lror_ (unsigned long, unsigned char);
extern unsigned char _crol_ (unsigned char, unsigned char);
extern unsigned int _irol_ (unsigned int, unsigned char);
extern unsigned long _lrol_ (unsigned long, unsigned char);
extern unsigned char _chkfloat_(float);
#if defined (__CX2__)
extern int abs (int);
extern void _illop_ (void);
#endif
#if !defined (__CX2__)
extern void _push_ (unsigned char _sfr);
extern void _pop_ (unsigned char _sfr);
#endif
#pragma RESTORE
#endif
