单片机零基础入门(9-1)实战:模块化编程(模块化两个案例含源码--以及无法显示头文件(.h)的解决方案)

单片机零基础入门(9-1)实战:模块化编程—(以及无法显示头文件(.h)的解决方案)

本文作为单片机零基础入门(8-5)模块化编程的拓展和补充,比前面的单片机零基础入门(8-5)模块化编程更为详细。

一、回顾

上篇文章,单片机零基础入门(8-4)实战:单片机动态数码管消影—附源代码。
解决了问题:如果多个位置显示不同的数字,就会出现字影,而不是清晰的显示对应的数字。

本节内容主要是:C语言预编译、如何创建工程文件、如何添加模块化编程文件、没有显示头文件(.h文件)的解决方案。

文末有两个案例(含源代码和原理图):
案例1:利用模块化利用LED灯写一个流水灯(逐个引脚定义使用版)。
案例2:利用模块化利用LED灯写一个流水灯(使用一个P2搞定所有的引脚)。



二、问题<模块化编程的来源>:

每个人的编程习惯不一样,编程风格不一样,所以会导致有时候阅读代码很吃力。在实际工作过程中,代码维护起来也不方便,后期项目升级或者变更,也会造成更多时间的浪费。这时候,就需要一个可以让代码看起来更规范,更整洁的规则,他就是:模块化编程
当我们把代码根据模块来编写后,会大大降低阅读代码的人的困难,提高效率,也便于后期的维护或升级。

本节解决题目:把“Delay.c”文件独立出来写,在主函数里面调用一个“Delay.h”文件,既可实现点亮LED灯。实现模块化编程



二、传统编程和模块化编程:

传统方式编程:所有的函数均放在main.c里,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码的组织和管理,而且很影响编程者的思路。
模块化编程:把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要#include "XXX.h"文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等。



三、模块化编程的框图示例和详解

在这里插入图片描述

1、模块化编程的操作

模块化编程仅需要在工程中新建一个.c文件,将需要实现某个功能的模块代码(函数的主体)放到.c里面,将函数的声明放到对应的.h里面。最后调用时,仅仅需要调用.h文件声明一下就行了。


2、注意事项:

(1).c文件:函数、变量的定义。
(2).h文件:可被外部调用的函数、变量的声明。

(3)任何自定义的变量、函数在调用前必须有定义或声明(同一个.c)。
(4)使用到的自定义函数的.c文件必须添加到工程参与编译。
(5)使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录、安装目录、自定义)。


3、C语言预编译

C语言的预编译以#开头,作用是在真正的编译开始之前,对代码做一些处理(预编译)

预编译意义
#include<REGX52.H>把REGX52.H文件的内容搬到此处
#define PI 3.14定义PI,将PI替换成3.14
#define ABC定义ABC
ifndef XX_H如果没有定义_XX_H_
#endif与#ifndef,#if匹配,组成“括号”

在这里插入图片描述

此外还有#ifdef,#if,#else,#elif,#undef等
注:

//例子1:
#ifdef AAA 
int a=1#endif

//如果定义了AAA,“int a=1”才会参与编译。
//例子2
#define AAA  //定义AAA
#ifdef AAA   
int b=0//int b=0参与编译
#endif

//#define定义AAA,#ifdef判断(是否)定义了AAA,int b=0参与编译,#endif结束。


四、创建模块化文件步骤:

1、创建main.c文件

步骤1、创建新项目:

打开keil----创建新项目,点击创建新工程。

在这里插入图片描述

步骤2、选择项目创建的文件夹

在文件名写项目名称(注意,不要填写中文)
在这里插入图片描述

步骤3、选择单片机的芯片

选择对应单片机的芯片(开发板的芯片,我这里是AT89C51.),点击“OK”

在这里插入图片描述

步骤4、展开项目

点击“Target 1”展开“Source Group 1”
在这里插入图片描述

步骤5、新建.C文件

鼠标右击“Source Group 1”,点击“Add New Item toGroup “Source Group 1”…”(可以理解为:在“Source Group 1”的文件夹里面创建新文件)。

在这里插入图片描述

步骤6、创建主函数

选择“.c”文件,命名为“main”,点击“Add”。
在这里插入图片描述

步骤7、查看添加成功的主函数

