【单片机/普中A2】学习笔记2-LED

点亮一个 LED

电阻的表示形式

如电阻 103,表示 10x10^3,即 10000 欧姆

同理,473 表示 47000 欧姆


编写程序

【单片机/普中A2】学习笔记2-LED_第1张图片

点击上图所示按钮,进入 options for target1

在 output 选项卡勾选 create hex file
这样每次 build 后都会自动生成 hex 文件,方便我们直接调试


【单片机/普中A2】学习笔记2-LED_第2张图片

source group1 下新建 main.c 文件,作为我们的主入口;
每个工程都必须存在一个主入口


main.c 代码清单

#include 

// 主入口
void main(){
	// 1表示高电平,0表示低电平,低电平亮灯
	// 由于有8个LED,故1111 1110表示7个关灯,一个亮灯
	P2=0xFE; // 对应二进制1111 1110
}

LED 闪烁

生成延迟函数

STC-ISP 自带了一个帮我们生成延迟函数的小工具

按下图所示找到该工具,下面是我们需要注意的几个关键点

  1. 系统频率:查看自己开发板中晶振频率,一般会写在上面
  2. 定时长度
  3. 8051 指令集:选择 STC-Y1 指令集,因为这个刚好对应 STC89C52

【单片机/普中A2】学习笔记2-LED_第3张图片


main.c

#include 
#include  // 注意哦,这里导入了一个新的头文件

// 生成的延迟函数
void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
	// 在循环中调用延迟函数,实现灯泡闪烁
	while(1)
	{
		P2=0xFE;
		Delay500ms();
		P2=0xFF;
		Delay500ms();
	}
}

流水灯

#include 
#include 

void Delay1ms(unsigned int xms);

void main()
{
	while(1)
	{
		P2=0xFE;//1111 1110
		Delay1ms(1000);
		P2=0xFD;//1111 1101
		Delay1ms(1000);
		P2=0xFB;//1111 1011
		Delay1ms(100);
		P2=0xF7;//1111 0111
		Delay1ms(100);
		P2=0xEF;//1110 1111
		Delay1ms(100);
		P2=0xDF;//1101 1111
		Delay1ms(100);
		P2=0xBF;//1011 1111
		Delay1ms(100);
		P2=0x7F;//0111 1111
		Delay1ms(100);
	}
}

void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


按键控制 LED 亮灭

sbit 分析

在头文件 REGX52.H 中,已经预定义好了各个引脚所对应的十六位值

譬如下图所示开发板的四个按钮原理图,他们分别对应 P3_1 P3_2 P3_3 P3_4

【单片机/普中A2】学习笔记2-LED_第4张图片


简单控制

#include 

void main()
{
	while(1)
	{
		// 通过预定义寄存器获取P32口对应电平
		// 0为低电平,即按钮按下时
		if(P3_1==0)
		{
			// 按钮按下时切换对应LED为低电平,此时灯亮
			P2_0=0;
		}
		else
		{
			// 否则切换为高电平,此时灯灭
			P2_0=1;
		}
	}
}

开关记忆

按键模块在使用的过程中存在三种状态:

  • 5-10ms 的按下态
  • 任意时长的持续按下态
  • 5-10ms 的松开态

我们需要做的是为按下态和松开态做防抖处理,以实现该效果:
按下按钮后松开才改变 LED 电平,而不是在使用按键的整个过程中改变电平!

#include 

// 可修改时长的延迟函数
void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;

	while(xms)
	{
		i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
	xms--;
	}
}


void main()
{
	while(1)
	{
		// 检测到按下按键
		if(P3_1==0)
		{
			// 延迟20ms,按下防抖
			Delay(20);
			// 阻塞线程,此刻为持续按下状态
			while(P3_1==0);
			// 延迟20ms,松开防抖
			Delay(20);

			// 最后直接取反,避免else编写重复逻辑
			P2_0=~P2_0;
		}
	}
}

LED 逐个亮灭

二进制知识

众所周知,点亮第一盏灯需要设置二进制为:1111 1110
则不难得出结论,上述二进制可以由 0000 0001 取反而来

所以从 0000 0001 开始,每次都左移位一次,然后取反,就可以完美的实现按顺序点亮 LED 的效果啦~

譬如如下过程

  1. 当前点亮第一盏灯,此时为 0000 0001
  2. 左移位一次,此时为 0000 0010
  3. 对其取反,得到 1111 1101,此时点亮第二盏灯

源码

这里定义了一个全局变量 LEDNumber,用来记录当前移位的长度(以此来决定需要点亮那一盏灯)

依然使用十六进制表示,0x01 表示 0000 0001

#include 

// 全局变量存储移位长度
unsigned char LEDNumber=0;

void Delay(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;

	while(xms--)
	{
		i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
	}
}

void main()
{

	while(1)
	{
		if(P3_1==0)
		{
			Delay(20);
			while(P3_1==0);
			Delay(20);

			// 首先序号+1
			LEDNumber++;
			// 假如序号大于等于8,表示已经移位到最后一个灯,此时需要执行复位操作
			if(LEDNumber>=8)
			{
				// 复位,回归零点
				LEDNumber=0;
			}

			// 按照上述原理,得出根据0x01进行移位后直接取反,点亮LED
			P2=~(0x01<<LEDNumber);
		}

		// 如法炮制一个递减点亮LED的判断语句
		if(P3_0==0)
		{
			Delay(20);
			while(P3_0==0);
			Delay(20);

			LEDNumber--;
			if(LEDNumber==0)
			{
				LEDNumber=7;
			}
			P2=~(0x01<<LEDNumber);
		}
	}
}

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