51 模块化编程

51 模块化编程

模块化编程

在一般的编程方式中,我们会将所有需要用到的代码放在一个.c文件中,即主函数和自定义函数放在同一文件。这样的写法在面对代码量较小的程序时,会显得直观,方便,但是在面对大量的代码、函数时,会导致我们难以直接确定各函数或是某部分代码所在的位置,反而不利于我们管理。因此,将部分常用函数或是实现某部分功能的代码单独放在一个.c文件中,并创建对应的头文件(.h),有利于我们对代码的维护和管理,我们称这种编程方式为模块化编程。

模块化编程的实例:

C语言实现扫雷(含标记、展开)(含源码)-CSDN博客

所用文件

对于模块化编程,我们首先需要了解在编程过程中我们需要用到哪些文件

在模块化编程中,我们主要运用到的有两种文件类型:

  1. .c(C Source) 文件:.c文件是我们最常用到的文件,我们之前的代码编写都是在.c文件中
  2. .h(C/C++ Header)文件:.h文件即为我们常说的头文件,里面常存放一些我们对常量的宏定义、函数的声明等。
.c

.c文件主要用于存放我们编写的函数或是用于实现某个功能的代码

.h

.h文件主要用于存放函数的声明以及宏定义的常量等

函数的声明

任何函数在调用前都必须被定义或声明,之前我们所用到的函数都是写在main函数前面,此时我们不需要对其进行声明,但对于写在main函数后面(在VS中,这种写法会报警告,但是不影响编译)或是写在另一个.c文件中的函数,我们就需要对其进行声明。

//函数声明的语法:
返回类型 函数名(传入变量);

可以看出,函数的声明就是把函数的定义进行复述

我们一般将函数的声明存放于头文件中

预编译

在之前所写的程序中,我们都需要引入如STC89C5xRC.H或是stdio.h等头文件,引入头文件实际就是对头文件中的代码进行预编译。

为了防止头文件的重定义(即一个头文件被包含两次),我们常在头文件中添加特定语句

语句意义
#include<name.h>预编译name.h,即将头文件的内容加入程序中
#define name value将name定义为值为value的常量
#define name定义一个名为name的常量
#ifndef name当没有定义name时,执行下列语句
#ifdef name当定义了name时,执行下列语句
#pragma once只包含一次头文件
#endif相当于大括号的右半边
还有#if,#else,#elif, #undef等

#pragma once指令的作用是告诉编译器,在编译过程中只包含一次该头文件,避免了头文件的重复包含问题。但需要注意的是,#pragma once并不是标准的C/C++语言特性,不是所有编译器都支持。(虽然#pragma once在大多数主流的C/C++编译器中都得到支持,但它并不是C/C++标准中的一部分,因此在使用时应该考虑到跨平台的兼容性。)


在C/C++中,#ifndef指令用于检查一个标识符是否已经被定义过,如果被定义过,则不执行其包含的语句。如果在#ifndef中加上__,比如#ifndef __HEADER_H__(头文件的文件名中不需要包含下划线),这种习惯通常用于用户自定义的头文件,用来避免与系统提供的头文件或其他库文件产生命名冲突。


对于只有大小写不同的文件名而言,在Windows上,文件名的大小写可能会被忽略。即include时也不一定要按照源文件的命名,可以改变大小写。(在Windows上,两个文件的命名只有大小写不同,而字母不同是无法实现的,当你尝试这样改名时,系统会提示”已包含同名文件“)

#ifndef __HEADER_H__
#define __HEADER_H__

// 头文件内容

#endif

模块化编程的运用

这里将延时和数码管显示两个功能分别存入相应.c和.h文件

main.c

#include<STC89C5xRC.H>
#include"Delay.h"
#include"Nixie_display.h"
//<>表示在安装目录寻找文件
//""表示在当前目录寻找文件


void main()
{
    while(1)
    {
        Delay(5000);
        NixieTube_Display(3, 3);
        Delay(5000);
        NixieTube_Display(4, 4);
    }
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

Delay.c

#include<INTRINS.H>
//用到了_nop_注意这里要加头文件
#include<STC89C5xRC.H>

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

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

    xms--;
    }
}

Nixie_display.h

#ifndef __NIXIE_DISPLAY_H__
#define __NIXIE_DISPLAY_H__

void NixieTube_Display(unsigned char location, unsigned char num);

#endif // !__NIXIE_DISPLAY_H__

Nixie_display.c

#include<STC89C5xRC.H>
#include"Delay.h"

unsigned char NixieTable[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};

void NixieTube_Display(unsigned char location, unsigned char num)
{
    switch(location)
    {
        case 1:
            P2_4 = 1;
            P2_3 = 1;
            P2_2 = 1;
            break;
        case 2:
            P2_4 = 1;
            P2_3 = 1;
            P2_2 = 0;
            break;
        case 3:
            P2_4 = 1;
            P2_3 = 0;
            P2_2 = 1;
            break;
        case 4:
            P2_4 = 1;
            P2_3 = 0;
            P2_2 = 0;
            break;
        case 5:
            P2_4 = 0;
            P2_3 = 1;
            P2_2 = 1;
            break;
        case 6:
            P2_4 = 0;
            P2_3 = 1;
            P2_2 = 0;
            break;
        case 7:
            P2_4 = 0;
            P2_3 = 0;
            P2_2 = 1;
            break;
        case 8:
            P2_4 = 0;
            P2_3 = 0;
            P2_2 = 0;
            break;
    }
    P0 =  NixieTable[num];
    Delay(1);
    //让数码管稳定显示,否则亮度会变低
    P0 = 0x00;
    //清零
}

LCD1602

关于lcd1602的运用,目前为止我只能根据江协科技提供的源码和头文件进行运用,自己还没能力进行编写

使用LCD1602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。

STC89C52RC开发板上的LCD1602接口(图源:普中科技开发手册)

在这里插入图片描述
图源:沃兹济派德
在这里插入图片描述

使用LCD后,数码管和LED6、7、8显示会出问题(LCD1602连接的是P0口和P2口,发生冲突)

可以通过调节接口旁的电位器来调节对比度

#include <STC89C5xRC.H>
#include"LCD1602.h"

void main()
{
    LCD_Init();
    //初始化
    LCD_ShowChar(1, 1, 'A');
    //在一行一列显示'A'
    LCD_ShowString(2, 1, "Hello,World!");
    //显示字符串
    LCD_ShowNum(1, 3, 52, 2);
    //显示无符号数字,长度过短,高位不显示,长度过长,高位补0
    LCD_ShowSignedNum(1, 6, -88, 2);
    //这里设定显示的位数不包括负号
    LCD_ShowHexNum(2, 1, 0xC4, 2);
    //显示16进制的数,后面显示的会把前面显示的覆盖
    LCD_ShowBinNum(1, 7, 0xA0, 8);
    //显示二进制数字
    while(1)
    {
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值