摘要:听说还有好多学单片机的小伙伴不会用结构体?指针和结构体是学单片机必须要掌握的,如果你C语言掌握的不牢,单片机根本学不到精髓,只能完成一些低级的项目。看得懂结构体并且能够灵活运用结构体才能说你入门了单片机。本篇将以最通俗的方式结合STM32单片来讲讲结构体的运用。解决你学完C语言、考过了计算机二级还是看不懂单片机结构体的苦恼。宝藏文章,记得点赞转发收藏。

大家知道指针和结构体是单片机的难点,所以就去学习C语言,找视频看书…

这里面每一个视频的播放量都非常高。对于单纯的学习C语言,这里讲的很清楚。看完你不禁在下面评论一句:哇!讲的真的太清楚了吧!但是等你真正的学单片机的时候,你会发现我不是学过C语言吗?计算机二级我也过了啊!怎么这个指针和结构体都不懂啊?难道我学了一个假的C语言?

其实这不是你的错,也不是单片机的错,而是在C语言和单片机之间需要一个过渡!这个需要过渡的点在很多单片机视频教程中并没有去讲解。因为教育机构默认你是知道的,所以在讲流水灯时他们并不会讲解GPIO初始化这个结构体,因为默认你是知道如何操作的。

申明一个GPIO_InitTypeDef的结构体,然后在LED_Init(void)函数中定义一个GPIO_InitStructure的变量GPIO_InitStructure,那么这个变量就可以设置这个GPIO_InitTypeDef的结构体中的成员。这里先做了解,请接着往下看。

1、为什么需要结构体

这里先不说什么是结构体,说说为什么需要结构体?只有知道为什么需要,才能按照你的需要去学习,这样效率才会高。你才知道在什么情况下我们需要写一个结构体,怎么样去用结构体。

这里我们以一个智能家居的项目为例。

先来看一个实际的问题

话说有一个项目上有4个传感器:光照传感器、烟雾传感器、酒精传感器、湿度传感器。然后这四个各个传感器还有设置报警的阈值范围。

一般都是这样写

#include "sys.h"
#include "delay.h"
#include "usart.h"/*记录传感器的数值*/
float temperature;  //温度
char  humidity;     //湿度
char  alcohol;      //酒精浓度
int   illumination; //光照强度/*记录传感器高低阈值*/
float temperature_threshold[2];
float humidity_threshold[2];
float alcohol_threshold[2];
float illumination_threshold[2];int main(void)
{   uart_init(115200);//串口初始化delay_init();while(1){ }
}

当然你做一个项目肯定还定义了很多其他的变量,还需要记录其它变量

然后过了几天又增加了个一氧化碳传感器

然后过了几天,每个传感器还需要加个是否正常工作的标志位

因为项目的需要,然后又增加了4个相同的传感器:温湿度、光照强度、烟雾浓度、酒精浓度。

然后又增加了4个相同的传感器 温湿度、光照强度、烟雾浓度、酒精浓度。

截图截不开了…

满屏的变量…

满屏的变量…

满屏的变量…

在项目刚开始做的时候如果不能未雨绸缪,接着干下去整个程序代码别说维护了,就是接着写都让人头疼!

满屏的变量…

满屏的变量…

2、结构体闪亮登场

然后搞C语言那帮家伙就造了个功能struct

1、结构体就是可以把变量包含到里面的东西

struct就代表要定义一个结构体
sensors是这个结构体的名字
然后是一个大括号 { }

大括号里面就随意定义变量啦~

怎么使用里面的变量呢?

注意结构体是一个数据类型
就像是int和char一样的这种类型

既然是一种数据类型

那么就可以用这个数据类型定义变量

定义一个该结构体的变量

为啥要那样子定义啊?

答:你去问造C语言的那帮家伙去!问问他们为啥要设计成这样子!

然后操作结构体变量里面的成员变量。当我们定义好结构体变量后,在初始化变量里面的成员变量时就会自动出现结构体里面的成员变量,如果这个代码是你一个一个敲出来的话,你就会感叹结构体在单片机中是那么的奇妙!

有人会问为啥是结构体变量中间加个点?

答:你去问造C语言的那帮家伙去!问问他们为啥要设计成这样子。

2、其实定义结构体变量可以下面这样子

也可以定义多个

发现了没,每个结构体变量都是单独拥有结构体里面的全部成员变量。

就像是最开始说的,如果再增加一套传感器:温湿度、光照强度、烟雾浓度、酒精浓度。

使用结构体的话只需要再定义一个结构体变量即可

但是很多时候我们在单片机中见到的结构体并不是上面那样定义的,而是在前面加了一个typedef关键字。

这样的例子在库函数的头文件中我们经常会看到如下结构体

