Autoleaders控制组——51单片机学习笔记(1)

51单片机

目录

51单片机

1.单片机基础

1-1.内部构成

1-2.51单片机

2.LED

2-1.点亮一个LED

2-2.LED闪烁

2-3.LED流水灯

2.独立按键控制LED

2-1 独立按键控制LED亮灭

2-2 按键的抖动

2-4独立按键控制LED状态

2-5独立按键控制LED展示二进制

3.数码管

3-1.静态数码管

假设数码管连接方式为 共阴极连接,如果上数码管显示 数字6 ?

3-2.动态数码管


1.单片机基础

1-1.内部构成

CPU、RAM、ROM、定时器、中断系统、通讯接口等

相当于袖珍版计算机,一个芯片能构成完整的计算机系统

1-2.51单片机

公司:STC公司

位数:8位

RAM:512字节 第二天丢失 相当于电脑内存条

ROM:8k(Flash) 长期储存 相当于电脑硬盘

ROM是read only memory;RAM是random access memory;

工作频率:12MHz

2.LED

LED:

中;发光二极管

英:Light Emitting Diode

图像如下:

Autoleaders控制组——51单片机学习笔记(1)_第1张图片

2-1.点亮一个LED

2-1-1.电阻

电阻表示方式:

102 = 1K => 10 00

473 => 47*10^3

电阻作用:

限流

2-1-2.点亮方式

原理:

改变每个二极管输出的高低电频

(高电频亮,低不亮)

方式;

通过CPU控制寄存器来控制硬件电路,由此控制电频

2-1-3.程序

注意:在C语言中不能直接输入二进制,必须进制转换——二转十六

例:

想让第一个灯亮的话,寄存器对应的是

1111 1110 转16进制就是 0xFE
Autoleaders控制组——51单片机学习笔记(1)_第2张图片

void main()
{
	P2=0xFE;
}

但编译不会成功,因为缺少头文件。

注:当延时函数中出现 nop() 时;

函数头加上 #include

所以:

#include 

void main()
{
	P2=0xFE;
}

这时编译就成功了!

eg:在用STC-ISP时,需要在编译后下载一个hex file

随后在STC-ISP上下载编程就可以啦

(注意:需要重新启动单片机LED才会亮)

2-2.LED闪烁

因为需要LED闪烁,我们只需让程序进入一个亮灭的循环——while循环就行了。

#include 

void main()
{
	while(1)
	{
		P2 = 0xFE;
		P2 = 0xFF;
	}
}

其余方法见“点亮一个LED”。

但是你执行完之后发现灯一直在亮,一看程序又没什么问题。

那么,问题出在哪里呢?

答案是单片机的速度问题。其实单片机上的LED灯在闪,但是由于速度太快,肉眼无法观测到。

由此可知,我们需要每执行完一行后延时500ms,这个可以在STC-ISP内执行。

执行方式:

在STC-ISP中找到软件延时计算器,然后选择需要延迟的时间(注意:需要根据自己单片机的型号和频率更改所涉频率以及指令集)。设定完后会出现一段代码,将这段代码复制至刚刚所写的程序中即可。

到这儿就结束了吗?显然没有。复制完代码段后,还要写一个它所属的头文件,这样才能进行编译,到这里程序才完全结束。

2-3.LED流水灯

普通方案,复制粘贴,在上述LED闪烁的while循环中设置八个灯依次闪烁的程序,内容如下。

#include 
#include 

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	while(1)
	{
		P2=0xFE;
		Delay500ms();
		P2=0xFD;
		Delay500ms();
		P2=0xFB;
		Delay500ms();
		P2=0xF7;
		Delay500ms();
		P2=0xEF;
		Delay500ms();
		P2=0xDF;
		Delay500ms();
		P2=0xBF;
		Delay500ms();
		P2=0x7F;
		Delay500ms();
	}
}

但这种方案仍有弊端——每次只能设置一次闪烁的时间间隔。但如果我们给一个函数,只需要在程序中给一个参数就可以修改间隔时间,那将会更加简便。

我们还是将延时函数复制下来,区别是,我们需要设置一个变量,例如:

void Delay1ms(unsigned int xms)

这时我们就有一个可以定义时间的参数。

下一步时修改程序,我们应该设置一个循环,没换一次时间它都能执行:

unsigned char i, j;
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}

随后函数写入使用即可。

2.独立按键控制LED

2-1 独立按键控制LED亮灭

单片机的按键可以改变电频,不按下是高电频,按下后是低电频。按键的按下与松开由寄存器来识别

#include 

void main()
{
	while(1)
	{	
		if(P3_1==0)
		{
			P2_0=0;
		}
		else
		{
			P2_0=1;
		}
	}
}

C51数据运算

0001 1110>>1 -> 0000 1111

0011 1100<<1 -> 0111 1000

按位异与(或):

0001 1000 & 0010 1010 -> 0000 1000

0001 1000 | 0010 1010 -> 0011 1010

按位异或:

0001 1000 ^ 0010 1010 -> 0011 0010(一样是0,不一样是1)

按位取反:

~0001 1000 -> 1110 0111

2-2 按键的抖动

