【51单片机】单片机基础实验程序

 最近在搞单片机,整理一下。


目录

前言

一、51单片机简介

二、点亮第一个LED灯

1.LED模块

2.软件设计

3.设计更新

三、LED流水灯

1.流水灯原理

2.软件设计

3.软件改进

4.灯光设计

 

四、蜂鸣器

1.蜂鸣器模块

2.软件设计

3.演奏乐曲

五、静态数码管

1.如何控制数码管显示字符

2.软件设计

六、动态数码管

1.动态数码管模块

2.软件设计

3.使用数码管告白

七、独立按键

1.独立按键模块

2.软件设计

八、矩阵按键

1.矩阵按键模块

 

参考博客链接


更新日志:5/10 在尝试这些模块的时候我以为我已经了解了单片机,但实际自己操作的时候才发现根本不是这回事。我想外接一个DHT11测温湿度,但是VCC和GND模块根本就不知道要插哪。后来链接上后我又不知道到底测没测数据,于是又接了一个LCD显示屏模块,运行时显示屏虽然亮了但是根本不显示数据,我现在不知道到底是我连线有误还是程序有错,还是测温模块根本就没有工作。

只能说我这些程序只能帮助大家初步了解这些模块都能干些什么,实际上连单片机的皮毛都没摸到。



前言

最近在学习单片机,刚入门也不是很会,就将一些简单的例子整理下来以供参考。如果哪些地方理解的有问题,欢迎大家积极留言,互相交流学习。


 

一、51单片机简介

 

我使用的这个单片机其内核是 STC 公司生产的经典 51 内核芯片 STC89C52,这是一 款拥有 64KB FLASH 超大存储器的 51 单片机,可容纳更大更复杂的程序。

                             80C51芯片管脚图

其内部资源:

  • 8位CPU
  • 4kbytes 程序存储器(ROM)(52为8K)
  • 128bytes 的数据存储器(RAM) (52有256bytes 的RAM)
  • 32条 I/O口线
  • 111条指令,大部分为单字节指令
  • 21个专用寄存器
  • 2个可编程定时/计数器
  • 5个中断源,2个优先级(52有6个)
  • 一个全双工串行通信口
  • 外部数据存储器寻址空间为64kB
  • 外部程序存储器寻址空间为64kB
  • 逻辑操作位寻址功能
  • 双列直插40PinDIP封装
  • 单一+5V电源供电

 

二、点亮第一个LED灯

1.LED模块

                                 8个LED链接单片机P2 IO口上

2.软件设计

#include <reg52.h>
sbit led = P2^0;
void main()
{
	led = 0;
	while(1)
	{
	
	}
	
}

通过将D1端口设置为低电平使其常亮

而main函数中设置一个while循环,在其中执行我们想实现的功能(这个程序中无用)

3.设计更新

#include <reg52.h>
sbit led1 = P2^0;
sbit led2 = P2^2;
sbit led3 = P2^4;
sbit led4 = P2^6;
void main()
{
	led1 = 0;
	led2 = 0;
	led3 = 0;
	led4 = 0;
	while(1)
	{
	
	}
	
}

使D1,D3,D5,D7四个灯常亮

 

三、LED流水灯

1.流水灯原理

         要实现LED的闪烁才能达到流水灯效果。需要设置延时使指示灯先亮一会后熄灭。

 

                                 

2.软件设计

#include <reg52.h>
#include <intrins.h>

typedef unsigned int uint;
typedef unsigned char uchar;

#define led P2
void delay(uint i)
{
	while(i--);
}

void main()
{
	uchar j;
	led = ~0x01;
	delay(50000);
	while(1)
	{
		for(j=0;j<8;j++)
		{
			P2 = ~(0x01<<j);
			delay(50000);
		
		}
	}
}

因为首先将P2口定义为led

而初始赋值是:

led = ~0x01;

就是0xFE

对应二进制 1111 1110,相当于D1=0(赋值低电平,所以会被点亮)

P2 = ~(0x01<<j);

0000 0001 左移一位就是 0000 0010,然后取反就是 1111 1101,这样D2=0(第二个灯就会被点亮)

以此类推达到流水灯的效果,而每次循环都要延时一段时间,这样我们肉眼才能分辨出来。

 

3.软件改进

上面这种形式虽然简单但是很难理解

因此还提供了移位库函数,_crol_() 左移 ,_cror_() 右移

从D1到D8流水灯

#include <reg52.h>
#include <intrins.h>

typedef unsigned int uint;
typedef unsigned char uchar;

#define led P2
void delay(uint i)
{
	while(i--);
}