3、typedef关键字

先看一下百度百科对typedef的定义

总结一句就是:typedef可以把一个数据类型取一个别的名字

typedef {数据类型} {别的名字}

#include "sys.h"
#include "delay.h"
#include "usart.h"typedef int zhjiguoxin;//zhjiguoxin就是intzhjiguoxin value = 0;int main(void)
{   uart_init(115200);//串口初始化delay_init();  printf("value=%d\r\n",value);while(1){   }
}

虽然typedef可以给变量取别名,但是没有谁回像上面那样取名字,我这里知识举一个例子。

4、结构体的精髓

注意下:

1、下面的代表了这个结构体数据类型

2、给这个数据类型起一个别名

注意是三部分, typedef {数据类型} {别的名字}。所以sensor就代表了这个结构体了。

建议初学者把下面这张图保存到你的电脑,这样你就永远也不会忘记typedef在结构体中的用法了,也能很快的记住结构体这个东东。

3、以后定义结构体变量的时候就不需要像最开始那样struct sensors sen;这样的定义结构体变量了,只需要sensors sen;即可

4、结构体名字可以省略

注意结构体定义可以不写结构体名,对C语言来说,那个sensors不叫结构体名,而是叫标签(tag)。C语言结构体名是struct关键字 + tag。所以为了简便我们看到的单片机中的结构体都是写成如下的形式。

5、结构体的变量可以放任何变量

1、结构体变量可以放任何变量(int型指针)

#include "sys.h"
#include "delay.h"
#include "usart.h"
typedef struct
{float temperature; //温度char  humidity;    //湿度char  alcohol;      //酒精浓度int   illumination;//光照强度char  CO;  //一氧化碳浓度int   *p;  //int型的指针变量
} sensor;
sensor sen;
int value =0;
int main(void)
{uart_init(115200);//串口初始化delay_init(); sen.p=&value;//把value的地址赋值 //打印p代表的地址里面的值(其实就是打印value的值)printf("value=%d\r\n",*(sen.p));    while(1){   }
}

既然是指针变量,所以给指针变量赋值时当然是赋值的是一个地址。

2、结构体变量可以放任何变量(函数指针)

#include "sys.h"
#include "delay.h"
#include "usart.h"
typedef struct
{float temperature; //温度char  humidity;    //湿度char  alcohol;      //酒精浓度int   illumination;//光照强度char  CO;  //一氧化碳浓度int   *p;  //int型的指针变量void (*fun)();
} sensor;
sensor sen;
void function()
{printf("zhiguoxin\r\n");
}
int value =0;
int main(void)
{   uart_init(115200);//串口初始化delay_init();  sen.fun=function;  sen.fun();  while(1){   }
}

既然是函数指针变量,所以给函数指针变量赋值时当然是赋值的是的也是地址,并且还要是一个函数的地址,而一个函数的函数名就是该函数的地址。所以才会有下面的把函数function();的地址function赋值给函数指针fun。这样大家是不是很清楚了。如果不清楚建议看个3遍以上!

3、结构体变量可以放任何变量(结构体变量)

这就是结构体嵌套,在一个结构体内包含了另一个结构体作为其成员。当出现结构体嵌套时,必须以级联方式访问结构体成员,即通过成员选择运算符逐级找到最底层的成员时再引用。

#include "sys.h"
#include "delay.h"
#include "usart.h"typedef struct
{int i;
}zhiguoxin;typedef struct
{float temperature; //温度char  humidity;    //湿度char  alcohol;      //酒精浓度int   illumination;//光照强度char  CO;  //一氧化碳浓度int   *p;  //int型的指针变量void (*fun)();   zhiguoxin guougo;
}sensor;sensor sen;int main(void)
{   uart_init(115200);//串口初始化delay_init();sen.guougo.i=100;printf("i=%d\r\n",sen.guougo.i);while(1){    }
}

4、结构体变量可以放任何变量(结构体指针)

结构体是一个数据类型。数据类型当然也可以定义对应的指针变量啦。

就像是int 类型可以定义 int *p; 一样

所以当大家如果发现你的代码中结构体是通过—>访问的话,那么这个结构体变量一定是指针类型的变量。同理如果代码中结构体是通过.访问的话,那么这个结构体变量就不是指针变量,而是一般的变量。

总结:到这里结构体在单片机中的应用你已经掌握的差不多了,大家可能感觉本期讲的内容太简单了,不过只有你把这个简单的基础性知识打牢,你就会进步的更快。否则你总感觉你的代码差点意思。

