星星点灯(二)-LED点灯中阶

经过千辛万苦,在上一章《星星点灯(一)-LED点灯初阶》我们终于把LED点亮了,丑是丑了点,但是总是有进步嘛!万丈高楼平地起,有了这个基础,只要我们本着不抛弃,不放弃的精神,来个打破砂锅问到底,我想就会百尺竿头更进一步的。
本章,我们把丑小鸭打扮一下,看看能不能离白天鹅更像一点。
第一步:代码模块化
我们把I/O初始化的代码独立出去,为以后驱动更多的LED做准备,而且由于各种硬件限制原因,可能驱动LED的端口并没有集中到一个顺序的端口,PA有几个,PB有几个等等。那就需要分别的初始化它。
这样我们把实现代码分离出来后,上层调用就不需要做任何的修改,只需要完成底层函数的修改就可以达到这个目的。
把调用和实现分离,这是实现模块化编写代码的第一步。

void LedInit(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);	
}

同样的,我们把延时函数写成一个通用的函数,就像这样:

void DelayMS(UINT32 ms)
{
	volatile UINT32 i,j; //注意这个变量一定要用volatile 声明,否则编译器会给你优化掉的。
	for(i = 0;i < ms;i++)
	{
		for(j = 0;j < 10 * 800;j++);
	}
}

第二步 把宏定义修理一下

还记得那个奇丑无比的LEDON吗?如果非得定义宏(比如一个系统只有一颗LED)的方式来操作LED的功能,那至少我们可以这样来定义它,使他看起来更加绅士一些:

//定义宏
#define LedOn()		(GPIOB->BRR = GPIO_Pin_14)
#define LedOff()	(GPIOB->BSRR= GPIO_Pin_14)

//调用宏
LedOn();
LedOff();

这有什么好处呢?
第一.它至少看起来像一个正常的语句了。
第二.为什么我们不用全部大写的方式来定义宏呢?这样的好处就是当有一天我后悔了,我要用函数的方式来实现这个LedOn()的功能,我只需要去掉宏的定义,用如下的函数去实现就可以了,但是调用的地方却不需要做任何修改。
是不是很有智慧的方式啊,你学会了吗?

void LedOn(void)
{
	GPIOB->BRR = GPIO_Pin_14;
}

好了,现在我们的点灯程序,有这些模块的支持,我们就比较简洁清爽了,如下:

void main(void)
{
	LedInit();
	while(1)
	{
		LedOn();
		DelayMS(500);
		LedOff();
		DelayMS(500);
	}
}

现在是不是看起来比较心情愉悦了很多啊?
我们把实现细节对调用者隐藏起来,比如LedInit()函数,把需要变化的参数,用函数传递参数的方式传入来实现调用和实现的分离,这就是函数的模块化最简单的实现。
函数模块化的好处是便于以后上层代码的移植,我们需要更换到其他芯片去实现的时候,上层逻辑就不用再去实现,只要把对应的底层驱动重新编写,就能达到移植的目的。

上面的代码现在还有没有什么缺陷呢?
那就是DelayMS(500)这个函数,我们总不能让CPU就在这里干等,啥事情都不干吧?要干其他事情吧,又怎么去保证LED点亮的延迟时间呢?这真是一个头疼的地方。
中断,对,你第一印象想到的就是中断,在中断里面计数,然后计数到了再点亮或者熄灭LED。大概就是下面这样子:

//1ms的中断程序
static int LedCnt = 0;
static int LedStatus = 0;
void TimerInt(void)
{
	if(++LedCnt > 500)
	{
		if(LedStatus == 0)
			LedOn();
		else
			LedOff();
		LedStatus  = ~LedStatus;
	}
}

没毛病,点亮一个LED也对了,在加上一些使能的条件也就差不多了。但是,也就是但是,现在要点亮更多的灯呢?还要玩几个花式呢?又傻眼了吧!系统里面还有按键,还有好多其他的事情,难道都在中断里面去扔一大堆变量?
显然,这是一个不可能完成的任务,如何来解决?请听下回分解。
大致思路提示:
1.消息队列
2.软定时器
3.LED操作函数的修改
在这里插入图片描述

发布了18 篇原创文章 · 获赞 7 · 访问量 5655

猜你喜欢

转载自blog.csdn.net/huangbinvip/article/details/104930980