0302GPIO外设输入功能

GPIO外设输入功能

  • 输入部分硬件电路
    • 按键简介
    • 传感器模块简介
    • 按键和传感器模块的硬件电路
  • C语言的学习
    • C语言数据类型
    • 宏定义
    • typedef
    • 结构体
    • 枚举
    • C语言知识总结
  • 按键控制LED灯&光敏传感器蜂鸣器
  • GPIO总结
    • GPIO使用方法总结
    • 模块化编程的方法:

两个程序:按键控制LED,光敏传感器控制LED灯

GPIO输入部分直接从外部硬件设备开始

C语言的相关知识点
C语言的数据类型、宏定义、typedef、结构体和枚举 知识点,是库函数里经常出现的东西,了解这些有利于对库函数的执行逻辑更加清晰明了。C语言的if else、加减乘除最基本的可以自学我的C++部分
同时C语言的指针。对于指针的含义和方法,这是需要熟练掌握的

输入部分硬件电路

按键简介

在这里插入图片描述

抖动通常在5-10ms之间,人分辨不出来,但对于高速运行的单片机而言,这就漫长了。所以要对抖动进行过滤,否则会出现按键按一下,单片机反映了多次的现象。按键松手时也会有一段抖动。
最简单的方法是软件加一段延时,把抖动时间耗过去

传感器模块简介

在这里插入图片描述
这些传感器都是利用传感器元件,
比如光线越强,光敏电阻的阻值越小
温度越高,热敏电阻的阻值越小
红外光线越强,红外接收管的阻值越小。但是电阻的变化不易被直接观察,所以一般通过分压来输出

N1代表可变电阻(相对于各传感器,可以对应为光敏电阻、热敏电阻、红外接收管)
上下拉电阻在单片机中经常出现,弱上拉、弱下拉、强上拉、强下拉。这里强弱指的是电阻阻值的大小,弱上拉的电阻阻值大,驱动能力弱一点,上拉下拉指接到VCC、GND。

分到的模拟电压表示强度,
二值化比较通常用于检测通断,所以IN+阈值不需要过多的调整

按键和传感器模块的硬件电路

在这里插入图片描述
下接按键的方式(常用下接方式,这是电路设计的习惯和规范),上接按键的方式
第一个图最常用的按键接法(需要上拉输入的模式,默认高电平,否则会出现引脚电压不确定的错误现象)
第二个图外部接了上拉电阻(可以配置成浮空输入或者上拉输入,如果是上拉输入,那就是内外两个上拉电阻共同作用,这时高电平更强一些,对应的高电平更加稳定,但当引脚被强行拉低时,损耗也会大一些)
第三个图(需单片机引脚可以配置成下拉输入模式,一般的单片机可能不一定有下拉输入模式,所以用的不多)
第四个图(下拉输入模式或者浮空输入模式)

C语言的学习

C语言数据类型

在这里插入图片描述

在51单片机中int是16位的,而在STM32单片机中,int是32位的。和51的不同之处,不要弄混了

右边是C语言的stdint.h文件和ST对这些变量的重命名。因为左边的名字比较长,而且int的位数根据系统的不同还有可能不一样,还有char本义字符型意思,按名字来说应该存放字符,但是我们用单片机来存放整数而不是字符。
综合以上原因,C语言和ST就给这些变量换了个名字。C语言提供的有stdint.h这个头文件,使用了新的名字
int8_t就是char的新名字,表示意思就是8位整数数据。
-t表示这个用typedef重名命名的变量类型,
unsigned char 的新名字就是uint8_t,意思是无符号8位整型数据

代表的就是前面的数据类型,只是换了一个名字而已。
在这里插入图片描述

s8、u8、s16 、u16、就是ST库函数以前用的名字
在这里插入图片描述
新版库函数仍然支持这些写法,明确了这是库函数老的类型,是为了传统目的保留的(兼容老版本)
在这里插入图片描述

推荐使用stdint关键字的定义,因为是新版库函数使用的方式,也是C语言stdint.h头文件提供的官方定义

宏定义

在这里插入图片描述
此处就是用ABC 直接替代 12345
如:#define GPIO_Pin_10 ((uint16_t)0x0400)
GPIO_Pin_10 替换的就是 ((uint16_t)0x0400),加了强制类型转换,是为了严谨性考虑的,目前我们暂时不用管。这里0x0400表示第10号口,但这不方便理解,所以用宏定义将10号口改一下名字,叫GPIO_Pin_10。
宏定义除了替换之外,还有其他的用法,可以后期再学。

typedef

