当前位置:首页 > 单片机 > 单片机
[导读]  目前我们在学习和开发单片机时广泛采用 c 语言进行编程,当我们开发的单片机项目较小时,或者我们所写的练习程序很小时,我们总是习惯于将所有代码编写在同一个 c 文件下,由于程序代码量较少,通常为几十行或者

  目前我们在学习和开发单片机时广泛采用 c 语言进行编程,当我们开发的单片机项目较小时,或者我们所写的练习程序很小时,我们总是习惯于将所有代码编写在同一个 c 文件下,由于程序代码量较少,通常为几十行或者上百行, 此时这种操作是可行方便的, 也没有什么问题。但如果要开发的项目较大,代码量上千行或者上万行甚至更大,如果你还继续将所有代码全部编写在仅有的一个 c 文件下, 这种方式的弊病会凸显出来, 它会给代码调试、更改及后期维护都会带来极大的不便。试想一下,当你尝试着从几千几万行代码中定位到某一位置或者去寻找某一错误点,上下拉动巨长的滚动条慢慢地、一点点地浏览整个 c 文件, 是件多么令人眼花缭乱,头昏脑胀的事。 模块化编程可解决这个问题,我们只要根据实际需要使用模块化编程的思维将具有不同功能的程序封装在不同模块中,将各个不同模块存放在不同的 c 文件中。 模块化编程后的程序不但使整体的程序功能结构清晰明了,同时也提高程序代码的利用率,有些模块代码我们可以直接进行移植或者经简单修改就可另作他用,好比封装好的函数。
  那么什么是模块化呢?首先我们来简单来聊聊模块概念,我们可能听说过电源模块,通信模块,这些是硬件模块,它们都提供一些接口,譬如电源模块会有输出额定电压电流的接口,通信模块可能提供了 RS232、 USB 等接口。那么对软件来说模块是怎样的呢?软件里的模块跟硬件模块类似,抽象地说就像一个黑盒子,盒子内部细节我们可以不予理会,我们只关心盒子给我们提供什么东西,即提供了什么接口,利用这些接口我们能实现什么功能。
我们把相对独立,具有独立功能用代码编写在一个 c 文件下,把需要对外的函数或变量进行声明供外部使用, 把不需要的细节尽可能对外部屏蔽起来,这就是软件模块化编程的思维。
这样不同的模块占用不同 c 文件,一个个 c 文件将整个项目串接起来实现所有的功能。

  1. 模块化编程的原则:
模块化编程通常要遵循以下几个原则:
  ? 每一个 c 文件对应一个同名的 h 头文件
  一个 h 文件伴随相应 c 文件存在, 头文件是为了声明对外公开的接口。如果一个 c 文件不需要对外公布任何接口,则其就不应当存在,除非它是程序的入口,如 main 函数所在的文件,同时 main 函数所在文件可以没有对应的头文件。 如有一个 led.c,那应该同时制作一个 led.h 头文件。
  ? 头文件中适合放置接口的声明,不适合放置实现

  头文件是模块的对外的接口,供外部程序调用。头文件中应放置对外部的声明,如对外提供的函数声明、宏定义、变量类型声明等。 函数的实现、变量的赋值、语句的操作等决不能放在头文件中。因为头文件的功能是向外提供接口,譬如函数,变量,具体如何实现是在 c 文件中进行,头文件仅是进行了描述声明。
  ? 任意一个 c 文件只要使用了其他 c 文件提供的接口, 都要同时包含其对应的头文件,每个 c 文件应该头文件自包含

  任意一个 c 文件只要使用了其他 c 文件提供的接口, 都要将其对应的头文件包含到该 c文件中,没有使用到其他 c 文件的接口就不应该将其匹配的头文件包含,并且每个 c 文件都应该包含自己的头文件。
  ? 防止头文件被重复包含
  避免一个头文件被重复包含,通常使用条件编译命令#ifndef--#endif,如下示例:
示例 1:

#ifndefTIME_H#defineTIME_H……#endif


示例 2:

#ifndefLED_H#defineLED_H……#endif

  其中#define FILENAME_H 为基本格式, FILENAME_H 为头文件名称,但要全部使用大写形式,使用单下划线后紧跟一个 H 表明是头文件。 不要在宏名最前面加上“ _"或“ __” ,即使用 FILENAME_H 代替_FILENAME_H_, 因为一般以"_"和” __"开头的标识符为系统保留或者标准库使用。

2. 模块化编程实例
  我们使用 AT89C52 单片机,在编程软件 keil 环境下实施一个工程,来说明模块化编程具体操作的方法和步骤。例子要实现的功能:和 P1 相连的 8 个 LED 灯每 500ms 亮灭交替闪烁,通过串口将数字 0-9 发送给单片机并显示在一个数码管上。 LED 闪烁的时间使用定时器 0 中断方式来控制, T0 每 50ms 溢出产生中断,定义一个计数器,每次 T0 中断就计数一次,累计计数 10 次,那么时长为 500ms,作为 LED 闪烁时间间隔。 单片机的时钟为11.0592MHz。那么使用模块化编程的方法, 整个项目将会有如下表中的文件。
表 1 工程文件清单

C 文件H 头文件描述main.c无Main 文件可以没有对应的头文件timer0.ctimer0.h定时器 0 定时 50ms 中断led.cled.hLed 闪烁实现uart.cuart.h串口通信配置实现digitron.cdigitron.h数码管显示

  2.1创建工程步骤
  2.1.1新建工程文件目录
  新建工程文件目录(如 test),在工程目录下创建 Project、 Source、 Output、 Listing 和Readme 这 5 个文件夹,并在文件夹 Readme 下创建 Readme.txt 文件。 这样做的目的是为
了增强工程文件的可读性及结构化,便于维护和管理。
? Project 存放工程文件
? Source 存放用户编写的 c 文件及 h 头文件
? Output 存放各种输出文件,如 hex 文件
? Listing 存放编译过程中产生的各种中间文件
? Readme 存放工程项目的说明文件
  2.1.2创建keil工程
( 1) 启动软件 Keil μVision, 点击工具栏上的 Project,选择 NewμVision Project,新建 test工程到目录 Project 下。

( 2) 选择目标器件,点击“ OK”确认。
( 3) 出现是否添加启动文件到工程中对话框,选择否。
( 4) 目标选项设置, 点击 target option 工具进入选项配置界面。
( 5) 选中 Target 项,根据实际情况设置晶振频率。本例子频率为 11.0592MHz。
( 6) 选中 output 选项,点击“ Select Folder for Objects…”选择工程目录下的 Output 文件夹, 将“ Create HEX File”勾选中。
( 7) 选中 Listing 选项,点击“ Select Folder for Listings…”选择工程目录下的 Listing 文件夹。
( 8) 最后点击“ OK”保存各选项的设置,至此完成 Target Option 的配置。
( 9)新建 5 个文件,以 c 为后缀名保存到工程目录的 Source 文件下,并分别命名为 main.c、led.c、 uart.c、 timer0.c 和 digitron.c。右击“ Source Group1”选择“ Add Existing Flies to Group‘Source Group1’”,将以上新建的 5 个文件添加到工程中。
(10) 至此,就完成整个 keil 工程的创建。
( 11) 工程 test 目录文件结构

  3.程序代码编写
  3.1 LED闪烁文件
  首先编写 led.c 文件代码,主要内容就是 LED 闪烁实现的函数,由于使用到 timer0.c 中TimeCounter 变量,故需要包含 timer0.h 头文件。其程序代码如下:

#include#include"led.h"#include"timer0.h"voidLight_LED(void){staticunsignedcharTickFlag=0;if(TimeCounter==0)//判断500ms定时是否到{TickFlag=1;TimeCounter=10;}if(TickFlag==1)//每间隔500msP1口取反{P1=~P1;TickFlag=0;}}


这个文件中,仅有 Light_LED()函数提供给外部使用,故在 led.h 仅声明该函数即可,声明时要使用关键字 extern 表明该函数可供外部模块使用, led.h 头文件内容如下:

