news 2026/5/9 2:11:34

第14章 实践项目开发——智能温控系统14.1

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第14章 实践项目开发——智能温控系统14.1

本章首先介绍实际项目开发中的一些技巧和规范性的内容,把一些实际开发中经常使用的零散知识点逐一的讲解,然后做一个温控器的小项目,模拟一个空调产品的程序控制功能,把项目开发的整个流程都走一遍,学习一下真正的项目流程。

本章内容非常重要,是否把本章内容消化理解是检验是否能够真正独立开发产品的重要的一步。实际上复杂的内容只是简单内容的堆叠,相信只要耐心认真反复学习实践,肯定可以越过龙门,步入电子工程师的行列。

14.1复合数据类型-

在前边学数据类型的时候,主要是字符型、整型、浮点型等基本类型,而学数组的时候,数组的定义要求数组元素必须是相同的数据类型。在实际应用中,有时候还需要把不同类型的数据组成一个有机的整体来处理,这些组合在一个整体中的数据之间还有一定的联系,比如一个学生的姓名、性别、年龄、考试成绩等,这就引入了复合数据类型。复合数据类型主要包含结构体数据类型、共用体数据类型和枚举体数据类型。

14.1.1结构体数据类型

Kingst51开发板上的LED显示有三部分,LED小灯、数码管和LED点阵。LED小灯是1个字节控制;数码管是6个字节控制;LED点阵是8个字节控制。它们都受P0口输出控制,控制方式有相似性,可以统一进行动态扫描刷新;这三者又属于独立的LED功能显示,要改变其显示内容需要单独分别赋值。三者需要允许一起处理,也允许独立操作。如果分别进行变量定义,一是操作容易出错,二是比较零散,可读性不强。

于是,就可以使用结构体来将这一组彼此相关的数据做一个封装,既组成了一个整体,易读不易错;又可以独立单独处理其中某一个元素,这就是结构体数据类型。结构体是一种构造而成的数据类型,使用之前需要先定义它。

声明结构体变量的一般格式如下:

struct 结构体名

{

类型1 变量名1;

类型2 变量名2;

……

类型n 变量名n;

} 结构体变量名1, 结构体变量名2, ... 结构体变量名n;

这种声明方式是在声明结构体类型的同时又用它定义了结构体变量,此时的结构体名是可以省略的,但如果省略后,就不能在别处再次定义这样的结构体变量了。这种方式把类型定义和变量定义混在了一起,降低了程序的灵活性和可读性,因此并不建议采用这种方式,而是推荐用以下这种方式:

struct 结构体名

{

类型1 变量名1;

类型2 变量名2;

……

类型n 变量名n;

};

struct 结构体名 结构体变量名1, 结构体变量名2, ... 结构体变量名n;

为了方便理解,首先定义一个变量unsigned char keyBuff;然后将LED小灯、LED数码管和LED点阵,构建一个结构体类型。

struct sLedBuff { //LED显示缓冲区结构

uint8 array[8]; //点阵缓冲区

uint8 number[6]; //数码管缓冲区

uint8 single; //独立LED缓冲区

};

struct sLedBuff ledBuff;

struct是结构体类型关键字,sLedBuff 是这个结构体名字。一旦结构体构建完成,sLedBuff 起到的作用和unsigned char类似,是表达变量类型的。ledBuff和keyBuff类似,即定义了一个sLedBuff 类型的结构体变量。如果要给结构体变量的成员赋值的话,写法是

ledBuff.single = 0xFF;

ledBuff.array[0] = 0xFF;

一个指针变量如果指向了一个结构体变量的时候,称之为结构指针变量。结构指针变量是指向的结构体变量的首地址,通过结构体指针也可以访问到这个结构变量。

结构指针变量声明的一般形式如下:

struct sLedBuff *pledBuff;

这里要特别注意的是,使用结构体指针对结构体成员的访问,和使用结构体变量名对结构体成员的访问,其表达式有所不同。结构体指针对结构体成员的访问表达式为

pledBuff ->single= 0xFF; 或者是

(*pledBuff).single= 0xFF;

很明显前者更简洁,所以推荐使用前者。

14.1.2共用体数据类型

