学会了C语言,从零开始单片机2

从这里开始我们需要来看原理图和写代码了哦。

新手会比较懵(我目前也是新手,我确实很懵),所以我会用两个单片机对比着学习,一个是我自己的板,一个是B站up主@江协科技 的板。

三、LED模块

LED与单片机核心板是直接连接的,所以写在核心板上的代码才能控制到LED。

stc89C52:单片机的21~28连接着LED的D1~D8灯。

电阻是1kΩ,用来减少电流保护电路不那么容易烧坏。

stc89c52rc:单片机的21~28连接着LED的D1~D8灯。

电阻是470Ω,用来减少电流保护电路不那么容易烧坏。(读数方法,不想说太多抽象理论,直接以这个为例子说明:471,最后一个数字1表示10的1次幂,剩下的数字直接乘,即47×10¹Ω。如果是473就是47×10³Ω)


代码首先控制的是单片机,然后单片机再控制各种器件。要控制LED模组,实际上控制的是单片机的P2.0~P2.7。

1.点亮一个LED

从物理上看,灯泡发光是因为灯泡两端有电势差,驱动电子运动形成电流,电流使了灯泡发光(这里解释得不够严谨具体,主要是高考完我物理已经忘得差不多了,等我有时间再学清楚再来解释)

由原理图看出,LED的一端由电源正极(5V,理解为一种规范吧,我理解是单片机都用5V和0V表示正负极)控制,我们的单片机只能控制另一端为5V或0V。

二进制里面一般1代表有/真,0代表无/假。这里”有“只有一种情况就是5V,所以1代表输入5V,0代表输入0V。

想要灯泡发光就要有电势差,一段是电源正极5V,另一端之只能是0V,即1代表灭灯,0代表亮灯。不过要用十六进制表示,理论不好解释,直接给例子:

#include <REGX52.H>

int main()
{
	P2=0xFE;//1111 1110
}

这里解释一下,二进制数字的顺序对应的LED编号是从右往左算的,即上面代码最右边的LED为0发光,亮的是D1灯,即第一个灯D1是最右边的一个数字。但是实际单片机开发板上的LED排列没有固定是从左往右还是从右到左,上面的代码只能决定亮的是D1灯,但D1灯再开发板上的实物可能是第一个灯也可能是第八个灯。

#include <REGX52.H>

int main()
{
	P2=0xFE;//1111 1110
	while(1)
	{}
}

这段代码和上面的代码基本一样,唯一的区别是上面的代码是不断地开始结束开始结束;而下面的代码开始后进入了死循环,除非手动关机否则不会自主结束。

2.延时:即代码运行的时间长度

为什么要用到延时呢?

我们要实现灯泡闪烁,可进行的操作是“先执行亮的代码,再执行暗的代码,两行代码循环运行”。这是正常的思路,简单的思路,正确的思路,唯一的不足是没有考虑到现实世界物理世界的硬件缺陷。这款单片机的频率是12MHz,它一次亮暗由于速度太快无法被人眼察觉,再循环下次人依旧无法察觉。

因此我们需要延时,这名字起得不好,不顾名思义,它并不延迟时间,而是持续时间(强行解释的话就是延迟结束的时刻,太勉强了,咱实干家不玩文字游戏)。

延时代码可以直接用STC-ISP生成,注意下面圈圈起来的地方。想要代码持续多长时间就在“定时长度”里写数字。

#include <REGX52.H>
#include <INTRINS.H>

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

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

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

注意这里新加了一个头文件,主要应对的是延时代码里的_nop_函数。

利用亮与暗的延时,可以实现灯泡闪烁;要实现灯泡轮流亮起(流水灯)也是同样的道理。

#include <REGX52.H>
#include <INTRINS.H>

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

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


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

这里有个弊端,就是每次延时都需要靠软件生成,比较麻烦。如何改进呢?我们做一个考虑,就是让一个1ms的延时循环执行n次就得到了nms的延时。

#include <REGX52.H>

void Delay1ms(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}


}

int 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);
	}
}

这里循环条件是xms,每执行一次xms自减1,直到为0时结束循环。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值