#ifndefLED_H#defineLED_HexternvoidLight_LED(void);#endif


3.2定时器0中断文件
定时器 0 文件 timer0.c 代码如下:

#include#include"timer0.h"unsignedcharTimeCounter=10;voidTimer0Config(void){TMOD|=0x01;//定时器0工作在方式2,即16位计数器TH0=0x3C;TL0=0xB0;//定时器0重赋初值ET0=1;//使能定时器0中断TR0=1;//开启定时器0}voidtimer0(void)interrupt1//定时器0中断函数{TH0=0x3C;TL0=0xB0;//定时器0重赋初值if(TimeCounter!=0){TimeCounter--;}}


其对应的头文要向 led.c 文件提供 TimeCounter 变量,向 main.c 提 Timer0Config 函数,因此要在头文件中进行声明,具体内容如下:

#ifndefTIMR0_H#defineTIMR0_HexternunsignedcharTimeCounter;externvoidTimer0Config(void);#endif

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

单片机是一种嵌入式系统,它是一块集成电路芯片,内部包含了处理器、存储器和输入输出接口等功能。

关键字: 单片机 编写程序 嵌入式

在现代电子技术的快速发展中,单片机以其高度的集成性、稳定性和可靠性,在工业自动化、智能家居、医疗设备、航空航天等诸多领域得到了广泛应用。S32单片机,作为其中的佼佼者,其引脚功能丰富多样,是实现与外部设备通信、控制、数据...

关键字: s32单片机引脚 单片机

在微控制器领域,MSP430与STM32无疑是两颗璀璨的明星。它们各自凭借其独特的技术特点和广泛的应用领域,在市场上占据了重要的位置。本文将深入解析MSP430与STM32之间的区别,探讨它们在不同应用场景下的优势和局限...

关键字: MSP430 STM32 单片机

该系列产品有助于嵌入式设计人员在更广泛的系统中轻松实现USB功能

关键字: 单片机 嵌入式设计 USB

单片机编程语言是程序员与微控制器进行交流的桥梁,它们构成了单片机系统的软件开发基石,决定着如何有效、高效地控制和管理单片机的各项资源。随着微控制器技术的不断发展,针对不同应用场景的需求,形成了丰富多样的编程语言体系。本文...

关键字: 单片机 微控制器

单片机,全称为“单片微型计算机”或“微控制器”(Microcontroller Unit,简称MCU),是一种高度集成化的电子器件,它是现代科技领域的关键组件,尤其在自动化控制、物联网、消费电子、汽车电子、工业控制等领域...

关键字: 单片机 MCU

STM32是由意法半导体公司(STMicroelectronics)推出的基于ARM Cortex-M内核的32位微控制器系列,以其高性能、低功耗、丰富的外设接口和强大的生态系统深受广大嵌入式开发者喜爱。本文将详细介绍S...

关键字: STM32 单片机

在当前的科技浪潮中,单片机作为嵌入式系统的重要组成部分,正以其强大的功能和广泛的应用领域受到越来越多行业的青睐。在众多单片机中,W79E2051以其卓越的性能和稳定的工作特性,成为市场上的明星产品。本文将深入探讨W79E...

关键字: 单片机 w79e2051单片机

单片机,又称为微控制器或微处理器,是现代电子设备中的核心部件之一。它集成了中央处理器、存储器、输入输出接口等电路,通过外部信号引脚与外部设备进行通信,实现对设备的控制和管理。本文将详细介绍单片机的外部信号引脚名称及其功能...

关键字: 单片机 微控制器 中央处理器

随着科技的飞速发展,单片机和嵌入式系统在现代电子设备中的应用越来越广泛。它们不仅提高了设备的智能化水平,还推动了各行各业的创新与发展。在单片机和嵌入式系统的开发中,编程语言的选择至关重要。本文将深入探讨单片机和嵌入式系统...

关键字: 单片机 嵌入式系统 电子设备
关闭
关闭