在这里插入图片描述
用途和宏定义差不多,
区别:宏定义的新的名字在左边,typedef的新名字在右边。(原来的名字也可以用)
宏定义不需要分号,typedef后面必须加分号。
宏定义任何名字都可以换,而typedef只能专门给变量类型换名字
所以宏定义的改名范围更宽,只不过对于变量类型重命名而言,使用typedef更加安全。
宏定义无脑改名,typedef会对命名进行检查,如果不是变量类型的名字,就报错

结构体

在这里插入图片描述
组合数据类型,一大堆基本数据类型的集合,数组只能组合相同类型的数据,想组合不同类型的数据就用结构体

变量就是定义数据和引用数据的
所以struct 要{}来打包变量,此处就是定义一个结构体变量StructName,包含了char 型的x,int型的y,float型的z

定义数据:
int a; 定义一个int型数据叫a,
int b[5]; 定义一个5个int型数据的数组
struct c; 定义一个结构体类型,叫c
但是既然是不同类型的数组组合,就需要告诉编译器是哪些数据的组合,所以还得加一个附加说明,告诉它是哪些数据,在struct后面加一个花括号,要打包哪些变量
struct{char x;int y;float z;} c; 这才是结构体的完整定义
定义一个结构体变量,名字叫c,其中包含了char 型的x,int型的y,float型的z3个子项

引用数据:
a=66;
b[0]=66; 数组名b加上方括号取索引,比如第0个元素等于66,
引用c 需要用结构体的名字c,然后用.运算符取索引,索引不是0,1,2,3,4,5了,而是结构体子项的名字,比如c.x=‘A’; c.y=66; c.z=3.14;
结构体成员多,一般会换行来写。

结构体的特殊用法
如果每次定义都写 struct{char x;int y;float z;} 这么一大串,那就麻烦,所以typedef的作用就出来了
typedef struct{char x;int y;float z;} StructName; 用StructName来替换前面的一长串,看上去就简单多了。

另一种引用方式:
pStructName->x=‘A’; pStructName是结构体的首地址,也就是结构体指针,加上->运算符,再加结构体成员名

加结构体指针的引用方式的原因:结构体是一种组合数据类型,在函数的数据传递过程中,通常用地址传递而不是值传递(地址传递、值传递在指针讨论 用法和利弊)

在这里插入图片描述
比如这个地方,结构体变量在传给GPIO_Init函数时,传递的是结构体的指针

在这里插入图片描述
对应GPIO_Init函数用结构体指针来接收,里面再引用结构体成员的时候,就可以使用->这个符号来引用
也可以用*号引出指针变量的内容,再用.点来引用结构体也是可以的,只不过用->这个运算符号更加方便
在这里插入图片描述
这个结构体就是一个数据打包的过程,首先将参数写到结构体的这3个变量里,然后统一打包,将结构体传递到函数里,函数里面再把这个结构体拆包出来,读取变量。这就是使用结构体的过程。(当需要参数很多时不方便管理就需要结构体了)

枚举

在这里插入图片描述
比如定义一个变量存储星期的值,那理论上取值是1-7,如果定义的整形变量,那变量任意存什么数都行,不会收到限制,这时可能出现数据不合法。比如星期8的出现,如果需要程序更加安全,就可以定义一个取值受限制的整形变量:枚举

也可以当成宏定义的集合:

定义和结构体差不多,这里是enum,然后是变量名字,中间是花括号,但注意里面是逗号,隔开
这样可以限制变量的取值范围,只能取花括号里面的定值。
另外,里面的定义,如果按照顺序累加的,那后面的幅值可以省略,编译器会自动添加上去。
同时也可以用typedef改一下名

比如:
typedef enum{
MONDAY=1,
TUESDAY,
WEDNESDAY
} week_t;

week_t week;
week MONDAY; //week = 1;
week = 8; //就会编译器报警:枚举里混入了其他变量

int a=MONDAY; //这样的用法和宏定义就差不多了,所以说枚举也是一个宏定义的集合,就是这个意思。

C语言知识总结

实际都不是C语言最根本的语法,没有这些东西照样可以完成功能,这些创造出来是为了更好地管理工程。虽然表面上多此一举,但是工程复杂起来后,使用这些知识可以使编程更加快捷、更容易理解,更不容易出错。

按键控制LED灯&光敏传感器蜂鸣器

