单片机零基础入门(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)模块化编程]更为详细,且有实例,但是我在不同时间不同阶段写的文章。
下一篇:不定时更新,具体时间待定。
------人生在勤,不索何获!------