void main()
{
	uchar j;
	led = ~0x01;
	
	delay(50000);
	while(1)
	{
		for(j=0;j<8;j++)
		{
			led = _crol_(led,1);
			delay(50000);
		
		}
	}
}

从D8到D1流水灯

#include <reg52.h>
#include <intrins.h>

typedef unsigned int uint;
typedef unsigned char uchar;

#define led P2
void delay(uint i)
{
	while(i--);
}

void main()
{
	uchar j;
	led = 0x7F;
	
	delay(50000);
	while(1)
	{
		for(j=0;j<8;j++)
		{
			led = _cror_(led,1);
			delay(50000);
		
		}
	}
}

 

4.灯光设计

根据前面所学的种种知识,可以设计出一个灯光秀了。

#include <reg52.h>
#include <intrins.h>

typedef unsigned int uint;
typedef unsigned char uchar;

#define led P2

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 delay(uint i)
{
	while(i--);
}

void main()
{
	uchar j;
	while(1)
	{


		led1 = 0;
		delay(20000);
		led3 = 0;
		delay(40000);
		led5 =0;
		delay(60000);
		led7 =0;
		delay(80000);
		
		led2 = 0;
		delay(20000);
		led4 = 0;
		delay(40000);
		led6 = 0;
		delay(60000);
		led8 = 0;
		delay(80000);
		
		led = 0xFF;
		delay(50000);
		
		
		led = 0xFE;
		delay(50000);
		
		for(j=0;j<7;j++)
		{
			led = _crol_(led,1);
			delay(50000);
		}
		
		for(j=0;j<7;j++)
		{
			led =_cror_(led,1);
			delay(50000);
		}
		
		led = 0x00;
		delay(50000);
		
		led = 0xFF;
		delay(50000);
	}	
}

 

四、蜂鸣器

1.蜂鸣器模块

我用的这款单片机,蜂鸣器控制管脚接到P1^5 上

2.软件设计

   使蜂鸣器发声

#include <reg52.h>
#include <intrins.h>

typedef unsigned int uint;
typedef unsigned char uchar;

sbit beep = P1^5;

void delay(uint i)
{
	while(i--);
}

void main()
{
	while(1)
	{
		beep = ~beep;
		delay(100);
	}
}
beep = ~beep;
delay(500);

  在循环内对beep进行取反,然后延时一定时间,就是P1^5间隔一定时间输出高低电平,以此产生脉冲信号。更改延时时间能达到不同的发生效果。

 

3.演奏乐曲

因为不太清楚音调和节拍应该怎么设置,没法实践,这个例子是我网上找的

大家如果感兴趣可以自己试试,也可以教教我。

 

《生日快乐》歌

#include <reg51.h>
typedef unsigned int uint; 
typedef unsigned char uchar;

sbit beep = P1^5;

uchar code SONG_TONE[]={212,212,190,212,159,169,212,212,190,212,142,159,212,212,106,126,159,169,190,119,119,126,159,142,159,0};
uchar code SONG_LONG[]={9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0};


void DelayMS(uint x)
{
     uchar t;
     while(x--)
		 {
				for(t=0;t<120;t++);
		 }
			 
}

void PlayMusic()
{
     uint i=0,j,k;
     while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
 {   
     for(j=0;j<SONG_LONG[i]*20;j++)  
   {
         beep=~beep;
         for(k=0;k<SONG_TONE[i]/3;k++);
   }
    DelayMS(10);
    i++;
 }
}

void main()
{
    beep=0;
    while(1)
    {
        PlayMusic(); 
        DelayMS(500); 
    }
}

五、静态数码管

1.如何控制数码管显示字符

对于每一个晶体管,当给其赋值1就是点亮,然后再以16进制输出就好。

 

 

2.软件设计

使一个数码管输出0

#include <reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;

//0-F
uchar code smgduan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void main()
{
	LSA = 0;
	LSB = 0;
	LSC = 0;
	P0 = smgduan[0];
	while(1)
	{
		
	}
}

 

六、动态数码管

1.动态数码管模块

动态数码管就是在静态的基础上,输出多个字符

2.软件设计

因为我们采用了138译码器实现

因此根据下图真值表可以控制如何点亮数码管(低电平时点亮)

数码管输出0-7

#include <reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;

uchar code smgduan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};

void delay(uint i)
{
	while(i--);
}