对于驱动代码而言,一般都会封装起来,单独放在另外的.c和.h文件里。(模块化编程的方式)
led.c文件存放驱动程序的主体代码,led.h用来存放驱动程序可以对外提供的函数或变量的声明
在这里插入图片描述
led.c的第一行,需要添加 stm32f10x.h文件
led.h要添加一个防止头文件重复包含的代码
在这里插入图片描述
这里面的函数代码思想值得学习。这8个函数都值得学习
在编写代码时,如果不显示代码提示的话,可以按一下快捷键ctrl+Alt+空格,这样就可以弹出代码提示框了
在主函数里面,代码变得更加简介,初始化就是初始化,开灯就是开灯,关灯就是关灯,不需要再管底层的各种参数了。这就是模块化编程的好处。

在这里插入图片描述
GPIO_ReadInputDataBit 读取输入数据寄存器某一个端口的输入值的 参数:GPIOx,GPIO_Pin 用来指定某一个端口,返回值是uint8_t,代表这个端口的高低电平
GPIO_ReadInputData 读取整个输入数据寄存器的 参数GPIOx 用来指定外设,返回值uint16_t,是16位的数据,每一位代表一个端口值
GPIO_ReadOutputDataBit 读取输出数据寄存器某一个端口的输入值的 参数:GPIOx,GPIO_Pin 用来指定某一个端口,返回值是uint8_t,代表这个端口的高低电平(原则上来说,并不是用来读取端口的输入数据的,一般用于输出模式下,用来看一下自己的输出是什么)
GPIO_ReadOutputData 读取整个输出数据寄存器的
下面是读取的对应关系
在这里插入图片描述

在这里插入图片描述

变量全局变量,局部变量,定义域不一样。名称相同但是强龙不压地头蛇。

函数写好后,尽量在函数上方加一些注释,说明函数的用途,参数的取值和返回值的意思。时间久了自己看起来也知道,别人看也容易理解。

GPIO总结

GPIO使用方法总结

首先初始化时钟,然后定义结构体,赋值结构体,
GPIO_MODE 可以选择8中输入输出模式
GPIO_Pin 可以选择引脚,可以用按位或的方式同时选中多个引脚
GPIO_Speed 选择输出速度,要求不高的话直接使用50MHz即可
最后使用GPIO_Init函数,将指定的GPIO外设初始化好

然后是8个读取和写入的函数,读写主要用这些函数即可。
在这里插入图片描述

模块化编程的方法:

自己做产品外围硬件比较多,这时候就尽量把每个硬件的驱动函数单独提取出来,封装在.c和.h文件里,这样有利于简化主函数的逻辑。主函数里面有更重要的任务要完成,不要让驱动函数混在主函数里面。另外把硬件驱动提取出来,也有利于我们移植程序,还有利于进行分工合作,比如让别人来写驱动函数。主要的精力就可以集中在主函数的逻辑上了。
最后既然要做封装,函数的注释就要写清楚,这样方柏霓使用这个模块的人快速上手这些函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/869301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL 里怎样解决多租户数据隔离的性能问题?

文章目录 一、多租户数据隔离的性能问题分析(一)大规模数据存储和查询(二)并发访问和锁争用(三)索引维护成本高(四)资源分配不均 二、解决方案(一)数据分区&a…

计算理论复习

1.Turing Machine 确定性图灵机 图灵机有很多不同的定义,这里选取其中一种,其它定义下的图灵机往往与下面这种定义的图灵机计算能力等价。 图灵机是一个在一条可双向无限延伸且被划分为若干格子的纸带上进行操作的机器,其有内部状态&#…

Springboot项目实训--day2

今天学习的是idea和MySQL的连接,以及一些基本的增删改查的功能实现。 一、软件下载 昨天下载了idea,今天要是西安它们的连接,就需要再下载MySQL,我的MySQL是前面几个学期别人帮忙下载的,所以具体的操作步骤我也不清楚…

基于Java+SpringMvc+Vue技术的智慧校园系统设计与实现

博主介绍:硕士研究生,专注于信息化技术领域开发与管理,会使用java、标准c/c等开发语言,以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年,拥有近12年的管理工作经验,拥有较丰富的技术架…

3-6 构建线性模型解决温度计示数转换问题

3-6 构建线性模型解决温度计示数转换问题 直接上源码 %matplotlib inline import numpy as np import torch torch.set_printoptions(edgeitems2, linewidth75)导入必要的库并设置 PyTorch 的打印选项,确保在打印张量时显示边缘项和行宽。 #%% t_c [0.5, 14.0,…

window.matchMedia