查看main.c文件已经添加成功,在main.c中添加头文件(#include <REGX51.H>),然后先把框架搭建好,查看编译是否有问题。
在这里插入图片描述
在这里插入图片描述

2、添加Delay.c和Delay.h文件

步骤同前面“创建main.c”。

2.1、添加Delay.c文件

步骤和创建main.c文件一致,就不一一赘述,详细步骤看截图。

加粗样式
在这里插入图片描述


2.2、添加Delay.h文件

步骤也是和前面添加.c文件一样,就不一一赘述,但是,注意,这次创建的.h文件,所以创建时选择“Header File (.h)”文件

在这里插入图片描述

注意:
1、创建头文件时,需要选择“Header File (.h)”文件。
2、命名时,和对应的.c文件命名一致。


3、问题:无法显示头文件??不存在刚刚添加的.h怎么办?

问题:当完成2.2的步骤时,竟然意外发现Delay.h文件没有展示出来,到底怎么回事呢??如下图:
在这里插入图片描述

别怕!!!!
解决方案来啦:
点击烟花旁边的小魔方,再点击添加文件,找到此目录下的.h文件,确定既可。如下图:

步骤1、 点击工具栏的小魔方,点击添加文件(Add files)。如下图:

在这里插入图片描述
步骤2、 文件类型选择"."也就是所有类型文件,最后选择需要添加的头文件“Delay.h”文件。如下图:

在这里插入图片描述

步骤3、 最后:查看列表,此时缺少的头文件显示在列表内了。如下图:

在这里插入图片描述

到此,又完美解决一个问题。



五、模块化编程实例:

1、头文件的编写:

Delay.h文件添加成功后,里面填写什么内容?代码如下:
Delay.h文件里面固定内容如下:

#ifndef _DELAY_H_
#define _DELAY_H_

		// 此处添加对应.c的函数名既可。

#endif

在这里插入图片描述


2、Delay.c文件

Delay.c文件里面是起延迟作用的代码。如下图:

void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;
	i = 4;
	j = 205;
	k = 187;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

在这里插入图片描述


3、完善Delay.h文件

在Delay.h文件里面添加对应.c文件的函数名既可。

#ifndef _DELAY_H_
#define _DELAY_H_

      // 此处添加对应的.c函数名既可
	void Delay500ms();  //.c里面的函数名

#endif

4、在主函数中运用Delay.c的内容

4.1、Delay.h文件内容:

#ifndef __DELAY_H__
#define __DELAY_H__

      // 此处添加对应的.c函数名既可
	void Delay200us(unsigned int xms);

#endif

在这里插入图片描述

4.2、Delay.c内容:

void Delay200us(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	
	while(xms--)
	{
		i = 3;
		j = 82;
		do
		{
			while (--j);
		} while (--i);
	}
	
}

在这里插入图片描述

4.3、main.c内容:
在这里插入图片描述



六、代码案例(2个):

前面的文章有详细写到如何看LED和数码管的引脚以及如何定义。忘记了可以跳转到“单片机零基础入门(8-2)实战:在数码管中实现显示一个数字–数码管知识的应用”和“单片机零基础入门(4):实现人生中的第一个流水灯(跑马灯)”文章中再巩固一下。

1、单片机原理图

1.1、原理图总览

在这里插入图片描述

1.2、原理图LED模块

在这里插入图片描述

1.3、原理图MCU部分

在这里插入图片描述

2、使用模块化写一个流水灯。(源码)

2.1、第一种:单个独立LED引脚控制:

代码如下:


//案例1:模块化写一个流水灯(第一种:单个独立LED引脚控制://使用P2_0、P2_1、P2_2....P2_7控制逐个LED亮灭的过程。

//led.c

#include <REGX51.H>
#include "Delay.h"
#include "led.h"

void led()
{
	P2_0=0;
	Delay(500);
	P2_0=1;
	Delay(500);
	
	P2_1=0;
	Delay(500);
	P2_1=1;
	Delay(500);	

	P2_2=0;
	Delay(500);
	P2_2=1;
	Delay(500);	
	
	P2_3=0;
	Delay(500);
	P2_3=1;
	Delay(500);	
	
	P2_4=0;
	Delay(500);
	P2_4=1;
	Delay(500);	
	
	P2_5=0;
	Delay(500);
	P2_5=1;
	Delay(500);	


	P2_6=0;
	Delay(500);
	P2_6=1;
	Delay(500);


	P2_7=0;
	Delay(500);
	P2_7=1;
	Delay(500);	
	
}
/*-------------分隔符----------------------*/

//led.h


#ifndef __LED_H__
#define __LED_H__

void led();


#endif



/*-------------分隔符----------------------*/

//Delay.c
/*
此处为延时函数
用于单片机的延时操作。
*/
void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	
	while(xms--)
	{
		i = 3;
		j = 82;
		do
		{
			while (--j);
		} while (--i);
	}
	
}