共用体也称之为联合体,共用体定义和结构体十分类似,使用以下形式:

union 共用体名

{

数据类型1 成员名1;

数据类型2 成员名2;

……

数据类型n 成员名n;

};

union 共用体名 共用体变量;

共用体表示的是几个变量共用一个内存位置,也就是成员1、成员2……成员n都用一个内存位置。共用体成员的访问方式和结构体是一样的,成员访问的方式是:共用体名.成员名,使用指针来访问的方式是:共用体名->成员名。

从程序安全性和可移植性角度考虑,除非用户非常了解所使用的开发环境的实现细节,否则使用共用体存在代码上的隐患,所以现在诸多以安全为首要诉求的C语言编程规范禁止使用共用体。因此共用体不推荐使用,也不再赘述。

14.1.3枚举数据类型

在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期从周一到周日有7天,一年从1月到12月有12个月,蜂鸣器有响和不响两种状态等等。如果把这些变量定义成整型或者字符型不是很合适,因为这些变量都有自己的范围。C语言提供了一种称为“枚举”的类型,在枚举类型的定义中列举出所有可能的值,并可以为每一个值取一个形象化的名字,它的这一特性可以提高程序代码的可读性。

枚举的说明形式如下:

enum 枚举名

{

标识符1[=整型常数],

标识符2[=整型常数],

……

标识符n[=整型常数]

};

enum 枚举名 枚举变量;

枚举的说明形式中,如果没有被初始化,那么“=整型常数”是可以被省略的,如果是默认值的话,从第一个标识符顺序赋值0、1、2……,但是当枚举中任何一个成员被赋值后,它后边的成员按照依次加1的规则确定数值。

比如本章的温控器系统,正常工作时一共有三种状态,分别为正常工作状态,设置继电器动作状态和设置报警器状态三种,可以定义一个枚举类型,根据枚举的定义E_NORMAL值为0,E_SET_ACT值为1,E_SET_ALARM值为2,具体应用后续有例程。

enum eStaSystem { //系统运行状态枚举

E_NORMAL, E_SET_ACT, E_SET_ALARM

};

枚举的使用,有几点要注意:

1、枚举中每个成员结束符是逗号,而不是分号,最后一个成员可以省略逗号。

2、枚举成员的初始化值可以是负数,但是后边的成员依然依次加1。

3、枚举变量只能取枚举结构中的某个标识符常量,不可以在范围之外。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 2:10:36

ARM big.LITTLE架构与全局任务调度技术解析

1. ARM big.LITTLE架构设计解析在移动计算领域,功耗与性能的平衡始终是芯片设计的核心挑战。2011年ARM推出的big.LITTLE技术开创性地将两种不同架构的处理器核心集成到同一芯片:高性能的"大核"(如Cortex-A15/A57)与高能…

作者头像 李华
网站建设 2026/5/9 2:10:33

XYZ晶圆检测平台:精准护航8寸/12寸晶圆检测的核心助力

在半导体制造领域,晶圆检测是守住芯片良率的关键一环,尤其是8寸、12寸晶圆,其表面电路精度已达微米甚至纳米级,对检测设备的稳定性和精准度有着极高要求。XYZ晶圆检测平台凭借巧妙的结构设计和扎实的性能,成为这类晶圆…

作者头像 李华
网站建设 2026/5/9 2:00:31

从零构建私有化智能语音助手:基于ESP32与开源后端的完整实践指南

1. 项目概述:从零构建你的智能语音助手后端如果你手头有一块ESP32开发板,并且已经体验过类似“小智”这样的智能语音助手项目,但总觉得依赖别人的云端服务不够自由、不够安全,或者想深度定制功能,那么今天这个内容就是…

作者头像 李华
网站建设 2026/5/9 1:59:31

什么是RGM收入增长管理?RGM收入增长管理工具怎么选?

在当今竞争激烈且瞬息万变的快消品市场中,企业面临着诸多挑战,如消费者需求日益多样化、市场竞争不断加剧、渠道成本持续上升等。在这样的背景下,如何实现可持续的收入增长成为了快消企业亟待解决的关键问题。而RGM收入增长管理,正…

作者头像 李华