matchMedia() 返回一个新的 MediaQueryList 对象,表示指定的媒体查询字符串解析后的结果。 const width ref(); const myFunction (x) > {if (x.matches) {// 媒体查询document.body.style.backgroundColor "yellow";width.value "yellow&quo…

alibabacloud学习笔记11

讲解什么是配置中心及使用前后的好处 讲解Nacos作为配置中心面板介绍 官方文档 Nacos config alibaba/spring-cloud-alibaba Wiki GitHub 加入依赖: 订单服务和视频服务也加上这个依赖。 讲解Nacos作为配置中心实战 订单服务添加配置。 我们注释掉之前的配置。 …

乐鑫ESP-NOW与Wi-Fi SoC方案家居设备无缝连接,启明云端乐鑫代理商

随着科技的不断进步,智能家居逐渐成为现代生活的一部分。ESP-NOW技术以其独特的无线通信能力,为智能家居领域带来了一场革命。 ESP-NOW是一种由乐鑫定义的无线通信协议,它能够在无需路由器的情况下,实现设备间的直接、快速、低功…

事务性数据系统中复制与 S3 Express One Zone 的成本分析

原文链接:https://jack-vanlightly.com/blog/2024/6/10/a-cost-analysis-of-replication-vs-s3-express-one-zone-in-transactional-data-systems作者|Jack Vanlightly AutoMQ 导读 随着 S3 在构建现代化数据基础设施的流行,广大 data in…

【免费的车间数据监控大屏】车间管理的新利器,让生产效率一目了然

面对生产车间里各种繁杂的数据,你不会还在用Excel敲击一个个无聊的数据吧?怎么不试试生动形象的车间数据看板呢? 在繁忙的车间里,每一寸空间都跳动着生产的脉搏,而车间数据监控看板,就像是这个舞台上的“智…

注解复习(java)

文章目录 注解内置注解**Deprecated**OverrideSuppressWarnings【不建议使用】Funcationallnterface 自定义注解元注解RetentionTargetDocumentedInherited 和 Repeatable 反射注解 前言:笔记基于动力节点 注解 注解可以标注在 类上,属性上&#xff0c…

opencv颜色识别,hsv采用滑块调节

识别效果如图所示,尽量排除了蓝色背景的干扰,hsv可用滑块进行调节,更加方便 import cv2 import numpy as np# 创建一个命名窗口,用于显示滑块 cv2.namedWindow("TrackBar")def nothing(x):pass# 创建滑块控件 cv2.cre…

Python深度学习

原文链接:Python深度学习https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247608512&idx1&sn16e2a0bb6b0a1f6b513be173730090c0&chksmfa826927cdf5e031b702deb04eef5cb0055f65b0d6e4c33588949ee81c7380ee044caeafd8c7&token2068755524&am…

arp缓存中毒实验

文章目录 一、相关知识1.什么是arp(地址解析协议)2.什么是免费arp(1)简介(2)主要应用(3)代码 3.什么是arp缓存中毒(1)简介(2)过程&…

24吉林事业单位报名照上传通过别忘了这一步

24吉林事业单位报名照上传通过别忘了这一步 #吉林事业单位 #吉林三支一扶 #吉林事业编 #事业单位报名照片 #吉林事业单位考试 #吉林市事业单位

泛微E9开发 控制Radio框字段打印是否仅显示选中项文字

控制Radio框字段打印是否仅显示选中项文字 1、需求说明2、实现方法3、扩展知识点控制Radio框字段打印是否仅显示选中项文字格式参数说明样例 1、需求说明 当我们对单选框进行打印时,往往会把所有的选项一起打印出来(如下图所示),现…

【AIGC】一、本地docker启动私有大模型

本地docker启动私有大模型 一、最终效果中英文对话生成代码 二、资源配置三、搭建步骤启动docker容器登录页面首次登录请注册登录后的效果 配置模型尝试使用选择模型选项下载模型选择适合的模型开始下载 试用效果返回首页选择模型中英文对话生成代码 四、附录资源监控 五、参考…

Redis过期策略

过期的key集合 Redis会将每个设置了过期时间的key放入到一个独立的字典中,以后会定时遍历这个字典来删除到期的key。除了定时遍历之外,他还会使用惰性策略来删除过期的key,所谓惰性策略就是在客户端访问这个key的时候,redis对key…

[C++] 由C语言过渡到C++的敲门砖

命名空间 在C/C中,变量、函数和后⾯要学到的类都是⼤量存在的,这些变量、函数和类的名称将都存在于全局作⽤域中,可能会导致很多冲突。使⽤命名空间的⽬的是对标识符的名称进⾏本地化,以避免命名冲突或名字污染 。 在同一个工程中…

Python基础-成年人判断(if条件语句联系)

注意输入的年龄需要转化为字符串 代码: print("欢迎来到游乐场:儿童免费,成人收费") age int(input("请输入你的年龄:")) if age>18:print("你已经成年,需要补票10元") # 四个空格缩进print…