/*-------------分隔符----------------------*/

//Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

      // 此处添加对应的.c函数名既可
	void Delay(unsigned int xms);

#endif

/*-------------分隔符----------------------*/

//main.c

#include <REGX51.H>
#include "Delay.h"
#include "led.h"

void main()	
{
	
		led();	//调用LED控制函数
	
}


2.2、第二种:八位1体LED引脚控制:

第二种为:单片机零基础入门(4):实现人生中的第一个流水灯(跑马灯)的知识。
八位一体,其实就是led.c文件中的定义方式和前面的引脚逐一定义的不同,其他代码都一样。<但这里源码我还是一样,全部附加上吧。>

代码如下:

/*-------------分隔符----------------------*/

//案例1:模块化写一个流水灯(第二种:八位1体LED引脚控制:)
//使用P2控制逐个LED亮灭的过程,无需详细到单个引脚。

//led.c

#include <REGX51.H>
#include "Delay.h"
#include "led.h"

/*

此处是单片机控制led灯的亮灭
--流水灯操作

*/

void led()
{
	  //1111 1110
		P2 = 0XFE;	//亮第1个灯
		Delay(500);
		P2 = 0XFF;
		
		//1111 1101
		P2 = 0XFD;	//亮第2个灯
		Delay(500);
		P2 = 0XFF;
		
		//1111 1011
		P2 = 0XFB;	//亮第3个灯
		Delay(500);
		P2 = 0XFF;
		
		//1111 0111
		P2 = 0XF7;	//亮第4个灯
		Delay(500);
		P2 = 0XFF;
		
		//1110 1111
		P2 = 0XEF;	//亮第5个灯
		Delay(500);
		P2 = 0XFF;
		
		//1101 1111
		P2 = 0XDF;	//亮第6个灯
		Delay(500);
		P2 = 0XFF;
		
		//1011 1111
		P2 = 0XBF;	//亮第7个灯
		Delay(500);
		P2 = 0XFF;
		
		//0111 1111
		P2 = 0X7F;	//亮第8个灯
		Delay(500);
		P2 = 0XFF;		
}


/*-------------分隔符----------------------*/

//led.h


#ifndef __LED_H__
#define __LED_H__

void led();


#endif



/*-------------分隔符----------------------*/

//Delay.c
/*
此处为延时函数
用于单片机的延时操作。
*/
void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	
	while(xms--)
	{
		i = 3;
		j = 82;
		do
		{
			while (--j);
		} while (--i);
	}
	
}

/*-------------分隔符----------------------*/

//Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

      // 此处添加对应的.c函数名既可
	void Delay(unsigned int xms);

#endif

/*-------------分隔符----------------------*/

//main.c

#include <REGX51.H>
#include "Delay.h"
#include "led.h"

void main()	
{
	
		led();	//调用LED控制函数
	
}


特别注意:
问题:
有朋友问我, 这个P2的定义怎么来的?
例如:P2 = 0XFF为什么是灭;;P2=0X7F为什么是点亮第8个灯?

答:0XFF是十六进制,单片机的LED点亮方式为二进制,所以,0XFF转化为二进制为:1111 1111<8个1,我们使用的这个单片机1为灭,0为亮>;以此计算:0X7F转换为二进制为0111 1111,所以得到第8个灯点亮。



本章节作为单片机零基础入门(8-5)模块化编程的拓展和补充,比前面的[单片机零基础入门(8-5)模块化编程]更为详细,且有实例,但是我在不同时间不同阶段写的文章。

下一篇:不定时更新,具体时间待定。



------人生在勤,不索何获!------



  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡先森ia

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值