基于51单片机的温度报警系统(程序分装)

文章目录

  • 目录

    前言

    一、程序结构

    1.1.1 全局变量

    1.1.2 静态本地变量

    1.2 预处理命令

    1.3.1 函数原型

    1.3.2 头文件

    标准头文件结构。

    1.4  *声明和定义*

    二、错误示范及解决办法

    1、lcd1602.c(12): error C279: 'tab': multiple initialization   //重复定义错误  下面也有另一种说法

    错误举例

    2、*** WARNING L1: UNRESOLVED EXTERNAL SYMBOLSYMBOL:  TAB       MODULE:  .\Objects\main.obj (MAIN)       *** WARNING L2: REFERENCE MADE TO UNRESOLVED  EXTERNAL      SYMBOL:  TAB      MODULE:  .\Objects\main.obj (MAIN)      ADDRESS: 001FH

    //只做了声明,没有进行定义

    错误举例

    3、*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS       SYMBOL:  TAB       MODULE:  .\Objects\lcd1602.obj (LCD1602)       *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR  OVERLAY PROCESS       SEGMENT: ?CO?LCD1602

    //也是属于重复定义类

    错误举例

    总结


 


前言

接上篇《基于51单片机的温度报警系统》,详细解释程序分装中遇到的问题。


一、程序结构

1.1.1 全局变量

定义在函数外面的变量是全局变量;

全局变量具有全局的生存期和作用域;

它们与任何函数都无关;

在任何函数内部都可以使用它们;

没有做初始化的全局变量会得到O值;

指针会得到NULL值;

只能用编译时刻已知的值来初始化全局变量;

它们的初始化发生在main函数之前。

(PS:如果函数内部存在与全局变量同名的变量,全局变量将会被隐藏。)

1.1.2 静态本地变量

在本地变量定义时加上static修饰符就成为静态本地变量;

当函数离开的时候,静态本地变量会继续存在并保持其值;

静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开时的值。

静态本地变量实际上是特殊的全局变量;

它们位于相同的内存区域;

静态本地变量具有全局的生存期,函数内的局部作用域;

static在这里的意思是局部作用域(本地可访问)。

1.2 预处理命令

预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的。程序员在程序

中用预处理命令来调用这些功能。

#开头的是编译预处理的指令,他们不是C语言的成分,但是C语言程序离不开他们。

指令 解释
# 空指令
#include 包含一个源代码文件
#define 定义宏
#undef 取消已定义的宏
#if 判断条件为真,则编译下面{}内的代码
#ifdef 如果宏已经定义,则编译下面{}内的代码
#ifndef 如果宏没有被定义,则编译下面{}内的代码
#elif 判断前面的#if的条件不为真,即#elif条件为真时,则编译下面{}内的代码
#endif 结束#if······#elif······程序块

(PS:只是简单解释了,具体的自己去看一下)

1.3.1 函数原型

如果不给出函数原型,编译器会猜测你所调用的函数的所有参数都是int,返回类型也是int。编译器

在编译的时候只看当前的一个编译单元,它不会去看同一个项目中的其他编译单元以找出那个函数

的原型。如果你的函数并非如此,程序链接的时候不会出错。但是执行的时候就不对了。所以需要

在调用函数的地方给出函数的原型,以告诉编译器那个函数究竟长什么样。

1.3.2 头文件

把函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中#include

这个头文件,就能让编译器在编译的时候知道函数的原型。