干货|手把手教你写单片机的结构体相关推荐

  1. 手把手教你写一个中文聊天机器人

    本文来自作者 赵英俊(Enjoy) 在 GitChat 上分享 「手把手教你写一个中文聊天机器人」,「阅读原文」查看交流实录. 「文末高能」 编辑 | 哈比 一.前言 发布这篇 Chat 的初衷是想和 ...

  2. 手把手教你写Linux I2C设备驱动

    手把手教你写Linux I2C设备驱动 标签:Linux 设备 驱动 详解 i2c 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http:/ ...

  3. 手把手教你写网站:Python WEB开发技术实战

    摘要:本文详细介绍了Python WEB开发的基础入门.以一个博客站点的开发为例讲解了基于Django框架开发WEB站点的全过程.通过本文的学习可以快速掌握基于Django的Python WEB的开发 ...

  4. 手把手教你写专利申请书/如何申请专利

    摘要 小前言 (一)申请前的准备工作     1.申请前查询     2.其他方面的考虑     3.申请文件准备 (二)填写专利申请系列文档     1.实际操作步骤     2.具体操作     ...

  5. hecto - 手把手教你写个 文本编辑器

    https://www.philippflenker.com/hecto/ 的阅读笔记. 我是学完[[Rust权威指南]] 之后才看的这个. 手把手教你写个 文本编辑器(1300+行代码). 作者是真 ...

  6. 手把手教你写批处理-批处理的介绍

    标题:手把手教你写批处理-批处理的介绍 作者:佚名 编者:Climbing 出处:中国 DOS 联盟之联合 DOS 论坛 题注:willsort 日期:2004-09-21 ------------- ...

  7. 手把手教你写专利申请书·如何申请专利

    摘要 小前言 (一)申请前的准备工作     1.申请前查询     2.其他方面的考虑     3.申请文件准备 (二)填写专利申请系列文档     1.实际操作步骤     2.具体操作     ...

  8. 手把手教你写专利申请书/怎样申请专利

    手把手教你写专利申请书·怎样申请专利 摘要 小前言 (一)申请前的准备工作     1.申请前查询     2.其它方面的考虑     3.申请文件准备 (二)填写专利申请系列文档     1.实际操 ...

  9. 手把手教你写个微信小程序

    手把手教你写个微信小程序 很多人看完bmob快速入门,并完成了bmob的基本配置之后依然不知道如何下手去写自己的代码,那么跟着我一起来一步一步做个小程序吧. 工具:Bmob后端云 新建小程序项目 一. ...

  10. Vue3 Typescript + Axios 全栈开发教程:手把手教你写「待办清单」APP

    本文完整版:<Vue3 Typescript + Axios 全栈开发教程:手把手教你写「待办清单」APP> Vue3 Typescript + Axios 全栈开发教程 前端 Vue3 ...

最新文章

  1. 主流html5桌面应用开发,主流HTML5开发工具推荐
  2. linux打开没有图形界面,linux无法打开图形界面
  3. swift中使用core data
  4. mysql 当前时间戳_kettle教程-mysql数据增量抽取-无需时间戳无需标识
  5. mysql自带订阅功能_为博客提供订阅功能
  6. aix如何查看日志策略_aix的日志的一些操作理解
  7. C/S和B/S模式的主要特点以及区别在那里?画出CGI工作原理图,具体描述CGI的主要流程和实现步骤。
  8. camera(21)---camera 客观测试 Imatest教程--曝光度测试
  9. 读书笔记--对象、实例、原型、继承 1
  10. Android 版本号及对应的版本名
  11. 2022-2028年全球与中国摆式斗式提升机市场现状及未来发展趋势分析报告
  12. GlobalMapper20如何把mbt或者tif导出为LSV下载一样的瓦片结构(如何提取mbtiles里面的瓦片文件)
  13. 手工选出的股票池和量化选股模型选出的股票池有哪些区别?
  14. 香港监管机构收紧加密货币相关法规
  15. 谷歌收购 ReCaptcha 2009
  16. 流水线性能吞吐率、加速比、效率计算
  17. GiB 与 GB 的区别
  18. c#开发初学者之mvc及架构分层
  19. 超级玛丽 python源码
  20. 软件编程网络资源汇总 .

热门文章

  1. matlab2017b 破解
  2. sqlbulkcopy是覆盖式更新吗_酒店无线覆盖解决方案,一文了解清楚
  3. Python实现人脸识别
  4. oracle驱动ojdbc6的下载安装
  5. 有关于FireBug和FirePath安装和使用-学习笔记
  6. Unity 不使用BMFont创建Font字体
  7. mysql关联子查询_MySQL 关联子查询
  8. oracle mysql认证考试流程_报考oraclemysql认证考试流程
  9. python参考手册下载_python学习手册下载|
  10. Unix和Windows比较