void Display()
{
	uchar j;
	for(j=0;j<8;j++)
	{
		switch(j)
		{
			case(0):
				LSA = 0;LSB = 0;LSC = 0;break;
			case(1):
				LSA = 1;LSB = 0;LSC = 0;break;
			case(2):
				LSA = 0;LSB = 1;LSC = 0;break;
			case(3):
				LSA = 1;LSB = 1;LSC = 0;break;
			case(4):
				LSA = 0;LSB = 0;LSC = 1;break;
			case(5):
				LSA = 1;LSB = 0;LSC = 1;break;
			case(6):
				LSA = 0;LSB = 1;LSC = 1;break;
			case(7):
				LSA = 1;LSB = 1;LSC = 1;break;
				
		}
		P0=smgduan[j];
		delay(100);
		P0=0x00;
	
	}
}
void main()
{
	
	while(1)
	{
		Display();
	}
}

 

3.使用数码管告白

#include <reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;

uchar code smgduan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};

void delay(uint i)
{
	while(i--);
}

void Display()
{
	uchar j;
	for(j=0;j<8;j++)
	{
		switch(j)
		{
			case(0):
				LSA = 0;LSB = 0;LSC = 0;break;
			case(1):
				LSA = 1;LSB = 0;LSC = 0;break;
			case(2):
				LSA = 0;LSB = 1;LSC = 0;break;
			case(3):
				LSA = 1;LSB = 1;LSC = 0;break;
			case(4):
				LSA = 0;LSB = 0;LSC = 1;break;
			case(5):
				LSA = 1;LSB = 0;LSC = 1;break;
			case(6):
				LSA = 0;LSB = 1;LSC = 1;break;
			case(7):
				LSA = 1;LSB = 1;LSC = 1;break;
				
		}
		switch(j)
		{
			case(0):
				P0=smgduan[0];break;
			case(1):
				P0=smgduan[2];break;
			case(2):
				P0=smgduan[5];break;
			case(3):
				P0=smgduan[16];break;
			case(4):
				P0=smgduan[4];break;
			case(5):
				P0=smgduan[1];break;
			case(6):
				P0=smgduan[3];break;
			case(7):
				P0=smgduan[1];break;
		}
		
		delay(100);
		P0=0x00;
	
	}
}
void main()
{
	
	while(1)
	{
		Display();
	}
}

七、独立按键

1.独立按键模块

可以看出其管脚为P30-P33

2.软件设计

使用不同按键控制不同小灯泡点亮与熄灭

#include <reg52.h>
#include <intrins.h>

typedef unsigned char uchar;
typedef unsigned int uint;

sbit K1 = P3^1;
//sbit K2 = P3^0;
sbit K3 = P3^2;
sbit K4 = P3^3;

sbit Led1 = P2^0;
//sbit Led2 = P2^1;
sbit Led3 = P2^2;
sbit Led4 = P2^3;

void delay(uint i)
{
	while(i--);
}


void keypros()
{
	if(K1 == 0)
	{
		delay(1000);
		if(K1 == 0)
		{
			Led1 =~Led1;
		}
		while(!K1);
		
	}
	
	/*if(K2 == 0)
	{
		delay(1000);
		if(K2 == 0)
		{
			Led2 =~Led2;
		}
		while(!K2);
		
	}
	*/
	
	
	if(K3 == 0)
	{
		delay(1000);
		if(K3 == 0)
		{
			Led3 =~Led3;
		}
		while(!K3);
		
	}
	
	if(K4 == 0)
	{
		delay(1000);
		if(K4 == 0)
		{
			Led4 =~Led4;
		}
		while(!K4);
		
	}
}

void main()
{
	Led1 = 1;
	//Led2 = 1;
	Led3 = 1;
	Led4 = 1;
	while(1)
	{
		keypros();
	}
}

实验的时候发现,如果联通K2按键,会对其他按键造成短路,而其他按键之间不会受到影响。

 

为什么对按键的判断需要双重if?

if(K1 == 0)
	{
		delay(1000);
		if(K1 == 0)

以为按下和释放的时候波形都是不稳定的,需要判断其稳定后的情况,避免不准确

八、矩阵按键

1.矩阵按键模块

无论是独立键盘还是矩阵键盘,单片机检测其是否被按下的依据都是一样 的,也就是检测与该键对应的 I/O 口是否为低电平。独立键盘有一端固定为低 电平,单片机写程序检测时比较方便。而矩阵键盘两端都与单片机 I/O 口相连, 因此在检测时需编程通过单片机 I/O 口送出低电平。

 

 


参考博客链接

1.单片机——蜂鸣器(生日快乐歌)_liu1910260504的博客-CSDN博客_蜂鸣器生日快乐

2. 蜂鸣器奏乐:https://www.cnblogs.com/xiaowuyi/p/3343757.html 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值