Autoleaders控制组——51单片机学习笔记(1)_第3张图片

按键按下时会有抖动,大概在10-15ms,为了规避这个对按键按下的影响,所以定义了一个Delay函数,并对其进行调用。

Delay(20);          
while(P3_1==0);    	                      
Delay(20);

按键消抖一般分为4步:

1、判断按键是否按下
2、消抖
3、再次判断按键是否按下
4、等待按键松开

### 2-3独立按键控制LED二进制显示

```c
#include 
#include 
void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms){
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
 
 
void main(){    
	unsigned char LEDnum=0;         //引入变量
	while(1){
		if(P3_1==0){
		    Delay(20);          //通过delay去抖
		    while(P3_1==0);     //while作用:
	                        //按键启动if循环,松手走出while循环,运行下一步代码
			Delay(20);
			LEDnum++;      //16进制0,1,2,3,4
			P2=~LEDnum;    //取反
		}
	}

2-4独立按键控制LED状态

#include 
 
void Delay(unsigned int xms)		//@12.000MHz
{
	while(xms)
	{
			unsigned char i, j;
 
	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
	xms--;
	}
 
}
 
void main()
{
	while (1)
	{
		if (P3_1 == 0)
		{
			Delay(20);
			while (P3_1 == 0)
			{
 
			}
			Delay(20);
			P2_0 = ~P2_0;
		}
	}
}

此程序表现为按一次亮,再按一次灭。(运用按位取反来实现)

2-5独立按键控制LED展示二进制

#include 
#include 
void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms){
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
 
 
void main(){
 
	unsigned char LEDnum=0;
	while(1){
		if(P3_1==0){
			Delay(20);
			while(P3_1==0);   
			Delay(20);
			
			if(LEDnum>=8){    
				LEDnum=0;
			}
			//LEDnum=1   0000 0001---0000 0010  取反1111 1101 
			P2=~(0x01<

此处主要运用移位运算方式。

3.数码管

3-1.静态数码管

3-1-1.一位数码管

Autoleaders控制组——51单片机学习笔记(1)_第4张图片
Autoleaders控制组——51单片机学习笔记(1)_第5张图片

上图为 一位数码管,数码管有两种连接方式(对应 右边上下两幅图);

右上图的原理图,8个LED的阴极都连在一个引脚上,称为共阴极连接;

右下图的原理图,8个LED的阳极都连在一个引脚上,称为共阳极连接;

Autoleaders控制组——51单片机学习笔记(1)_第6张图片

左下角的 左边图片 ,定义了8个LED的名称;

左下角的 右边图片 ,定义了引脚的名称,与右图的引脚名称一一对应

假设数码管连接方式为 共阳极连接,观察可以发现,数码管中的 LED 的引脚引出,使用的是就近原则

假设数码管连接方式为 共阴极连接,如果上数码管显示 数字6 ?

要让数码管显示 数字6,让要 LED-A、C、D、E、F、G亮起;

共阴极的公共端 要接地(给数据‘0’,或者是低电平);

阳极(称为位选端)根据LED的亮灭需求给 数据0或1(1亮、0灭) ,称为 段码(阳码) (1011 1110 即为段码);

如果 共阳极连接,共阳极端 要接到 VCC(高电平),阴极给 数据0或1 (1灭,0亮),称为 段码(阴码),和共阴极正好是相反关系;
Autoleaders控制组——51单片机学习笔记(1)_第7张图片

共阳极连接→共阳极端接VCC并选中→阴极(位选端)传递(阴码)段码(1亮、0灭)→数码管显示共阴极连接→共阴极端接GND并选中→阳极(位选端)传递(阳码)段码(1灭、0亮)→数码管显示

3-1-2.四位一体数码管

Autoleaders控制组——51单片机学习笔记(1)_第8张图片

开发板上即为 四位一体的数码管,且有两个,正好组成了 八位数码管;

2.四位数码管,(每位的公共端 单独引出来,位选端全部连在一起(所有A段连在一起、所有B段连在一起……),总共有12个引脚;

代码:让数码管第三位显示6

#include 
void main()
{
	P2_4=1;
	P2_3=0;
	P2_2=1;
	P0=0x7D;
	while(1)
	{
	}
}

3-2.动态数码管

发现这样一个现象,数码管无法在同一时间显示多个数字,其在同一时刻下只能有一个显示,

只有一个数码管能被点亮,即使有多个被选中的数码管,显示的数字也是相同的;

那么如何让数码管多位显示不同数字(动态数码管显示)?

利用人眼视觉的暂留 和 数码管显示的余辉 的原理

先让第一位数码管显示1,然后很快地让第二位数码管显示2,再很快地让第三位数码管显示3,
让它不断地扫描,重复显示1、2、3的过程,这样三个数字就“同时”显示了;

Autoleaders控制组——51单片机学习笔记(1)_第9张图片

如图,数码管连接方式为 共阴极连接,这样传输数据,就能让第三位显示 数字1 了;

而上面的 LED1 ~ 8,其实接在了138译码器的输出端,138译码器正好可以实现让LED1 ~ 8输出 0或1.

你可能感兴趣的:(单片机,嵌入式硬件)