(PS:使用尖括号和双引号的区别在于头文件的搜索路径

尖括号:编译器会到系统路径下查找头文件

双引号:编译器会先在当前目录下查找头文件,如果没有找到,再到系统路径下查找

同一个头文件可以被多次引入,多次引入的效果和一次引入的效果相同,因为头文件在代码层面有

防止重复引入的机制。

(头文件只能包含变量和函数的声明,不能包含定义,否则在多次引入时会引起重复定义错误。) 

只有声明可以被放在头文件中

是规则不是法律

否则会造成一个项目中多个编译单元里有重名的实体.

某些编译器允许几个编译单元中存在同名的函数,或者用weak修饰符来强调这种存在。
 

标准头文件结构。

 

同一个编译单元里,同名的结构不能被重复声明。如果你的头文件里有结构的声明,很难这个头文

件不会在一个编译单元里被#include多次,所以需要“标准头文件结构”。

#ifndef __LIST__HEAD__
#define __LIST__HEAD__

#include "node.h"

typedef struct _list{
    Node* head;
    Node* tail;
}list;

#endif

运用条件编译和宏,保证这个都文件在一个编译器单元中只会被#include一次;

#pragma once也能起到相同的作用,但不是所有的编译器都支持。

1.4  *声明和定义*

超级重要,一定要理解。

定义:表示创建变量或分配存储单元(产生代码)

变量的声明
int i;//变量的定义
extern int i;//变量的声明

基于51单片机的温度报警系统(程序分装)_第1张图片

声明:说明变量的性质,但并不分配存储单元(不产生代码 )

基于51单片机的温度报警系统(程序分装)_第2张图片

二、错误示范及解决办法

对下列经常出现的错误解释(以分享的代码为例)

1、lcd1602.c(12): error C279: 'tab': multiple initialization   //重复定义错误  下面也有另一种说法

(多个地方对这几个常量初始化了重复定义)

tips:如果在声明的时候给变量赋值,那么就和去掉extern直接定义变量赋值是等价的

int i = 0;
extern int i = 0; //在声明时对变量进行了赋值,声明不再是声明,变成定义了。
上述两者时等价的

错误举例

基于51单片机的温度报警系统(程序分装)_第3张图片

基于51单片机的温度报警系统(程序分装)_第4张图片

撤销lcd1602.h中的赋值操作

基于51单片机的温度报警系统(程序分装)_第5张图片

错误得到解决。

2、*** WARNING L1: UNRESOLVED EXTERNAL SYMBOL
SYMBOL:  TAB
       MODULE:  .\Objects\main.obj (MAIN)
       *** WARNING L2: REFERENCE MADE TO UNRESOLVED  EXTERNAL
      SYMBOL:  TAB
      MODULE:  .\Objects\main.obj (MAIN)
      ADDRESS: 001FH

//只做了声明,没有进行定义

错误举例

基于51单片机的温度报警系统(程序分装)_第6张图片

基于51单片机的温度报警系统(程序分装)_第7张图片

补上定义即可。(还有一种类似错误,可能是没有把C文件添加进项目中。)

基于51单片机的温度报警系统(程序分装)_第8张图片

3、*** ERROR L104: MULTIPLE PUBLIC DEFINITIONS
       SYMBOL:  TAB
       MODULE:  .\Objects\lcd1602.obj (LCD1602)
       *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR  OVERLAY PROCESS
       SEGMENT: ?CO?LCD1602

//也是属于重复定义类

错误举例

基于51单片机的温度报警系统(程序分装)_第9张图片

产生原因是在lcd1602.h中对 tab[] 进行了定义 

extern uchar code tab[]={'0','1','2','3','4','5','6','7','8','9'};//这是定义(上面有讲)

对于复杂的程序,有很多C文件头文件,这个时候全局变量就必须在头文件中声明(不需要初始

),然后在C文件中定义(该初始化的要初始化)。如果在头文件中定义,则编译的时候会出现

重复定义的错误。如果只有头文件中声明就会出现没有定义有警告。

在.c文件中定义,在.h文件中声明,就可避免此类错误的发生。

***(只有声明可以被放在头文件中,是规则不是法律。)

高概率出现的错误只有这些了吧,若还是有问题请留言,我会做出解答。


总结

主要解释了分装遇到的知识点和常见问题。分装代码已经上传。

基于51单片机的温度报警系统(程序分装)_第10张图片

下载这个,只用获取下载码。(是免费的)

还有你们蜂鸣器可能不会响,不要说是我的问题哦。

记得改电阻(RES)的阻值和(BUZZER)的Operating Voltage。

你可能感兴趣的:(C51,单片机,c语言,单片机)