本次实验使用的是普中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